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>On Solaris, this piece of code produces a result of:
#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);
}
Default: Addr=00000000 Size=0This 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 (
Stack : Addr=00000000 Size=0
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>Here's the output from the above program:
#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);
}
Default: Addr=00000000 Size=0Moral of the story:
Stack : Addr=fee80000 Size=3145728
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.hOtherwise system is going to return the default values for all pthread_attr_getxxxx() calls.
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);
________________
Technorati tag: Programming | POSIX | Solaris
Giri,
ReplyDeleteSince this is my sample code, you might at least let me know you posted it here. There is a lot more to this story, which I will reveal on this newsgroup thread.
http://groups.google.com/group/comp.programming.threads/browse_frm/thread/cb0eb84f300b7e99
You left out details like ... what am I trying to accomplish? It certainly wasn't to see if Sun implemented getstack() correctly.
I was trying to find the kernel provided stack: start_addr, size, end_addr ... so that I could determine if a recursive function was about to overflow the stack.
This very simple problem has generated a lot of kernel->diving exercises to ensure it works on all *nix platforms.
The platforms we're interested in covering is Solaris, AIX, HPUX, Linux, and (regrettably) Windows.
Hey Dick,
ReplyDeleteMy intention is to address only part of the problem, you were trying to resolve ie., why pthread_attr_getstackaddr() and pthread_attr_getstacksize() are not returning the proper address and size of the stack, as soon as we create a new thread.
I found another thread with title pthread_attr_getstack broken? at opensolaris.org, with the same question. So, I just thought of documenting my interpretation, in here.