Upload
others
View
1
Download
0
Embed Size (px)
Citation preview
1
Recitation: Wait-Free Synchronization and Deadlock
avoidance.
ECE469 Feb 11
Aravind Machiry
2
Reading assignment● Dinosaur chapter 7
● Comet Ch 32 (Ch 33 for last lecture)
3
Can we not use locks and still solve concurrency problems?
● Can we design data structures in a way that allows safe concurrent accesses?● no mutual exclusion necessary● no possibility of deadlock● only using tsa ● no busy waiting
4
Wait-free Synchronization
● Design data structures in a way that allows safe concurrent accesses● no mutual exclusion (lock acquire & release) necessary● no possibility of deadlock
● Approach: use a single atomic operation to● commit all changes
● move the shared data structure from one consistent state to another
5
Simple example – Queue insertiontypedef struct { QItem *item; QElem *next;} QElem;
queue
6
Simple example – Queue insertiontypedef struct { QItem *item; QElem *next;} QElem;
queue
new
7
Simple example – Queue insertiontypedef struct { QItem *item; QElem *next;} QElem;
queue
new
8
Singly-linked Queue Insertion
QElem *queue;
void Insert(item) { QElem *new = malloc(sizeof(QElem)); new->item = item; new->next = queue; queue = new;}
9
[lec6] Read-modify-write on CISC
● Most CISC machines provide atomic read-modify-write instruction● read existing value● store back a new value● Example: test-and-set by IBM and others
● Using TAS to implement lock (mutex)
int TAS(int *old_ptr, int new { int old = *old_ptr; // fetch old value at old_ptr *old_ptr = new; // store ’new’ into old_ptr return old; // return the old value }
10
Singly-linked Queue Insertion
QElem *queue;
void Insert(item) { QElem *new = malloc(sizeof(QElem)); new->item = item; do { new->next = queue; } while (tas(&queue, new) != new->next);}
Is this busy waitinga problem?
11
Limitation
● Example only works for simple data structures where changes can be committed with one store instruction
● What about more complex data structures?
12
More General Approach
● Maintain a pointer to the “master copy” of the data structure
● To modify,1. remember current value of the master pointer2. copy shared data structure to a scratch location3. modify copy4. atomically:
● verify that master pointer has not changed● write pointer to refer to new master
5. if verification fails (another process interfered), start over at step 1
What can go wrong?
● Primarily, we worry about:● Starvation: A policy that can leave some
philosopher hungry in some situation (even one where the others collaborate)
● Deadlock: A policy that leaves all the philosophers “stuck”, so that nobody can do anything at all
● Livelock: A policy that makes them all do something endlessly without ever eating!
Starvation vs Deadlock● Starvation vs. Deadlock
● Starvation: thread waits indefinitely● Example, low-priority thread waiting for resources constantly in
use by high-priority threads● Deadlock: circular waiting for resources
● Thread A owns Res 1 and is waiting for Res 2Thread B owns Res 2 and is waiting for Res 1
● Deadlock ⇒ Starvation but not vice versa● Starvation can end (but doesn’t have to)● Deadlock can’t end without external intervention
Res 2Res 1
ThreadB
ThreadA
WaitFor
WaitFor
OwnedBy
OwnedBy
15
Deadlocks
● Definition: in a multiprogramming environment, a process is waiting forever for a resource held by another waiting process
● Topics:● Conditions for deadlocks● Strategies for handling deadlocks
System Model● Resources
● Resource types R1, R2, . . ., Rm● CPU cycles, memory space, I/O devices, mutex
● Each resource type Ri has Wi instances● Preemptable: can be taken away by scheduler, e.g. CPU● Non-preemptable: cannot be taken away, to be released
voluntarily, e.g., mutex, disk, files, ...
● Each process utilizes a resource as follows:● request ● use ● release 16
Resource-Allocation Graph
● A set of vertices V and a set of edges E● V is partitioned into two types:
● P = {P1, P2, …, Pn}, the set consisting of all the processes in the system
● R = {R1, R2, …, Rm}, the set consisting of all resource types in the system
● request edge – directed edge P1 → Rj● assignment edge – directed edge Rj → Pi
17
Resource-Allocation Graph (Cont.)
● Process
● Resource type with 4 instances
● Pi requests instance of Rj
● Pi is holding an instance of Rj
18
19
● What happens if there is a cycle in the resource allocation graph?
A S
BR
Example of a Resource Allocation Graph – one instance per type
Example of a Resource Allocation Graph – multiple instances / type
20
Resource Allocation Graph with a cycle – is there a deadlock?
21
22
Resource Allocation Graph with a cycle – is there a deadlock?
Basic Facts
● If graph contains no cycles ⇒ no deadlock
● If graph contains a cycle ⇒● if only one instance per resource type, then deadlock● if several instances per resource type, possibility of
deadlock
23
24
4 Necessary Conditions for Deadlock
● Mutual exclusion● Each resource instance is assigned to exactly one process
● Hold and wait● Holding at least one and waiting to acquire more
● No preemption● Resources cannot be taken away
● Circular chain of requests
Eliminating any condition eliminates deadlock!
Program behavior
Resource nature
25
Four Possible Strategies
1. Ignore the problem● It is user’s fault● used by most operating systems, including UNIX
2. Detection and recovery (by OS)● Fix the problem after occurring
3. Dynamic avoidance (by OS, programmer help)● Careful allocation
4. Prevention (by programmer, practically)● Negate one of the four conditions
26
Four Possible Strategies
1. Ignore the problem● It is user’s fault● used by most operating systems, including UNIX
2. Detection and recovery (by OS)● Fix the problem after occurring
3. Dynamic avoidance (by OS, programmer help)● Careful allocation
4. Prevention (by programmer, practically)● Negate one of the four conditions
27
Four Necessary Conditions for Deadlock
● 4.1 Mutual exclusion● Each resource instance is assigned to exactly one process
● 4.2 Hold and wait● Holding at least one and waiting to acquire more
● 4.3 No preemption● Resources cannot be taken away
● 4.4. Circular chain of requests
Eliminating any condition eliminates deadlock!
Program behavior
Resource nature
28
4.1 Prevention: Remove Mutual Exclusion
● Some resources can be made sharable● Read-only files, memory, etc
● Some resources are not sharable● Printer, mutex, etc
● Reduce/remove as much ME as possible
● How?● Using hardware primitives (e.g., TAS)● Wait-free synchronization
● Dining philosophers problem? (work out on your own)
29
4.2 Prevention: (change app) Remove Hold and Wait
● Two-phase locking● Phase I:
● Try to lock all needed resources at the beginning, atomically (how?)
● Phase II: ● If successful, use the resources & release them● If not, release all resources and start over
● This is how telephone company prevents deadlocks● 2 Problems with this approach?
● Dining philosophers problem? (work out on your own)
30
4.3 Prevention: Preemption (w/o changing app)● Make scheduler aware of resource allocation● Method
● If a request from a process holding resources cannot be satisfied, preempt the process and release all resources
● Schedule it only if the system satisfies all resources● Applicability?
● Preemptable resources:● CPU registers, physical memory
● What about Un-preemptable resources?● Network, storage
● Difficult for OS to understand app intention
4.3 Prevention: Preemption (changing app using hw primitive)
● Trylock approachtop:lock(L1); if (trylock(L2) == -1) {
unlock(L1); goto top;
}
● Problems? Livelock
● Dining philosophers problem? 31
32
4.4 Prevention: (change app)No Circular Wait● Impose some order of requests for all resources● How?● Does it always work? ● Can we prove it?
● How is this different from two-phase locking?
Dining philosophers?
33
Four Possible Strategies
1. Ignore the problem● It is user’s fault● used by most operating systems, including UNIX
2. Detection and recovery (by OS)● Fix the problem afterwards
3. Dynamic avoidance (by OS & programmer)● Careful allocation
4. Prevention (by programmer & OS)● Negate one of the four conditions
34
Four Possible Strategies
1. Ignore the problem● It is user’s fault● used by most operating systems, including UNIX
2. Detection and recovery (by OS)● Fix the problem afterwards
3. Dynamic avoidance (by OS)● Careful allocation
4. Prevention (mostly by programmer)● Negate one of the four conditions (mostly 2 and 4)
35
Deadlock examples
36
Conditions for Deadlock
Guns don’t cause deadlocks – people do
Non-Deadlock Bugs
● Atomicity-Violation Bugs● The desired serializability among multiple memory
accesses is violated (i.e. a code region is intended to be atomic, but the atomicity is not enforced during execution).
● Real example in MySQL
Thread 1:: if (thd->proc_info) {
... fputs(thd->proc_info, ...); ...
}37
Thread 2:: thd->proc_info = NULL;
Not Atomic!
Non-Deadlock Bugs
● Order-Violation Bugs● The desired order between two (groups of) memory
accesses is flipped (i.e., A should always be executed before B, but the order is not enforced during execution)
Thread 1:: void init() { ... mThread = PR_CreateThread(mMain, ...);
... } 38
Thread 2:: void mMain(...) {
... mState = mThread->State; ...
}
Non-Deadlock Bugs
● Real study found that non-deadlock bugs happen more often than deadlock bugs and are the majority of concurrency bugs!
39
40
Next class!
● Concurrency bugs and techniques to find them.