Lecture 5
Lecture 5
5
Achieving Mutual Exclusion
6
Achieving Mutual Exclusion
x.P():
while (x == 0) wait;
x–
// binary Semaphore = Mutex
x.V(): x=1; Unlocked, Resource Available
x++ x=0; Locked, Must wait for resource
8
Semaphones to Create a FIFO
b.Insert(x)
Insert item into queue
b.Remove()
Block until queue not empty (if necessary)
Return element at head of queue
b.Flush():
Clear queue
b.Init(): .
b.sb = NewBuf() .
b.mutex = 1 .
.
b.Insert(x): b.Remove():
b.mutex.lock() retry:
b.sb.Insert(x) b.mutex.lock()
b.mutex.unlock() if !(b.sb.len() > 0) {
b.mutex.unlock()
b.Remove(): goto retry
b.mutex.lock() }
x = b.sb.Remove() .
b.mutex.unlock() .
return x .
cvar.Signal():
If no thread suspended, then NO-OP
Wake up (at least) one suspended thread.
(Typically do within scope of mutex, but not required)
12
Buffer using ConditionVars
b.Init():
b.sb = NewBuf()
b.mutex = 1
b.cvar = NewCond(b.mutex)
b.Insert(x):
b.mutex.lock()
b.sb.Insert(x)
b.sb.Signal() // Signal() If no thread suspended, then NO-OP
b.mutex.unlock() Wake up (at least) one suspended thread.
(Typically do within scope of mutex, but not required)
b.Remove():
b.mutex.lock()
if b.sb.Empty() {
b.cvar.wait() // wait() Note that lock is first released & then retaken
} Atomically: release mutex & suspend operation
x = b.sb.Remove() When resume, lock mutex (but maybe not right away)
b.mutex.unlock()
return x
b.Flush():
b.mutex.lock()
b.sb.Flush()
b.mutex.unlock()
13
Buffer using ConditionVars
b.Init(): Cvar.wait() // 3 steps
b.sb = NewBuf()
b.mutex = 1 Atomically {release lock + suspend operation)
b.cvar = NewCond(b.mutex) .
.
b.Insert(x): .
b.mutex.lock() Resume Execution
b.sb.Insert(x) .
b.sb.Signal() // point of vulnerability, someone can flush here
b.mutex.unlock() .
Lock Mutex
b.Remove():
b.mutex.lock()
if b.sb.Empty() {
b.cvar.wait() What a signal means:
} Mesa semantics (looser) vs Hoare Semantics (tighter)
x = b.sb.Remove()
b.mutex.unlock()
return x
b.Flush():
b.mutex.lock()
b.sb.Flush()
b.mutex.unlock()
14
Buffer using ConditionVars
b.Init(): // What happens
b.sb = NewBuf() Lock
b.mutex = 1 if !sb.empty() goto ready
b.cvar = NewCond(b.mutex) Unlock
wait for signal
b.Insert(x): Lock
b.mutex.lock()
if !sb.empty() goto ready
b.sb.Insert(x) Unlock
b.sb.Signal() wait for signal
b.mutex.unlock() Lock
. . .
b.Remove(): ready: Can safely assume have lock & that buffer nonempty
b.mutex.lock()
while b.sb.Empty() {
b.cvar.wait() // wait() Note that lock is first released & then retaken
} Atomically: release mutex & suspend operation
x = b.sb.Remove() When resume, lock mutex (but maybe not right away)
b.mutex.unlock()
return x
15