17.04.2014 Views

Semaphores, bounded-buffer

Semaphores, bounded-buffer

Semaphores, bounded-buffer

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Oct 2, 2000<br />

• Processes and concurrent programming<br />

– Synchronization and communication<br />

– Higher-level primitives<br />

Operating System Concepts<br />

Silberschatz and Galvin ©1999<br />

1.28<br />

CS134a, 2000


Peterson’s algorithm<br />

• Use both turn and critical section flags<br />

bool c1 = true;<br />

bool c2 = true;<br />

int turn;<br />

cobegin<br />

while(true) {<br />

c1 = false;<br />

turn = 1;<br />

while(!c2 && turn = 1); // busy wait<br />

critical_section_1;<br />

c1 = true;<br />

program_1;<br />

} | ...<br />

coend<br />

Operating System Concepts<br />

Silberschatz and Galvin ©1999<br />

1.29<br />

CS134a, 2000


Multi-process mutual exclusion<br />

• n processes, numbered 0...n-1<br />

• Bakery algorithm: when entering the critical section<br />

– Take a number and wait<br />

– Can’t guarantee that numbers are distinct<br />

✴ Process with lowest process-id goes first<br />

Operating System Concepts<br />

Silberschatz and Galvin ©1999<br />

1.30<br />

CS134a, 2000


Bakery algorithm<br />

bool choosing[n]; // initially false<br />

int number[n]; // initially 0<br />

cobegin<br />

/* process i */<br />

while(true) {<br />

choosing[i] = true;<br />

number[i] = max(number[0], ..., number[n]) + 1;<br />

choosing[i] = false;<br />

for(j = 0; j != i; j++) {<br />

while(choosing[j]); // busy wait<br />

while(number[j] && number[j]


Problems with these algorithms<br />

• Solutions are complex and awkward<br />

• Too much time spent in the busy wait<br />

Operating System Concepts<br />

Silberschatz and Galvin ©1999<br />

1.32<br />

CS134a, 2000


<strong>Semaphores</strong> (Dijkstra 1965)<br />

• Slightly more abstract primitives<br />

• A semaphore is a non-negative integer variable with two<br />

atomic operations:<br />

– Passeren (wait): P(s) decrements s by 1 if possible,<br />

otherwise it waits until s becomes positive, then<br />

decrements it.<br />

– Verhogen (signal): V(s) increments s by one.<br />

• The operations are atomic: no other process is allowed to<br />

access the semaphore during a P or V operation, unless<br />

the P operation is blocked.<br />

Operating System Concepts<br />

Silberschatz and Galvin ©1999<br />

1.33<br />

CS134a, 2000


Mutual-exclusion with semaphores<br />

• Semaphore s;<br />

V(s); // increment the semaphore initially<br />

...<br />

P(s);<br />

critical section;<br />

V(s);<br />

...<br />

Operating System Concepts<br />

Silberschatz and Galvin ©1999<br />

1.34<br />

CS134a, 2000


The producer/consumer problem<br />

Producer<br />

Buffer<br />

Consumer<br />

Semaphore s = new Semaphore();<br />

cobegin<br />

/* Producer */<br />

while(true) {<br />

produce;<br />

V(s);<br />

} |<br />

/* Consumer */<br />

while(true) {<br />

P(s);<br />

consume;<br />

}<br />

coend<br />

Operating System Concepts<br />

Silberschatz and Galvin ©1999<br />

1.35<br />

CS134a, 2000


The <strong>bounded</strong>-<strong>buffer</strong> problem (Dijkstra 1968)<br />

• A producer produces data and adds it to a <strong>buffer</strong>.<br />

• A consumer consumes data from the <strong>buffer</strong>.<br />

• The <strong>buffer</strong> contains room for n values.<br />

Operating System Concepts<br />

Silberschatz and Galvin ©1999<br />

1.36<br />

CS134a, 2000


The <strong>bounded</strong>-<strong>buffer</strong> algorithm<br />

Semaphore e(n); // number of empty <strong>buffer</strong>s<br />

Semaphore f(0); // number of full <strong>buffer</strong>s<br />

Semaphore b(1); // critical section<br />

cobegin<br />

while(true) {<br />

produce;<br />

P(e); P(b);<br />

add to <strong>buffer</strong>;<br />

V(b); V(f);<br />

} |<br />

while(true) {<br />

P(f); P(b);<br />

take from <strong>buffer</strong>;<br />

V(b); V(e);<br />

consume;<br />

}<br />

coend<br />

Operating System Concepts<br />

Silberschatz and Galvin ©1999<br />

1.37<br />

CS134a, 2000


Implementing semaphores<br />

• Most CPUs have an atomic test-and-set instruction, or<br />

atomic exchange:<br />

int ts(int *x) { int y = *x; *x = 1; return y; }<br />

int xchg(int *x, int *y) { int z = *x; *x = *y; *y = z; }<br />

• This is used to implement a binary semaphore<br />

• void Pb(&sb) {<br />

do {<br />

int key = 0;<br />

exch(&key, sb);<br />

} while(!key);<br />

}<br />

• void Vb(&sb) { sb = 1; }<br />

Operating System Concepts<br />

Silberschatz and Galvin ©1999<br />

1.38<br />

CS134a, 2000


Exchange instruction<br />

XCHG—Exchange Register/Memory with Register<br />

INSTRUCTION SET REFERENCE<br />

Opcode Instruction Description<br />

87 /r XCHG r32,r/m32 Exchange doubleword from r/m32 with<br />

Description<br />

This instruction exchanges the contents of the destination (first) and source (second) operands.<br />

The operands can be two general-purpose registers or a register and a memory location. If a<br />

memory operand is referenced, the processor’s locking protocol is automatically implemented<br />

for the duration of the exchange operation, regardless of the presence or absence of the LOCK<br />

prefix or of the value of the IOPL. Refer to the LOCK prefix description in this chapter for more<br />

information on the locking protocol.<br />

This instruction is useful for implementing semaphores or similar data structures for process<br />

synchronization. Refer to Section 7.1.2., Bus Locking in Chapter 7, Multiple-Processor<br />

Management of the Intel Architecture Software Developer’s Manual, Volume 3, for more information<br />

on bus locking.<br />

The XCHG instruction can also be used instead of the BSWAP instruction for 16-bit operands.<br />

Operation<br />

TEMP ← DEST<br />

DEST ← SRC<br />

SRC ← TEMP<br />

Flags Affected<br />

None.<br />

Operating System Concepts<br />

Silberschatz and Galvin ©1999<br />

1.39<br />

CS134a, 2000


Normal semaphore<br />

• A normal semaphore has an integer, and two binary<br />

semaphores<br />

• struct Semaphore {<br />

int value;<br />

BinarySemaphore mutex, delay;<br />

}<br />

• P(Semaphore &s) {<br />

disable interrupts;<br />

Pb(s.mutex);<br />

s.value--; // decrement s.value by 1<br />

if(s.value < 0) { Vb(s.mutex); Pb(s.delay); }<br />

Vb(s.mutex);<br />

enable interrupts;<br />

}<br />

Operating System Concepts<br />

Silberschatz and Galvin ©1999<br />

1.40<br />

CS134a, 2000


Problems with semaphores<br />

• Still too low-level<br />

• Semaphore operations are scattered through code<br />

• P and V are used in pairs: how do you know which<br />

pairs match?<br />

Operating System Concepts<br />

Silberschatz and Galvin ©1999<br />

1.41<br />

CS134a, 2000

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!