Download presentation
Presentation is loading. Please wait.
1
Lecture 8: POSIX Threads
2
Review: Threads Why threads? Why not use multiple processes?
Efficiency Many threads executing in parallel Parallelism within the same process Why not use multiple processes? Process creation expensive Each process needs memory, lots of state Threads share process address space
3
Review: The Thread Model
Shared by all threads within a process. Private to a thread.
4
Review: When are Threads Useful?
CPU-intensive computations and I/O operations can be separated Multiple processors Examples Multiplying huge matrices on a single processor? The same problem on multiple processors
5
In this lecture POSIX threads standard
6
Why we need standards? Code portability Economic
7
POSIX Threads Standards
The IEEE POSIX standards Define a set of functions/interfaces on threads operations Individual operating systems are allowed some freedom in implementing the interfaces UNIX-based systems POSIX a -> c, other variants by companies Microsoft Win32 Despite the advantages of programming with threads, only recently have standard APIs for multithreaded programming been developed. The most important of these APIs, at least in the Unix world, is the one developed by the group known as POSIX a. This effort took a number of years and in the summer of ’95 resulted in an approved standard, which is now known by the number c. While POSIX a was in development, a number of companies (e.g., Digital, HP, IBM, Sun) developed their own threads packages. The differences between the final POSIX standard and these variations are not terribly significant, but there are a number of major syntactical issues. Microsoft, characteristically, has produced a threads package whose interface has little in common with those of the Unix world. Moreover, as discussed in some of the following chapters, there are significant differences between the Microsoft and POSIX approaches—some of the constructs of one cannot be easily implemented in terms of the constructs of the other, and vice versa. Despite this, it certainly appears that both approaches are equally useful for multithreaded programming. Copyright © 2002 Thomas W. Doeppner. All rights reserved.
8
Example POSIX APIs pthread_create() pthread_exit() pthread_join()
pthread_yield()
9
pthread_create() Use pthread_create() to add a new thread of control to the current process. int pthread_create( pthread_t *tid, const pthread_attr_t *tattr, void*(*start_routine)(void *), void *arg); The function writes the thread id in tid.
10
pthread_create() Use pthread_create() to add a new thread of control to the current process. int pthread_create( pthread_t *tid, const pthread_attr_t *tattr, void*(*start_routine)(void *), void *arg); The address of a thread attribute object is passed using tattr.
11
pthread_create() Use pthread_create() to add a new thread of control to the current process. int pthread_create( pthread_t *tid, const pthread_attr_t *tattr, void*(*start_routine)(void *), void *arg); The thread runs a function passed in start_routine.
12
pthread_create() Use pthread_create() to add a new thread of control to the current process. int pthread_create( pthread_t *tid, const pthread_attr_t *tattr, void*(*start_routine)(void *), void *arg); The start routine’s arguments are passed with arg.
13
An example start_servers( ) { } void *server(void *arg) {
pthread_t thread; int i; for (i=0; i<nr_of_server_threads; i++) pthread_create(&thread, // thread ID NULL, // default attributes server, // start routine argument); // argument } void *server(void *arg) { while(1) { /* get and handle request */ To create a thread, one calls the pthread_create routine. This skeleton code for a server application creates a number of threads, each to handle client requests. If pthread_create returns successfully (i.e., returns 0), then a new thread has been created that is now executing independently of the caller. This new thread has an ID that is returned via the first parameter. The second parameter is a pointer to an attributes structure that defines various properties of the thread. Usually we can get by with the default properties, which we specify by supplying a null pointer (we discuss this in more detail later). The third parameter is the address of the routine in which our new thread should start its execution. The last argument is the argument that is actually passed to the first procedure of the thread. If pthread_create fails, it returns a code indicating the cause of the failure. Copyright © 2002 Thomas W. Doeppner. All rights reserved.
14
Multiple Arguments typedef struct { } two_ints_t;
int first, second; } two_ints_t; func(int r_in, int r_out, int l_in, int l_out) { pthread_t in_thread, out_thread; two_ints_t in={r_in, l_out}, out={l_in, r_out}; pthread_create(&in_thread, 0, incoming, &in); ... } To pass more than one argument to the first procedure of a thread, we must somehow encode multiple arguments as one. Here we pack two arguments into a structure, then pass the pointer to the structure. Copyright © 2002 Thomas W. Doeppner. All rights reserved.
15
Thread attributes Some POSIX thread (pthread) attributes include:
A thread may have local or global scope of contention That is, it may compete with all threads in the system for CPU time, or it may compete only with threads in the same task (process) A thread has a priority for scheduling Threads may use several scheduling methods, some of which use priority A thread may be detached Only non-detached threads my be joined join is to wait as thread is to process
16
The thread attribute object
The attributes of a thread are held in a thread attribute object, which is a struct defined in pthread.h. You can declare a pthread attribute in your code, but it can only be initialized or modified by the following functions: int pthread_attr_init(pthread_attr_t *attr); pthread_attr_setstackaddr(); pthread_attr_setstacksize(); pthread_attr_setdetachstate();
17
The thread attribute object
Creating a thread using a NULL attribute argument has the same effect as using a default attribute: Non-detached (joinable) With a default stack and stack size With the parent’s priority To create threads with other attributes, the generating attribute object must be modified using the pthread_attr_set functions.
18
Thread Attributes pthread_t thread; pthread_attr_t thr_attr; pthread_attr_init(&thr_attr); ... /* establish some attributes */ pthread_create(&thread, &thr_attr, startroutine, arg); A number of properties of a thread can be specified via the attributes argument when the thread is created. Some of these properties are specified as part of the POSIX specification, others are left up to the implementation. By burying them inside the attributes structure, we make it straightforward to add new types of properties to threads without having to complicate the parameter list of pthread_create. To set up an attributes structure, one must call pthread_attr_init. As seen in the next slide, one then specifies certain properties, or attributes, of threads. One can then use the attributes structure as an argument to the creation of any number of threads. Note that the attributes structure only affects the thread when it is created. Modifying an attributes structure has no effect on already-created threads, but only on threads created subsequently with this structure as the attributes argument. Storage may be allocated as a side effect of calling pthread_attr_init. To ensure that it is freed, call pthread_attr_destroy with the attributes structure as argument. Note that if the attributes structure goes out of scope, not all storage associated with it is necessarily released—to release this storage you must call pthread_attr_destroy. Contrast this approach vs providing a long list of parameters.. Copyright © 2002 Thomas W. Doeppner. All rights reserved.
19
Stack Size pthread_t thread; pthread_attr_t thr_attr;
pthread_attr_init(&thr_attr); pthread_attr_setstacksize(&thr_attr, 20*1024*1024); ... pthread_create(&thread, &thr_attr, startroutine, arg); Among the attributes that can be specified is a thread’s stack size. The default attributes structure specifies a stack size that is probably good enough for “most” applications. How big is it? The default stack size is not mandated by POSIX. In Digital Unix 4.0, the default stack size is 21,120 bytes, while in Solaris it is one megabyte. To establish a different stack size, use the pthread_attr_setstacksize routine, as shown in the slide. How large a stack is necessary? The answer, of course, is that it depends. If the stack size is too small, there is the danger that a thread will attempt to overwrite the end of its stack. There is no problem with specifying too large a stack, except that, on a 32-bit machine, one should be careful about using up too much address space (one thousand threads, each with a megabyte stack, use a fair portion of the address space). Copyright © 2002 Thomas W. Doeppner. All rights reserved.
20
Summary POSIX standards for threads operations on UNIX-based systems
Create new threads via pthread_create() Thread attributes
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.