12.6 Thread Attributes

Team-FLY

POSIX takes an object-oriented approach to representation and assignment of properties by encapsulating properties such as stack size and scheduling policy into an object of type pthread_attr_t . The attribute object affects a thread only at the time of creation. You first create an attribute object and associate properties, such as stack size and scheduling policy, with the attribute object. You can then create multiple threads with the same properties by passing the same thread attribute object to pthread_create . By grouping the properties into a single object, POSIX avoids pthread_create calls with a large number of parameters.

Table 12.3 shows the settable properties of thread attributes and their associated functions. Other entities, such as condition variables and mutex locks, have their own attribute object types. Chapter 13 discusses these synchronization mechanisms.

Table 12.3. Summary of settable properties for POSIX thread attribute objects.

property

function

attribute objects

pthread_attr_destroy

pthread_attr_init

state

pthread_attr_getdetachstate

pthread_attr_setdetachstate

stack

pthread_attr_getguardsize

pthread_attr_setguardsize

pthread_attr_getstack

pthread_attr_setstack

scheduling

pthread_attr_getinheritsched

pthread_attr_setinheritsched

pthread_attr_getschedparam

pthread_attr_setschedparam

pthread_attr_getschedpolicy

pthread_attr_setschedpolicy

pthread_attr_getscope

pthread_attr_setscope

The pthread_attr_init function initializes a thread attribute object with the default values. The pthread_attr_destroy function sets the value of the attribute object to be invalid. POSIX does not specify the behavior of the object after it has been destroyed , but the variable can be initialized to a new thread attribute object. Both pthread_attr_init and pthread_attr_destroy take a single parameter that is a pointer to a pthread_attr_t attribute object.

  SYNOPSIS  #include <pthread.h>    int pthread_attr_destroy(pthread_attr_t *attr);    int pthread_attr_init(pthread_attr_t *attr);  POSIX:THR  

If successful, pthread_attr_destroy and pthread_attr_init return 0. If unsuccessful , these functions return a nonzero error code. The pthread_attr_init function sets errno to ENOMEM if there is not enough memory to create the thread attribute object.

Most of the get/set thread attribute functions have two parameters. The first parameter is a pointer to a thread attribute object. The second parameter is the new value of the attribute for a set operation or a pointer to location to hold the value for a get operation. The pthread_attr_getstack and pthread_attr_setstack each have one additional parameter.

12.6.1 The thread state

The pthread_attr_getdetachstate function examines the state of an attribute object, and the pthread_attr_setdetachstate function sets the state of an attribute object. The possible values of the thread state are PTHREAD_CREATE_JOINABLE and PTHREAD_CREATE_DETACHED . The attr parameter is a pointer to the attribute object. The detachstate parameter corresponds to the value to be set for pthread_attr_setdetachstate and to a pointer to the value to be retrieved for pthread_attr_getdetachstate .

  SYNOPSIS  #include <pthread.h>   int pthread_attr_getdetachstate(const pthread_attr_t *attr,                                   int *detachstate);   int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);  POSIX:THR  

If successful, these functions return 0. If unsuccessful, they return a nonzero error code. The pthread_attr_setdetachstate function sets errno to EINVAL if detachstate is invalid.

Detached threads release their resources when they terminate, whereas joinable threads should be waited for with a pthread_join . A thread that is detached cannot be waited for with a pthread_join . By default, threads are joinable. You can detach a thread by calling the pthread_detach function after creating the thread. Alternatively, you can create a thread in the detached state by using an attribute object with thread state PTHREAD_CREATE_DETACHED .

Example 12.15

The following code segment creates a detached thread to run processfd .

 int error, fd; pthread_attr_t tattr; pthread_t tid; if (error = pthread_attr_init(&tattr))    fprintf(stderr, "Failed to create attribute object: %s\n",                     strerror(error)); else if (error = pthread_attr_setdetachstate(&tattr,                  PTHREAD_CREATE_DETACHED))    fprintf(stderr, "Failed to set attribute state to detached: %s\n",            strerror(error)); else if (error = pthread_create(&tid, &tattr, processfd, &fd))    fprintf(stderr, "Failed to create thread: %s\n", strerror(error)); 

12.6.2 The thread stack

A thread has a stack whose location and size are user -settable, a useful property if the thread stack must be placed in a particular region of memory. To define the placement and size of the stack for a thread, you must first create an attribute object with the specified stack attributes. Then, call pthread_create with this attribute object.

The pthread_attr_getstack function examines the stack parameters, and the pthread_attr_setstack function sets the stack parameters of an attribute object. The attr parameter of each function is a pointer to the attribute object. The pthread_attr_setstack function takes the stack address and stack size as additional parameters. The pthread_attr_getstack takes pointers to these items.

  SYNOPSIS  #include <pthread.h>   int pthread_attr_getstack(const pthread_attr_t *restrict attr,            void **restrict stackaddr, size_t *restrict stacksize);   int pthread_attr_setstack(pthread_attr_t *attr,            void *stackaddr, size_t stacksize);  POSIX:THR,TSA,TSS  

If successful, the pthread_attr_getstack and pthread_attr_setstack functions return 0. If unsuccessful, these functions return a nonzero error code. The pthread_attr_setstack function sets errno to EINVAL if stacksize is out of range.

POSIX also provides functions for examining or setting a guard for stack overflows if the stackaddr has not been set by the user. The pthread_attr_getguardsize function examines the guard parameters, and the pthread_attr_setguardsize function sets the guard parameters for controlling stack overflows in an attribute object. If the guardsize parameter is 0, the stack is unguarded. For a nonzero guardsize , the implementation allocates additional memory of at least guardsize . An overflow into this extra memory causes an error and may generate a SIGSEGV signal for the thread.

  SYNOPSIS  #include <pthread.h>   int pthread_attr_getguardsize(const pthread_attr_t *restrict attr,                             size_t *restrict guardsize);   int pthread_attr_setguardsize(pthread_attr_t *attr,                             size_t guardsize);  POSIX:THR,XSI  

If successful, pthread_attr_getguardsize and pthread_attr_setguardsize return 0. If unsuccessful, these functions return a nonzero error code. They return EINVAL if the attr or guardsize parameter is invalid. Guards require the POSIX:THR Extension and the POSIX:XSI Extension.

12.6.3 Thread scheduling

The contention scope of an object controls whether the thread competes within the process or at the system level for scheduling resources. The pthread_attr_getscope examines the contention scope, and the pthread_attr_setscope sets the contention scope of an attribute object. The attr parameter is a pointer to the attribute object. The contentionscope parameter corresponds to the value to be set for pthread_attr_setscope and to a pointer to the value to be retrieved for pthread_attr_getscope . The possible values of the contentionscope parameter are PTHREAD_SCOPE_PROCESS and PTHREAD_SCOPE_SYSTEM .

  SYNOPSIS  #include <pthread.h>   int pthread_attr_getscope(const pthread_attr_t *restrict attr,                             int *restrict contentionscope);   int pthread_attr_setscope(pthread_attr_t *attr, int contentionscope);  POSIX:THR,TPS  

If successful, pthread_attr_getscope and pthread_attr_setscope return 0. If unsuccessful, these functions return a nonzero error code. No mandatory errors are defined for these functions.

Example 12.16

The following code segment creates a thread that contends for kernel resources.

 int error; int fd; pthread_attr_t tattr; pthread_t tid; if (error = pthread_attr_init(&tattr))    fprintf(stderr, "Failed to create an attribute object:%s\n",            strerror(error)); else if (error = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM))    fprintf(stderr, "Failed to set scope to system:%s\n",            strerror(error)); else if (error = pthread_create(&tid, &tattr, processfd, &fd))    fprintf(stderr, "Failed to create a thread:%s\n", strerror(error)); 

POSIX allows a thread to inherit a scheduling policy in different ways. The pthread_attr_getinheritsched function examines the scheduling inheritance policy, and the pthread_attr_setinheritsched function sets the scheduling inheritance policy of an attribute object.

The attr parameter is a pointer to the attribute object. The inheritsched parameter corresponds to the value to be set for pthread_attr_setinheritsched and to a pointer to the value to be retrieved for pthread_attr_getinheritsched . The two possible values of inheritsched are PTHREAD_INHERIT_SCHED and PTHREAD_EXPLICIT_SCHED . The value of inheritsched determines how the other scheduling attributes of a created thread are to be set. With PTHREAD_INHERIT_SCHED , the scheduling attributes are inherited from the creating thread and the other scheduling attributes are ignored. With PTHREAD_EXPLICIT_SCHED , the scheduling attributes of this attribute object are used.

  SYNOPSIS  #include <pthread.h>   int pthread_attr_getinheritsched(const pthread_attr_t *restrict attr,                             int *restrict inheritsched);   int pthread_attr_setinheritsched(pthread_attr_t *attr,                             int inheritsched);  POSIX:THR,TPS  

If successful, these functions return 0. If unsuccessful, they return a nonzero error code. No mandatory errors are defined for these functions.

The pthread_attr_getschedparam function examines the scheduling parameters, and the pthread_attr_setschedparam sets the scheduling parameters of an attribute object. The attr parameter is a pointer to the attribute object. The param parameter is a pointer to the value to be set for pthread_attr_setschedparam and a pointer to the value to be retrieved for pthread_attr_getschedparam . Notice that unlike the other pthread_attr_set functions, the second parameter is a pointer because it corresponds to a structure rather than an integer. Passing a structure by value is inefficient.

  SYNOPSIS  #include <pthread.h>   int pthread_attr_getschedparam(const pthread_attr_t *restrict attr,                             struct sched_param *restrict param);   int pthread_attr_setschedparam(pthread_attr_t *restrict attr,                             const struct sched_param *restrict param);  POSIX:THR  

If successful, these functions return 0. If unsuccessful, they return a nonzero error code. No mandatory errors are defined for these functions.

The scheduling parameters depend on the scheduling policy. They are encapsulated in a struct sched_param structure defined in sched.h . The SCHED_FIFO and SCHED_RR scheduling policies require only the sched_priority member of struct sched_param . The sched_priority field holds an int priority value, with larger priority values corresponding to higher priorities. Implementations must support at least 32 priorities.

Program 12.10 shows a function that creates a thread attribute object with a specified priority. All the other attributes have their default values. Program 12.10 returns a pointer to the created attribute object or NULL if the function failed, in which case it sets errno . Program 12.10 illustrates the general strategy for changing parameters ”read the existing values first and change only the ones that you need to change.

Example 12.17

The following code segment creates a dothis thread with the default attributes, except that the priority is HIGHPRIORITY .

 #define HIGHPRIORITY 10 int fd; pthread_attr_t *tattr; pthread_t tid; struct sched_param tparam; if ((tattr = makepriority(HIGHPRIORITY))) {    perror("Failed to create the attribute object"); else if (error = pthread_create(&tid, tattr, dothis, &fd))    fprintf(stderr, "Failed to create dothis thread:%s\n", strerror(error)); 

Threads of the same priority compete for processor resources as specified by their scheduling policy. The sched.h header file defines SCHED_FIFO for first-in-first-out scheduling, SCHED_RR for round- robin scheduling and SCHED_OTHER for some other policy. One additional scheduling policy, SCHED_SPORADIC , is defined for implementations supporting the POSIX:SS Process Sporadic Server Extension and the POSIX:TSP Thread Sporadic Server Extension. Implementations may also define their own policies.

Program 12.10 makepriority.c

A function to create a thread attribute object with the specified priority .

 #include <errno.h> #include <pthread.h> #include <stdlib.h> pthread_attr_t *makepriority(int priority) {    /* create attribute object */    pthread_attr_t *attr;    int error;    struct sched_param param;    if ((attr = (pthread_attr_t *)malloc(sizeof(pthread_attr_t))) == NULL)       return NULL;    if (!(error = pthread_attr_init(attr)) &&        !(error = pthread_attr_getschedparam(attr, &param))) {        param.sched_priority = priority;        error = pthread_attr_setschedparam(attr, &param);    }    if (error) {                      /* if failure, be sure to free memory */       free(attr);       errno = error;       return NULL;    }    return attr; } 

First-in-first-out scheduling policies (e.g., SCHED_FIFO) use a queue for threads in the runnable state at a specified priority. Blocked threads that become runnable are put at the end of the queue corresponding to their priority, whereas running threads that have been preempted are put at the front of their queue.

Round-robin scheduling (e.g., SCHED_RR ) behaves similarly to first-in-first-out except that when a running thread has been running for its quantum, it is put at the end of the queue for its priority. The sched_rr_get_interval function returns the quantum.

Sporadic scheduling, which is similar to first-in-first-out, uses two parameters (the replenishment period and the execution capacity) to control the number of threads running at a given priority level. The rules are reasonably complex, but the policy allows a program to more easily regulate the number of threads competing for the processor as a function of available resources.

Preemptive priority policy is the most common implementation of SCHED_OTHER . A POSIX-compliant implementation can support any of these scheduling policies. The actual behavior of the policy in the implementation depends on the scheduling scope and other factors.

The pthread_attr_getschedpolicy function gets the scheduling policy, and the pthread_attr_setschedpolicy function sets the scheduling policy of an attribute object. The attr parameter is a pointer to the attribute object. For the function pthread_attr_setschedpolicy , the policy parameter is a pointer to the value to be set; for pthread_attr_getschedpolicy , it is a pointer to the value to be retrieved. The scheduling policy values are described above.

  SYNOPSIS  #include <pthread.h>   int pthread_attr_getschedpolicy(const pthread_attr_t *restrict attr,                                  int *restrict policy);   int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);  POSIX:THR  

If successful, these functions return 0. If unsuccessful, they return a nonzero error code. No mandatory errors are defined for these functions.

Team-FLY


Unix Systems Programming
UNIX Systems Programming: Communication, Concurrency and Threads
ISBN: 0130424110
EAN: 2147483647
Year: 2003
Pages: 274

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net