Go to main content

Multithreaded Programming Guide

Exit Print View

Updated: November 2020
 
 

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

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

Figure 1, Table 1, Default Attribute Values for tattr shows the default values for attributes (tattr).

Table 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
0
New thread has system-defined stack size.
priority
0
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 Oracle 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 later release. To avoid any potential problems caused by this change, call pthread_attr_setinheritsched() to set the inheritsched attribute to the appropriate value.

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() 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 a Thread 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 5  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() 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:

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

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

pthread_attr_setschedpolicy() 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

    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 user id 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() 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:

  • 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

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

This example shows how to create a child thread with a priority that is different from its parent's priority.

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

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 7  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() 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 allocates a stack for the new thread with at least stacksize bytes.

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