pthread_getattr_np(3)
π pthread_getattr_np β get attributes of created thread π
okay bestie, welcome to pthread_getattr_np(3) β that's section 3 of the manual, library functions energy. this one lives in the POSIX threads library (that's libpthread, and you link it with -lpthread), and it's about peeking at what a running thread actually looks like. no cap. β¨
π NAME π
pthread_getattr_np β get attributes of created thread π«Ά
π LIBRARY π
POSIX threads library β libpthread, -lpthread.
πΈ SYNOPSIS πΈ
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <pthread.h>
int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr);
π DESCRIPTION π
so what does pthread_getattr_np() even do? it initializes the thread attributes object that attr points at, filling it with the actual attribute values describing the running thread thread. like, the real ones. the truth. not the vibes you thought you set.
and here's the tea, bestie: those returned values can totally differ from the attribute values you passed in the attr object that created the thread with pthread_create(3). it's giving "the implementation had opinions." specifically, these ones can differ:
- the detach state β because a joinable thread may have detached itself after creation. main character move, honestly.
- the stack size β because the implementation may align it to a suitable boundary.
- and the guard size β because the implementation may round it upward to a multiple of the page size, or just ignore it entirely (i.e., treat as 0) if the application is allocating its own stack.
plus! if the stack address attribute wasn't set in the thread attributes object used to create the thread, then the returned thread attributes object will report the actual stack address that the implementation selected for the thread. so you finally find out where it's living. π
and when you're done with the thread attributes object that pthread_getattr_np() gave you? destroy it with pthread_attr_destroy(3). don't leave it hanging, that's rude. π
π RETURN VALUE π
on success, this function returns 0. on error, it returns a nonzero error number. iconic behavior, very consistent of it. β¨
π ERRORS π
ENOMEMβ insufficient memory. bestie is broke.
in addition, if thread refers to the main thread, then pthread_getattr_np() can fail because of errors from various underlying calls:
fopen(3), if/proc/self/mapscan't be opened;- and
getrlimit(2), if theRLIMIT_STACKresource limit is not supported.
π ATTRIBUTES π
for an explanation of the terms used in this section, see attributes(7). so like, if you don't know what "MT-Safe" means, go read that one, iykyk.
- Interface:
pthread_getattr_np() - Attribute: Thread safety
- Value:
MT-Safe
periodt. π
π STANDARDS π
GNU! which is why it's got that _np suffix in the name β _np means nonportable, so don't be bringing this to a portable party. π
π¦ HISTORY π¦
glibc 2.2.3. vintage. an elder. we respect her. β
π EXAMPLES π
the program below demonstrates the use of pthread_getattr_np(). it creates a thread that then uses pthread_getattr_np() to retrieve and display its guard size, stack address, and stack size attributes. command-line arguments can be used to set these attributes to values other than the default when creating the thread. and the shell sessions below demonstrate the use of the program. let's goooo.
run #1 β default attributes, x86-32
in the first run, on an x86-32 system, a thread is created using default attributes:
$ ulimit -s # No stack limit ==> default stack size is 2 MB
unlimited
$ ./a.out
Attributes of created thread:
Guard size = 4096 bytes
Stack address = 0x40196000 (EOS = 0x40397000)
Stack size = 0x201000 (2101248) bytes
run #2 β guard size gets rounded up
in the following run, we see that if a guard size is specified, it is rounded up to the next multiple of the system page size (4096 bytes on x86-32):
$ ./a.out -g 4097
Thread attributes object after initializations:
Guard size = 4097 bytes
Stack address = (nil)
Stack size = 0x0 (0) bytes
Attributes of created thread:
Guard size = 8192 bytes
Stack address = 0x40196000 (EOS = 0x40397000)
Stack size = 0x201000 (2101248) bytes
4097 in, 8192 out. glow up. β¨
run #3 β manually allocated stack, guard size ignored
in the last run, the program manually allocates a stack for the thread. in this case, the guard size attribute is ignored.
$ ./a.out -g 4096 -s 0x8000 -a
Allocated thread stack at 0x804d000
Thread attributes object after initializations:
Guard size = 4096 bytes
Stack address = 0x804d000 (EOS = 0x8055000)
Stack size = 0x8000 (32768) bytes
Attributes of created thread:
Guard size = 0 bytes
Stack address = 0x804d000 (EOS = 0x8055000)
Stack size = 0x8000 (32768) bytes
guard size = 0 bytes. it said "not my problem, you brought your own stack." π
π Program source π
okay here's the whole thing, verbatim, every line, not touching a single character:
#define _GNU_SOURCE /* To get pthread_getattr_np() declaration */
#include <err.h>
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static void
display_stack_related_attributes(pthread_attr_t *attr, char *prefix)
{
int s;
size_t stack_size, guard_size;
void *stack_addr;
s = pthread_attr_getguardsize(attr, &guard_size);
if (s != 0)
errc(EXIT_FAILURE, s, "pthread_attr_getguardsize");
printf("%sGuard size = %zu bytes\n", prefix, guard_size);
s = pthread_attr_getstack(attr, &stack_addr, &stack_size);
if (s != 0)
errc(EXIT_FAILURE, s, "pthread_attr_getstack");
printf("%sStack address = %p", prefix, stack_addr);
if (stack_size > 0)
printf(" (EOS = %p)", (char *) stack_addr + stack_size);
printf("\n");
printf("%sStack size = %#zx (%zu) bytes\n",
prefix, stack_size, stack_size);
}
static void
display_thread_attributes(pthread_t thread, char *prefix)
{
int s;
pthread_attr_t attr;
s = pthread_getattr_np(thread, &attr);
if (s != 0)
errc(EXIT_FAILURE, s, "pthread_getattr_np");
display_stack_related_attributes(&attr, prefix);
s = pthread_attr_destroy(&attr);
if (s != 0)
errc(EXIT_FAILURE, s, "pthread_attr_destroy");
}
static void * /* Start function for thread we create */
thread_start(void *arg)
{
printf("Attributes of created thread:\n");
display_thread_attributes(pthread_self(), "\t");
exit(EXIT_SUCCESS); /* Terminate all threads */
}
static void
usage(char *pname, char *msg)
{
if (msg != NULL)
fputs(msg, stderr);
fprintf(stderr, "Usage: %s [-s stack-size [-a]]"
" [-g guard-size]\n", pname);
fprintf(stderr, "\t\t-a means program should allocate stack\n");
exit(EXIT_FAILURE);
}
static pthread_attr_t * /* Get thread attributes from command line */
get_thread_attributes_from_cl(int argc, char *argv[],
pthread_attr_t *attrp)
{
int s, opt, allocate_stack;
size_t stack_size, guard_size;
void *stack_addr;
pthread_attr_t *ret_attrp = NULL; /* Set to attrp if we initialize
a thread attributes object */
allocate_stack = 0;
stack_size = -1;
guard_size = -1;
while ((opt = getopt(argc, argv, "ag:s:")) != -1) {
switch (opt) {
case 'a': allocate_stack = 1; break;
case 'g': guard_size = strtoul(optarg, NULL, 0); break;
case 's': stack_size = strtoul(optarg, NULL, 0); break;
default: usage(argv[0], NULL);
}
}
if (allocate_stack && stack_size == -1)
usage(argv[0], "Specifying -a without -s makes no sense\n");
if (argc > optind)
usage(argv[0], "Extraneous command-line arguments\n");
if (stack_size != -1 || guard_size > 0) {
ret_attrp = attrp;
s = pthread_attr_init(attrp);
if (s != 0)
errc(EXIT_FAILURE, s, "pthread_attr_init");
}
if (stack_size != -1) {
if (!allocate_stack) {
s = pthread_attr_setstacksize(attrp, stack_size);
if (s != 0)
errc(EXIT_FAILURE, s, "pthread_attr_setstacksize");
} else {
s = posix_memalign(&stack_addr, sysconf(_SC_PAGESIZE),
stack_size);
if (s != 0)
errc(EXIT_FAILURE, s, "posix_memalign");
printf("Allocated thread stack at %p\n\n", stack_addr);
s = pthread_attr_setstack(attrp, stack_addr, stack_size);
if (s != 0)
errc(EXIT_FAILURE, s, "pthread_attr_setstacksize");
}
}
if (guard_size != -1) {
s = pthread_attr_setguardsize(attrp, guard_size);
if (s != 0)
errc(EXIT_FAILURE, s, "pthread_attr_setstacksize");
}
return ret_attrp;
}
int
main(int argc, char *argv[])
{
int s;
pthread_t thr;
pthread_attr_t attr;
pthread_attr_t *attrp = NULL; /* Set to &attr if we initialize
a thread attributes object */
attrp = get_thread_attributes_from_cl(argc, argv, &attr);
if (attrp != NULL) {
printf("Thread attributes object after initializations:\n");
display_stack_related_attributes(attrp, "\t");
printf("\n");
}
s = pthread_create(&thr, attrp, &thread_start, NULL);
if (s != 0)
errc(EXIT_FAILURE, s, "pthread_create");
if (attrp != NULL) {
s = pthread_attr_destroy(attrp);
if (s != 0)
errc(EXIT_FAILURE, s, "pthread_attr_destroy");
}
pause(); /* Terminates when other thread calls exit() */
}
π₯ SEE ALSO π₯
go read these next, bestie, they're all in the family:
pthread_attr_getaffinity_np(3), pthread_attr_getdetachstate(3), pthread_attr_getguardsize(3), pthread_attr_getinheritsched(3), pthread_attr_getschedparam(3), pthread_attr_getschedpolicy(3), pthread_attr_getscope(3), pthread_attr_getstack(3), pthread_attr_getstackaddr(3), pthread_attr_getstacksize(3), pthread_attr_init(3), pthread_create(3), pthreads(7)
okay that's the whole page, you ate it, you understood it, you're literally a pthreads girly now π
this little love letter was brought to you by Linux man-pages 6.20, dated 2025-09-25 β and yeah, it's the pthread_getattr_np(3) page, no cap. go forth and destroy your attribute objects responsibly. mwah π«Άβ¨
π¦ where this page comes from
- arch rolling: man-pages 6.20-1 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
- nixpkgs unstable: man-pages 6.20
- π the page's license: Linux-man-pages-copyleft
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms