COP 4600 Operating Systems Fall 2010
Dan C. Marinescu
Office: HEC 439 B
Office hours: Tu-Th 3:30-4:30 PM
Last time: Discussion of the solutions for the midterm
Today: Presentation of the paper “Distributed object model of Java” Thread coordination with a bounded buffer. Semaphores Virtual memory
Next time Presentation of the paper “Cooperating sequential processes” Virtual memory
Lecture 21 – Tuesday November 2, 2010
Lecture 21 2
1 2 N-1N-2
out
in
Read from the bufferlocation
pointed by out
Write to the bufferlocation
pointed by out
shared structure buffer message instance message[N] integer in initially 0 integer out initially 0
procedure SEND (buffer reference p, message instance msg) while p.in – p.out = N do nothing /* if buffer full wait p.message [p.in modulo N] ß msg /* insert message into buffer cell p.in ß p.in + 1 /* increment pointer to next free cell
procedure RECEIVE (buffer reference p) while p.in = p.out do nothing /* if buffer empty wait for message msgß p.message [p.in modulo N] /* copy message from buffer cell p.out ß p.out + 1 /* increment pointer to next message return msg
0 1
Lecture 21 3
Implicit assumptions for the correctness of the implementation1. One sending and one receiving thread. Only one thread updates each
shared variable.
2. Sender and receiver threads run on different processors to allow spin locks
3. in and out are implemented as integers large enough so that they do not overflow (e.g., 64 bit integers)
4. The shared memory used for the buffer provides read/write coherence
5. The memory provides before-or-after atomicity for the shared variables in and out
6. The result of executing a statement becomes visible to all threads in program order. No compiler optimization supported
Lecture 21 4
time
Operations of Thread A
Buffer is empty
in=out=0
on=out=0
Fill entry 0 at time t1 with item b
0
Operations of Thread B
Fill entry 0 at time t2with item a
Increment pointer at time t3
inß 1
Increment pointer at time t4
inß 2
Two senders execute the code concurrently
Processor 1 runs thread A
Processor 2 runs thread B
Memory contains shared dataBuffer
Inout
Processor-memory bus
Item b is overwritten, it is lost
Lecture 21 5
time
Another manifestation of race conditions à incrementing a pointer is not atomic
in ß in+11. L R1,in
2. ADD R1,1
3. ST R1,in
Operations of Thread A
Operations of Thread B
A1 A2 A3
B1 B2 B3
inß 1 inß 2
Correct execution
Operations of Thread A
Operations of Thread B
A1 A2 A3
B1 B2 B3
inß 1 inß 1
Incorrect execution
Lecture 21 6
Lecture 6 77Lecture 21
1 2 N-1N-2
out
inRead from the bufferlocation pointed by out
Write to the bufferlocation pointed by out
shared structure buffer message instance message[N] integer in initially 0 integer out initially 0 lock instance buffer_lock initially UNLOCKED
procedure SEND (buffer reference p, message instance msg) ACQUIRE (p_buffer_lock) while p.in – p.out = N do /* if buffer full wait RELEASE (p_buffer_lock) YIELD() ACQUIRE (p_buffer_lock) p.message [p.in modulo N] ß msg /* insert message into buffer cell p.in ß p.in + 1 /* increment pointer to next free cell RELEASE (p_buffer_lock)
procedure RECEIVE (buffer reference p) ACQUIRE (p_buffer_lock) while p.in = p.out do /* if buffer empty wait for message RELEASE (p_buffer_lock) YIELD() ACQUIRE (p_buffer_lock) msgß p.message [p.in modulo N] /* copy message from buffer cell p.out ß p.out + 1 /* increment pointer to next message return msg
0 1
8Lecture 21
Lecture 21 9
shared structure buffer message instance message[N] integer in initially 0 integer out initially 0 lock instance buffer_lock initially UNLOCKED event instance room event instance notempty
procedure SEND (buffer reference p, message instance msg) ACQUIRE (p_buffer_lock) while p.in – p.out = N do /* if buffer full wait RELEASE (p_buffer_lock) WAIT (p.room) ACQUIRE (p_buffer_lock) p.message [p.in modulo N] ß msg /* insert message into buffer cell if p.in= p.out then NOTIFY(p.notempty) p.in ß p.in + 1 /* increment pointer to next free cell RELEASE (p_buffer_lock)
procedure RECEIVE (buffer reference p) ACQUIRE (p_buffer_lock) while p.in = p.out do /* if buffer empty wait for message RELEASE (p_buffer_lock) WAIT (p.notempty) ACQUIRE (p_buffer_lock) msgß p.message [p.in modulo N] /* copy message from buffer cell if (p.in- p.out=N) then NOTIFY(p.room) p.out ß p.out + 1 /* increment pointer to next message RELEASE (p_buffer_lock) return msg
This solution does not work
Lecture 21 10
The NOTIFY should always be sent after the WAIT. If the sender and the receiver run on two different processor there could be a race condition for the notempty event. The NOTIFY could be sent before the WAIT.
Tension between modularity and locks Several possible solutions: AWAIT/ADVANCE, semaphores, etc
AWAIT - ADVANCE solution A new state, WAITING and two before-or-after actions that take a
RUNNING thread into the WAITING state and back to RUNNABLE state. eventcount variables with an integer value shared between threads and
the thread manager; they are like events but have a value. A thread in the WAITING state waits for a particular value of the
eventcount AWAIT(eventcount,value)
If eventcount >value the control is returned to the thread calling AWAIT and this thread will continue execution
If eventcount ≤value the state of the thread calling AWAIT is changed to WAITING and the thread is suspended.
ADVANCE(eventcount) increments the eventcount by one then searches the thread_table for threads waiting for this eventcount if it finds a thread and the eventcount exceeds the value the thread is waiting for then
the state of the thread is changed to RUNNABLE
Lecture 21 11
Solution for a single sender and multiple receivers
Lecture 21 12
Supporting multiple senders: the sequencer
Sequencer shared variable supporting thread sequence coordination -it allows threads to be ordered and is manipulated using two before-or-after actions.
TICKET(sequencer) returns a negative value which increases by one at each call. Two concurrent threads calling TICKET on the same sequencer will receive different values based upon the timing of the call, the one calling first will receive a smaller value.
READ(sequencer) returns the current value of the sequencer
Lecture 21 13
Multiple sender solution; only the SEND must be modified
Lecture 21 14
Implementation of AWAIT and ADVANCE
Lecture 21 15
Semaphores
Introduced by Dijkstra in 1965 Does not require busy waiting Semaphore S – integer variable Two standard operations modify S: wait() and signal()
Originally called P() and V() Less complicated Can only be accessed via two indivisible (atomic) operations
wait (S) { while S <= 0
; // no-op S--; } signal (S) { S++; }
16Lecture 21
Lecture 21 17
shared structure buffer message instance message[N] eventcount instance in initially 0 eventcount instance out initially 0 sequencer instance sender
procedure SEND (buffer reference p, message instance msg) t ß TICKET(p.sender) AWAIT (p.in,t) AWAIT (p.out,READ(p.in) -N ) p.message [p.in modulo N] ß msg /* insert message into buffer cell ADVANCE (p.in)
Lecture 21 18
Lecture 21 19
Wait for graph
Lecture 21 20