Slide 8 1 Copyright 2004 Pearson Education Inc







































![Implementing Semaphores: Test and Set Instruction Slide 8 -40 • TS(m): [Reg_i = memory[m]; Implementing Semaphores: Test and Set Instruction Slide 8 -40 • TS(m): [Reg_i = memory[m];](https://slidetodoc.com/presentation_image_h/79cc05f852f655414f0fb8301aa1fb4a/image-40.jpg)


- Slides: 42
Slide 8 -1 Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8
Slide 8 -2 Basic Synchronization Principles Copyright © 2004 Pearson Education, Inc. 8 Operating Systems: A Modern Perspective, Chapter 8
Concurrency • Value of concurrency – speed & economics • But few widely-accepted concurrent programming languages (Java is an exception) • Few concurrent programming paradigm – Each problem requires careful consideration – There is no common model • OS tools to support concurrency tend to be “low level” Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8 Slide 8 -3
Command Execution Enter Loop Slide 8 -4 Enter Loop Another Command? No Yes Exit Loop fork()code Execute Command Yes Another Command? No Exit Loop Create. Process()code … Execute Command Wait for Child to Terminate (a) UNIX Shell Copyright © 2004 Pearson Education, Inc. (b) Windows Command Launch Operating Systems: A Modern Perspective, Chapter 8
Synchronizing Multiple Threads with a Shared Variable Slide 8 -5 Initialize Exit Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8 TRUE Terminate … FALSE run. Flag? FALSE run. Flag=FALSE Thread Work FALSE Wait run. Time seconds TRUE Create. Thread(…)
Traffic Intersections Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8 Slide 8 -6
Critical Sections Slide 8 -7 shared double balance; Code for p 1 Code for p 2 . . . balance = balance + amount; . . . balance = balance - amount; . . . balance+=amount balance-=amount balance Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8
Critical Sections (2) Execution of p 1 … load R 1, balance load R 2, amount Timer interrupt add R 1, R 2 store R 1, balance … Copyright © 2004 Pearson Education, Inc. Slide 8 -8 Execution of p 2 … load sub store … R 1, R 2, R 1, Operating Systems: A Modern Perspective, Chapter 8 balance amount R 2 balance
Critical Sections (3) • Mutual exclusion: Only one process can be in the critical section at a time • There is a race to execute critical sections • The sections may be defined by different code in different processes – cannot easily detect with static analysis • Without mutual exclusion, results of multiple execution are not determinate • Need an OS mechanism so programmer can resolve races Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8 Slide 8 -9
Some Possible Solutions Slide 8 -10 • Disable interrupts • Software solution – locks • Transactions • FORK(), JOIN(), and QUIT() [Chapter 2] – Terminate processes with QUIT() to synchronize – Create processes whenever critical section is complete – See Figure 8. 7 • … something new … Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8
Disabling Interrupts Slide 8 -11 shared double balance; Code for p 1 disable. Interrupts(); balance = balance + amount; enable. Interrupts(); Code for p 2 disable. Interrupts(); balance = balance - amount; enable. Interrupts(); • Interrupts could be disabled arbitrarily long • Really only want to prevent p 1 and p 2 from interfering with one another; this blocks all pi • Try using a shared “lock” variable Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8
Using a Lock Variable Slide 8 -12 shared boolean lock = FALSE; shared double balance; Code for p 1 Code for p 2 /* Acquire the lock */ L 1: while(lock) ; L 5: while(lock) ; L 2: lock = TRUE; L 6: lock = TRUE; /* Execute critical sect */ L 3: balance = balance + amount; L 7: balance = balance amount; /* Release lock */ L 4: lock = FALSE; L 8: lock = FALSE; Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8
Busy Wait Condition Slide 8 -13 shared boolean lock = FALSE; shared double balance; Code for p 1 Code for p 2 Copyright © 2004 Pearson Education, Inc. Interrupt lock = FALSE Interrupt lock = TRUE p 2 p 1 /* Acquire the lock */ while(lock) ; lock = TRUE; /* Execute critical sect */ balance = balance - amount; /* Release lock */ lock = FALSE; Blocked at while /* Acquire the lock */ while(lock) ; lock = TRUE; /* Execute critical sect */ balance = balance + amount; /* Release lock */ lock = FALSE; Operating Systems: A Modern Perspective, Chapter 8
Unsafe “Solution” Slide 8 -14 shared boolean lock = FALSE; shared double balance; Code for p 1 /* Acquire the lock */ while(lock) ; lock = TRUE; /* Execute critical sect */ balance = balance + amount; /* Release lock */ lock = FALSE; Code for p 2 /* Acquire the lock */ while(lock) ; lock = TRUE; /* Execute critical sect */ balance = balance - amount; /* Release lock */ lock = FALSE; • Worse yet … another race condition … • Is it possible to solve the problem? Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8
Atomic Lock Manipulation enter(lock) { L 1: disable. Interrupts(); /* Loop until lock is TRUE */ L 2: while(lock) { /* Let interrupts occur */ L 3: enable. Interrupts(); L 4: disable. Interrupts(); } L 5: lock = TRUE; L 6: enable. Interrupts(); } exit(lock) { L 7: disable. Interrupts(); L 8: lock = FALSE; L 9: enable. Interrupts(); } • Bound the amount of time that interrupts are disabled • Can include other code to check that it is OK to assign a lock • … but this is still overkill … Copyright © 2004 Pearson Education, Inc. Slide 8 -15 Operating Systems: A Modern Perspective, Chapter 8
Slide 8 -16 Fig 8 -9: Deadlocked Pirates Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8
Deadlock (2) Slide 8 -17 shared boolean lock 1 = FALSE; shared boolean lock 2 = FALSE; shared list L; Code for p 1 . . . /* Enter CS to delete elt */ L 1: enter(lock 1); L 2: <delete element>; L 3: <intermediate computation>; /* Enter CS to update len */ L 4: enter(lock 2); L 5: <update length>; /* Exit both CS */ L 6: exit(lock 1); L 7: exit(lock 2); . . . Copyright © 2004 Pearson Education, Inc. Code for p 2 . . . /* Enter CS to update len */ L 8: enter(lock 2); L 9: <update length>; L 10: <intermediate omputation> /* Enter CS to add elt */ L 11: enter(lock 1); L 12: <add element>; /* Exit both CS */ L 13: exit(lock 2); L 14: exit(lock 1); . . . Operating Systems: A Modern Perspective, Chapter 8
Processing Two Components Slide 8 -18 shared boolean lock 1 = FALSE; shared boolean lock 2 = FALSE; shared list L; Code for p 1 . . . /* Enter CS to delete elt */ enter(lock 1); <delete element>; /* Exit CS */ exit(lock 1); <intermediate computation>; /* Enter CS to update len */ enter(lock 2); <update length>; /* Exit CS */ exit(lock 2); . . . Copyright © 2004 Pearson Education, Inc. Code for p 2 . . . /* Enter CS to update len */ enter(lock 2); <update length>; /* Exit CS */ exit(lock 2); <intermediate computation> /* Enter CS to add elt */ enter(lock 1); <add element>; /* Exit CS */ exit(lock 1); . . . Operating Systems: A Modern Perspective, Chapter 8
Transactions • A transaction is a list of operations – When the system begins to execute the list, it must execute all of them without interruption, or – It must not execute any at all • Example: List manipulator – Add or delete an element from a list – Adjust the list descriptor, e. g. , length • Too heavyweight – need something simpler Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8 Slide 8 -19
A Semaphore Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8 Slide 8 -20
Dijkstra Semaphore Slide 8 -21 • Invented in the 1960 s • Conceptual OS mechanism, with no specific implementation defined (could be enter()/exit()) • Basis of all contemporary OS synchronization mechanisms Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8
Solution Constraints Slide 8 -22 • Processes p 0 & p 1 enter critical sections • Mutual exclusion: Only one process at a time in the CS • Only processes competing for a CS are involved in resolving who enters the CS • Once a process attempts to enter its CS, it cannot be postponed indefinitely • After requesting entry, only a bounded number of other processes may enter before the requesting process Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8
Notation Slide 8 -23 • Let fork(proc, N, arg 1, arg 2, …, arg. N)be a command to create a process, and to have it execute using the given N arguments • Canonical problem: Proc_0() { while(TRUE) { <compute section>; <critical section>; } } proc_1() { while(TRUE { <compute section>; <critical section>; } } <shared global declarations> <initial processing> fork(proc_0, 0); fork(proc_1, 0); Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8
Solution Assumptions • Memory read/writes are indivisible (simultaneous attempts result in some arbitrary order of access) • There is no priority among the processes • Relative speeds of the processes/processors is unknown • Processes are cyclic and sequential Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8 Slide 8 -24
Dijkstra Semaphore Definition Slide 8 -25 • Classic paper describes several software attempts to solve the problem (see problem 4, Chapter 8) • Found a software solution, but then proposed a simpler hardware-based solution • A semaphore, s, is a nonnegative integer variable that can only be changed or tested by these two indivisible functions: V(s): [s = s + 1] P(s): [while(s == 0) {wait}; s = s - 1] Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8
Solving the Canonical Problem Proc_0() { while(TRUE) { <compute section>; P(mutex); <critical section>; V(mutex); } } proc_1() { while(TRUE { <compute section>; P(mutex); <critical section>; V(mutex); } } semaphore mutex = 1; fork(proc_0, 0); fork(proc_1, 0); Copyright © 2004 Pearson Education, Inc. Slide 8 -26 Operating Systems: A Modern Perspective, Chapter 8
Shared Account Balance Problem Proc_0() {. . . /* Enter the CS */ P(mutex); balance += amount; V(mutex); . . . } proc_1() {. . . /* Enter the CS */ P(mutex); balance -= amount; V(mutex); . . . } semaphore mutex = 1; fork(proc_0, 0); fork(proc_1, 0); Copyright © 2004 Pearson Education, Inc. Slide 8 -27 Operating Systems: A Modern Perspective, Chapter 8
Sharing Two Variables Slide 8 -28 proc_A() { proc_B() { L 1: while(TRUE) { L 8: while(TRUE) { L 2: <compute section A 1>; /* Wait for proc_A */ L 3: update(x); L 9: P(s 1); /* Signal proc_B */ L 10: retrieve(x); L 4: V(s 1); L 11: <compute section B 1>; L 5: <compute section A 2>; L 12: update(y); /* Wait for proc_B */ /* Signal proc_A */ L 6: P(s 2); L 13: V(s 2); L 7: retrieve(y); L 14: <compute section B 2>; } } semaphore s 1 = 0; semaphore s 2 = 0; fork(proc_A, 0); fork(proc_B, 0); Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8
Device Controller Synchronization Slide 8 -29 • The semaphore principle is logically used with the busy and done flags in a controller • Driver signals controller with a V(busy), then waits for completion with P(done) • Controller waits for work with P(busy), then announces completion with V(done) • Check Figure 8. 17 of the textbook Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8
Bounded Buffer Problem Empty Pool Producer Consumer Full Pool Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8 Slide 8 -30
Bounded Buffer Problem (3) Slide 8 -31 producer() { consumer() { buf_type *next, *here; L 1 while(TRUE) { L 12 while(TRUE) { L 2 produce_item(next); /* Claim full buffer */ /* Claim an empty */ L 13 P(full); L 3 P(empty); L 14 P(mutex); L 15 here = obtain(full); L 5 here = obtain(empty); L 16 V(mutex); L 17 copy_buffer(here, next); L 7 copy_buffer(next, here); L 18 P(mutex); L 19 release(here, empty. Pool); L 9 release(here, full. Pool); L 20 V(mutex); L 10 V(mutex); /* Signal an empty buffer */ /* Signal a full buffer */ L 21 V(empty); L 11 V(full); L 22 consume_item(next); } } semaphore mutex = 1; semaphore full = 0; /* A general (counting) semaphore */ semaphore empty = N; /* A general (counting) semaphore */ buf_type buffer[N]; fork(producer, 0); fork(consumer, 0); Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8
Readers-Writers Problem Slide 8 -32 Writers Readers Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8
Readers-Writers Problem (2) Reader Reader Writer Writer Shared Resource Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8 Slide 8 -33
Readers-Writers Problem (3) Writer Writer Reader Reader Shared Resource Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8 Slide 8 -34
Readers-Writers Problem (4) Reader Reader Writer Writer Shared Resource Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8 Slide 8 -35
First Solution reader() { L 1 while(TRUE) { L 2 <other computing>; L 3 P(mutex); L 4 read. Count++; L 5 if(read. Count == 1) L 6 P(write. Block); L 7 V(mutex); /* Critical section */ L 8 access(resource); L 9 P(mutex); L 10 read. Count--; L 11 if(read. Count == 0) L 12 V(write. Block); L 13 V(mutex); } } resource. Type *resource; int read. Count = 0; semaphore mutex = 1; semaphore write. Block = 1; fork(reader, 0); fork(writer, 0); Copyright © 2004 Pearson Education, Inc. Slide 8 -36 writer() { L 14 while(TRUE) { L 15 <other computing>; L 16 P(write. Block); /* Critical section */ L 17 access(resource); L 18 V(write. Block); } } • First reader competes with writers • Last reader signals writers Operating Systems: A Modern Perspective, Chapter 8
First Solution (2) reader() { while(TRUE) { <other computing>; P(mutex); read. Count++; if(read. Count == 1) P(write. Block); V(mutex); /* Critical section */ access(resource); P(mutex); read. Count--; if(read. Count == 0) V(write. Block); V(mutex); } } resource. Type *resource; int read. Count = 0; semaphore mutex = 1; semaphore write. Block = 1; fork(reader, 0); fork(writer, 0); Copyright © 2004 Pearson Education, Inc. Slide 8 -37 writer() { while(TRUE) { <other computing>; P(write. Block); /* Critical section */ access(resource); V(write. Block); } } • First reader competes with writers • Last reader signals writers • Any writer must wait for all readers • Readers can starve writers • “Updates” can be delayed forever • May not be what we want Operating Systems: A Modern Perspective, Chapter 8
Implementing Semaphores • Minimize effect on the I/O system • Processes are only blocked on their own critical sections (not critical sections that they should not care about) • If disabling interrupts, be sure to bound the time they are disabled Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8 Slide 8 -38
Implementing Semaphores: enter() & exit() class semaphore { int value; public: semaphore(int v = 1) { value = v; }; P(){ disable. Interrupts(); while(value == 0) { enable. Interrupts(); disable. Interrupts(); } value--; enable. Interrupts(); }; V(){ disable. Interrupts(); value++; enable. Interrupts(); }; }; Copyright © 2004 Pearson Education, Inc. Operating Systems: A Modern Perspective, Chapter 8 Slide 8 -39
Implementing Semaphores: Test and Set Instruction Slide 8 -40 • TS(m): [Reg_i = memory[m]; memory[m] = TRUE; ] Data CC Register R 3 … m … FALSE Primary Memory (a) Before Executing TS Copyright © 2004 Pearson Education, Inc. Data CC Register R 3 FALSE m =0 TRUE Primary Memory (b) After Executing TS Operating Systems: A Modern Perspective, Chapter 8
Using the TS Instruction boolean s = FALSE; . . . while(TS(s)) ; <critical section> s = FALSE; . . . Copyright © 2004 Pearson Education, Inc. semaphore s = 1; . . . P(s) ; <critical section> V(s); . . . Operating Systems: A Modern Perspective, Chapter 8 Slide 8 -41
Implementing the General Semaphore Slide 8 -42 struct semaphore { int value = <initial value>; boolean mutex = FALSE; boolean hold = TRUE; }; shared struct semaphore s; P(struct semaphore s) { L 1 while(TS(s. mutex)) ; L 2 s. value--; L 3 if(s. value < 0) ( L 4 s. mutex = FALSE; L 5 while(TS(s. hold)) ; } else L 6 s. mutex = FALSE; } Copyright © 2004 Pearson Education, Inc. V(struct semaphore s) { L 7 while(TS(s. mutex)) ; L 8 s. value++; L 9 if(s. value <= 0) ( L 10 while(!s. hold) ; L 11 s. hold = FALSE; } L 12 s. mutex = FALSE; } Operating Systems: A Modern Perspective, Chapter 8