Upload
stuart-brandon-merritt
View
221
Download
0
Embed Size (px)
Citation preview
CIS 5512 - Operating SystemsSynchronization
Professor Qiang Zeng
Fall 2015
CIS 5512 – Operating Systems 2
Previous class…
• IPC– Pipes– FIFO (named pipes)– message queues– shared memory
• Concepts– Race condition, critical section, mutual exclusion
• Synchronization primitives
CIS 5512 – Operating Systems 3
Compare different IPCs
IPC method Features
Pipes Can only be used among parent and child
FIFOs(named pipes)
Can be referred to by a string, so doesn’t have the limitation above
Message queues Unlike Pipes and FIFOs, they support message boundary and message types
Shared memory Data passing doesn’t go through kernel, so it is usually the most efficient one
Concepts: race condition, critical section, and mutual exclusion
lock();
counter++ //critical section
unlock();
What goes here?
The code below is run simultaneously in multiple threads/processesRace condition exists unless…
Big picture of synchronization primitives
Spin locks (busy-waiting locks)
Algorithms that do not rely on special instructions (Dekker’, Peterson’s, Bakery)
Algorithms based on atomic read-modify-write instructions (test-and-set, xchg)
CIS 5512 – Operating Systems 6
Solutions based on atomic read-modify-write instructions
test_and_set(int* p){ int t = *p; *p = 1; return t;}
enter_region() { while(test_and_set(&lock) == 1) ;}
leave_region() { lock = 0;}
Big picture of synchronization primitives
7
Sync. Primitives(or loosely, “locks”)
Spin locks (busy-waiting locks)
Semaphore: it contains an internal counter indicating the number of resources; API: down()/up() (or, sem_wait/sem_signal)Binary Semaphore is a special semaphore, whose counter value can only be 0 or 1; sometimes it is used as a mutex
Conditional Variables: they are used to ease concurrent programming. You have to use it with a mutex. Monitor encapsulates CV and mutex
Blocking locks
Algorithms that do not rely on special instructions (Dekker’, Peterson’s, Bakery)
Algorithms based on atomic read-modify-write instructions (test-and-set, xchg)
CIS 5512 – Operating Systems 8
Semaphore – avoids busy-waiting
// Atomicdown(S) { // or, P(), sem_wait() if(S.cnt>0) S.cnt--; else put the current process in queue; block the current process;}
// Atomicup(S) { // or, V(), sem_signal() if(any process is in S’s wait queue) remove a process from the queue; resume it; else S.cnt++;}
Using Mutexs and Semaphores:The restroom problem and the bar problem
Binary Semaphore for the restroom problem: mutual exclusion
• Customers try to enter a single-spot restroom• please write code describing the customers• Hint: Binary Semaphore, a special semaphore,
whose counter value can only be 0 or 1• Here, Binary Semaphore is used as Mutex, a
blocking lock for MUTual EXclusion
S = 1; // shared among customers (processes)
// each customer (process) does the followingdown(S); // try to enter the restroom; = lock()Use the restroom //critical sectionup(S); // leave the restroom; = unlock()
CIS 5512 – Operating Systems 11
Semaphore for the bar problem
• Capacity = 100• Many customers try to enter the bar concurrently• Please write code describing the customers• Caution: a Mutex will not work well; why?
S = 100; // shared among processes
// each process does the followingdown(S); // try to enter the barHave fun; up(S); // leave the bar
Using Semaphores:A simple signaling problem
Semaphore for signaling
• Process 0 and Process 1• How to make sure statement A in Process 0 gets
executed before statement B in Process 1• Hint: use a semaphore and initialize it as 0
S = 0; // shared
// Process 0A;up(S);
// Process 1down(S);B;
CIS 5512 – Operating Systems 14
Semaphore for signaling
• How to make sure event A1 in Process 0 occurs before B1 in Process 1, and B2 in Process 1 occurs before A2 in Process 0?
• Hint: use two semaphores
S1 = 0; // sharedS2 = 0; // shared
// Process 0A1;up(S1);down(S2);A2;
// Process 1down(S1);B1;B2;up(S2);
CIS 5512 – Operating Systems 15
Single-slot Producer-Consumer problem
• Hint:– Consumer.removeItem() has to occur after
Producer.fillSlot()– Producer.fillSlot(), once the slot is filled, has to occur
after Consumer.removeItem()S_slot = 1; // sharedS_item = 0; // shared
// Producerwhile(true) { down(S_slot); fillSlot(); up(S_item);}
// Consumerwhile(true) { down(S_item); removeItem(); up(S_slot);}
Using Semaphores:The Producer-Consumer
Problem
Acknowledgement: some slides courtesy of Dr. Brighten Godfrey
Producer-consumer problem
• Chefs cook items and put them on a conveyer belt
Waiters pick items off the belt
Producer-consumer problem
• Now imagine many chefs!
...and many waiters!
Producer-consumer problem
• A potential mess!
Producer-consumer problemChef (Producer) Waiter (Consumer)
inserts items removes items
Shared resource:bounded buffer
Efficient implementation:circular fixed-size buffer
Shared bufferChef (Producer) Waiter (Consumer)
Shared buffer
insertPtr
removePtr
What does the chef do with a
new pizza?
Where does the waiter take a pizza from?
Chef (Producer) Waiter (Consumer)
Shared buffer
insertPtr
removePtr
Insert pizza
insertPtr
Chef (Producer) Waiter (Consumer)
Shared buffer
insertPtr
removePtr
Insert pizza
Chef (Producer) Waiter (Consumer)
Shared buffer
insertPtr
removePtr
Insert pizza
Chef (Producer) Waiter (Consumer)
Shared buffer
insertPtr
removePtr
Remove pizza
removePtr
Chef (Producer) Waiter (Consumer)
Shared buffer
insertPtr
removePtr
Insert pizza
Chef (Producer) Waiter (Consumer)
Shared buffer
insertPtr
removePtr
Insert pizza
Chef (Producer) Waiter (Consumer)
Shared buffer
insertPtr
removePtr
BUFFER FULL: Producer must wait!
Insert pizza
Chef (Producer) Waiter (Consumer)
Shared buffer
insertPtrremovePtrRemove pizza
Chef (Producer) Waiter (Consumer)
Shared buffer
insertPtr
removePtr
Remove pizza
Chef (Producer) Waiter (Consumer)
Shared buffer
insertPtr
removePtr
Remove pizza
Chef (Producer) Waiter (Consumer)
Shared buffer
insertPtr
removePtr
Remove pizza
Chef (Producer) Waiter (Consumer)
Shared buffer
insertPtr
removePtr
Remove pizza
Chef (Producer) Waiter (Consumer)
Shared buffer
insertPtr
removePtr
Remove pizza
Chef (Producer) Waiter (Consumer)
Shared buffer
insertPtr
removePtr
Remove pizza
Chef (Producer) Waiter (Consumer)
Shared buffer
insertPtrremovePtr
Buffer empty: Consumer must be blocked!
Remove pizza
Chef (Producer) Waiter (Consumer)
Designing a solutionChef (Producer) Waiter (Consumer)
Wait for empty slotInsert itemSignal item arrival
Wait for item arrivalRemove item
Signal empty slot available
What synchronization do we need?
Designing a solutionChef (Producer) Waiter (Consumer)
Wait for empty slotInsert itemSignal item arrival
Wait for item arrivalRemove item
Signal empty slot available
What synchronization do we need?
Mutex(shared buffer)
Designing a solutionChef (Producer) Waiter (Consumer)
Wait for empty slotInsert itemSignal item arrival
Wait for item arrivalRemove item
Signal empty slot available
What synchronization do we need?
Semaphore(# empty slots)
Designing a solutionChef (Producer) Waiter (Consumer)
Wait for empty slotInsert itemSignal item arrival
Wait for item arrivalRemove item
Signal empty slot available
What synchronization do we need?
Semaphore(# filled slots)
Producer-Consumer Code
buffer[ insertPtr ] = data;
insertPtr = (insertPtr + 1) % N;
result = buffer[removePtr];
removePtr = (removePtr +1) % N;
Critical Section: move insert pointer
Critical Section: move remove pointer
Producer-Consumer Code
sem_wait(&slots);mutex_lock(&mutex);buffer[ insertPtr ] =
data;insertPtr = (insertPtr
+ 1) % N;mutex_unlock(&mutex);sem_post(&items);
sem_wait(&items);mutex_lock(&mutex);result =
buffer[removePtr];removePtr = (removePtr
+1) % N;mutex_unlock(&mutex);sem_post(&slots);
Block if there are no free slots
Block if there are no items
to take
Counting semaphore – check and decrement the number of free slots
Counting semaphore – check and decrement the number of available items
Done – increment the number of available items
Done – increment the number of free slots
Consumer Pseudocode: getItem()
sem_wait(&items);pthread_mutex_lock(&mutex);result = buffer[removePtr];removePtr = (removePtr +1) % N;pthread_mutex_unlock(&mutex);sem_signal(&slots);
Error checking/EINTR handling not shown
Producer Pseudocode: putItem(data)
sem_wait(&slots);pthread_mutex_lock(&mutex);buffer[ insertPtr ] = data;insertPtr = (insertPtr + 1) % N;pthread_mutex_unlock(&mutex);sem_signal(&items);
Error checking/EINTR handling not shown
Readers-Writers Problem
Readers-Writers Problem
• Mutual exclusion problem• Problem statement:
– Reader threads only read the object– Writer threads modify the object– Writers must have exclusive access to the object– Unlimited number of readers can access the object
• Occurs frequently in real systems, e.g.,– Online airline reservation system– Multithreaded caching Web proxy
void writer(void) { while (1) { sem_wait(&w);
/* Critical section */ /* Writing here */
sem_post(&w); }}
Writers:
int readcnt; /* Initially = 0 */sem_t mutex, w; /* Both initially = 1 */
Shared:
Solution favoring readers
(full codeonline)
void reader(void) { while (1) { sem_wait(&mutex); readcnt++; if (readcnt == 1) /* First reader in */ sem_wait(&w); /* Lock out writers */ sem_post(&mutex);
/* Main critical section */ /* Reading would happen here */
sem_wait(&mutex); readcnt--; if (readcnt == 0) /* Last out */ sem_post(&w); /* Let in writers */ sem_post(&mutex); }}
Readers:
Solution favoring readers
Summary
• Synchronization: more than just locking a critical section
• Semaphores useful for counting available resources– sem_wait(): wait for resource only if none available– sem_post(): signal availability of another resource
• Multiple semaphores / mutexes can work together to solve complex problems