Apparently there seems to be some confusion
1 2 around when the structure
pthread_attr_t gets updated. In one of the above threads, it appears that the initiator believes that the attribute structure must be updated at least when a thread was created by calling
pthread_create()
.
Let's start with an example:(Taken from:
pthread_attr_getstack(), pthread_attr_getstackaddr() thread -- for simplicity, I just removed the error checking code)
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
void* Proc(void* param)
{
sleep(3);
return 0;
}
int main(int argc, char *argv[])
{
pthread_attr_t Attr;
pthread_t Id;
void *Stk;
size_t Siz;
int err;
pthread_attr_init(&Attr);
pthread_attr_getstacksize(&Attr, &Siz);
pthread_attr_getstackaddr(&Attr, &Stk);
printf("Default: Addr=%08x Size=%d\n", Stk, Siz);
pthread_create(&Id, &Attr, Proc, NULL);
pthread_attr_getstackaddr(&Attr, &Stk);
pthread_attr_getstacksize(&Attr, &Siz);
printf("Stack : Addr=%08x Size=%d\n", Stk, Siz);
return (0);
}
On Solaris, this piece of code produces a result of:
Default: Addr=00000000 Size=0
Stack : Addr=00000000 Size=0
This result may surprise (and
confuse) some of the users, who expects a valid base address and a valid size for the stack. However on Solaris, a value of NULL for stack address, and 0 for stack size indicates that the new thread will have system defined stack address and system allocated stack size (1M for 32-bit and 2M for 64-bit processes) respectively. Other default values for attribute (
Attr
, in the example) is mentioned in
Solaris 10 Multithreaded Programming Guide. To understand when the interfaces
pthread_attr_getstackaddr()
and
pthread_attr_getstacksize()
, return valid values, first we need to know a little about attribute object.
What is an Attribute object?Attributes are a way to specify behavior that is different from the default. Any variable of type
pthread_attr_t
can be used specify the new behavior. Attribute object can be specified, when a thread is created with
pthread_create()
or when a synchronization variable is initialized. Note that these attributes cannot be altered while the thread is in use.
Now it all makes sense for the OS to return NULL and 0 for base address and size of a stack. Since the POSIX specification didn't specify the default values to be returned, the output for the same program might be different on different platforms (see previous paragraphs for the default values chosen by Sun).
Let's modify the C code a little to place a 3M stack, at a different location than the system defined address. (The newly introduced code is in green color)
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/mman.h>
void* Proc(void* param)
{
sleep(3);
return 0;
}
int main(int argc, char *argv[])
{
pthread_attr_t Attr;
pthread_t Id;
void *Stk;
size_t Siz;
int err;
size_t stksize = 0x300000;
void *stack;
pthread_attr_init(&Attr);
pthread_attr_getstacksize(&Attr, &Siz);
pthread_attr_getstackaddr(&Attr, &Stk);
printf("Default: Addr=%08x Size=%d\n", Stk, Siz);
stack = mmap(NULL, stksize, PROT_WRITE|PROT_READ, MAP_ANON|MAP_SHARED, -1, 0);
pthread_attr_setstack(&Attr, stack, stksize);
pthread_create(&Id, &Attr, Proc, NULL);
pthread_attr_getstackaddr(&Attr, &Stk);
pthread_attr_getstacksize(&Attr, &Siz);
printf("Stack : Addr=%08x Size=%d\n", Stk, Siz);
return (0);
}
Here's the output from the above program:
Default: Addr=00000000 Size=0
Stack : Addr=fee80000 Size=3145728
Moral of the story:
pthread_attr_getstack()
is not broken; and the structure
pthread_attr_t (ie., the attribute object) gets updated only if we update it, with the help of pthread_attr_setxxxx() interfaces defined in pthread.h ie.,
% grep "pthread_attr_set*" /usr/include/pthread.h
int pthread_attr_setstack(pthread_attr_t *, void *, size_t);
int pthread_attr_setstacksize(pthread_attr_t *, size_t);
int pthread_attr_setstackaddr(pthread_attr_t *, void *);
int pthread_attr_setdetachstate(pthread_attr_t *, int);
int pthread_attr_setscope(pthread_attr_t *, int);
int pthread_attr_setinheritsched(pthread_attr_t *, int);
int pthread_attr_setschedpolicy(pthread_attr_t *, int);
int pthread_attr_setschedparam(pthread_attr_t *_RESTRICT_KYWD,
int pthread_attr_setguardsize(pthread_attr_t *, size_t);
Otherwise system is going to return the default values for all pthread_attr_getxxxx() calls.
________________
Technorati tag:
Programming |
POSIX |
Solaris