Skip Navigation Links | |
Exit Print View | |
Multithreaded Programming Guide Oracle Solaris 11.1 Information Library |
1. Covering Multithreading Basics
pthread_attr_init Return Values
pthread_attr_destroy Return Values
pthread_attr_setdetachstate(3C) Syntax
pthread_attr_setdetachstate Return Values
pthread_attr_getdetachstate Syntax
pthread_attr_getdetachstate Return Values
pthread_attr_setguardsize(3C) Syntax
pthread_attr_setguardsize Return Values
pthread_attr_getguardsize Syntax
pthread_attr_getguardsize Return Values
pthread_attr_setscope Return Values
pthread_attr_getscope Return Values
Setting the Thread Concurrency Level
pthread_setconcurrency Return Values
Getting the Thread Concurrency Level
pthread_getconcurrency Return Values
pthread_attr_setschedpolicy(3C) Syntax
pthread_attr_setschedpolicy Return Values
pthread_attr_getschedpolicy Syntax
pthread_attr_getschedpolicy Return Values
Setting the Inherited Scheduling Policy
pthread_attr_setinheritsched Syntax
pthread_attr_setinheritsched Return Values
Getting the Inherited Scheduling Policy
pthread_attr_getinheritsched Syntax
pthread_attr_getinheritsched Return Values
Setting the Scheduling Parameters
pthread_attr_setschedparam Syntax
pthread_attr_setschedparam Return Values
Getting the Scheduling Parameters
pthread_attr_getschedparam Syntax
Creating a Thread With a Specified Priority
Example of Creating a Prioritized Thread
pthread_attr_getschedparam Return Values
Allocating Stack Space for Threads
pthread_attr_setstacksize Syntax
pthread_attr_setstacksize Return Values
pthread_attr_getstacksize Syntax
pthread_attr_getstacksize Return Values
Setting the Stack Address and Size
pthread_attr_setstack(3C) Syntax
pthread_attr_setstack(3C) Return Values
4. Programming with Synchronization Objects
5. Programming With the Oracle Solaris Software
6. Programming With Oracle Solaris Threads
Attributes provide a way to specify behavior that is different from the default thread creation behavior. When a thread is created with pthread_create(3C) or when a synchronization variable is initialized, an attribute object can be specified. The defaults are usually sufficient.
An attribute object is opaque, and cannot be directly modified by assignments. A set of functions is provided to initialize, configure, and destroy each object type.
Once an attribute is initialized and configured, the attribute has process-wide scope. The suggested method for using attributes is to configure all required state specifications at one time in the early stages of program execution. The appropriate attribute object can then be referred to as needed.
The use of attribute objects provides two primary advantages.
Using attribute objects adds to code portability.
Even though supported attributes might vary between implementations, you need not modify function calls that create thread entities. These function calls do not require modification because the attribute object is hidden from the interface.
If the target port supports attributes that are not found in the current port, provision must be made to manage the new attributes. Management of these attributes is an easy porting task because attribute objects need only be initialized once in a well-defined location.
State specification in an application is simplified.
As an example, consider that several sets of threads might exist within a process. Each set of threads provides a separate service. Each set has its own state requirements.
At some point in the early stages of the application, a thread attribute object can be initialized for each set. All future thread creations will then refer to the attribute object that is initialized for that type of thread. The initialization phase is simple and localized. Any future modifications can be made quickly and reliably.
Attribute objects require attention at process exit time. When the object is initialized, memory is allocated for the object. This memory must be returned to the system. The pthreads standard provides function calls to destroy attribute objects.
Pthreads functions can be used to manipulate thread attribute objects. The functions are described in the following sections.
Use pthread_attr_init(3C) to initialize object attributes to their default values. The storage is allocated by the thread system during execution.
int pthread_attr_init(pthread_attr_t *tattr);
#include <pthread.h> pthread_attr_t tattr; int ret; /* initialize an attribute to the default value */ ret = pthread_attr_init(&tattr);
Table 3-1 shows the default values for attributes (tattr).
Table 3-1 Default Attribute Values for tattr
|
Note - The default value for the inheritsched attribute might change from PTHREAD_EXPLICIT_SCHED to PTHREAD_INHERIT_SCHED in a future Oracle Solaris release. You should call pthread_attr_setinheritsched() to set the inheritsched attribute to the value you want rather than accepting the default, in order to avoid any potential problems caused by this change.
pthread_attr_init() returns zero after completing successfully. Any other return value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
ENOMEM
Description: Returned when not enough memory is allocated to initialize the thread attributes object.
Use pthread_attr_destroy(3C) to remove the storage that was allocated during initialization. The attribute object becomes invalid.
int pthread_attr_destroy(pthread_attr_t *tattr);
#include <pthread.h> pthread_attr_t tattr; int ret; /* destroy an attribute */ ret = pthread_attr_destroy(&tattr);
pthread_attr_destroy() returns zero after completing successfully. Any other return value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
EINVAL
Description: Indicates that the value of tattr was not valid.
When a thread is created detached (PTHREAD_CREATE_DETACHED), its thread ID and other resources can be reused as soon as the thread exits. Use pthread_attr_setdetachstate(3C) when the calling thread does not want to wait for the thread to exit.
int pthread_attr_setdetachstate(pthread_attr_t *tattr,int detachstate);
#include <pthread.h> pthread_attr_t tattr; int ret; /* set the thread detach state */ ret = pthread_attr_setdetachstate(&tattr,PTHREAD_CREATE_DETACHED);
When a thread is created nondetached with PTHREAD_CREATE_JOINABLE, the assumption is that your application will wait for the thread to complete. That is, the program will execute a pthread_join() on the thread.
Whether a thread is created detached or nondetached, the process does not exit until all threads have exited. See Finishing Up for a discussion of process termination caused by premature exit from main().
Note - When no explicit synchronization prevents a newly created, detached thread from exiting, its thread ID can be reassigned to another new thread before its creator returns from pthread_create().
Nondetached threads must have a thread join with the nondetached thread after the nondetached thread terminates. Otherwise, the resources of that thread are not released for use by new threads that commonly results in a memory leak. So, when you do not want a thread to be joined, create the thread as a detached thread.
Example 3-1 Creating a Detached Thread
#include <pthread.h> pthread_attr_t tattr; pthread_t tid; void *start_routine; void arg int ret; /* initialized with default attributes */ ret = pthread_attr_init (&tattr); ret = pthread_attr_setdetachstate (&tattr,PTHREAD_CREATE_DETACHED); ret = pthread_create (&tid, &tattr, start_routine, arg);
pthread_attr_setdetachstate() returns zero after completing successfully. Any other return value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
EINVAL
Description: Indicates that the value of detachstate or tattr was not valid.
Use pthread_attr_getdetachstate(3C) to retrieve the thread create state, which can be either detached or joined.
int pthread_attr_getdetachstate(const pthread_attr_t *tattr, int *detachstate;
#include <pthread.h> pthread_attr_t tattr; int detachstate; int ret; /* get detachstate of thread */ ret = pthread_attr_getdetachstate (&tattr, &detachstate);
pthread_attr_getdetachstate() returns zero after completing successfully. Any other return value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
EINVAL
Description: Indicates that the value of detachstate is NULL or tattr is invalid.
pthread_attr_setguardsize(3C) sets the guardsize of the attr object.
#include <pthread.h> int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);
The guardsize attribute is provided to the application for two reasons:
Overflow protection can potentially result in wasted system resources. When your application creates a large number of threads, and you know that the threads will never overflow their stack, you can turn off guard areas. By turning off guard areas, you can conserve system resources.
When threads allocate large data structures on stack, a large guard area might be needed to detect stack overflow.
The guardsize argument provides protection against overflow of the stack pointer. If a thread's stack is created with guard protection, the implementation allocates extra memory at the overflow end of the stack. This extra memory acts as a buffer against stack overflow of the stack pointer. If an application overflows into this buffer an error results, possibly in a SIGSEGV signal being delivered to the thread.
If guardsize is zero, a guard area is not provided for threads that are created with attr. If guardsize is greater than zero, a guard area of at least size guardsize bytes is provided for each thread created with attr. By default, a thread has an implementation-defined, nonzero guard area.
A conforming implementation is permitted to round up the value contained in guardsize to a multiple of the configurable system variable PAGESIZE . See PAGESIZE in sys/mman.h. If an implementation rounds up the value of guardsize to a multiple of PAGESIZE, a call to pthread_attr_getguardsize() that specifies attr stores, in guardsize, the guard size specified in the previous call to pthread_attr_setguardsize().
pthread_attr_setguardsize() fails if:
EINVAL
Description: The argument attr is invalid, the argument guardsize is invalid, or the argument guardsize contains an invalid value.
pthread_attr_getguardsize(3C) gets the guardsize of the attr object.
#include <pthread.h> int pthread_attr_getguardsize(const pthread_attr_t *restrict attr, size_t *restrict guardsize);
A conforming implementation is permitted to round up the value contained in guardsize to a multiple of the configurable system variable PAGESIZE . See PAGESIZE in sys/mman.h. If an implementation rounds up the value of guardsize to a multiple of PAGESIZE, a call to pthread_attr_getguardsize() that specifies attr stores, in guardsize, the guard size specified in the previous call to pthread_attr_setguardsize().
pthread_attr_getguardsize() fails if:
EINVAL
Description: The argument attr is invalid, the argument guardsize is invalid, or the argument guardsize contains an invalid value.
Use pthread_attr_setscope(3C) to establish the contention scope of a thread, either PTHREAD_SCOPE_SYSTEM or PTHREAD_SCOPE_PROCESS. With PTHREAD_SCOPE_SYSTEM, this thread contends with all threads in the system. With PTHREAD_SCOPE_PROCESS , this thread contends with other threads in the process.
Note - Both thread types are accessible only within a given process.
int pthread_attr_setscope(pthread_attr_t *tattr,int scope);
#include <pthread.h> pthread_attr_t tattr; int ret; /* bound thread */ ret = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM); /* unbound thread */ ret = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_PROCESS);
This example uses three function calls: a call to initialize the attributes, a call to set any variations from the default attributes, and a call to create the pthreads.
#include <pthread.h> pthread_attr_t attr; pthread_t tid; void *start_routine(void *); void *arg; int ret; /* initialized with default attributes */ ret = pthread_attr_init (&tattr); ret = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM); ret = pthread_create (&tid, &tattr, start_routine, arg);
pthread_attr_setscope() returns zero after completing successfully. Any other return value indicates that an error occurred. If the following conditions occur, the function fails and returns the corresponding value.
EINVAL
Description: An attempt was made to set tattr to a value that is not valid.
Use pthread_attr_getscope(3C) to retrieve the thread scope.
int pthread_attr_getscope(pthread_attr_t *restrict tattr, int *restrict scope);
#include <pthread.h> pthread_attr_t tattr; int scope; int ret; /* get scope of thread */ ret = pthread_attr_getscope(&tattr, &scope);
pthread_attr_getscope() returns zero after completing successfully. Any other return value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
EINVAL
Description: The value of scope is NULL or tattr is invalid.
pthread_setconcurrency(3C) is provided for standards compliance. pthread_setconcurrency() is used by an application to inform the system of the application's desired concurrency level. For the threads implementation introduced in the Solaris 9 release, this interface has no effect, all runnable threads are attached to LWPs.
#include <pthread.h> int pthread_setconcurrency(int new_level);
pthread_setconcurrency() fails if the following conditions occur:
EINVAL
Description: The value specified by new_level is negative.
EAGAIN
Description: The value specified by new_level would cause a system resource to be exceeded.
pthread_getconcurrency(3C) returns the value set by a previous call to pthread_setconcurrency().
#include <pthread.h> int pthread_getconcurrency(void);
If the pthread_setconcurrency() function was not previously called, pthread_getconcurrency() returns zero.
pthread_getconcurrency() always returns the concurrency level set by a previous call to pthread_setconcurrency() . If pthread_setconcurrency() has never been called, pthread_getconcurrency() returns zero.
Use pthread_attr_setschedpolicy(3C) to set the scheduling policy. The POSIX standard specifies the scheduling policy values of SCHED_FIFO (first-in-first-out), SCHED_RR (round-robin), or SCHED_OTHER (an implementation-defined method). In the Oracle Solaris OS, SCHED_OTHER threads run in the traditional time-sharing (TS) scheduling class.
int pthread_attr_setschedpolicy(pthread_attr_t *tattr, int policy);
#include <pthread.h> pthread_attr_t tattr; int policy; int ret; /* set the scheduling policy to SCHED_OTHER */ ret = pthread_attr_setschedpolicy(&tattr, SCHED_OTHER);
SCHED_FIFO
A First-In-First-Out thread runs in the real-time (RT) scheduling class and require the calling process to be privileged. Such a thread, if not preempted by a higher priority thread, executes until it yields or blocks.
SCHED_RR
Round-Robin threads whose contention scope is system (PTHREAD_SCOPE_SYSTEM) are in real-time (RT) scheduling class if the calling process has an effective user id of 0. These threads, if not preempted by a higher priority thread, and if the threads do not yield or block, will execute for the system-determined time period. Use SCHED_RR for threads that have a contention scope of process (PTHREAD_SCOPE_PROCESS) is based on the TS scheduling class. Additionally, the calling process for these threads does not have an effective userid of 0.
A Round-Robin thread runs in the real-time (RT) scheduling class and requires the calling process to be privileged. If a round robin thread is not preempted by a higher priority thread, and does not yield or block, it will execute for a system-determined time period. The thread is then forced to yield to another real time thread of equal priority.
SCHED_FIFO and SCHED_RR are optional in the POSIX standard, and are supported for real-time threads only.
For a discussion of scheduling, see the section Thread Scheduling.
pthread_attr_setschedpolicy() returns zero after completing successfully. Any other return value indicates that an error occurred. When either of the following conditions occurs, the function fails and returns the corresponding value.
EINVAL
Description: An attempt was made to set tattr to a value that is not valid.
ENOTSUP
Description: An attempt was made to set the attribute to an unsupported value.
Use pthread_attr_getschedpolicy(3C) to retrieve the scheduling policy.
int pthread_attr_getschedpolicy(pthread_attr_t *restrict tattr, int *restrict policy);
#include <pthread.h> pthread_attr_t tattr; int policy; int ret; /* get scheduling policy of thread */ ret = pthread_attr_getschedpolicy (&tattr, &policy);
pthread_attr_getschedpolicy() returns zero after completing successfully. Any other return value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
EINVAL
Description: The parameter policy is NULL or tattr is invalid.
Use pthread_attr_setinheritsched(3C) to set the inherited scheduling policy.
int pthread_attr_setinheritsched(pthread_attr_t *tattr, int inheritsched);
#include <pthread.h> pthread_attr_t tattr; int inheritsched; int ret; /* use creating thread's scheduling policy and priority*/ ret = pthread_attr_setinheritsched(&tattr, PTHREAD_INHERIT_SCHED);
An inheritsched value of PTHREAD_INHERIT_SCHED means that the scheduling policy and priority of the creating thread are to be used for the created thread. The scheduling policy and priority in the attribute structure are to be ignored. An inheritsched value of PTHREAD_EXPLICIT_SCHED means that the scheduling policy and priority from the attribute structure are to be used for the created thread. The caller must have sufficient privilege for pthread_create() to succeed in this case.
pthread_attr_setinheritsched() returns zero after completing successfully. Any other return value indicates that an error occurred. When either of the following conditions occurs, the function fails and returns the corresponding value.
EINVAL
Description: An attempt was made to set tattr to a value that is not valid.
pthread_attr_getinheritsched(3C) returns the inheritsched attribute contained in the attribute structure.
int pthread_attr_getinheritsched(pthread_attr_t *restrict tattr int *restrict inheritsched);
#include <pthread.h> pthread_attr_t tattr; int inheritsched; int ret; ret = pthread_attr_getinheritsched (&tattr, &inheritsched);
pthread_attr_getinheritsched() returns zero after completing successfully. Any other return value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
EINVAL
Description: The parameter inherit is NULL or tattr is invalid.
pthread_attr_setschedparam(3C) sets the scheduling parameters.
int pthread_attr_setschedparam(pthread_attr_t *restrict tattr, const struct sched_param *restrict param);
#include <pthread.h> pthread_attr_t tattr; int ret; int newprio; sched_param param; newprio = 30; /* set the priority; others are unchanged */ param.sched_priority = newprio; /* set the new scheduling param */ ret = pthread_attr_setschedparam (&tattr, ¶m);
Scheduling parameters are defined in the param structure. Only the priority parameter is supported.
pthread_attr_setschedparam() returns zero after completing successfully. Any other return value indicates that an error occurred. If the following conditions occur, the function fails and returns the corresponding value.
EINVAL
Description: The value of param is NULL or tattr is invalid.
You can manage pthreads priority in either of two ways:
You can set the priority attribute before creating a child thread
You can change the priority of the parent thread and then change the priority back
pthread_attr_getschedparam(3C) returns the scheduling parameters defined by pthread_attr_setschedparam().
int pthread_attr_getschedparam(pthread_attr_t *restrict tattr, const struct sched_param *restrict param);
#include <pthread.h> pthread_attr_t attr; struct sched_param param; int ret; /* get the existing scheduling param */ ret = pthread_attr_getschedparam (&tattr, ¶m);
You can set the priority attribute before creating the thread. The child thread is created with the new priority that is specified in the sched_param structure. This structure also contains other scheduling information.
Example 3-2 shows an example of creating a child thread with a priority that is different from its parent's priority.
Example 3-2 Creating a Prioritized Thread
#include <pthread.h> #include <sched.h> pthread_attr_t tattr; pthread_t tid; int ret; int newprio = 20; sched_param param; /* initialized with default attributes */ ret = pthread_attr_init (&tattr); /* safe to get existing scheduling param */ ret = pthread_attr_getschedparam (&tattr, ¶m); /* set the priority; others are unchanged */ param.sched_priority = newprio; /* setting the new scheduling param */ ret = pthread_attr_setschedparam (&tattr, ¶m); /* specify explicit scheduling */ ret = pthread_attr_setinheritsched (&tattr, PTHREAD_EXPLICIT_SCHED); /* with new priority specified */ ret = pthread_create (&tid, &tattr, func, arg);
pthread_attr_getschedparam() returns zero after completing successfully. Any other return value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
EINVAL
Description: The value of param is NULL or tattr is invalid.
Typically, thread stacks begin on page boundaries. Any specified size is rounded up to the next page boundary. A page with no access permission is appended to the overflow end of the stack. Most stack overflows result in sending a SIGSEGV signal to the offending thread. Thread stacks allocated by the caller are used without modification.
When a stack is specified, the thread should also be created with PTHREAD_CREATE_JOINABLE. That stack cannot be freed until the pthread_join(3C) call for that thread has returned. The thread's stack cannot be freed until the thread has terminated. The only reliable way to know if such a thread has terminated is through pthread_join(3C).
Generally, you do not need to allocate stack space for threads. The system allocates 1 megabyte (for 32 bit systems) or 2 megabytes (for 64 bit systems) of virtual memory for each thread's stack with no swap space reserved. The system uses the MAP_NORESERVE option of mmap() to make the allocations.
Each thread stack created by the system has a red zone. The system creates the red zone by appending a page to the overflow end of a stack to catch stack overflows. This page is invalid and causes a memory fault if accessed. Red zones are appended to all automatically allocated stacks whether the size is specified by the application or the default size is used.
Note - Runtime stack requirements vary for library calls and dynamic linking. You should be absolutely certain that the specified stack satisfies the runtime requirements for library calls and dynamic linking.
Very few occasions exist when specifying a stack, its size, or both, is appropriate. Even an expert has a difficult time knowing whether the right size was specified. Even a program that is compliant with ABI standards cannot determine its stack size statically. The stack size is dependent on the needs of the particular runtime environment in execution.
When you specify the thread stack size, you must account for the allocations needed by the invoked function and by each subsequent function called. The accounting should include calling sequence needs, local variables, and information structures.
Occasionally, you want a stack that differs a bit from the default stack. An obvious situation is when the thread needs more than the default stack size. A less obvious situation is when the default stack is too large. You might be creating thousands of threads with insufficient virtual memory to handle the gigabytes of stack space required by thousands of default stacks.
The limits on the maximum size of a stack are often obvious, but what about the limits on its minimum size? Sufficient stack space must exist to handle all stack frames that are pushed onto the stack, along with their local variables, and so on.
To get the absolute minimum limit on stack size, call the macro PTHREAD_STACK_MIN. The PTHREAD_STACK_MIN macro returns the amount of required stack space for a thread that executes a NULL procedure. Useful threads need more than the minimum stack size, so be very careful when reducing the stack size.
pthread_attr_setstacksize(3C) sets the thread stack size.
int pthread_attr_setstacksize(pthread_attr_t *tattr, size_t size);
#include <pthread.h> #include <limits.h> pthread_attr_t tattr; size_t size; int ret; size = (PTHREAD_STACK_MIN + 0x4000); /* setting a new size */ ret = pthread_attr_setstacksize(&tattr, size);
The size attribute defines the size of the stack (in bytes) that the system allocates. The size should not be less than the system-defined minimum stack size. See About Stacks for more information.
size contains the number of bytes for the stack that the new thread uses. If size is zero, a default size is used. In most cases, a zero value works best.
PTHREAD_STACK_MIN is the amount of stack space that is required to start a thread. This stack space does not take into consideration the threads routine requirements that are needed to execute application code.
Example 3-3 Example of Setting Stack Size
#include <pthread.h> #include <limits.h> pthread_attr_t tattr; pthread_t tid; int ret; size_t size = PTHREAD_STACK_MIN + 0x4000; /* initialized with default attributes */ ret = pthread_attr_init(&tattr); /* setting the size of the stack also */ ret = pthread_attr_setstacksize(&tattr, size); /* only size specified in tattr*/ ret = pthread_create(&tid, &tattr, start_routine, arg);
pthread_attr_setstacksize() returns zero after completing successfully. Any other return value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
EINVAL
Description: The value of size is less than PTHREAD_STACK_MIN, or exceeds a system-imposed limit, or tattr is not valid.
pthread_attr_getstacksize(3C) returns the stack size set by pthread_attr_setstacksize().
int pthread_attr_getstacksize(pthread_attr_t *restrict tattr, size_t *restrict size);
#include <pthread.h> pthread_attr_t tattr; size_t size; int ret; /* getting the stack size */ ret = pthread_attr_getstacksize(&tattr, &size);
pthread_attr_getstacksize() returns zero after completing successfully. Any other return value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
EINVAL
Description: tattr or size is not valid.
pthread_attr_setstack(3C) sets the thread stack address and size.
int pthread_attr_setstack(pthread_attr_t *tattr,void *stackaddr, size_t stacksize);
#include <pthread.h> #include <limits.h> pthread_attr_t tattr; void *base; size_t size; int ret; base = (void *) malloc(PTHREAD_STACK_MIN + 0x4000); /* setting a new address and size */ ret = pthread_attr_setstack(&tattr, base,PTHREAD_STACK_MIN + 0x4000);
The stackaddr attribute defines the base (low address) of the thread's stack. The stacksize attribute specifies the size of the stack. If stackaddr is set to non-null, rather than the NULL default, the system initializes the stack at that address, assuming the size to be stacksize.
base contains the address for the stack that the new thread uses. If base is NULL, then pthread_create(3C) allocates a stack for the new thread with at least stacksize bytes.
pthread_attr_setstack() returns zero after completing successfully. Any other return value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
EINVAL
Description: The value of base or tattr is incorrect. The value of stacksize is less than PTHREAD_STACK_MIN.
The following example shows how to create a thread with a custom stack address and size.
#include <pthread.h> pthread_attr_t tattr; pthread_t tid; int ret; void *stackbase; size_t size; /* initialized with default attributes */ ret = pthread_attr_init(&tattr); /* setting the base address and size of the stack */ ret = pthread_attr_setstack(&tattr, stackbase,size); /* address and size specified */ ret = pthread_create(&tid, &tattr, func, arg);
pthread_attr_getstack(3C) returns the thread stack address and size set by pthread_attr_setstack().
int pthread_attr_getstack(pthread_attr_t *restrict tattr, void **restrict stackaddr, size_t *restrict stacksize);
#include <pthread.h> pthread_attr_t tattr; void *base; size_t size; int ret; /* getting a stack address and size */ ret = pthread_attr_getstack (&tattr , &base, &size);
pthread_attr_getstack() returns zero after completing successfully. Any other return value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
EINVAL
Description: The value of tattr is incorrect.