Multithreaded Programming Guide

Attribute Object

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.

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.

Initializing Attributes

Use pthread_attr_init(3C) to initialize object attributes to their default values. The storage is allocated by the thread system during execution.

pthread_attr_init Syntax

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

Attribute 

Value 

Result 

scope

PTHREAD_SCOPE_PROCESS

New thread contends with other threads in the process. 

detachstate

PTHREAD_CREATE_JOINABLE

Completion status and thread ID are preserved after the thread exits.

stackaddr

NULL

New thread has system-allocated stack address. 

stacksize

New thread has system-defined stack size. 

priority

New thread has priority 0. 

inheritsched

PTHREAD_EXPLICIT_SCHED

New thread does not inherit parent thread scheduling priority. 

schedpolicy

SCHED_OTHER

New thread uses the traditional Solaris time-sharing (TS) scheduling class. 

guardsize

PAGESIZE

Stack overflow protection. 


Note –

The default value for the inheritsched attribute might change from PTHREAD_EXPLICIT_SCHED to PTHREAD_INHERIT_SCHED in a future 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 Return Values

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.

Destroying Attributes

Use pthread_attr_destroy(3C) to remove the storage that was allocated during initialization. The attribute object becomes invalid.

pthread_attr_destroy Syntax

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 Return Values

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.

Setting Detach State

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.

pthread_attr_setdetachstate(3C) Syntax

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 Return Values

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.

Getting the Detach State

Use pthread_attr_getdetachstate(3C) to retrieve the thread create state, which can be either detached or joined.

pthread_attr_getdetachstate Syntax

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 Return Values

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.

Setting the Stack Guard Size

pthread_attr_setguardsize(3C) sets the guardsize of the attr object.

pthread_attr_setguardsize(3C) Syntax

#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:

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 Return Values

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.

Getting the Stack Guard Size

pthread_attr_getguardsize(3C) gets the guardsize of the attr object.

pthread_attr_getguardsize Syntax

#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 Return Values

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.

Setting the Scope

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.


pthread_attr_setscope Syntax

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 Return Values

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.

Getting the Scope

Use pthread_attr_getscope(3C) to retrieve the thread scope.

pthread_attr_getscope Syntax

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 Return Values

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.

Setting the Thread Concurrency Level

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.

pthread_setconcurrency Syntax

#include <pthread.h>

int pthread_setconcurrency(int new_level);

pthread_setconcurrency Return Values

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.

Getting the Thread Concurrency Level

pthread_getconcurrency(3C) returns the value set by a previous call to pthread_setconcurrency().

pthread_getconcurrency Syntax

#include <pthread.h>

int pthread_getconcurrency(void);

If the pthread_setconcurrency() function was not previously called, pthread_getconcurrency() returns zero.

pthread_getconcurrency Return Values

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.

Setting the Scheduling Policy

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 Solaris OS, SCHED_OTHER threads run in the traditional time-sharing (TS) scheduling class.

pthread_attr_setschedpolicy(3C) Syntax

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 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 Return Values

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.

Getting the Scheduling Policy

Use pthread_attr_getschedpolicy(3C) to retrieve the scheduling policy.

pthread_attr_getschedpolicy Syntax

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 Return Values

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.

Setting the Inherited Scheduling Policy

Use pthread_attr_setinheritsched(3C) to set the inherited scheduling policy.

pthread_attr_setinheritsched Syntax

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 Return Values

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.

Getting the Inherited Scheduling Policy

pthread_attr_getinheritsched(3C) returns the inheritsched attribute contained in the attribute structure.

pthread_attr_getinheritsched Syntax

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 Return Values

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.

Setting the Scheduling Parameters

pthread_attr_setschedparam(3C) sets the scheduling parameters.

pthread_attr_setschedparam Syntax

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, &param); 

Scheduling parameters are defined in the param structure. Only the priority parameter is supported.

pthread_attr_setschedparam Return Values

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:

Getting the Scheduling Parameters

pthread_attr_getschedparam(3C) returns the scheduling parameters defined by pthread_attr_setschedparam().

pthread_attr_getschedparam Syntax

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, &param);

Creating a Thread With a Specified Priority

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 of Creating a Prioritized Thread

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, &param);

/* set the priority; others are unchanged */
param.sched_priority = newprio;

/* setting the new scheduling param */
ret = pthread_attr_setschedparam (&tattr, &param);

/* 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 Return Values

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.

About Stacks

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).

Allocating Stack Space for Threads

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.

Building Your Own Stack

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.

Setting the Stack Size

pthread_attr_setstacksize(3C) sets the thread stack size.

pthread_attr_setstacksize Syntax

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 Return Values

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.

Getting the Stack Size

pthread_attr_getstacksize(3C) returns the stack size set by pthread_attr_setstacksize().

pthread_attr_getstacksize Syntax

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 Return Values

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.

Setting the Stack Address and Size

pthread_attr_setstack(3C) sets the thread stack address and size.

pthread_attr_setstack(3C) Syntax

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(3C) Return Values

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);

Getting the Stack Address and Size

pthread_attr_getstack(3C) returns the thread stack address and size set by pthread_attr_setstack().

pthread_attr_getstack Syntax

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 Return Values

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.