Академический Документы
Профессиональный Документы
Культура Документы
TCB for
Thread1
Stack thread2
PC
SP
State
Registers
TCB for
Thread2
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Threads Life Cycle
Threads (just like processes) go through a sequence of start, ready, running,
waiting, and done states
Running Ready
Waiting
Start
Done
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.17
Threads vs. Processes
Threads use and exist within the process resources
A thread maintains its own stack and registers, scheduling properties,
set of pending and blocked signals.
Secondary Threads vs. Initial Threads
An initial thread is created automatically when a process is created.
Secondary threads are peers.
Threads vs. Processes
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.18
Thread Libraries
Thread libraries provide programmer with APIs (Application Programming
Interface) for creating and managing threads
Two primary ways of implementing
User-Level Threads (ULT): library entirely in user space (invoking a
function in the library results in a local function call in user space and
not a system call)
Kernel-Level Threads (KLT): Kernel-level library supported by the OS
(system call).
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.19
User-Level Thread
All of the work of thread management is done by the application and the
kernel is not aware of the existence of threads
An application can be programmed to be multithreading by using a threads
library, which is a package of routines for thread management
Threads library contains code for:
creating and destroyng threads
passing data between threads
scheduling thread execution
saving and restoring thread context.
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.20
User LeveL Threads
Implemented as a thread library, which contains the code for thread
creation, termination, scheduling and switching
Kernel sees one process and it is unaware of its thread activity
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.21
User-Level Thread
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.22
ULT: behavior (I)
By default, an application begins with a single thread and begins running the thread
This application and its thread are allocated to a single process managed by the
kernel
At any time that the application is running (i.e., the process is in the Running state),
the application may spawn a newthread to run within the same process. Spawning is
done by invoking the spawn utility in the threads library. Control is passed to that
utility by a procedure call
The threads library creates a data structure for the new thread and then passes
control to one of the threads, within this process, in the Ready state using some
schedulingalgorithm
When control is passed to the library, the context of the current thread is saved, and
when the control is passed fromthe library to a thread the context of that thread is
restored. The context consists of the contents of user registers, the programcounter
and the stack pointers.
All the previous activities takes place in the user space and within a single process.
The kernel is anaware of this activity.
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.23
ULT: behavior (II)
The kernel continues to schedule the process as a unit and assigns a single
execution state (Running, Blocked, Ready, etc.) to that process
When a thread does something that may cause it to become blocked locally
(e.g., waiting for another thread in its process to complete some work), it
calls a procedure in the threads library
This procedure checks if the thread must be put into blocked state. If so, it
saves its context, calls the thread scheduler to pick another thread to run
The thread scheduler looks in the thread table for a ready thread to run and
restores its context
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.24
User-level Threads Scheduling
B1, B2, B3,
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.25
User-level threads: comments
+ Fast to create and switch
procedures that saves the thread's state and the scheduler are user
procedures
no system call is needed
no context switch is needed
- When a ULT executes a system call, all the threads within the process are
blocked
E.g., read from file can block all threads
- User-level scheduler can fight with kernel-level scheduler
- A multithread application cannot take advantage of multiprocessing. A
kernel assigns one process to only one processor at a time. There are
applications that would benefit the ability to execute portions of code
simultaneously.
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.26
Kernel-Level Threads
The kernel knows the threads and manges them
There is no thread table in each process. Instead, the kernel has a thread
table that keeps track of all the threads in the system
When a process wants to create a new thread or destroy an existing thread,
it makes a kernel call, which then does the creation or destruction by
updating the kernel thread table
The thread table containing TCBs holds the same information as with the
ULT, but now kept in the kernel instead of in user space.
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.27
Kernel-Level Threads
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.28
Kernel Level Threads
Thread management done by the kernel
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.29
Kernel-level Threads Scheduling
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition
Kernel-level threads
+ Kernel-level threads do not block process for a system call
if one thread in a process is blocked by a system call (e.g., for a
page fault), the kernel can easily check if the process has one
thread ready to run
+ Only one scheduler (and kernel has global view)
- Can be difficult to make efficient (create & switch)
Kernel-level threads: comments
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.31
Pthreads
May be provided either as user-level or kernel-level
A POSIX standard (IEEE 1003.1c) API to:
create and destroy threads
synchronize threads and lock program resources
manage thread scheduling
API specifies behavior of the thread library, implementation is up to the
development of the library
Common in UNIX operating systems (Solaris, Linux, Mac OS X).
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.32
pthread_create()
Synthax:
pt hr ead_cr eat e( t hr ead, at t r , st ar t _r out i ne, ar g)
Arguments:
t hr ead: a unique identifier for the new thread returned by the
subroutine.
at t r : it specifies a thread attributes object, or NULL for the default
values.
st ar t _r out i ne: the C routine that the thread will execute once it is
created.
ar g: A single argument that may be passed to start_routine. It must be
passed by reference as a pointer cast of type void. NULL may be used if
no argument is to be passed.
Return value:
If successfull, it returns 0. Otherwise, it returns a nonzero error code.
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.33
#i ncl ude <st di o. h>
#i ncl ude <pt hr ead. h>
mai n( ) {
pt hr ead_t f 2_t hr ead, f 1_t hr ead, f 3_t hr ead; i nt i 1=1, i 2=2;
voi d *f 2( ) , *f 1( ) , *f 3( ) ;
pt hr ead_cr eat e( &f 1_t hr ead, NULL, f 1, &i 1) ;
pt hr ead_cr eat e( &f 2_t hr ead, NULL, f 2, &i 2) ;
pt hr ead_cr eat e( &f 3_t hr ead, NULL, f 3, NULL) ;
}
voi d *f 1( i nt *i ) {
}
voi d *f 2( i nt *i ) {
}
voi d *f 3( ) {
}
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.34
pthread_exit()
When a thread has finished its work, it can exit by calling the
pt hr ead_exi t ( ) library procedure
The thread then vanishes and is no longer schedulable and the stack is
released.
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.35
Example
#i ncl ude <st di o. h>
#i ncl ude <st dl i b. h>
#i ncl ude <si gnal . h>
#i ncl ude <sys/ t ypes. h>
#i ncl ude <uni st d. h>
#i ncl ude <pt hr ead. h> / * POSI X t hr eads */
voi d *myt hr ead( voi d *) ;
int sharedVar ; /* global variable */
i nt mai n( ) {
pt hr ead_t t i d;
shar edVar = 1234;
pr i nt f ( " Mai n: shar edVar = %d\ n" , shar edVar ) ;
pt hr ead_cr eat e( &t i d, NULL, myt hr ead, NULL) ;
sl eep( 1) ; / * yi el d t o anot her t hr ead */
pr i nt f ( " Mai n: shar edVar = %d\ n" , shar edVar ) ;
shar edVar = 999;
pr i nt f ( " Mai n: shar edVar = %d\ n" , shar edVar ) ;
sl eep( 1) ; / * yi el d t o anot her t hr ead */
pr i nt f ( " Mai n: shar edVar = %d\ n" , shar edVar ) ;
pr i nt f ( " DONE\ n" ) ;
exi t ( 0) ;
}
voi d *myt hr ead ( voi d *ar g)
{
/ * di spl ay t he val ue of t he gl obal var i abl e */
pr i nt f ( "t hr ead %l u: shar edVar i s %d \ n" , pt hr ead_sel f ( ) , shar edVar ) ;
shar edVar = 111;
pr i nt f ( "t hr ead %l u: shar edVar i s %d \ n" , pt hr ead_sel f ( ) , shar edVar ) ;
sl eep( 1) ; / * yi el d t o anot her t hr ead or mai n */
pr i nt f ( "t hr ead %l u: shar edVar i s %d \ n" , pt hr ead_sel f ( ) , shar edVar ) ;
shar edVar = 222;
pr i nt f ( "t hr ead %l u: shar edVar i s %d. \ n" , pt hr ead_sel f ( ) , shar edVar ) ;
sl eep( 1) ; / * yi el d t o anot her t hr ead or mai n */
/ * t hr ead exi t wi t h an i nt eger */
pt hr ead_exi t ( NULL) ;
}
OUTPUT
Main: sharedVar= 1234
thread 792: sharedVar is 1234
thread 792: sharedVar is 111
Main: sharedVar= 111
Main: sharedVar= 999
thread 792: sharedVar is 999
thread 792: sharedVar is 222
Main: sharedVar= 222
DONE
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.36
Example
#i ncl ude <st di o. h>
#i ncl ude <st dl i b. h>
#i ncl ude <pt hr ead. h>
#def i ne NUM_THREADS 5
voi d *Pr i nt Hel l o ( voi d *t hr eadi d)
{
l ong * t i d;
t i d = ( l ong *) t hr eadi d;
pr i nt f ( " Hel l o Wor l d! I t ' s me, t hr ead #%l d! \ n" , * t i d) ;
pt hr ead_exi t ( NULL) ;
}
i nt mai n( i nt ar gc, char *ar gv[ ] )
{
pt hr ead_t t hr eads[ NUM_THREADS] ;
i nt r c;
l ong t ;
f or ( t =0; t <NUM_THREADS; t ++) {
pr i nt f ( " I n mai n: cr eat i ng t hr ead %l d\ n" , t ) ;
r c = pt hr ead_cr eat e( &t hr eads[ t ] , NULL, Pr i nt Hel l o, ( voi d *) &t ) ;
i f ( r c) {
pr i nt f ( " ERROR; r et ur n code f r ompt hr ead_cr eat e( ) i s %d\ n" , r c) ;
exi t ( - 1) ;
}
}
pt hr ead_exi t ( NULL) ;
}
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.37
Example
#i ncl ude <st di o. h>
#i ncl ude <st dl i b. h>
#i ncl ude <pt hr ead. h>
#def i ne NUM_THREADS 5
voi d *Pr i nt Hel l o ( voi d *t hr eadi d)
{
l ong * t i d;
t i d = ( l ong *) t hr eadi d;
pr i nt f ( " Hel l o Wor l d! I t ' s me, t hr ead #%l d! \ n" , * t i d) ;
pt hr ead_exi t ( NULL) ;
}
i nt mai n( i nt ar gc, char *ar gv[ ] )
{
pt hr ead_t t hr eads[ NUM_THREADS] ;
i nt r c;
l ong t ;
f or ( t =0; t <NUM_THREADS; t ++) {
pr i nt f ( " I n mai n: cr eat i ng t hr ead %l d\ n" , t ) ;
r c = pt hr ead_cr eat e( &t hr eads[ t ] , NULL, Pr i nt Hel l o, ( voi d *) &t ) ;
i f ( r c) {
pr i nt f ( " ERROR; r et ur n code f r ompt hr ead_cr eat e( ) i s %d\ n" , r c) ;
exi t ( - 1) ;
}
}
pt hr ead_exi t ( NULL) ;
}
In main: creating thread 0
In main: creating thread 1
Hello World! It's me, thread #0!
In main: creating thread 2
Hello World! It's me, thread #1!
Hello World! It's me, thread #2!
In main: creating thread 3
In main: creating thread 4
Hello World! It's me, thread #3!
Hello World! It's me, thread #4!
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.38
Multiple arguments via a structure: example
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 5
char *messages[NUM_THREADS];
struct thread_data
{
int thread_id;
int sum;
char *message;
};
struct thread_data thread_data_array[NUM_THREADS];
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.39
void *PrintHello(void *threadarg)
{
int taskid, sum;
char *hello_msg;
struct thread_data *my_data;
sleep(1);
my_data = (struct thread_data *) threadarg;
taskid = my_data->thread_id;
sum = my_data->sum;
hello_msg = my_data->message;
printf("Thread %d: %s Sum=%d\n", taskid, hello_msg, sum);
pthread_exit(NULL);
}
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.40
int main(int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int *taskids[NUM_THREADS];
int rc, t, sum =0;
messages[0] ="English: Hello World!";
messages[1] ="French: Bonjour, le monde!";
messages[2] ="Spanish: Hola al mundo";
messages[3] ="German: Guten Tag, Welt!";
messages[4] ="Russian: Zdravstvytye, mir!";
for(t=0;t<NUM_THREADS;t++) {
sum =sum +t;
thread_data_array[t].thread_id =t;
thread_data_array[t].sum =sum;
thread_data_array[t].message =messages[t];
printf("Creating thread %d\n", t);
rc =pthread_create(&threads[t], NULL, PrintHello, (void *) &thread_data_array[t]);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.41
pthread_join()
In some thread systems, one thread can wait for a (specific) thread to exit
by calling the pt hr ead_j oi n( ) procedure
This procedure blocks the calling thread until (a specific) thread has exited
The thread identifier of the thread to wait for is given as a parameter.
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.42
Example
void *howdy(void *vargp);
int main() {
pthread_t tid;
pthread_create(&tid, NULL, howdy, NULL);
pthread_join(tid, NULL);
exit(0);
}
/* thread routine */
void *howdy(void *vargp) {
printf("Hello, world!\n");
pthread_exit(NULL);
}
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.43
Execution
main thread
peer thread
pthread_exit()
main thread waits for
peer thread to terminate
exit()
terminates
main thread and
any peer threads
call Pthread_create()
call Pthread_join()
Pthread_join() returns
printf()
(peer thread
terminates)
Pthread_create() returns
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.44
Example
#i ncl ude <st di o. h>
#i ncl ude <st dl i b. h>
#i ncl ude <pt hr ead. h>
#def i ne NTHREADS 5
voi d *myFun ( voi d *x)
{
i nt t i d;
t i d = *( ( i nt *) x) ;
pr i nt f ( " Hi f r omt hr ead %d! \ n" , t i d) ;
pt hr ead_exi t ( NULL) ;
}
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.45
i nt mai n( i nt ar gc, char *ar gv[ ] )
{
pt hr ead_t t hr eads[ NTHREADS] ;
i nt t hr ead_ar gs[ NTHREADS] ;
i nt r c, i ;
/ * spawn t he t hr eads */
f or ( i =0; i <NTHREADS; ++i )
{
t hr ead_ar gs[ i ] = i ;
pr i nt f ( " spawni ng t hr ead %d\ n" , i ) ;
r c = pt hr ead_cr eat e( &t hr eads[ i ] , NULL, myFun, ( voi d *) &t hr ead_ar gs[ i ] ) ;
}
/ * wai t f or t hr eads t o f i ni sh */
f or ( i =0; i <NTHREADS; ++i ) {
r c = pt hr ead_j oi n( t hr eads[ i ] , NULL) ;
}
r et ur n 1;
}
Output:
spawning thread 0
spawning thread 1
Hi from thread 0!
spawning thread 2
Hi from thread 1!
spawning thread 3
Hi from thread 2!
spawning thread 4
Hi from thread 3!
Hi from thread 4!
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.46
Example
A program implementing the summation function where the summation
operation is run as a separate thread.
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.47
Solution
#include <pthread.h>
#include <stdio.h>
int sum; /* this data is shared by the thread(s) */
void *runner(void *param); /* the thread */
int main(int argc, char *argv[])
{
pthread_t tid; /* the thread identifier */
if (argc !=2) {fprintf(stderr,"usage: a.out <integer value>\n");
return -1; }
if (atoi(argv[1]) <0) {
fprintf(stderr,"Argument %d must be non-negative\n",atoi(argv[1]));
return -1;
}
/* create the thread */
pthread_create(&tid,NULL,runner,argv[1]);
/* now wait for the thread to exit */
pthread_join(tid,NULL);
printf("sum =%d\n",sum);
}
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.48
/**
* The thread will begin control in this function
*/
void *runner(void *param)
{
int i, upper =atoi(param);
sum =0;
if (upper >0) {
for (i =1; i <=upper; i++)
sum +=i;
}
pthread_exit(0);
}
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.49
Exercise
Write a counting program, which should have 2 threads
While the peer thread loops, incrementing a counter, the main thread peeks
at the counter every second and prints its value
After 10 iterations, the main thread kills the peer one and computes the
average number of counts.
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.50
#i ncl ude <st di o. h>
#i ncl ude <st dl i b. h>
#i ncl ude <pt hr ead. h>
#i ncl ude <uni st d. h>
#i ncl ude <er r no. h>
char r unni ng = 1;
l ong l ong count er = 0;
voi d * pr ocess( )
{
whi l e ( r unni ng)
count er ++;
pr i nt f ( " Thr ead: exi t \ n" ) ;
pt hr ead_exi t ( NULL) ;
}
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.51
i nt mai n( )
{
i nt i ;
pt hr ead_t t hr ead_I d;
i f ( pt hr ead_cr eat e( &t hr ead_I d, NULL, pr ocess, NULL) )
{
pr i nt f ( "ERROR i n pt hr ead_cr eat e( ) \ n" ) ;
exi t ( - 1) ;
}
f or ( i =0 ; i < 10 ; i ++)
{
sl eep( 1) ;
pr i nt f ( "count er = %l l d\ n", count er ) ;
}
r unni ng = 0;
pt hr ead_j oi n( t hr ead_I d, NULL) ;
pr i nt f ( "Aver age I nst r uct i ons = %l l d \ n", count er / 10) ;
r et ur n 0;
}
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.52
Thread and Processes
#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>
int value =0; /* this data is shared by the thread(s) */
void *runner(void *param); /* the thread */
void *runner(void *param)
{
value =5;
pthread_exit(0);
}
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.53
int main(int argc, char *argv[])
{
pid_t pid;
pthread_t tid; /* the thread identifier */
pid =fork();
if (pid ==0) {/* child process */
pthread_create(&tid, NULL,runner,NULL);
/* now wait for the thread to exit */
pthread_join(tid,NULL);
printf(" CHILD: value = %d\n" ,value);
}
else if (pid >0) {/* parent process */
wait(NULL);
printf(" PARENT: value = %d\n" ,value);
}
}
Silberschatz, Galvin and Gagne 2009
Operating System Concepts 8
th
Edition 4.54
Semantics of fork() and exec()
Does fork() duplicate only the calling thread or all threads?
some UNIX systems have chosen to have two versions of fork():
one that duplicates all threads (forkall())
one that duplicates only the thread invoked by the fork() system call
(fork1())
If exec() is called immediately after forking, then duplicating all threads
is unnecessary. In this istance, duplicating only the calling thread is
appropriate.