Creating a Thread
Every process contains at least one main or initial thread of control created by the operating system when the process begins to execute. The library function pthread_create is used to add a new thread of control to the current process. The new thread executes in concert with the other threads within the process and, if directed, with other threads of control in other processes. The syntax for pthread_create is shown in Table 11.1.
There are four pointer-based arguments for pthread_create . [4] The first, *thread , is a reference to a pthread_t type object (an unsigned integer that is typedef ed as the data type pthread_t ). Upon successful completion of the pthread_create call, *thread will reference aunique (to this process only) integer thread ID (TID) value. If this argument is set to NULL, the generated thread ID will not be returned. The second argument, indicated as *attr , references a dynamically allocated attribute structure. This structure contains a single void pointer (as shown in the code sequence below lifted from the /usr/include/bits/pthreadtypes.h file).
[4] This time the e is back in create!
Table 11.1. The pthread_create Library Function.
Include File(s) |
Manual Section |
3 |
||
Summary |
[View full width]
int pthread_create(pthread_t *thread,
pthread_attr_t *attr,
void *(*start_routine)(void
|
|||
Return |
Success |
Failure |
Sets errno |
|
Nonzero |
/* Attributes for threads. */ typedef struct __pthread_attr_s { int __detachstate; int __schedpolicy; struct __sched_param __schedparam; int __inheritsched; int __scope; size_t __guardsize; int __stackaddr_set; void *__stackaddr; size_t __stacksize; } pthread_attr_t;
Attributes govern how the thread behaves. Attributes include stack sizeaddress; scheduling policypriority and detached state. If the *attr value is set to NULL , the new thread uses the system defaults for its attributes. If the user wants to modify the default attributes prior to thread creation, he or sheshould call the library function pthread_attr_init . The pthread_attr_init library function and related attribute setting functions are covered in a following section.
The third argument for pthread_create is a reference to a user-defined function that will be executed by the new thread. The user-defined function should be written to return a pointer to a void and have a single void pointer argument. If the return type of the user-defined function is a pointer, but it is not of type void , use a typecast (e.g., (void * (*)()) ) to pass the function reference and keep the compiler from complaining. A reference to the actual argument to be passed to the user-defined function is the fourth argument for pthread_create . As with the user-defined function reference, this argument is also a void pointer. If multiple arguments are to be passed to the user-defined function, a structure containing the arguments should be statically allocated and initialized . [5] The reference to the structure should be cast to a void pointer when pthread_create is called.
[5] As would be anticipated, locally allocated objects reside on the stack, and their value is undefined when we leave their scope.
Once a thread is created, it has its own set of attributes and an execution stack. It inherits its signal mask (which it then can alter) and scheduling priority from the calling program (the initiating thread). It does not inherit any pending signals. If needed, a thread can allocate its own storage for thread-specific data.
If the pthread_create call is successful, it returns a value of 0 and sets the *thread reference to a unique ID for this process. If the call fails, it returns a nonzero value. POSIX thread functions do not routinely set errno when they fail, but instead return a nonzero value, which indicates the source of the error encountered . However, errno is set when a library function or system call fails in a code segment being executed by the thread. In these cases the errno value is thread-specific. If the pthread_create call fails and returns the value EAGAIN (11), it indicates a system-imposed limitfor example, the total number of threads has been exceeded. A newly created thread (which in Linux is directly tied to an LWP) begins with the execution of the referenced user-defined function. The thread continues to execute until
- the function completes (implicitly or explicitly).
- a call is made to pthread_exit .
- the thread is canceled with a call to pthread_cancel .
- the process that created the thread exits (implicitly or explicitly).
- one of the threads performs an exec .