You are on page 1of 64

Multithreaded Programming

Modified by M.Rebaudengo - 2016


Operating System Concepts 8th Edition Silberschatz, Galvin and Gagne 2009
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 tasks.
z Programming with threads is a natural way to handle concurrency

Monothreaded process Multithreaded process

Process A Process B Thread1


Thread 1 Thread2
Thread3
Thread4

Operating System Concepts 8th Edition 4.2 Silberschatz, Galvin and Gagne 2009
Example of multithreads (I)
Consider how a Web server can improve performance and interactivity by
using threads.
z When a Web server receives requests for images and pages from many
clients, it serves each request (from each client) with a different thread
z The process that receives all the requests, creates a new separate
thread for each request received
z This new thread sends the required information to the remote client.
z While this thread is doing its task, the original thread is free to accept
more requests
z Web servers are multiprocessor systems that allow for concurrent
completion of several requests, thus improving throughput and
response time.

Operating System Concepts 8th Edition 4.3 Silberschatz, Galvin and Gagne 2009
How Can it Help?
Create a number of threads, and for each thread do
z get network message from client
z get URL data from disk
z send data over network

What did we gain?

Operating System Concepts 8th Edition 4.4 Silberschatz, Galvin and Gagne 2009
Overlapping Requests (Concurrency)
Request 1 Request 2
Thread 1 Thread 2
get network message (URL) from client
get URL data from disk
get network message (URL) from client
(disk access latency)
get URL data from disk

(disk access latency)


send data over network

send data over network

Total time is less than request 1 + request 2


Time

Operating System Concepts 8th Edition 4.5 Silberschatz, Galvin and Gagne 2009
Example of multithreads (II)
Consider a word processor composed of the following threads:
z a thread interacts with the user
z a thread handles reformatting the document in the background and
performing spell checking
z a thread handles the disk backups without interfering with the others 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.

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

A thread lives within a process


Threads are a finer-grained unit of execution than processes: a process can have
several threads
A thread possesses an independent flow of control, and can be scheduled to run
separately from other threads, because it maintains its own:
z stack
z registers (CPU state)
The other resources of the process are shared by all its threads:
z code
z memory
z open files
z and more...

Threads are lightweight


z Creating a thread is more efficient than creating a process
z Communication between threads is easier than between processes
z Context switching between threads requires fewer CPU cycles and memory
references than switching processes
z Threads only track a subset of process state (share list of open files, pid, ).

Operating System Concepts 8th Edition Silberschatz, Galvin and Gagne 2009
Single and Multithreaded Processes

Operating System Concepts 8th Edition Silberschatz, Galvin and Gagne 2009
Performance Benefits
It takes far less time to create a new thread in an existing process than to
create a new process (100x)
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.
useful if some threads are I/O-bound overlap computation and I/O

If there is an application (or 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.
Parallel execution: the same process is executed in parallel on a multicore
CPU.

Operating System Concepts 8th Edition 4.9 Silberschatz, Galvin and Gagne 2009
Thread Model

Items shared by all threads in a process Items private to each thread

Operating System Concepts 8th Edition 4.10 Silberschatz, Galvin and Gagne 2009
Thread Control Block (TCB)
Each thread has:
z an identifier,
z a set of registers (including the program counter and stack pointer)
z a set of attributes (including the state, the stack size, scheduling
parameters, etc).

Operating System Concepts 8th Edition 4.11 Silberschatz, Galvin and Gagne 2009
Threads vs. Processes

Threads Processes

A process has code/data/heap &


A thread has no data segment or
heap other segments
There must be at least one thread in
A thread cannot live on its own, it
must live within a process a process
There can be more than one thread Threads within a process share
in a process, the first thread calls code/data/heap, share I/O, but each
main and has the processs stack has its own stack and registers
If a thread dies, its stack is If a process dies, its resources are
reclaimed reclaimed and all threads die
Inter-thread communication via Inter-process communication via OS
memory and data copying
Each thread can run on a different Each process can run on a different
physical processor physical processor
Inexpensive creation and context Expensive creation and context
switch switch

Operating System Concepts 8th Edition Silberschatz, Galvin and Gagne 2009
Threads Life Cycle
Threads (just like processes) go through a sequence of start, ready, running,
waiting, and done states

Start Done

Ready Running

Waiting

Operating System Concepts 8th Edition Silberschatz, Galvin and Gagne 2009
Implementing Threads
TCB for
Processes define an address
Thread1
space; threads share the address
space Processs
PC address space
SP
Process Control Block (PCB) State
contains process-specific Registers Heap
information
z Owner, PID, heap pointer,
priority, active thread, and
pointers to thread information TCB for Stack thread2
Thread2
Thread Control Block (TCB)
contains thread-specific information PC Stack thread1
z Stack pointer, PC, thread state SP
(running, ), register values, a State Initialized data
pointer to PCB, Registers

Code

Operating System Concepts 8th Edition Silberschatz, Galvin and Gagne 2009
Threads vs. Processes

z 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.
z Secondary Threads vs. Initial Threads
 An initial thread is created automatically when a process is created.
 Secondary threads are peers
 Secondary threads may create other threads and so on, in a
hierarchical way.

Operating System Concepts 8th Edition 4.15 Silberschatz, Galvin and Gagne 2009
Thread Libraries
Thread libraries provide programmer with APIs (Application Programming
Interface) for creating and managing threads
Two primary ways of implementing
z 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)
z Kernel-Level Threads (KLT): Kernel-level library supported by the OS
(system call).

Operating System Concepts 8th Edition 4.16 Silberschatz, Galvin and Gagne 2009
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:
z creating and destroyng threads
z passing data between threads
z scheduling thread execution
z saving and restoring thread context.

Operating System Concepts 8th Edition 4.17 Silberschatz, Galvin and Gagne 2009
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

Operating System Concepts 8th Edition 4.18 Silberschatz, Galvin and Gagne 2009
User-Level Thread

Operating System Concepts 8th Edition 4.19 Silberschatz, Galvin and Gagne 2009
ULT: behavior (I)
An application begins with a single thread
This application and its thread are allocated to a single process managed by
the kernel
At any time that 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.

Operating System Concepts 8th Edition 4.20 Silberschatz, Galvin and Gagne 2009
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)
z it calls a procedure in the threads library
z 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
z the thread scheduler looks in the thread table for a ready thread to run
and restores its context
When a thread requires the intervention of the kernel (through a system
call), the process changes its state and all the threads are blocked.

Operating System Concepts 8th Edition 4.21 Silberschatz, Galvin and Gagne 2009
User-level threads: comments
+ Fast to create and switch
z
procedures that saves the thread's state and the scheduler are user
procedures
z no system call is needed
z no context switch is needed
- When a ULT executes a system call, all the threads within the process are
blocked
z 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.

Operating System Concepts 8th Edition 4.22 Silberschatz, Galvin and Gagne 2009
Kernel-Level Threads
The kernel knows the threads and manages 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.

Operating System Concepts 8th Edition 4.23 Silberschatz, Galvin and Gagne 2009
Kernel-Level Threads

Operating System Concepts 8th Edition 4.24 Silberschatz, Galvin and Gagne 2009
Kernel Level Threads
Thread management done by the kernel

Operating System Concepts 8th Edition 4.25 Silberschatz, Galvin and Gagne 2009
Kernel-level threads: comments
Kernel-level threads
z + 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
z + Only one scheduler (and kernel has global view)
z - Can be difficult to make efficient (create & switch)

Operating System Concepts 8th Edition Silberschatz, Galvin and Gagne 2009
Semantics of fork() and exec()
Does fork() duplicate only the calling thread or all threads?
z 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())
z If exec() is called immediately after forking, then duplicating all threads
is unnecessary. In this istance, duplicating only the calling thread is
appropriate.

Operating System Concepts 8th Edition 4.27 Silberschatz, Galvin and Gagne 2009
Pthreads
May be provided either as user-level or kernel-level
A POSIX standard (IEEE 1003.1c) API to:
z create and destroy threads
z synchronize threads and lock program resources
z 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).

Operating System Concepts 8th Edition 4.28 Silberschatz, Galvin and Gagne 2009
Library and compile
pthread functions are defined into the header file <pthreads.h>:
z #include <pthread.h>
It is needed to compile the source code with the option pthread or
including the library pthread
z gcc Wall g o <exeName> pthread <file.c>
z gcc Wall g o <exeName> <file.c> lpthread.

Operating System Concepts 8th Edition 4.29 Silberschatz, Galvin and Gagne 2009
pthread_create()

Synthax:
z pthread_create(thread,attr,start_routine,arg)
Arguments:
z thread: a unique identifier for the new thread returned by the
subroutine (its type is pthread_t)
z attr: it specifies a thread attributes object, or NULL for the default
values (see later, slide #43, an example of attribute)
z start_routine: the C routine that the thread will execute once it is
created
z 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.
Return value:
z If successfull, it returns 0. Otherwise, it returns a nonzero error code.

Operating System Concepts 8th Edition 4.30 Silberschatz, Galvin and Gagne 2009
#include <stdio.h>
#include <pthread.h>
main() {
pthread_t f2_thread, f1_thread, f3_thread; int i1=1,i2=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() {
}
Operating System Concepts 8th Edition 4.31 Silberschatz, Galvin and Gagne 2009
Thread Identification
Synthax:
z pthread_id pthread_self(void)
Return value:
z A thread can obtain its thread ID by calling pthread_self()function.

Operating System Concepts 8th Edition 4.32 Silberschatz, Galvin and Gagne 2009
Example
pthread_t ntid;
void printds (const char *s)
{
pid_t pid;
pthread_t tid;

pid = getpid();
tid =pthread_self();
printf(%s pid %ud tid \n, pid, (unsigned int) tid);
}
void * thr_fn (void * arg)
{
printds(New Thread: );
return(0);
}
int main (void)
{
int err;
err = pthread_create(&ntid, NULL, thr_fn, NULL);
if (err != 0) printf(cant create thread \n);
printds(main thread: );
sleep(1);
exit(0);
}

Operating System Concepts 8th Edition 4.33 Silberschatz, Galvin and Gagne 2009
Thread / Process termination
A whole process (with all its threads) terminates if:
z one of its threads executes an exit()
z one of its threads receives a signal to terminate
z the main threads executes a return()
A single thread terminates if:
z It executes a pthread_exit()
z It executes a return() in its initial function
z It receives a pthread_cancel() from another thread.

Operating System Concepts 8th Edition 4.34 Silberschatz, Galvin and Gagne 2009
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.

Operating System Concepts 8th Edition 4.35 Silberschatz, Galvin and Gagne 2009
Example
#include <stdio.h> void *mythread (void *arg)
#include <stdlib.h> {
#include <signal.h> /* display the value of the global variable */
printf("thread %lu: sharedVar is %d \n", pthread_self(), sharedVar);
#include <sys/types.h>
#include <unistd.h> sharedVar = 111;
#include <pthread.h> /* POSIX threads */ printf("thread %lu: sharedVar is %d \n", pthread_self(), sharedVar);

sleep(1); /* yield to another thread or main */


void *mythread(void *);
int sharedVar ; /* global variable */ printf("thread %lu: sharedVar is %d \n", pthread_self(), sharedVar);

sharedVar = 222;
int main() { printf("thread %lu: sharedVar is %d.\n", pthread_self(), sharedVar);
sleep(1); /* yield to another thread or main */
pthread_t tid;
/* thread exit with an integer */
pthread_exit (NULL);
sharedVar = 1234; }
printf("Main: sharedVar= %d\n", sharedVar);
pthread_create(&tid, NULL, mythread, NULL);
sleep(1); /* yield to another thread */ OUTPUT
Main: sharedVar= 1234
printf("Main: sharedVar= %d\n", sharedVar); thread 792: sharedVar is 1234
thread 792: sharedVar is 111
sharedVar = 999; Main: sharedVar= 111
printf("Main: sharedVar= %d\n", sharedVar); Main: sharedVar= 999
thread 792: sharedVar is 999
sleep(1); /* yield to another thread */
thread 792: sharedVar is 222
Main: sharedVar= 222
printf("Main: sharedVar= %d\n", sharedVar); DONE
printf("DONE\n");
exit(0);
}

Operating System Concepts 8th Edition 4.36 Silberschatz, Galvin and Gagne 2009
Example
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUM_THREADS 5
void *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);
}

Operating System Concepts 8th Edition 4.37 Silberschatz, Galvin and Gagne 2009
Example In main: creating thread 0
#include <stdio.h>
In main: creating thread 1
#include <stdlib.h> Hello World! It's me, thread #1!
#include <pthread.h> In main: creating thread 2
#define NUM_THREADS 5 Hello World! It's me, thread #2!
void *PrintHello (void *threadid)
{
Hello World! It's me, thread #3!
long * tid; In main: creating thread 3
tid = (long *) threadid; In main: creating thread 4
printf("Hello World! It's me, thread #%ld!\n", * tid);
Hello World! It's me, thread #4!
pthread_exit(NULL);
} Hello World! It's me, thread #5!
int main(int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
t is a pointer and its
long t;
value changes during
the execution
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);
}
Operating System Concepts 8th Edition 4.38 Silberschatz, Galvin and Gagne 2009
Example In main: creating thread 0
#include <stdio.h>
In main: creating thread 1
#include <stdlib.h> Hello World! It's me, thread #0!
#include <pthread.h> In main: creating thread 2
#define NUM_THREADS 5 Hello World! It's me, thread #1!
void *PrintHello (void *threadid)
{
Hello World! It's me, thread #2!
long * tid; In main: creating thread 3
tid = (long *) threadid; In main: creating thread 4
printf("Hello World! It's me, thread #%ld!\n", * tid);
Hello World! It's me, thread #3!
pthread_exit(NULL);
} Hello World! It's me, thread #4!
int main(int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc, t;
long t_numb[NUM_THREADS];
for(t=0;t<NUM_THREADS;t++){
t_numb[t] = t;
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *) &t_numb[t]);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
Operating System Concepts 8th Edition 4.39 Silberschatz, Galvin and Gagne 2009
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];

Operating System Concepts 8th Edition 4.40 Silberschatz, Galvin and Gagne 2009
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);
}

Operating System Concepts 8th Edition 4.41 Silberschatz, Galvin and Gagne 2009
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;
strcpy(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);
}
Operating System Concepts 8th Edition 4.42 Silberschatz, Galvin and Gagne 2009
At its creation a thread can be declared as:
z Joinable (default): another thread can execute a "wait"
(pthread_join) on it
z Detached: it is not possible to wait explicitly its end (it is not joinable),
i.e., a detached thread cannot be waited. This attribute is set through
the argument attr (with the pthread_attr_setdetachstate()
call), as the following code:
pthread_attr_t attr;
void *status;
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr,
PTHREAD_CREATE_DETACHED);

Operating System Concepts 8th Edition 4.43 Silberschatz, Galvin and Gagne 2009
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.

Operating System Concepts 8th Edition 4.44 Silberschatz, Galvin and Gagne 2009
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);
}

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

main thread

call Pthread_create()
Pthread_create() returns peer thread
call Pthread_join()
printf()
main thread waits for pthread_exit()
peer thread to terminate (peer thread
terminates)
Pthread_join() returns

exit()
terminates
main thread and
any peer threads

Operating System Concepts 8th Edition 4.46 Silberschatz, Galvin and Gagne 2009
Example
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#define NTHREADS 5

void *myFun (void *x)


{
int tid;
tid = *((int *) x);
printf ("Hi from thread %d!\n", tid);
pthread_exit(NULL);
}

Operating System Concepts 8th Edition 4.47 Silberschatz, Galvin and Gagne 2009
int main(int argc, char *argv[]) Output:
{
pthread_t threads[NTHREADS]; spawning thread 0
spawning thread 1
int thread_args[NTHREADS];
Hi from thread 0!
int rc, i;
spawning thread 2
Hi from thread 1!
/* spawn the threads */ spawning thread 3
for (i=0; i<NTHREADS; ++i) Hi from thread 2!
{ spawning thread 4
thread_args[i] = i;
Hi from thread 3!
Hi from thread 4!
printf("spawning thread %d\n", i);
rc = pthread_create(&threads[i], NULL, myFun, (void *) &thread_args[i]);
}

/* wait for threads to finish */


for (i=0; i<NTHREADS; ++i) {
rc = pthread_join(threads[i], NULL);
}

return 1;
}

Operating System Concepts 8th Edition 4.48 Silberschatz, Galvin and Gagne 2009
Example
A program implementing the summation function where the summation
operation is run as a separate thread.

Operating System Concepts 8th Edition 4.49 Silberschatz, Galvin and Gagne 2009
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);
}
Operating System Concepts 8th Edition 4.50 Silberschatz, Galvin and Gagne 2009
/**
* 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);
}

Operating System Concepts 8th Edition 4.51 Silberschatz, Galvin and Gagne 2009
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.

Operating System Concepts 8th Edition 4.52 Silberschatz, Galvin and Gagne 2009
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>

char running = 1;

long long counter = 0;

void * process()
{
while (running)
counter++;

printf("Thread: exit\n");

pthread_exit(NULL);
}

Operating System Concepts 8th Edition 4.53 Silberschatz, Galvin and Gagne 2009
int main()
{
int i;
pthread_t thread_Id;

if (pthread_create(&thread_Id, NULL, process, NULL))


{
printf("ERROR in pthread_create()\n");
exit(-1);
}

for (i=0 ; i < 10 ; i++)


{
sleep(1);
printf("counter = %lld\n", counter);
}

running = 0;

pthread_join(thread_Id, NULL);

printf("Average Instructions = %lld \n", counter/10);

return 0;
}
Operating System Concepts 8th Edition 4.54 Silberschatz, Galvin and Gagne 2009
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);
}

Operating System Concepts 8th Edition 4.55 Silberschatz, Galvin and Gagne 2009
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);
}
}

Operating System Concepts 8th Edition 4.56 Silberschatz, Galvin and Gagne 2009
pthread_cancel ()

Syntax:
z int pthread_cancel (pthread_t tid);
It terminates the specified thread (as that executes a pthread_exit)
Parameters
z tid: thread identifier
Return value:
0, in case of success
an error code, in case of failure.

Operating System Concepts 8th Edition 4.57 Silberschatz, Galvin and Gagne 2009
pthread_detach()
Syntax:
z int pthread_detach (pthread_t tid);
It declares that the thread tid has been detached and its memory can be
gave back
It is not possibile to call a join with thread tid
All the future calls pthread_join to thread tid will fail with an error code.
A detached thread cannot be joined.

Parameters
z tid: thread identifier
Return value:
0, in case of success
an error code, in case of failure.

Operating System Concepts 8th Edition 4.58 Silberschatz, Galvin and Gagne 2009
Example
pthread_t tid;
int rc;
void *status;
rc = pthread_create (&tid, NULL, PrintHello, NULL);
if (rc) { ... }
...
pthread_detach (tid); /* Detach a thread */
rc = pthread_join (tid, &status);
if (rc) {
// Error
exit (-1);
}
pthread_exit (NULL);

Operating System Concepts 8th Edition 4.59 Silberschatz, Galvin and Gagne 2009
Exercise
Execute a code source able to guarantee the following graph of
precedences.
A

B C

D E F

Operating System Concepts 8th Edition 4.60 Silberschatz, Galvin and Gagne 2009
Solution
void waitRandomTime (int max){
sleep ((int)(rand() % max) + 1);
}

int main (void) {


pthread_t th_cf, th_e;
void *retval;
srand (getpid());
waitRandomTime (10);
printf ("A\n");

Operating System Concepts 8th Edition 4.61 Silberschatz, Galvin and Gagne 2009
waitRandomTime (10);
pthread_create (&th_cf,NULL,CF,NULL);
waitRandomTime (10);
printf ("B\n");
waitRandomTime (10);
pthread_create (&th_e,NULL,E,NULL);
waitRandomTime (10);
printf ("D\n");
pthread_join (th_cf, &retval);
pthread_join (th_e, &retval);
waitRandomTime (10);
printf ("G\n);
return 0;
}

Operating System Concepts 8th Edition 4.62 Silberschatz, Galvin and Gagne 2009
static void *CF () {
waitRandomTime (10);
printf ( "C\n");
waitRandomTime (10);
printf ( "F\n");
return ((void *) 1); // Return code
}
static void *E () {
waitRandomTime (10);
printf ("E\n");
return ((void *) 2); // Return code
}

Operating System Concepts 8th Edition 4.63 Silberschatz, Galvin and Gagne 2009
Home Work
Execute a code source able to guarantee the following graph of
precedences.
A

B D C

F G
E

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

You might also like