Presentation is loading. Please wait.

Presentation is loading. Please wait.

Instructor: Junfeng Yang

Similar presentations


Presentation on theme: "Instructor: Junfeng Yang"— Presentation transcript:

1 Instructor: Junfeng Yang
W4118 Operating Systems Instructor: Junfeng Yang

2 Logistics Homework 2 due time: 3:09 pm this Thursday (one hour before class) Submit everything electronically at courseworks, including written assignment

3 Last lecture Synchronization Layered approach to synchronization
Critical section requirements: safe, live, bounded Desirable: efficient, fair, simple Locks Uniprocessor implementation: disable and enable interrupts Software-based locks: peterson’s algorithm Locks with hardware support atomic test_and_set all pointer paramters are untrusted and from user.

4 Today Lock (wrap up) Semaphore Monitor
A classical synchronization problem: read and write lock

5 Recall: Spin-wait or block
Spin-lock may waste CPU cycles: lock holder gets preempted, and scheduled threads try to grab lock Shouldn’t use spin-lock on single core On multi-core, good plan is: spin a bit, then yield Worst as # of threads increase

6 Problem with simple yield
lock() { while(test_and_set(&flag)) yield(); } Problem: Still a lot of context switches; poll for lock Starvation possible Why? No control over who gets the lock next Need explicit control over who gets the lock

7 Implementing locks: version 4
The idea Add thread to queue when lock unavailable In unlock(), wake up one thread in queue Problem I: may lose the wake up Fix: use a spin_lock or lock w/ simple yield! Doesn’t completely avoid spin-wait, but make wait time short, thus reasonable Problem II: may not wake up the right thread Fix: unlock() directly transfers lock to waiting thread lock() { if (flag == 1) add myself to wait queue yield } unlock() { flag = 0 if(any thread in wait queue) wake up one wait thread } Lock from a third thread

8 Implementing locks: version 4, the code
typedef struct __mutex_t { int flag; // 0: mutex is available, 1: mutex is not available int guard; // guard lock to avoid losing wakeups queue_t *q; // queue of waiting threads } mutex_t; void lock(mutex_t *m) { while (test_and_set(m->guard)) ; //acquire guard lock by spinning if (m->flag == 0) { m->flag = 1; // acquire mutex m->guard = 0; } else { enqueue(m->q, self); yield(); } void unlock(mutex_t *m) { while (test_and_set(m->guard)) ; if (queue_empty(m->q)) // release mutex; no one wants mutex m->flag = 0; else // direct transfer mutex to next thread wakeup(dequeue(m->q)); m->guard = 0; } This is a more realistic mutex implementation than previous versions Interesting bits What is guard? A spin_lock to protect internal data structure. Possible that a thread gets preempted when holding m->guard, thus has the overhead discussed before. But since we hold m->guard for very short period of time, The spin-wait time is short and reasonable Queue to control lock order, thus increase efficiency and avoid starvation. In lock: Lock unavailabe  enqueue in unlock, dequeue a task and wake it up Flag not set to 0 in unlock. Not an error, but a must! current thread is holding guard, next thread can’t modify flag can set to 0, and let next thread grab lock, but a 3rd thread can come in and grab the lock first. This is very close to real mutex implementations

9 Today Lock (wrap up) Semaphore Monitor
A classical synchronization problem: read and write lock

10 Semaphore Motivation Problem with lock: mutual exclusion, but no ordering; may want more E.g. Producer-consumer problem $ cat 1.txt | sort | uniq | wc Producer: creates a resource Consumer: uses a resource bounded buffer between them Scheduling order: producer waits if buffer full, consumer waits if buffer empty

11 Semaphore Definition A synchronization variable that:
Contains an integer value Can’t access directly Must initialize to some value sem_init(sem_t *s, int pshared, unsigned int value) Has two operations to manipulate this integer sem_wait, or down(), P() (comes from Dutch) sem_post, or up(), V() (comes from Dutch) sem_wait: no wait if s > 0 Sem_post: never block caller sem_wait, sem_post are atomic int sem_wait(sem_t *s) { wait until value of semaphore s is greater than 0 decrement the value of semaphore s by 1 } int sem_post(sem_t *s) { increment the value of semaphore s by 1 if there are 1 or more threads waiting, wake 1 }

12 Semaphore Uses Mutual exclusion Scheduling order Semaphore as mutex
// initialize to X sem_init(s, 0, X) sem_wait(s); // critical section sem_post(s); Mutual exclusion Semaphore as mutex What should initial value be? Binary semaphore: X=1 ( Counting semaphore: X>1 ) Scheduling order One thread waits for another //thread 0 … // 1st half of computation sem_post(s); // thread 1 sem_wait(s); … //2nd half of computation

13 Producer-Consumer (Bounded-Buffer) Problem
Bounded buffer: size ‘N’ Access entry 0… N-1, then “wrap around” to 0 again Producer process writes data to buffer Must not write more than ‘N’ items more than consumer “ate” Consumer process reads data from buffer Should not try to consume if there is no data 1 N-1 Producer Consumer

14 Solving Producer-Consumer problem
Two semaphores sem_t full; // # of filled slots sem_t empty; // # of empty slots Problem: mutual exclusion? sem_init(&full, 0, 0); sem_init(&empty, 0, N); producer() { sem_wait(empty); … // fill a slot sem_post(full); } consumer() { sem_wait(full); … // empty a slot sem_post(empty); }

15 Solving Producer-Consumer problem: Final
Three semaphores sem_t full; // # of filled slots sem_t empty; // # of empty slots sem_t mutex; // mutual exclusion sem_init(&full, 0, 0); sem_init(&empty, 0, N); sem_init(&mutex, 0, 1); producer() { sem_wait(empty); sem_wait(&mutex); … // fill a slot sem_post(&mutex); sem_post(full); } consumer() { sem_wait(full); sem_wait(&mutex); … // empty a slot sem_post(&mutex); sem_post(empty); }

16 How to Implement Semaphores?
Part of your next programming assignment

17 Today Lock (wrap up) Semaphore Monitor
A classical synchronization problem: read and write lock

18 Monitors Background Concurrent programming meets object-oriented programming When concurrent programming became a big deal, object-oriented programming too People started to think about ways to make concurrent programming more structured Monitor: object with a set of monitor procedures and only one thread may be active (i.e. running one of the monitor procedures) at a time

19 Schematic view of a Monitor
Can think of a monitor as one big lock for a set of operations/ methods In other words, a language implementation of mutexes

20 How to Implement Monitor?
Compiler automatically inserts lock and unlock operations upon entry and exit of monitor procedures class account { int balance; public synchronized void deposit() { ++balance; } public synchronized void withdraw() { --balance; }; lock(m); ++balance; unlock(m); lock(m); --balance; unlock(m);

21 Condition Variables Need wait and wakeup as in semaphores
Monitor uses Condition Variables Conceptually associated with some conditions Operations on condition variables: wait(): suspends the calling thread and releases the monitor lock. When it resumes, reacquire the lock. Called with condition is not true signal(): resumes one thread (if any) waiting in wait(). Called when condition becomes true broadcast(): resumes all threads waiting in wait() Why release monitor lock? only one thread can be in monitor at a time. Since current thread wants to wait, must release lock to let other threads to enter monitor

22 Monitor with Condition Variables

23 Subtle Differences between condition variables and semaphores
Semaphores are sticky: they have memory, sem_post() will increment the semaphore, even if no one has called sem_wait() Condition variables are not: if no one is waiting for a signal(), this signal() is not saved

24 Producer-Consumer with Monitors
monitor ProducerConsumer { int nfull = 0; cond notfull, notempty; producer() { if (nfull == N) wait (notfull); … // fill a slot ++ nfull; signal (notempty); } consumer() { if (nfull == 0) wait (notempty); … // empty a slot -- nfull signal (notfull); }; nfull: number of filled buffers Need to do our own counting for condition variables notfull and notempty: two condition variables notfull: not all slots are full notempty: not all slots are empty

25 Condition Variable Semantics
Problem: when signal() wakes up a waiting thread, which thread to run inside the monitor, the signaling thread, or the waiting thread? Hoare semantics: suspends the signaling thread, and immediately transfers control to the woken thread Difficult to implement in practice Mesa semantics: signal() moves a single waiting thread from the blocked state to a runnable state, then the signaling thread continues until it exits the monitor Easy to implement Problem: race! E.g. before a woken consumer continues, another consumer comes in and grabs the buffer Tony Hoare: theoretician, invented quick sort "Experience with Processes and Monitors in Mesa", B.W. Lampson, D.R. Redell. Communications of the ACM. Volume 23, Number 2. pages February 1980.

26 Fixing the Race in Mesa Monitors
monitor ProducerConsumer { int nfull = 0; cond notfull, notempty; producer() { while (nfull == N) wait (notfull); … // fill slot ++ nfull; signal (notempty); } consumer() { while (nfull == 0) wait (notempty); … // empty slot -- nfull signal (notfull); }; The fix: when woken, a thread must recheck the condition it was waiting on Most systems use mesa semantics E.g. pthread Thus, you should remember to recheck

27 Monitor with pthread C/C++ don’t provide monitors; but we can implement monitors using pthread mutex and condition variable For producer-consumer problem, need 1 pthread mutex and 2 pthread condition variables (pthread_cond_t) Manually lock and unlock mutex for monitor procedures pthread_cond_wait (cv, m): atomically waits on cv and releases m Why atomically? You figure out class ProducerConsumer { int nfull = 0; pthread_mutex_t m; pthread_cond_t notfull, notempty; public: producer() { pthread_mutex_lock(&m); while (nfull == N) ptherad_cond_wait (&notfull, &m); … // fill slot ++ nfull; pthread_cond_signal (notempty); pthread_mutex_unlock(&m); } }; Instead of pthread_cond_wait(cv, m), why not pthread_mutex_unlock(m); pthread_cond_awit(cv); ?

28 Today Lock (wrap up) Semaphore Monitor
A classical synchronization problem: read and write lock

29 Readers-Writers Problem
Courtois et al 1971 Models access to a database A reader is a thread that needs to look at the database but won’t change it. A writer is a thread that modifies the database Example: making an airline reservation When you browse to look at flight schedules the web site is acting as a reader on your behalf When you reserve a seat, the web site has to write into the database to make the reservation

30 Solving Readers-Writers w/ Regular Lock
sem_t lock; Writer sem_wait (lock); . . . // write shared data sem_post (lock); Reader sem_wait (lock); . . . // read shared data sem_post(lock); Problem: unnecessary synchronization Only one writer can be active at a time However, any number of readers can be active simultaneously ! Solution: Idea: differentiate lock for read and lock for write

31 Readers-Writers Lock Problem: may starve writer
int nreader = 0; sem_t lock = 1, write_lock = 1; Writer sem_wait (write_lock); . . . // write shared data sem_post (write_lock); Reader sem_wait (lock); ++ nreader; if (nreader == 1) // first reader sem_wait (write_lock); sem_post (lock); . . . // read shared data -- nreader; if (nreader == 0) // last reader sem_post (write_lock); nreader: number of readers lock: protect update to internal data structure write_lock: mutual exlusion between (1) one writer and other writers, and (2) one writer and all readers first reader grabs write_lock to drive out future writers last reader signals on write_lock to wake up waiting writers Once a reader is active, other readers can go through, too how to determine first or last? Use nreader to track how many readers If there is a writer First reader blocks on write_lock Other readers block on lock Other writers block on write_lock Problem: may starve writer How to fix? Not that straightforward. You figure out


Download ppt "Instructor: Junfeng Yang"

Similar presentations


Ads by Google