+ All Categories
Transcript

CS444/CS544Operating Systems

Deadlock

3/7/2007

Prof. Searleman

[email protected]

Outline

Summary: Synchronization Handling Deadlock

NOTE: Next topic: Memory Management, Chapters 8–9 Makeup class on Friday 3/09/07:

section §10: lab@1:00 in ITL; lecture@2:00 in SC356 section §20: lecture@1:00 in SC342; lab@2:00 in ITL

Exam#2 – Tues. 3/13, 7:00 pm, SC160

void startRead(){ if ( busy || (waitingWriters > 0) ) { waitingReader++; OKtoRead.wait(); waitingReaders--; } readercount = readercount + 1; OKtoRead.signal();}void endRead(){ readercount = readercount - 1; if (readercount == 0) OKtoWrite.signal();}

can a newly arriving reader enter the queue for OKtoRead? could this starve a waiting writer?

Recap: Reader/Writer Monitor

// Monitor procedures for writers:

void startWrite(){ if ( (readercount != 0) || busy ) { waitingWriters++; OKtoWrite.wait(); waitingWriters--; } busy = true;}void endWrite(){ busy = false; if (waitingReaders > 0) OKtoRead.signal(); else OKtoWrite.signal();}

Remember

Game is obtaining highest possible degree of concurrency and greatest ease of programming

Tension Simple high granularity locks easy to program Simple high granularity locks often means low

concurrency Getting more concurrency means

Finer granularity locks, more locks More complicated rules for concurrent access

Pseudo-Monitors Monitor = a lock (implied/added by compiler)

for mutual exclusion PLUS zero or more condition variables to express ordering constraints

What if we wanted to have monitor without programming language support? Declare locks and then associate condition

variables with a lock If wait on the condition variable, then release the

lock Java – “synchronized” methods

Example: Pseudo-monitorspthread_mutex_t monitorLock;

pthread_cond_t conditionVar;

void pseudoMonitorProc(void)

{

pthread_mutex_lock(&mutexLock);

…..

pthread_cond_wait(&conditionVar, &monitorLock);

….

pthread_mutex_unlock(&mutexLock);

}

Synchronization Mechanisms Hardware Solutions

disable/enable interrupts uninterruptible machine instruction (e.g. test-and-set, swap)

Software Solutions Peterson’s solution and variations semaphores:

counting & binary semaphores spinlock semaphores

monitors condition variables

Thread packages: mutex (lock), condition variables, reader-writer locks

Events, Message Passing, Timers, Regions, and others…

(busy waiting)

(busy waiting)

(busy waiting)(blocking)

(blocks other threads from running)

(blocking)

(blocking)

Software Synchronization Primitives Summary Locks

Simple semantics, often close to HW primitives Can be inefficient if implemented as a spin lock

Semaphores Internal queue – more efficient if integrated with scheduler

Monitors Language constructs that automate the locking Easy to program with where supported and where model fits

the task Once add in condition variables much of complexity is back

Events/Messages Simple model of synchronization via data sent over a channel

Value Queue “acquire”

op

“release”

op

“broadcast” or “release all” op

Lock0/1 ?

Lock

Block till value = 0; set value = 1

Unlock

value = 0 No

Semaphoreint Y

Wait, down, P

value—

If value < 0

add self to queue

Signal, up, V

value++

If value <= 0

wake up one

No?

while (getValue()<0) {

signal()

}

Condition variable N/A Y

Wait

Put self on queue

Signal

If process on queue, wake up exactly one

Easy to support

a signal all

MonitorN/A Y

Call proc in monitor

Return from proc in monitor No

Semaphores vs Monitors

If have one you can implement the other…

Converting a monitor solution to a semaphore solution

Basic concept: Each condition c; simulated with

semaphore cSem = 0; For mutual exclusion, introduce a new semaphore:

semaphore mutex = 1; A wait on a condition variable c: c.wait() becomes:

signal(mutex); // release exclusionwait(cSem); // blockwait(mutex); // regain exclusion before

accessing // shared variables What about a signal on a condition variable?

Implementing Monitors with Semaphores

semaphore_t mutex, next;int nextCount = 1;

Initialization code:mutex.value = 1;next.value = 0;

For each procedure P in Monitor,

implement P as

Wait (mutex);unsynchronizedBodyOfP();if (nextCount >0){

signal(next);}else {

signal(mutex);}

conditionVariable_t {int count;semaphore_t sem;

}condWait (conditionVariable_t *x) {

//one more waiting on this condx->count = x_count++;if (nextCount > 0){

signal(next); //wake up someone} else { signal (mutex); }wait(x->sem);x->count = x->count--;

}condSignal(conditionVariable_t *x){

//if no one waiting do nothing!if (x->count > 0){

next_count = nextCount++;signal(x->sem);wait (next);nextCount--; } }

Implementing Semaphores With Monitors Monitor semaphore {

int value;condition waitQueue;

void wait(){ value--;

while (value < 0){ //Notice Mesa semantics

condWait(&waitQueue);}

}

void signal(){value++;

condSignal(&waitQueue);

}

} //end monitor semaphore

void setValue(int value){value = newValue;

}

int getValue(){return value;

}

Need for Synchronization

Have a number of cooperating, sequential processes/threads running asynchronously. When must they synchronize?

When timing or ordering of execution is required e.g. one process/thread must wait for another

When sharing a resource Each process/thread does the following

request/acquire the resource;

use the resource;

release the resource;

resources: shared variables/files, buffers, devices (such as printers), databases, etc.

Criteria for a “good” solution Mutual exclusion is preserved The progress requirement is satisfied The bounded-waiting requirement is met.

In other words, you want the solution to be correct (under any circumstances) without any

assumptions about relative running times (no race conditions possible)

fair not subject to starvation (indefinite postponement) or

deadlock

Synchronization Mechanisms

It is common for Operating Systems to have a variety of synchronization mechanisms.

Solaris

adaptive mutexes, condition variables, semaphores, reader-writer locks, turnstiles

Windows XP dispatcher objects: mutexes, semaphores, events, timers

Linux spinlocks, semaphores, reader-writer locks, Pthread API

(mutex locks, condition variables, read-write locks)

Why??

Summary: Synchronization Synchronization primitives all boil down to

controlling access to a shared state (or resource) with a small amount of additional shared state

All need to be built on top of HW support Once have one kind, can implement the others Which one you use is a matter of matching the

primitive to the problem short-term locking: spinlocks, mutexes longer-term locking: counting semaphores, condition

variables read-only access with occasional writes: reader-writer

locks

Deadlock (aka “Deadly Embrace”)

Compliments of Oleg Dulin, CS major, Clarkson alumni

Methods for Handling Deadlock

Allow deadlock to occur, but…

Ignore it (ostrich algorithm)

Detection and recovery

Ensure that deadlock never occurs, by…

Prevention (negate at least 1 of the 4 necessary conditions for deadlock to occur)

Dynamic avoidance (be careful)

What are the consequences?

May be expensive

Constrains how requests for resources can be made

Processes must give maximum requests in advance


Top Related