scuola superiore sant’anna operating systems and concurrent programming giuseppe lipari aa 2006...
TRANSCRIPT
![Page 1: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/1.jpg)
Scuola Superiore Sant’Anna
Operating Systems and Concurrent Programming
Giuseppe Lipari
AA 2006 – 2007
![Page 2: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/2.jpg)
Concurrency: mutual exclusion and synchronisation
![Page 3: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/3.jpg)
The need for concurrency
• There are many reason for concurrency• Functional
– Many users may be connected to the same system at the same time
• Each user can have its own processes that execute concurrently with the processes of the other users
– Perform many operations concurrently• For example, listen to music, write with a word processor,
burn a CD, etc• They are all different and independent activities• They can be done “at the same time”
![Page 4: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/4.jpg)
The need for concurrency
• Performance– Take advantage of blocking time
• While some thread waits for a blocking condition, another thread performs another operation
– Parallelism in multi-processor machines• If we have a multi-processor machine, independent activities
can be carried out on different processors are the same time
![Page 5: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/5.jpg)
Theoretical model
• A system is a set of concurrent activities– They can be processes or threads
• They interact in two ways– They access the hardware resources
• Processor• Disk• Memory, etc.
– They exchange data
• These activities compete for the resources and/or cooperate for some common objective
![Page 6: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/6.jpg)
Resource
• A resource can be– A HW resource like a I/O device– A SW resource, i.e. a data structure– In both case, access to a resource must be regulated to avoid
interference
• Example 1– If two processes want to print on the same printer, their access
must be sequentialised, otherwise the two printing could be intermangled!
• Example 2– If two threads access the same data structure, the operation on
the data must be sequentialized otherwise the data could be inconsistent!
![Page 7: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/7.jpg)
Interaction model
• Activities can interact according to two fundamental models– Shared memory
• All activities access the same memory space
– Message passing• All activities communicate each other by sending messages
through OS primitives
– We will analize both models in the following
![Page 8: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/8.jpg)
Resource Allocation
• Allocation of resource can be – Dedicated: one activity at time only is granted access to the
resource– Shared: many activity can access the resource at the same time– Static: once the resource is granted, it is never revoked– Dynamic: resource can be granted and revoked dynamically
Dedicated Shared
Static
Dynamic
CompileTime
Manager
ManagerManager
![Page 9: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/9.jpg)
Cooperative vs Competitive
• The interaction between concurrent activities (threads or processes) can be classified into:
• Competitive concurrency– Different activities compete for the resources– One activity does not know anything about the other– The OS must manage the resources so to
• Avoid conflicts• Be fair
• Cooperative concurrency– Many activities cooperate to perform an operation– Every activity knows about the others– They must synchronize on particular events
![Page 10: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/10.jpg)
Competing activities
• Cooperative and competitive activities need different models of execution and synchronization– Competing activities need to be “protected” from each
other• Separate memory spaces
• The process model is the best
– The allocation of the resource and the synchronization must be centralized
• Competitive activities requests for services to a central manager (the OS or some dedicated process) which allocates the resources in a fair way
– Client/Server model• Communication is usually done through messages
![Page 11: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/11.jpg)
Message passing
• In a client/server system– A server manages the resource exclusively
• For example, the printer
– If a process needs to access the resource, it sends a request to the server
• For example, printing a file, or asking for the status
– The server can send back the responses– The server can also be on a remote system
• Two basic primitives– Send and receive Client 1
Client 2
Server
![Page 12: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/12.jpg)
Cooperative model
• Cooperative activities know about each other– They do not need protection
• Not using protection, we have less overhead
– They need to access the same data structures– Allocation of the resource is de-centralized– Shared memory is the best model– The thread model of execution is the best one
![Page 13: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/13.jpg)
Cooperation and Competion
• Competion is best resolved by using the message passing model– However it can be implemented using a shared
memory paradigm too
• Cooperation is best implemented by using a shared memory paradigm– However, it can be realized by using pure message
passing mechanisms
• Shared memory or message passing?– In the past, there were OS that supported only
shared memory or only message passing
![Page 14: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/14.jpg)
Competition and cooperation
• A general purpouse OS needs to support both models – We need at least protection for competing activities– We need to support client/server models. So we
need message passing primitives– We need to support shared memory for reducing the
overhead
• Some special OS supports only one of the two– For example, many RTOS support only shared
memory
![Page 15: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/15.jpg)
Shared memory
• Shared memory communication– It was the first one to be supported in old OS– It is the simplest one and the closest to the machine– All threads can access the same memory locations
Thread 1 Thread 2 Thread 3
Shared memory
![Page 16: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/16.jpg)
Hardware analogy
• An abstract model that presents a good analogy is the following– Many HW CPU, each one running one activity
(thread)– One shared memory
CPU CPU CPU
Memory
![Page 17: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/17.jpg)
Mutual exclusion problem
• We do not know in advance the relative speed of the processes– Hence, we do not know the order of execution of the
hardware instructions– Recall the example of incrementing variable x
(slide 56)
int x ;
Shared memory void *threadA(void *){
...;x = x + 1;...;
}
void *threadB(void *){
...;x = x + 1;...;
}
![Page 18: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/18.jpg)
Example
• Bad interleaving:
...LD R0, x TA x = 0LD R0, x TB x = 0INC R0 TB x = 0ST x, R0 TB x = 1INC R0 TA x = 1ST x, R0 TA x = 1...
![Page 19: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/19.jpg)
Resource in a non-consistent state!
Consistency: after each operation, a == b
Example - II
• Bad interleaving
class A {int a;int b;
public:A() : a(1), b(1) {};void inc() { a = a + 1; b = b +1; }void double() { b = b * 2; a = a * 2;}
} obj;
Shared object (sw resource)
void * threadA(void *){
...obj.inc();...
}
void * threadB(void *){
...obj.double();...
}a = a + 1; TA a = 2b = b * 2; TB b = 2b = b + 1; TA b = 3a = a * 2; TB a = 4
![Page 20: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/20.jpg)
Consistency
• For each resource, we can state some consistency property– A consistency property Ci is a boolean expression on the values of
the internal variables– A consistency property must hold before and after each operation– It does not hold during an operation– If the operations are properly sequentialized, the consistency
properties must hold
• Formal verification– Let R be a resource, and let C(R) be a set of consistency properties
on the resource• C = { Ci }
– A concurrent program is correct if, for every possible interleaving of the operations on the resource, the consistency properties hold after each operation
![Page 21: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/21.jpg)
Example
class CircularArray {int array[10];int head, tail, num;
public:CircularArray() : head(0),
tail(0), num(0) {}bool insert(int elem) {
if (num == 10) return false;array[head] = elem;head = (head + 1) % 10;num ++;return true;
}bool extract(int &elem) {
if (num == 0) return false;elem = array[tail];tail = (tail + 1) % 10;num - -;return true;
}} queue;
Consistency Properties
C1: if (num == 0 || num == 10) head == tail;
C2: if (0 < num < 10) num == (head – tail) %
10
C3: num == NI - NE
C4: (insert x)pre: if (num < 10) post:num == num + 1 &&
array[(head-1)%10] == x;
C5: (extract &x) pre: if (num > 0)post: (num == num –1) &&
(x == array[(tail-1)%10]);
![Page 22: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/22.jpg)
C3 holdsC4 holds
head = 1head = 0tail = 0
num = 0
Example - Insert
Initial state:
head = 0; tail = 0; num = 0;
queue.insert (5) ;
5
head = 1; tail = 0; num = 1;
C2: if (0 < num < 10) num == (head – tail) % 10
C4: (insert x)pre: if (num < 10) post: (num == num + 1) &&
(array[(head-1)%10] == x);
![Page 23: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/23.jpg)
tailhead
Example - Insert II
queue. insert (3) ;
5 3 Initial state:
head = 0; tail = 0; num = 0;
queue.insert (5) ;
head = 1; tail = 0; num = 1;
head = 2; tail = 0; num = 2;
C3 and C4
hold
C2: if (0 < num < 10) num == (head – tail) % 10
C4: (insert x)pre: if (num < 10) post: (num == num + 1) &&
(array[(head-1)%10] == x);
![Page 24: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/24.jpg)
Example - Inserting III
tail head
1 3 7 4 Initial state:
head = 9; tail = 5; num = 4;
queue. insert (6) ;
head = 0; tail = 5; num = 5head
C3 and C4
holdC2: if (0 < num < 10)
num == (head – tail) % 10
C4: (insert x)pre: if (num < 10) post: (num == num + 1) &&
(array[(head-1)%10] == x);
6
![Page 25: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/25.jpg)
Example - Extract
7 4 6 Initial state:
head = 0; tail = 5; num = 0;
tail
head
queue. extract (int &elem) ;head = 0; tail = 6; num = 4
tail
1 31
C3 and C5
holdC2: if (0 < num < 10)
num == (head – tail) % 10
C5: (extract &x) pre: if (num > 0) post: (num == num –1) &&
(x == array[(tail-1)%10]);
![Page 26: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/26.jpg)
Problems
• If the insert operation is performed by two processes, some consistency property may be violated!
void *threadA(void *){
...queue.insert(5);...
}
void *threadB(void *){
...queue.insert(2);...
}
CircularArray queue;
7 46 3
![Page 27: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/27.jpg)
Interference
7 46 3
Initial state:
head = 7; tail = 3; num = 4;
queue. insert (5) ;(TA)
if (num == 10) return false;array[head] = 5;head = (head + 1) % 10;num ++;return true; queue. insert (2) ;(TB)
if (num == 10) return false;array[head] = 2;head = (head + 1) % 10;num ++;return true;
if (num == 10) return false; (TA)array[head] = 5; (TA)if (num == 10) return false; (TB)array[head] = 2; (TB)head = (head + 1) % 10; (TB)num ++; (TB)return true; (TB)head = (head + 1) % 10; (TA)num ++; (TA)return true; (TA)
5
Final State:
head = 9; tail = 3; num = 6;
2 head (2)
head (1)
C4 is violated!
2 != array[head – 1]
![Page 28: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/28.jpg)
Correctness
• The previous program is not correct– There exists a possible interleaving of two operations
that leaves the resource in a inconsistent state
• Proving the non-correctness is easy– It suffices to find a counter example
• Proving the correctness is not easy– It is necessary to prove the correctness for every
possible interleaving of every operation
![Page 29: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/29.jpg)
Problem
• What if an insert and an extract are interleaved?– Nothing bad can happen!! – Proof
• If 0<num<10, insert() and extract() are independent• If num==0
– If extract begins before insert, it immediately returns false, so nothing bad can happen
– If insert begins before, extract will still return false, so it cannot interfere with insert
• Same thing when num==10
– Question: what happens if we exchange the sequence of instructions in insert or extract?
![Page 30: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/30.jpg)
CircularArray properties
• a) If more than one thread executes queue.insert()– inconsistency!!
• b) If we have only two threads– One threads calls queue.insert() and the other thread
calls queue.extract()– no inconsistency!
• The order of the operations is important! – A wrong order can make the object inconsistency
even under the assumption b)
![Page 31: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/31.jpg)
Questions
• Problem:– In the previous example, we supposed that num++
and num-- are atomic operations– What happens if they are not atomic?
• Question:– Assuming that operation -- and ++ are not atomic,
can we make the CircularArray safe under the assumption b)
• Hint: try to substitute variable num with two boolean variables, bool empty and bool full;
![Page 32: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/32.jpg)
Critical sections
• Definitions– The shared object where the conflict may happen is a
“resource”– The parts of the code where the problem may
happen are called “critical sections”• A critical section is a sequence of operations that cannot be
interleaved with other operations on the same resource
– Two critical sections on the same resource must be properly sequentialized
– We say that two critical sections on the same resource must execute in MUTUAL EXCLUSION
![Page 33: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/33.jpg)
Q&D solutions to mutual exclusion
• In single processor systems– Disable interrupts during a ciritical section
• Problems:– If the critical section is long, no interrupt can arrive
during the critical section• Consider a timer interrupt thas arrives every 1 msec. • If a critical section lasts for more than 1 msec, a timer
interrupt could be lost!
– Concurrency is disabled during the critical section!• We must avoid conflicts on the resource, not disabling
interrupts!
![Page 34: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/34.jpg)
Q&D solutions to mutual exclusion
• Single processor systems– In some scheduler, it is possible to disable
preemption for a limited interval of time– Problems:
• If a high priority critical thread needs to execute, it cannot make preemption and it is delayed
• Even if the high priority task does not access the resource!
<disable preemption><critical section><enable preemption>
No contextswitch may happen during the critical
section
![Page 35: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/35.jpg)
Q&D solutions to mutual exclusion
• Multi-processor– Define a flag s for each resource– Use lock(s)/unlock(s) around the critical section
• Problems:– Busy waiting: if the critical section is long, we waste a
lot of time– Cannot be used in single processors!
int s;...lock(s);<critical section>unlock(s);...
![Page 36: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/36.jpg)
A SW solution to mutual exclusion
• Mutual exclusion– We need one general mechanism to protect critical
sections and synchronization– Djikstra proposed one algorithm (by Dekker)– The algorithm was later improved by Petterson– (Algorithms in Stallings’ book)
![Page 37: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/37.jpg)
Synchronisation
• Mutual exclusion is not the only problem– We need a way of synchronise two or more threads
• Example: producer/consumer– Suppose we have two threads,
• one produces some integers and sends them to another thread (the PRODUCER)
• another one takes the integer and elaborates it (CONSUMER)
Producer Consumer
![Page 38: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/38.jpg)
Producer/consumer
• The two threads have different speeds– For example the producer is much faster than the
consumer– We need to store the integers in a queue, so that
no data is lost– Let’s use the CircularArray class
![Page 39: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/39.jpg)
Producer/Consumer
• Problems with this approach:– If the queue is full, the producer actively waits– If the queue is empty, the consumer actively
waits
void *producer(void *){
bool res;int data;while(1) {
<obtain data>while (!queue.insert(data));
}}
void *consumer(void *){
bool res;int data;while(1) {
while (!queue.extract(&data));<use data>
}}
CircularArray queue; (to slide 127)
![Page 40: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/40.jpg)
A more general approach
• We need to provide a general mechanism for synchonisation
• Requirements– Synchronise two threads on one condition
• For example, block the producer when the queue is full
– Provide mutual exclusion between critical sections• Avoid two insertions operation to interleave
![Page 41: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/41.jpg)
General mechanism
• Djikstra proposed the semaphore mechanism– A semaphore is an abstract entity that consists
• a counter• a blocking queue• operation wait• operation signal
– The operations on a semaphore are considered atomic
![Page 42: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/42.jpg)
Semaphores
• Semaphores are basic mechanisms for providing synchronization– It has been shown that every kind of synchronization
and mutual exclusion can be implemented by using sempahores
– We will analyze possible implementation of the semaphore mechanism later
class Semaphore {<blocked queue> blocked;int counter;
public:Semaphore (int n) : count (n) {...}void wait();void signal();
};
![Page 43: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/43.jpg)
wait
• A wait operation has the following behaviour– If counter == 0, the requiring thread is blocked
• It is removed from the ready queue• It is inserted in the blocked queue
– If counter > 0, then counter--;
• A signal operation has the following behaviour– If counter == 0 and there is some blocked thread,
unblock it• The thread is removed from the blocked queue• It is inserted in the ready queue
– Otherwise, increment counter
![Page 44: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/44.jpg)
Semaphores
class Semaphore {<blocked queue> blocked;int count;
public:Semaphore (int n) : count (n)
{...}void wait() {
if (counter == 0) <block the thread>
else counter--;}void signal() {
if (<some blocked thread>) <unblock the thread>
else counter++; }
};
![Page 45: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/45.jpg)
Signal semantics
• Strong semaphore– The threads are removed in well-specified order
• for example, the FIFO order is the fairest policy• Also, priority based ordering
• Weak semaphore– Does not specify how the threads are removed
• It can lead to some problem
• Signal and suspend– After the new thread has been unblocked, a thread switch
happens
• Signal and continue– After the new thread has been unblocked, the thread that
executed the signal continues to execute
![Page 46: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/46.jpg)
Mutual exclusion with semaphores
• How to use a semaphore for critical sections– Define a semaphore initialized to 1– before entering the critical section, perform a wait– After leaving the critical section, perform a signal
Semaphore s(1);
void *threadA(void *){
...s.wait();<critical section>s.signal();...
}
void *threadB(void *){
...s.wait();<critical section>s.signal();...
}
![Page 47: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/47.jpg)
Mutual exclusion with semaphores
semaphore
counter 10
s.wait(); (TA)<critical section (1)>(TA)s.wait() (TB)<critical section (2)>(TA)s.signal() (TA)<critical section> (TB)s.signal() (TB)
1
Blocked queue
ExeTATB TBTA TA
TB
TBTA
![Page 48: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/48.jpg)
Producer/Consumer with semaphores
• Consider a producer/consumer system– One producer executes queue.insert()
• We want the producer to be blocked when the queue is full• The producer will be unblocked when there is some space
again
– One consumer executes queue.extract• We want the consumer to be blocked when the queue is
empty• The consumer will be unblocked when there is some space
again
– First attempt: one producer and one consumer only
![Page 49: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/49.jpg)
Producer/Consumer with semaphores
class CircularArray {int array[10];int head, tail;Semaphore empty, full;
public:CircularArray() : head(0),
tail(0),empty(0), full(10) {}
void insert(int elem) {wait(full);array[head] = elem;head = (head + 1) % 10;signal(empty);
}void extract(int &elem) {
wait(empty);elem = array[tail];tail = (tail + 1) % 10;signal(full);
}} queue;
![Page 50: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/50.jpg)
Properties
• Notice that– the value of the counter of empty is the number of
elements in the queue• It is the number of times we can call extract without blocking
– the value of the counter of full is the complement of the elements in the queue
• It is the number of times we can call insert without blocking
• Exercise:– Prove that the implementation is correct
• insert() never overwrites elements• extract() always gets an element of the queue
![Page 51: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/51.jpg)
Producers/consumers
• Now let’s combine mutual exclusion and synchronization– Consider a system in which there are many
producers and many consumers– We want to implement synchronization– We want to protect the data structure
![Page 52: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/52.jpg)
Does it work?
class CircularArray {int array[10];int head, tail;Semaphore full, empty;Semaphore mutex;
public:CircularArray() : head(0),
tail(0),empty(0), full(10),
mutex(1) {}void insert(int elem); void extract(int &elem);
} queue;void CircularArray::insert(int elem){
mutex.wait();full.wait();array[head]=elem;head = (head+1)%10;empty.signal();mutex.signal();
}
void CircularArray::extract(int &elem){
mutex.wait();empty.wait();elem = array[tail];tail = (tail+1)%10;full.signal();mutex.signal();
}
![Page 53: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/53.jpg)
Correct solution
class CircularArray {int array[10];int head, tail;Semaphore full, empty;Semaphore mutex;
public:CircularArray() : head(0),
tail(0),empty(0), full(10),
mutex(1) {}void insert(int elem); void extract(int &elem);
} queue;void CircularArray::insert(int elem){
full.wait();mutex.wait();array[head]=elem;head = (head+1)%10;mutex.signal();empty.signal();
}
void CircularArray::extract(int &elem){
empty.wait();mutex.wait();elem = array[tail];tail = (tail+1)%10;mutex.signal();full.signal();
}
![Page 54: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/54.jpg)
Deadlock situation
• Deadlock situation– A thread executes mutex.wait() and then blocks on a
synchronisation semaphore– To be unblocked another thread must enter a critical
section guarded by the same mutex semaphore!– So, the first thread cannot be unblocked and free the
mutex!– The situation cannot be solved!
![Page 55: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/55.jpg)
Semaphore implementation
• System calls– wait() and signal() involve a possible thread-switch– therefore they must be implemented as system calls!
• One blocked thread must be removed from state RUNNING and be moved in the semaphore blocking queue
• Protection:– a semaphore is itself a shared resource– wait() and signal() are critical sections!– they must run with interrupt disabled and by using
lock() and unlock() primitives
![Page 56: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/56.jpg)
Implementation
void Semaphore::wait(){
spin_lock_irqsave();if (counter==0) {
<block the thread>schedule();
} else counter--;spin_lock_irqrestore();
}
void Semaphore::signal(){
spin_lock_irqsave();if (counter== 0) {
<unblock a thread>schedule();
} else counter++;spin_lock_irqrestore();
}
![Page 57: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/57.jpg)
Problems
• Barbershop– Three chairs – Three barbers – A waiting area
• (4 persons on the sofa and the others in another room)
– One cashier
![Page 58: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/58.jpg)
Readers/writers
• One shared buffer• Readers:
– They read the content of the buffer– Many readers can read at the same time
• Writers– They write in the buffer– While one writer is writing no other reader or writer
can access the buffer
• Use semaphores to implement the resource
![Page 59: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/59.jpg)
Simple implementation
class Buffer {Semaphore wsem;Semaphore x;int nr;
public: Buffer() : wsem(1), x(1), nr(0) {}void read();void write();
} buffer;
void Buffer::read() {x.wait();nr++;if (nr==1) wsem.wait();x.signal();<read the buffer>x.wait();nr--;if (nr==0) wsem.signal();x.signal();
}
void Buffer::write() {wsem.wait();<write the buffer>wsem.signal();
}
![Page 60: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/60.jpg)
Problem: starvation
• Suppose we have 2 readers (R1 and R2) and 1 writer (W1)– Suppose that R1 starts to read– While R1 is reading, W1 blocks because it wants to
write– Now R2 starts to read– Now R1 finishes, but, since R2 is reading, W1 cannot
be unblocked– Before R2 finishes to read, R1 starts to read again– When R2 finishes, W1 cannot be unblocked because
R1 is reading
![Page 61: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/61.jpg)
Priority to writers!
class Buffer {Semaphore x, y, z, wsem, rsem;int nr, nw;
public: Buffer() : x(1), y(1), z(1), wsem(1), rsem(1), nr(0), nw(0) {}
}
void Buffer::read() {z.wait();rsem.wait();x.wait();nr++;if (nr==1) wsem.wait();x.signal();rsem.signal();z.signal();<read the buffer>x.wait();nr--;if (nr==0) wsem.signal();x.signal();
}
void Buffer::write() {y.wait();nw++;if (nw==1) rsem.wait();y.signal();wsem.wait();<write the buffer>wsem.signal();y.wait();nw--;if (nw == 0) rsem.signal();y.signal();
}
![Page 62: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/62.jpg)
Problem
• Can you solve the readers/writers problem in the general case?– No starvation for readers– No starvation for writers
• Solution– Maintain a FIFO ordering with requests
• If at least one writer is blocked, every next reader blocks• If at least one reader is blocked, every next writer blocks• One single semaphore!
![Page 63: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/63.jpg)
Solution
class Buffer {int nbr, nbw;int nr, nw;Semaphore rsem, wsem;Semaphore m;
public:Buffer():
nbw(0),nbr(0), nr(0), nw(0), rsem(0), wsem(0) {}
void read();void write();
};
![Page 64: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/64.jpg)
Solution II
void Buffer::read(){
m.wait();if (nw || nbw) {
nbr++;m.signal();rsem.wait();m.wait();while (nbr>0)
{nbr--;rsem.signal();}}nr++;m.signal();<read buffer>;m.wait();nr--;if (nbw && nr == 0) wsem.signal();m.signal();
}
void Buffer::write(){
m.wait();if (nw || nbw || nr || nbr) {
nbw++;m.signal();wsem.wait();m.wait();nbw--;
}nw++;m.signal();<read buffer>;m.wait();nw--;if (nbr) {nbr--; rsem.signal();}else if (nbw) wsem.signal();m.signal();
}
![Page 65: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/65.jpg)
Monitors
• Monitors are a language structure equivalent to semaphores, but cleaner– A monitor is similar to an object in a OO language– It contains variables and provides procedures to
other software modules– Only one thread can execute a procedure at a certain
time• Any other thread that has invoked the procedure is blocked
and waits for the first threads to exit• Therefore, a monitor implicitely provides mutual exclusion
![Page 66: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/66.jpg)
Monitors
• Monitors support synchronization with Condition Variables– A condition variable is a blocking queue– Two operations are defined on a condition variable
• wait() -> suspends the calling thread on the queue
• signal() -> resume execution of one thread blocked on the queue
• Important note: – wait() and signal() operation on a condition variable are different
from wait and signal on a semaphore!– There is not any counter in a condition variable!– If we do a signal on a condition variable with an empty queue,
the signal is lost
![Page 67: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/67.jpg)
CircularArray with monitors
class CircularArray {int array[10];int head, tail, num;Condition empty, full;
public:CircularArray() : head(0),
tail(0),num(0) {}
void insert(int elem) synchronized;
void extract(int &elem) synchronized;} queue;
void CircularArray::insert(int elem)synchronized
{if (num==10) full.wait();array[head]=elem;head = (head+1)%10;num++;if (num==1) empty.signal();
}
void CircularArray::extract(int &elem) synchronized
{if (num== 0) empty.wait();elem = array[tail];tail = (tail+1)%10;num--;if (num == 9) full.signal();
}
![Page 68: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/68.jpg)
Problem
• Implement the readers/writers problem with monitors– Hint: follow the previous solution with semaphores!
![Page 69: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/69.jpg)
Message passing
• Message passing systems are based on the basic concept of message
• Two basic operations– send(destination, message);– receive(source, &message);
– Two variants• Both operations can be synchronous or asynchronous• receive can be symmetric or asymmetric
![Page 70: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/70.jpg)
Producer/Consumer with MP
• The producer executes send(consumer, data)• The consumer executes receive(producer, data);• No need for a special communication structure
(already contained in the send/receive semantic)
Producer Consumer
![Page 71: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/71.jpg)
Synchronous communication
• Synchronous send/receiveproducer: s_send(consumer, d);
consumer: s_receive(producer, &d);
producer consumer
send
receive
blocked
producer consumer
send
receive
blocked
![Page 72: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/72.jpg)
Async send/ Sync receive
• Asynchronous send / synchronous receiveproducer:
a_send(consumer, d);
consumer:
s_receive(producer, &d);
producer consumer
send
receiveproducer consumer
send
receive
blocked
![Page 73: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/73.jpg)
Asymmetric receive
• Symmetric receive– receive(source, &data);
• Often, we do not know who is the sender– Imagine a web server;
• the programmer cannot know in advance the address of the browser that will request the service
• Many browser can ask for the same service
• Asymmetric receive– source = receive(&data);
![Page 74: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/74.jpg)
Message passing systems
• In message passing– Each resource needs one threads manager– The threads manager is responsible for giving access
to the resource
• Example: let’s try to implement mutual exclusion with message passing primitives– One thread will ensure mutual exclusion– Every thread that wants to access the resourec must
• send a message to the manager thread• access the critical section• send a message to signal the leaving of the critical section
![Page 75: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/75.jpg)
Sync send / sync receive
void * manager(void *){
thread_t source;int d;while (true) {
source = s_receive(&d);s_receive_from(source, &d);
}}
void * thread(void *){
int d;while (true) {
s_send(manager, d);<critical section>s_send(manager, d);
}}
manager
TA
TB
<critical section>
<critical section>
rec_from rec rec_fromrec
send send
send send
![Page 76: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/76.jpg)
With Async send and sync receive
void * manager(void *){
thread_t source;int d;while (true) {
source = s_receive(&d);a_send(source,d);s_receive_from(source,&d);
}}
void * thread(void *){
int d;while (true) {
a_send(manager, d);s_receive_from(manager, &d);<critical section>a_send(manager, d);
}}
manager
TA
TB
<critical section>
<critical section>
rec_from
rec rec_fromrec send send
![Page 77: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/77.jpg)
Problem
• Implement readers/writers with message passing– Hints: – define a manager thread– the service type (read/write) can be passed as data– use asynchronouse send and synchronous receive– use symmetric and asymmetric receive
![Page 78: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/78.jpg)
DEADLOCK
![Page 79: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/79.jpg)
Deadlock
• Deadlock is the situation in which a group of threads are permanently blocked waiting for some resource
• Deadlock can happen in many subtle cases• Here we will study ways of avoiding deadlock
situations
![Page 80: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/80.jpg)
DEADLOCK!!
Example of deadlock
void *threadA(void *){
...s1.wait();s2.wait();...s1.signal();s2.signal();...
}
void *threadB(void *){
...s2.wait();s1.wait();...s2.signal();s1.signal();...
}
Semaphore s1(1);Semaphore s2(1);
TA
TB
s1.wait()
s2.wait()
s2.wait()
s1.wait()
![Page 81: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/81.jpg)
Graphical situation
TA
TB
get s1
get s2
get s2
get s1Deadlockinevitable
release s2
release s1
rele
ase
s1
rele
ase
s2
TA and TBwant s1
TA and TBwant s2
![Page 82: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/82.jpg)
Deadlockinevitable
Graphical situation
TA
TB
get s1
get s2
get s2
get s1
release s2
release s1
rele
ase
s1
rele
ase
s2
![Page 83: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/83.jpg)
Example with no deadlock
TA
TB
get s1
get s2
get s2
get s1
release s2
release s1
rele
ase
s1
rele
ase
s2
![Page 84: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/84.jpg)
Other examples of deadlock
• Bad situations can happen even when the resource is not “on-off”
• Consider a memory allocator– Suppose that the maximum memory allocable is 200
Kbvoid * threadA(void *){
request(80kb);...request(60kb);...release(140kb);
}
void * threadB(void *){
request(70kb);...request(80kb);...release(150kb);
}
![Page 85: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/85.jpg)
Consumable and reusable resources
• Reusable resources– It can be safely used by only one thread at time and is nod
depleted by the use– Threads must request the resource and later release it, so it can
be reused by other threads– Examples are processor, memory, semaphores, etc.
• Consumable resources– It is created and destroyed dynamically– Once the resource is acquired by a thread, it is immediately
“destroyed” and cannot be reused– Examples are messages in a FIFO queue, interrupts, I/O data,
etc.
![Page 86: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/86.jpg)
Deadlock with consumable resources
void *threadA(void *){
s_receive_from(threadB, msg1);...s_send(threadB, msg2);...
}
void *threadB(void *){
s_receive_from(threadA, msg1);...s_send(threadA, msg2);...
}
TA
TB
s_receive_from(threadB,msg1)
s_receive_from(threadA,msg1)
![Page 87: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/87.jpg)
Conditions for deadlock
• Three conditions– Mutual exclusion
• Only one process may use the resource at the same time
– Hold and wait• A process may hold allocated resources when it blocks
– No preemption• The resource cannot be revoked
• If the three above conditions hold and – Circular wait
• A closed chain of threads exists such that each thread holds at least one resources needed by the next thread in the chain
• then a deadlock can occur!• These are necessary and sufficient conditions for a
deadlock
![Page 88: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/88.jpg)
How to solve the problem of deadlock
• To prevent deadlock from happening we can distinguish two class of techniques– Static: we impose strict rules in the way resources may be
requested so that a deadlock cannot occur– Dynamic: dynamically, we avoid the system to enter in
dangerous situations
• The basic idea is to avoid that one of the previous conditions hold
• Three strategies– Deadlock prevention (static)– Deadlock avoidance (dynamic)– Deadlock detection (dynamic)
![Page 89: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/89.jpg)
Conditions
• Mutual exclusion– This cannot be disallowed. If a resource must be
accessed in mutual exclusion, there is nothing else we can do!
• Hold and wait– We can impose the tasks to take all resources at the
same time with a single operation– This is very restrictive! Even if we use the resource
for a small interval of time, we must take it at the beginning!
– Reduces concurrency
![Page 90: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/90.jpg)
Conditions
• No preemption– This technique can be done only if we can actually
suspend what we are doing on a resource and give it to another thread
– For the “processor” resource, this is what we do with a thread switch!
– For other kinds of resources, we should “undo” what we were doing on the resource
– This may not be possible in many cases!
![Page 91: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/91.jpg)
Conditions
• Circular wait– This condition can be prevented by defining a linear
ordering of the resources– For example: we impose that each thread must
access resources in a certain well-defined ordervoid *threadA(void *){
...s1.wait();s2.wait();...s1.signal();s2.signal();...
}
void *threadB(void *){
...s2.wait();s1.wait();...s2.signal();s1.signal();...
}
![Page 92: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/92.jpg)
Why this strategy works?
• Let us define a oriented graph– A vertex can be
• a thread (round vertex)• a resource (square vertex)
– An arrow from a thread to a resource denotes that the thread requires the resource
– An arrow from a resource to a thread denotes that the resource is granted to the thread
• Deadlock definition– A deadlock happens if at some point in time there is
a cycle in the graph
![Page 93: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/93.jpg)
Graph
void *threadA(void *){
...s1.wait();s2.wait();...s1.signal();s2.signal();...
}
void *threadB(void *){
...s2.wait();s1.wait();...s2.signal();s1.signal();...
}
TA
TB
S1
S2
![Page 94: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/94.jpg)
Theorem
• If all threads access resources in a given order, a deadlock cannot occur– Proof: by contradiction.– Suppose that a deadlock occurs. Then, there is a cycle. – By hypothesis all threads access resources by order– Therefore, each thread is blocked on a resource that has an
order number grater than the resources it holds.– Starting from a thread and following the cycle, the order number
of the resource should always increase. However, since there is a cycle, we go back to the first thread. Then there must be a thread T that holds a resource Ra and requests a Resource Rb with Ra < Rb
– This is a contradiction!
![Page 95: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/95.jpg)
Deadlock avoidance
• This technique consists in monitoring the system to avoid deadlock– We check the behaviour of the system– If we see that we are going into a dangerous
situation, we block the thread that is doing the request, even if the resource is free
![Page 96: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/96.jpg)
Naive approach
• Definitions– (R1, R2, ... Rm): total amount of each resource– (V1, V2, ..., Vm): amount of free resources at time t– Claim:
– Allocation:
.........
...
...
2221
1211
CC
CC
.........
...
...
2221
1211
AA
AA
![Page 97: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/97.jpg)
Naive approach
• Deadlock avoidance rule:– A new thread T(n+1) is started only if:
n
kkiii AVR
1iki RCik :, kiki CAik :,
n
kkiini CCR
1)1(
Too restrictive!
![Page 98: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/98.jpg)
Example
• In case of the semaphores– R1 = 1, R2 = 1
– Ca1 = 1, Ca2 = 1
– Cb1 = 1, Cb2 = 1
• The previous rule was:
111 ba CCR
![Page 99: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/99.jpg)
The banker’s algorithm
• Tries to identify “safe states”– Analyse a thread request– If the situation after the tequest is unsafe (i.e. it leads
to a deadlock) block the thread– Otherwise, grant the resource!
![Page 100: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/100.jpg)
The banker’s algorithm
// M is the number of different resources// N is the number of distinct processesclass Bank {
int avail[M]; // How many are left for each resourceint request[N,M]; // How much each process requiresint assigned[N, M]; // how much each process is assigned
public:// p identifies the process. p is in [0,N-1]// r identifies the resource. r is in [0, M-1]bool try(int p, int r);
};
![Page 101: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/101.jpg)
The banker’s algorithm
bool Bank::try(int p, int r){
bool flag[N];int i,j;bool ok = true;for (i=0; i<N; i++) flag[i]=true;int my_avail[M];for (j=0; j<M; j++)
my_avail[j] = avail[j];my_avail[r]--;request[p,r]--;assigned[p,r]++;i=0;...
while (i<N) {if (flag[i]) {
ok = true;for (j=0; j<M; j++)
if (request[i,j]>my_avail[j]) ok = false;
}if (ok) {
for (j=0; j<M; j++) my_avail[j] += assigned[i,j];
flag[i] = false;i = 0;
}else i++;
}bool safe = true;for (i=0; i<N; i++)
if (flag[i]) safe = false;if (safe) avail[p,r]--;return safe;
}
![Page 102: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/102.jpg)
Deadlock detection
• In this strategy, we monitor the system to check for deadlocks after they happen– We look for cycles between threads and resources– How often should we look?
• It is a complex thing to do, so it takes precious processing time
• It can be done not so often
– Once we discover deadlock, we must recover– The idea is to kill some blocked thread
![Page 103: Scuola Superiore Sant’Anna Operating Systems and Concurrent Programming Giuseppe Lipari AA 2006 – 2007](https://reader036.vdocuments.site/reader036/viewer/2022062423/56649e995503460f94b9c0c4/html5/thumbnails/103.jpg)
Recovery
1. Abort all threads– Used in almost all OS. The simplest thing to do.
2. Check point– All threads define safe check points. When the OS discover a
deadlock, all involved threads are restarted to a previous check point• Problem. The can go in the same deadlock again!
3. Abort one thread at time– Threads are aborted one after the other until deadlock
disappears
4. Successively preempt resources– Preempt resources one at time until the deadlock disappears