Threads 2x[1]

21
4.1 Silberschatz, Galvin and Gagne ©2009 Operating System Concepts – 8 th Edition Multithreaded Programming Modified by M.Rebaudengo - 2010 4.2 Silberschatz, Galvin and Gagne ©2009 Operating System Concepts – 8 th Edition Processes and Threads Process abstraction combines two concepts Concurrency Each process is a sequential execution stream of instructions Protection Each process defines an address space Address space identifies all addresses that can be touched by the program Threads Key idea: separate the concepts of concurrency from protection A thread is a sequential execution stream of instructions A process defines the address space that may be shared by multiple threads Threads can execute on different cores on a multicore CPU (parallelism for performance) and can communicate with other threads by updating memory. 4.3 Silberschatz, Galvin and Gagne ©2009 Operating System Concepts – 8 th Edition Single Thread vs. Multithreads In traditional operating systems, each process has an address space and a single thread of control There are frequently solutions in which it is desirable to have multiple threads of control in the same address space running concurrently, as though they are (almost) separate processes (except for the shared address space). 4.4 Silberschatz, Galvin and Gagne ©2009 Operating System Concepts – 8 th Edition Thread Model (a) Three processes each with one thread (b) One process with three threads

Transcript of Threads 2x[1]

Page 1: Threads 2x[1]

4.1 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Multithreaded Programming

Modified by M.Rebaudengo - 2010

4.2 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Processes and Threads

� Process abstraction combines two concepts

� Concurrency� Each process is a sequential execution stream of instructions

� Protection� Each process defines an address space

� Address space identifies all addresses that can be touched by the program

� Threads

� Key idea: separate the concepts of concurrency from protection

� A thread is a sequential execution stream of instructions

� A process defines the address space that may be shared by multiple threads

� Threads can execute on different cores on a multicore CPU (parallelism for performance) and can communicate with other threads by updating memory.

4.3 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Single Thread vs. Multithreads

� In traditional operating systems, each process has an address space and a single thread of control

� There are frequently solutions in which it is desirable to have multiple threads of control in the same address space running concurrently, as though they are (almost) separate processes (except for the shared address space).

4.4 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Thread Model

� (a) Three processes each with one thread

� (b) One process with three threads

Page 2: Threads 2x[1]

4.5 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Example of multithreads (I)

� Consider how a Web server can improve performance and interactivity by using threads.

� When a Web server receives requests for images and pages from many clients, it serves each request (from each client) with a different thread

� The process that receives all the requests, creates a new separate thread for each request received

� This new thread sends the required information to the remote client.

� While this thread is doing its task, the original thread is free to accept more requests

� Web servers are multiprocessor systems that allow for concurrentcompletion of several requests, thus improving throughput and response time.

4.6 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

The Case for Threads

Consider a Web server

get network message (URL) from client

get URL data from disk

compose response

send response

How well does this web server perform?

4.7 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

How Can it Help?

� Consider a Web server

� Create a number of threads, and for each thread do

� get network message from client

� get URL data from disk

� send data over network

� What did we gain?

4.8 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Overlapping Requests (Concurrency)

get network message (URL) from client

get URL data from disk

send data over network

get network message (URL) from client

get URL data from disk

send data over network

Request 1Thread 1

Request 2Thread 2

Time

(disk access latency) (disk access latency)

Total time is less than request 1 + request 2

Page 3: Threads 2x[1]

4.9 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Example of multithreads (II)

� Consider a word processor composed of three threads:

� a thread interacts with the user

� a thread handles reformatting in the background processing the document

� a thread performs spell checking

� a thread handle the disk backups without interfering with the other two in order to automatically save the entire file every few minutes to protect the user against losing the work in the event of program crash.

4.10 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Process vs. Threads

� A process has an address space containing program text and data, as well other resources like, open files, child processes, pending alarms, signal handlers, accounting information, etc.

� A thread of execution has a program counter, registers and a stack.

� Processes are used to group resources together

� Threads are the entities scheduled for execution on the CPU.

4.11 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Multithreads

� Different threads in a process are not as independent as different processes:

� All threads have exactly the same address space, which means that they share the same global variables.

4.12 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Threads

� A thread represents an abstract entity that executes a sequence of instructions� It has its own set of CPU registers � It has its own stack� There is no thread-specific heap or data segment (unlike process)

� Threads are lightweight� Creating a thread more efficient than creating a process.� Communication between threads easier than btw. processes.� Context switching between threads requires fewer CPU cycles and memory

references than switching processes.� Threads only track a subset of process state (share list of open files, pid,

…).

Page 4: Threads 2x[1]

4.13 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Single and Multithreaded Processes

4.14 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Benefits

� Responsiveness

� When one thread is blocked, your browser still responds

� E.g. download images while allowing your interaction

� Resource Sharing

� Share the same address space

� Reduce overhead (e.g. memory)

� Economy

� Creating a new process costs memory and resources

� E.g. in Solaris, 30 times slower in creating process than thread

� Scabality / Parallelization

� Threads can be executed in parallel on multiple processors

� Increase concurrency and throughput

4.15 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Performance Benefits

� It takes far less time to create a new thread in an existing process than to create a new process

� It takes less time to terminate a thread than a process

� It takes less time to switch between 2 threads within the same process than to switch between processes

� Threads between the same process share memory and files: they can communicate with each other without invoking the kernel.

� If there is an application od function that should be implemented as a set of related units of execution, it is far more efficient to do so as a collection of threads rather than a collection of separate processes.

4.16 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Parallel Execution on a Multicore System

Page 5: Threads 2x[1]

4.17 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Multicore Programming

� Multicore systems putting pressure on programmers, challenges include

� Dividing activities

� Balance

� Data splitting

� Data dependency

� Testing and debugging

4.18 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

How Can it Help?

� How can this code take advantage of 2 threads?

for(k = 0; k < n; k++)

a[k] = b[k] * c[k] + d[k] * e[k];

� Rewrite this code fragment as:

do_mult(l, m) {

for(k = l; k < m; k++)

a[k] = b[k] * c[k] + d[k] * e[k];

}

main() {

CreateThread(do_mult, 0, n/2);

CreateThread(do_mult, n/2, n);

4.19 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Latency and Throughput

� Latency : time to complete an operation

� Throughput : work completed per unit time.

4.20 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Relationship between Latency and Throughput

� Latency and bandwidth only loosely coupled

� Henry Ford: assembly lines increase bandwidth without reducing latency

� My factory takes 1 day to make a Model-T Ford.

� But I can start building a new car every 10 minutes

� At 24 hrs/day, I can make 24 * 6 = 144 cars per day

� A special order for 1 green car, still takes 1 day

� Throughput is increased, but latency is not.

� Latency reduction is difficult

� Often, one can buy bandwidth

� E.g., more memory chips, more disks, more computers

� Big server farms (e.g., google) are high bandwidth

Page 6: Threads 2x[1]

4.21 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Latency and bandwith

� Multiplying vector example: reduced latency

� Web server example: increased throughput

� What is “High speed Internet?”

� Low latency: needed to interactive gaming

� High bandwidth: needed for downloading large files.

4.22 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Thread Programming models

� Boss/worker

� Peer model

� Pipeline

� Thread pool

4.23 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

taskXtaskX

taskYtaskY

taskZtaskZ

main ( )main ( )

WorkersProgram

Files

Resources

Databases

Disks

SpecialDevices

Boss

Input (Stream)

The boss/worker model

4.24 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Example

main() /* the boss */

{

forever {

get a request;

switch( request )

case X: thread_create(....,taskX);

case Y: thread_create(....,taskY);

....

}

}

taskX() /* worker */

{

perform the task, sync if accessing shared resource s

}

taskY() /* worker */

{

perform the task, sync if accessing shared resource s

}

Page 7: Threads 2x[1]

4.25 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

The peer model

taskXtaskX

taskYtaskY

WorkersProgram

Files

Resources

Databases

Disks

SpecialDevices

taskZtaskZ

Input(static)

Input(static)

4.26 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Example

main()

{

thread_create(....,task1);

thread_create(....,task2);

....

signal all workers to start

wait for all workers to finish

do any cleanup

}

}

task1() /* worker */

{

wait for start

perform the task, sync if accessing shared resource s

}

task2() /* worker */

{

wait for start

perform the task, sync if accessing shared resource s

}

4.27 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Resources Files

Databases

Disks

Special Devices

Files

Databases

Disks

Special Devices

Files

Databases

Disks

Special Devices

Stage 1Stage 1 Stage 2Stage 2 Stage 3Stage 3

Program Filter Threads

Input (Stream)

A thread pipeline

4.28 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Examplemain()

{

thread_create(....,stage1);

thread_create(....,stage2);

....

wait for all pipeline threads to finish

do any cleanup

}

stage1() {

get next input for the program

do stage 1 processing of the input

pass result to next thread in pipeline

}

stage2(){

get input from previous thread in pipeline

do stage 2 processing of the input

pass result to next thread in pipeline

}

stageN()

{

get input from previous thread in pipeline

do stage N processing of the input

pass result to program output.

}

Page 8: Threads 2x[1]

4.29 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Thread pool

� Runtime overhead of creating thread can be solved by thread pool the main thread creates all worker threads at program initialization and each worker thread suspends itself immediately for a wakeup call from boss.

� Typically there are more tasks than threads. Tasks are organized in queue. As soon as a thread completes its task, it will request the next task from the queue.

� The number of threads is a parameter that can be tuned to provide the best performance.

� The number of threads could be dynamic based on the number of waiting tasks.

4.30 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Thread Model

� Items shared by all threads in a process

� Items private to each thread

4.31 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Thread Control Block (TCB)

� Each thread has:

� an identifier,

� a set of registers (including the program counter)

� a set of attributes including the state, the stack size, scheduling parameters, etc.

4.32 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Stacks

� Each thread has its own stack:

� Each stack contains one frame for each procedure called but not yet returned from

� This frame contains the procedure’s local variables and the return address to use when the procedure call has finished

� Each thread will call different procedures and thus have a different execution history.

Page 9: Threads 2x[1]

4.33 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Threads vs. Processes

Threads

� A thread has no data segment or heap

� A thread cannot live on its own, it must live within a process

� There can be more than one thread in a process, the first thread calls main and has the process’s stack

� If a thread dies, its stack is reclaimed

� Inter-thread communication via memory.

� Each thread can run on a different physical processor

� Inexpensive creation and context switch

Processes

A process has code/data/heap & other segmentsThere must be at least one thread in a processThreads within a process share code/data/heap, share I/O, but each has its own stack and registers

If a process dies, its resources are reclaimed and all threads dieInter-process communication via OS and data copying.

Each process can run on a different physical processorExpensive creation and context switch

4.34 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Implementing Threads

� Processes define an address space; threads share the address space

� Process Control Block (PCB) contains process-specific information

� Owner, PID, heap pointer, priority, active thread, and pointers to thread information

� Thread Control Block (TCB) contains thread-specific information

� Stack pointer, PC, thread state (running, …), register values, a pointer to PCB, …

Code

Initialized data

Heap

DLL’s

mapped segments

Process’s address space

Stack – thread1

PCSP

StateRegisters

PCSP

StateRegisters

TCB for Thread1

Stack – thread2

PCSP

StateRegisters

PCSP

StateRegisters

TCB for Thread2

4.35 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Threads’ Life Cycle

� Threads (just like processes) go through a sequence of start, ready, running, waiting, and done states

RunningRunningReadyReady

WaitingWaiting

StartStart DoneDone

4.36 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Exercise

Context switch time for which entity is greater?

1. Process

2. Thread

Page 10: Threads 2x[1]

4.37 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Exercise

Threads have their own…?

1. CPU

2. Address space

3. PCB

4. Stack

5. Registers

4.38 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Exercise

Threads have the same scheduling states as processes

1. True

2. False

4.39 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

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

}

4.40 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Exercise (cont.)

int main(int argc, char *argv[])

{

pid_t pid;

pthread_t tid; /* the thread identifier */

pthread_attr_t attr; /* set of attributes for the thread */

pid = fork()

if (pid == 0) { /* child process */

pthread_attr_init(&attr);

pthread_create(&tid,&attr,runner,NULL);

/* now wait for the thread to exit */

pthread_join(tid,NULL);

printf("CHILD: value = %d\n",value); 5

}

else if (pid > 0) { /* parent process */

wait(NULL);

printf("PARENT: value = %d\n",value); 0

}

Page 11: Threads 2x[1]

4.41 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Thread Libraries

� Thread library provides programmer with API 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).

4.42 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

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 threadslibrary , 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.

4.43 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

User-Level Thread

4.44 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

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 new thread 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 scheduling algorithm

� When control is passed to the library, the context of the current thread is saved, and when the control is passed from the library to a thread the context of that thread is restored. The context consists of the contents of user registers, the program counter 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.

Page 12: Threads 2x[1]

4.45 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

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

4.46 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

User-level Threads Scheduling

4.47 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

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

� the memory cache does need to be flushed

� - 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 applcations that would benefit the ability to execute portions of code simultaneously.

4.48 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Exercise

When a user level thread does I/O it blocks the ent ire process.

1. True

2. False

Page 13: Threads 2x[1]

4.49 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

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.

4.50 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Kernel-Level Threads

4.51 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Kernel-level Threads Scheduling

4.52 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

� Kernel-level threads

� + Kernel-level threads do not block process for 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

Page 14: Threads 2x[1]

4.53 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Multithreading Models

� Many-to-One

� One-to-One

� Many-to-Many

4.54 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Many-to-One (ULT)

� Many user-level threads mapped to single kernel thread

� the kernel has no knowledge of the application threads

� Examples:

� Solaris Green Threads

� GNU Portable Threads

4.55 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Many-to-One Model

4.56 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

One-to-One (KLT)

� Each user-level thread maps to kernel thread

� Examples

� Windows NT/XP/2000

� Linux

� Solaris 9 and later

Page 15: Threads 2x[1]

4.57 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

One-to-one Model

4.58 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Many-to-Many Model

� Allows many user level threads to be mapped to many kernel threads

� Allows the operating system to create a sufficient number of kernel threads

� The threads library is responsible for scheduling user threads on the available schedulable entities

� When a thread performs a blocking system call, the kernel can schedule another thread for execution

� Examples:

� Solaris prior to version 9

� Windows NT/2000 with the ThreadFiber package

4.59 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Many-to-Many Model

4.60 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Two-level Model

� Similar to M:M, except that it allows a user thread to be bound to kernel thread

� Examples

� IRIX

� HP-UX

� Tru64 UNIX

� Solaris 8 and earlier

Page 16: Threads 2x[1]

4.61 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Two-level Model

4.62 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

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 resourses

� manage thread scheduling

� API specifies behavior of the thread library, implementation is up to development of the library

� Common in UNIX operating systems (Solaris, Linux, Mac OS X).

4.63 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

pthread_create()

� Synthax:

� pthread_create(thread,attr,start_routine,arg)

� Arguments:

� thread : A unique identifier for the new thread returned by the subroutine.

� attr : it specifies a thread attributes object, or NULL for the default values.

� start_routine : the C routine that the thread will execute once it is created.

� arg : 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.

4.64 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

#include <stdio.h>

#include <pthread.h>

main() {

pthread_t f2_thread, f1_thread, f3_thread; int i1=1,i 2=2;

void *f2(), *f1(),*f3();

pthread_create(&f1_thread,NULL,f1,&i1);

pthread_create(&f2_thread,NULL,f2,&i2);

pthread_create(&f3_thread,NULL,f3,NULL);

}

void *f1(int *i){

}

void *f2(int *i){

}

void *f3() {

}

Page 17: Threads 2x[1]

4.65 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

pthread_exit()

� When a thread has finished its work, it can exit by calling the pthread_exit() library procedure

� The thread then vanishes and is no longer schedulable and the stack is released.

4.66 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Examplevoid *PrintHello(void *threadid)

{

long tid;

tid = (long) threadid;

printf("Hello World! It's me, thread #%ld!\n", tid) ;

pthread_exit(NULL);

}

int main(int argc, char *argv[])

{

pthread_t threads[NUM_THREADS];

int rc;

long t;

for(t=0;t<NUM_THREADS;t++){

printf("In main: creating thread %ld\n", t);

rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);

if (rc){

printf("ERROR; return code from pthread_create() is %d\n", rc);

exit(-1);

}

}

pthread_exit(NULL);

}

4.67 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Examplevoid *PrintHello(void *threadid)

{

long tid;

tid = (long) threadid;

printf("Hello World! It's me, thread #%ld!\n", tid) ;

pthread_exit(NULL);

}

int main(int argc, char *argv[])

{

pthread_t threads[NUM_THREADS];

int rc;

long t;

for(t=0;t<NUM_THREADS;t++){

printf("In main: creating thread %ld\n", t);

rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);

if (rc){

printf("ERROR; return code from pthread_create() is %d\n", rc);

exit(-1);

}

}

pthread_exit(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!

4.68 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Multiple arguments via a structure: exampleinclude <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];

Page 18: Threads 2x[1]

4.69 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

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

}

4.70 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

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

}

4.71 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

pthread_join()

� In some thread systems, one thread can wait for a (specific) thread to exit by calling the pthread_join() 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.

4.72 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Joinable or not?

� When a thread is created, one of its attributes defines whether it is joinable or detached.

� Only threads that are created as joinable can be joined.

� If a thread is created as detached, it can never be joined.

� Define and initialize attribute object:

pthread_attr_t attr;

� To explicitly create a thread as joinable, the attr argument in the pthread_create() routine is used:

� Initialize the attribute variable with pthread_attr_init()

� To set the detach state:� pthread_attr_setdetachstate(&attr, THREAD_CREATE_DETACHED );

Page 19: Threads 2x[1]

4.73 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

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"); return NULL;

}

Thread attributes (usually NULL)

Thread arguments(void *p)

return value(void **p)

4.74 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Execution

main thread

peer thread

return NULL;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 threadterminates)

Pthread_create() returns

4.75 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

pthread_yield()

� pthread_yield() is another library call that allows a thread to voluntarily give up the CPU to let another thread run

� There is no such call for processes because the assumption is that processes are competitive and each one wants all the CPU time it can get. However, since the threads of a process are working together and their code is written by the same programmer, it is possible that a thread activates another thread.

4.76 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Example

� A pthread program illustrating how to create a simple thread and some of the pthread API

� The program implements the summation function where the summation operation is run as a separate thread.

Page 20: Threads 2x[1]

4.77 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

#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 */

pthread_attr_t attr; /* set of attributes for the thread */

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

/* get the default attributes */

pthread_attr_init(&attr);

/* create the thread */

pthread_create(&tid,&attr,runner,argv[1]);

/* now wait for the thread to exit */

pthread_join(tid,NULL);

printf("sum = %d\n",sum);

}

4.78 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

/**

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

}

4.79 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Example of Threads Accessing Another Thread’s Stack

char **ptr; /* global */

int main(){

int i;pthread_t tid;char *msgs[N] = {

"Messagge 1","Messagge 2"

};ptr = msgs;for (i = 0; i < 2; i++)

Pthread_create(&tid, NULL, thread, (void *)i);

Pthread_exit(NULL);}

/* thread routine */void *thread(void *vargp){

int myid = (int)vargp;static int svar = 0;

printf("[%d]: %s (svar=%d)\n", myid, ptr[myid], ++svar);

}

Peer threads access main thread’s stackindirectly through global ptr variable

4.80 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Mapping Vars to Mem. Instances

char **ptr; /* global */

int main(){

int i;pthread_t tid;char *msgs[N] = {

"Messagge 1","Messagge 2"

};ptr = msgs;for (i = 0; i < 2; i++)

Pthread_create(&tid, NULL, thread, (void *)i);

Pthread_exit(NULL);}

/* thread routine */void *thread(void *vargp){

int myid = (int)vargp;static int svar = 0;

printf("[%d]: %s (svar=%d)\n", myid, ptr[myid], ++svar);

}

Global var : 1 instance ( ptr [data])

Local static var : 1 instance ( svar [data])

Local automatic vars : 1 instance ( i.m, msgs.m )

Local automatic var: 2 instances (myid.p0[peer thread 0’s stack],myid.p1[peer thread 1’s stack]

)

Page 21: Threads 2x[1]

4.81 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Shared Variable Analysis

� Which variables are shared?

Variable Referenced by Referenced by Referenced byinstance main thread? peer thread 0? peer thread 1?

ptr yes yes yessvar no yes yesi.m yes no nomsgs.m yes yes yesmyid.p0 no yes nomyid.p1 no no yes

� Answer : A variable x is shared if multiple threads reference at least one instance of x. Thus:

� ptr , svar , and msgs are shared.

� i and myid are NOT shared.

4.82 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

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.

4.83 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Thread Cancellation

� Terminating a thread before it has completed. This case is called target thread. The pthread_cancel( thread) function requests that thread be canceled

� Cancelability state determines whether a thread can receive a cancellation request. If the cancelability state is disabled, the thread does not receive any cancellation requests. The current thread's cancelability state can be changed by calling pthread_setcancelstate()

� Two approaches (types) (the current thread's cancelability type can be changed by calling pthread_setcanceltype()) :

� Asynchronous cancellation terminates the target thread immediately.

If you set a thread's cancelability type to asynchronous, the thread can receive a cancellation request at any time.

� Deferred cancellation allows the target thread to periodically check if it should be cancelled

If you set a thread's cancelability type to deferred, cancellation requests are acted on as soon as the thread reaches a cancellation pointpthread_testcancel() creates a cancellation point in the calling thread.

4.84 Silberschatz, Galvin and Gagne ©2009Operating System Concepts – 8 th Edition

Signal

� Signals are used in UNIX systems to notify a process that a particular event has occurred

� Examples:� Typing certain key combinations at the terminal of a running

process causes the system to send it certain signals:

� CTRL-C sends an INT signal (SIGINT); by default, this causes the process to terminate.

� CTRL-Z sends a TSTP signal (SIGTSTP); by default, this causes the process to suspend execution.

� CTRL-\ sends a QUIT signal (SIGQUIT); by default, this causes the process to terminate and store the content of the memory (core dump).