![Page 1: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/1.jpg)
Synchronization
CSCI 3753 Operating Systems
Spring 2005
Prof. Rick Han
![Page 2: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/2.jpg)
Announcements
• HW #3 is online, due Friday Feb. 25 at 11 am
• PA #2 is coming, assigned next Tuesday
• Midterm is tentatively Thursday March 10
• Read chapter 8
![Page 3: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/3.jpg)
From last time...
• Many cases where processes and threads want to access shared common variables, buffers, etc.
• Producer-Consumer with a shared bounded buffer in between– Producer increments counter++– Consumer decrements counter--
• race conditions between producer and consumer– Machine-level instructions can be interleaved,
resulting in unpredictable value of shared counter variable
![Page 4: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/4.jpg)
Synchronization
while(1) { while(counter==MAX); buffer[in] = nextdata; in = (in+1) % MAX; counter++;}
Data
Bounded Buffer
counter
ProducerProcess
ConsumerProcess
while(1) { while(counter==0); getdata = buffer[out]; out = (out+1) % MAX; counter--;}
Producer writes new data intobuffer and increments counter
Consumer reads new data frombuffer and decrements counter
counterupdates
can conflict!
buffer[0]
buffer[MAX]
![Page 5: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/5.jpg)
Synchronization
counter++; can translate into several machine language instructions, e.g.
reg1 = counter;
reg1 = reg1 + 1;
counter = reg1;
counter--; can translate into several machine language instructions, e.g.
reg2 = counter;
reg2 = reg2 - 1;
counter = reg2;
If these low-level instructions are interleaved, e.g. the Producer processis context-switched out, and the Consumer process is context-switched in,and vice versa, then the results of counter’s value can be unpredictable
![Page 6: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/6.jpg)
Synchronization
// counter++ reg1 = counter; reg1 = reg1 + 1; counter = reg1;
// counter--;
reg2 = counter;
reg2 = reg2 - 1;
counter = reg2;
(1) [5](3) [6]
(2) [5](4) [4]
(5) [6]
(6) [4]
• Suppose we have the following sequence of interleaving, where the brackets [value] denote the local value of counter in either the producer or consumer’s process. Let counter=5 initially.
• At the end, counter = 4. But if steps (5) and (6) were reversed, then counter=6 !!!
• Value of shared variable counter changes depending upon (an arbitrary) order of writes - very undesirable!
![Page 7: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/7.jpg)
Critical Section• Kernel data structures - e.g. access to list of open files subject to
race condition• Kernel developer must ensure that no such race conditions occur• Identify critical sections in code where each process access shared
variables
do { entry section critical section (manipulate common var’s) exit section remainder code} while (1)
mutual exclusion, bounded waiting, progress
![Page 8: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/8.jpg)
Critical Section
• How do we protect access to critical sections?– want to prevent another process from
executing while current process is modifying this variable - mutual exclusion
– disable interrupts• bad, because I/O may be prevented• bad, because program may have an infinite loop
![Page 9: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/9.jpg)
Critical Section
• Don’t disable interrupts for the entire time you’re in the critical section
• Solution: Set a variable/flag called a lock to indicate that the critical section is busy, then unset the flag when critical section is done– doesn’t disable interrupts in the critical section– also Peterson’s solution
![Page 10: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/10.jpg)
Using a Lock Variableshared boolean lock = FALSE;shared int counter;
Code for p1 Code for p2
/* Acquire the lock */ /* Acquire the lock */ while(lock) ; while(lock) ; lock = TRUE; lock = TRUE;/* Execute critical sect */ /* Execute critical sect */ counter++; counter--;/* Release lock */ /* Release lock */ lock = FALSE; lock = FALSE;
![Page 11: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/11.jpg)
Busy Wait Conditionshared boolean lock = FALSE;shared int counter;
Code for p1 Code for p2
/* Acquire the lock */ /* Acquire the lock */ while(lock) ; while(lock) ; lock = TRUE; lock = TRUE;/* Execute critical sect */ /* Execute critical sect */ counter++; counter--;/* Release lock */ /* Release lock */ lock = FALSE; lock = FALSE;
p1
p2
Blo
cked
at while
lock = TRUE
lock = FALSE
Inte
rrup
t
Inte
rrup
t
Inte
rrup
t
![Page 12: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/12.jpg)
Unsafe “Solution”shared boolean lock = FALSE;shared double balance;
Code for p1 Code for p2
/* Acquire the lock */ /* Acquire the lock */ while(lock) ; while(lock) ; lock = TRUE; lock = TRUE;/* Execute critical sect */ /* Execute critical sect */ counter++; counter--;/* Release lock */ /* Release lock */ lock = FALSE; lock = FALSE;
• Worse yet … another race condition …
• Is it possible to solve the problem?
![Page 13: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/13.jpg)
Critical Section
while (lock==TRUE) ;lock = TRUE;
• test-and-set solution doesn’t work if process is interrupted right after while()
• Want an atomic instruction testandset() that tests shared variable lock then sets it
• Some hardware provides such an instruction
![Page 14: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/14.jpg)
Atomic Lock Manipulationshared boolean lock = FALSE;shared int counter;
Code for p1 Code for p2
/* Acquire the lock */ /* Acquire the lock */ while(TestandSet(&lock)) ; while(TestandSet(&lock)) ;
/* Execute critical sect */ /* Execute critical sect */ counter++; counter--;/* Release lock */ /* Release lock */ lock = FALSE; lock = FALSE;______________________________________________________________
boolean TestandSet(boolean *target) { // this is atomic, one machine instruction boolean rv = *target; *target = TRUE; return rv;}
![Page 15: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/15.jpg)
Atomic Lock Manipulation
• The system is exclusively occupied for only a short time - the time to test and set the lock, and not for entire critical section– about 10 instructions
• don’t have to disable and reenable interrupts - time-consuming
• disadvantage: requires user to put in while()• low level assembly language manipulation of a
machine instruction TS
![Page 16: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/16.jpg)
![Page 17: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/17.jpg)
Bounded Buffer Problem
ProducerProducer ConsumerConsumer
Empty Pool
Full Pool
![Page 18: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/18.jpg)
Bounded Buffer Problem (2)producer() { buf_type *next, *here; while(TRUE) { produce_item(next); /* Claim an empty */ P(empty); P(mutex); here = obtain(empty); V(mutex); copy_buffer(next, here); P(mutex); release(here, fullPool); V(mutex); /* Signal a full buffer */ V(full); }}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);
consumer() { buf_type *next, *here; while(TRUE) { /* Claim full buffer */ P(mutex); P(full); here = obtain(full); V(mutex); copy_buffer(here, next); P(mutex); release(here, emptyPool); V(mutex); /* Signal an empty buffer */ V(empty); consume_item(next); }}
![Page 19: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/19.jpg)
Bounded Buffer Problem (3)producer() { buf_type *next, *here; while(TRUE) { produce_item(next); /* Claim an empty */ P(empty); P(mutex); here = obtain(empty); V(mutex); copy_buffer(next, here); P(mutex); release(here, fullPool); V(mutex); /* Signal a full buffer */ V(full); }}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);
consumer() { buf_type *next, *here; while(TRUE) { /* Claim full buffer */ P(full); P(mutex); here = obtain(full); V(mutex); copy_buffer(here, next); P(mutex); release(here, emptyPool); V(mutex); /* Signal an empty buffer */ V(empty); consume_item(next); }}
![Page 20: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/20.jpg)
Readers-Writers Problem
Readers
Writers
![Page 21: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/21.jpg)
Readers-Writers Problem (2)
ReaderReader
Shared Resource
ReaderReaderReaderReader
ReaderReaderReaderReaderReaderReader
ReaderReaderReaderReader
WriterWriterWriterWriterWriterWriter
WriterWriterWriterWriterWriterWriter
WriterWriter
![Page 22: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/22.jpg)
Readers-Writers Problem (3)
ReaderReader
Shared Resource
ReaderReaderReaderReaderReaderReaderReaderReader
ReaderReaderReaderReaderReaderReader
WriterWriterWriterWriterWriterWriter
WriterWriterWriterWriterWriterWriter
WriterWriter
![Page 23: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/23.jpg)
Readers-Writers Problem (4)
ReaderReader
Shared Resource
ReaderReaderReaderReader
ReaderReaderReaderReaderReaderReader
ReaderReaderReaderReader
WriterWriterWriterWriterWriterWriter
WriterWriterWriterWriterWriterWriter
WriterWriter
![Page 24: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/24.jpg)
First Solutionreader() { while(TRUE) { <other computing>; P(mutex); readCount++; if(readCount == 1) P(writeBlock); V(mutex); /* Critical section */ access(resource); P(mutex); readCount--; if(readCount == 0) V(writeBlock); V(mutex); }}resourceType *resource;int readCount = 0;semaphore mutex = 1;semaphore writeBlock = 1;fork(reader, 0);fork(writer, 0);
writer() { while(TRUE) { <other computing>; P(writeBlock); /* Critical section */ access(resource); V(writeBlock); }}
•First reader competes with writers•Last reader signals writers
![Page 25: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/25.jpg)
First Solution (2)reader() { while(TRUE) { <other computing>; P(mutex); readCount++; if(readCount == 1) P(writeBlock); V(mutex); /* Critical section */ access(resource); P(mutex); readCount--; if(readCount == 0) V(writeBlock); V(mutex); }}resourceType *resource;int readCount = 0;semaphore mutex = 1;semaphore writeBlock = 1;fork(reader, 0);fork(writer, 0);
writer() { while(TRUE) { <other computing>; P(writeBlock); /* Critical section */ access(resource); V(writeBlock); }}
•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
![Page 26: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/26.jpg)
Writer Precedencereader() { while(TRUE) { <other computing>;
P(readBlock); P(mutex1); readCount++; if(readCount == 1) P(writeBlock); V(mutex1); V(readBlock);
access(resource); P(mutex1); readCount--; if(readCount == 0) V(writeBlock); V(mutex1); }}int readCount = 0, writeCount = 0;semaphore mutex = 1, mutex2 = 1;semaphore readBlock = 1, writeBlock = 1, writePending = 1;fork(reader, 0);fork(writer, 0);
writer() { while(TRUE) { <other computing>; P(mutex2); writeCount++; if(writeCount == 1) P(readBlock); V(mutex2); P(writeBlock); access(resource); V(writeBlock); P(mutex2) writeCount--; if(writeCount == 0) V(readBlock); V(mutex2); }}
1
23
4
![Page 27: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/27.jpg)
Writer Precedence (2)reader() { while(TRUE) { <other computing>; P(writePending); P(readBlock); P(mutex1); readCount++; if(readCount == 1) P(writeBlock); V(mutex1); V(readBlock); V(writePending); access(resource); P(mutex1); readCount--; if(readCount == 0) V(writeBlock); V(mutex1); }}int readCount = 0, writeCount = 0;semaphore mutex = 1, mutex2 = 1;semaphore readBlock = 1, writeBlock = 1, writePending = 1;fork(reader, 0);fork(writer, 0);
writer() { while(TRUE) { <other computing>; P(mutex2); writeCount++; if(writeCount == 1) P(readBlock); V(mutex2); P(writeBlock); access(resource); V(writeBlock); P(mutex2) writeCount--; if(writeCount == 0) V(readBlock); V(mutex2); }}
1
23
4
![Page 28: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/28.jpg)
The Sleepy Barber
Waiting Room
Entrance to WaitingRoom (sliding door)
Entrance to Barber’sRoom (sliding door)
Shop Exit
• Barber can cut one person’s hair at a time
• Other customers wait in a waiting room
![Page 29: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/29.jpg)
Sleepy Barber (aka Bounded Buffer)customer() {
while(TRUE) { customer = nextCustomer(); if(emptyChairs == 0) continue; P(chair); P(mutex); emptyChairs--; takeChair(customer); V(mutex); V(waitingCustomer); }}
semaphore mutex = 1, chair = N, waitingCustomer = 0;int emptyChairs = N;fork(customer, 0);fork(barber, 0);
barber() { while(TRUE) { P(waitingCustomer); P(mutex); emptyChairs++; takeCustomer(); V(mutex); V(chair); }}
![Page 30: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/30.jpg)
Cigarette Smoker’s Problem
• Three smokers (processes)
• Each wish to use tobacco, papers, & matches– Only need the three resources periodically– Must have all at once
• 3 processes sharing 3 resources– Solvable, but difficult
![Page 31: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/31.jpg)
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
![Page 32: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/32.jpg)
Implementing Semaphores:enter() & exit()
class semaphore { int value;public: semaphore(int v = 1) { value = v;}; P(){ disableInterrupts(); while(value == 0) { enableInterrupts(); disableInterrupts(); } value--; enableInterrupts(); }; V(){ disableInterrupts(); value++; enableInterrupts(); };};
![Page 33: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/33.jpg)
Implementing Semaphores:Test and Set Instruction
FALSEm
PrimaryMemory
…R3 …
DataRegister
CCRegister
(a) Before Executing TS
TRUEm
PrimaryMemory
FALSER3 =0
DataRegister
CCRegister
(b) After Executing TS
• TS(m): [Reg_i = memory[m]; memory[m] = TRUE;]
![Page 34: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/34.jpg)
Using the TS Instruction
boolean s = FALSE; . . . while(TS(s)) ; <critical section> s = FALSE; . . .
semaphore s = 1; . . . P(s) ; <critical section> V(s); . . .
![Page 35: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/35.jpg)
Implementing the General Semaphore
struct semaphore { int value = <initial value>; boolean mutex = FALSE; boolean hold = TRUE;};
shared struct semaphore s;
P(struct semaphore s) { while(TS(s.mutex)) ; s.value--; if(s.value < 0) ( s.mutex = FALSE; while(TS(s.hold)) ; } else s.mutex = FALSE;}
V(struct semaphore s) { while(TS(s.mutex)) ; s.value++; if(s.value <= 0) ( while(!s.hold) ; s.hold = FALSE; } s.mutex = FALSE;}
![Page 36: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/36.jpg)
Active vs Passive Semaphores• A process can dominate the semaphore
– Performs V operation, but continues to execute
– Performs another P operation before releasing the CPU
– Called a passive implementation of V
• Active implementation calls scheduler as part of the V operation.– Changes semantics of semaphore!– Cause people to rethink solutions
![Page 37: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/37.jpg)
Atomic Lock Manipulation
shared double balance;
shared int lock = FALSE;
P1
enter(lock);
counter++;
exit(lock);
P2
enter(lock); // atomic system call
counter--;
exit(lock);
![Page 38: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/38.jpg)
Atomic Lock Manipulation
enter(lock) { exit(lock) { disableInterrupts(); disableInterrupts();/* Loop until lock is TRUE */ lock = FALSE; while(lock) { enableInterrupts(); /* Let interrupts occur */ } enableInterrupts(); disableInterrupts(); } lock = TRUE; enableInterrupts();}
• 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 …
![Page 39: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/39.jpg)
![Page 40: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/40.jpg)
Critical Section
do { flag[i] = TRUE
turn = j; while (flag[j] && turn==j);
critical section
flag[i] = FALSE
remainder section
} while (TRUE)
![Page 41: Synchronization CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han](https://reader035.vdocuments.mx/reader035/viewer/2022062304/56649d3b5503460f94a162bd/html5/thumbnails/41.jpg)
Critical Section
• Solution: instead disable only on entry and exit. Use a shared variable to control access to another shared variable.– this introduces complexity - what if you’re
interrupted while having the lock?