Operating Systems CMPSC 473 Mutual Exclusion Lecture 12

  • Slides: 21
Download presentation
Operating Systems CMPSC 473 Mutual Exclusion Lecture 12: October 7, 2010 Instructor: Bhuvan Urgaonkar

Operating Systems CMPSC 473 Mutual Exclusion Lecture 12: October 7, 2010 Instructor: Bhuvan Urgaonkar

Agenda • Last class – Liveness conditions accompanying mutual exclusion – Mutex locks •

Agenda • Last class – Liveness conditions accompanying mutual exclusion – Mutex locks • Peterson’s solution: based only on atomic loads/stores • Solutions based on test&set and swap atomic instructions • Next: Solutions that eliminate busy wait – Condition variables – Semaphores

Condition Variables • Mutex locks waste CPU cycles via busy wait • Mutex locks

Condition Variables • Mutex locks waste CPU cycles via busy wait • Mutex locks not suitable for making a thread wait till a certain condition becomes true • One Solution: Condition variables – A condition variable indicates an event and has no value – Manipulated using wait() and signal() operations

Condition Variables • Wait operation – When a thread executes a wait call on

Condition Variables • Wait operation – When a thread executes a wait call on a condition variable, it is immediately suspended • It is now is waiting for the event that is represented by the condition variable to occur • Signal operation – Eventually, a thread will cause the event to occur after which it will call the signal method on the corresponding condition variable • If there are threads waiting on the signaled condition variable, the “monitor” will allow one of the waiting threads to resume its execution • If there is no waiting thread on the signaled condition variable, this signal is lost as if it never occured

cond_t not_full, not_empty; int count == 0; Produce() { if (count == N) wait

cond_t not_full, not_empty; int count == 0; Produce() { if (count == N) wait (not_full); … ADD TO BUFFER, count++ … } signal (not_empty); Consume() { if (count == 0) wait (not_empty); … REMOVE FROM BUFFER, count-- … } signal (not_full); What is wrong?

cond_t not_full, not_empty; mutex_lock m; int count == 0; Produce() { mutex_lock (m); if

cond_t not_full, not_empty; mutex_lock m; int count == 0; Produce() { mutex_lock (m); if (count == N) wait (not_full, m); … ADD TO BUFFER, count++ … } signal (not_empty); mutex_unlock (m); Consume() { mutex_lock (m); if (count == 0) wait (not_empty, m); … REMOVE FROM BUFFER, count-- … } signal (not_full); mutex_unlock (m); NOTE: You can improve this code for more concurrency!

 • Wait operation Condition Variables – When a thread executes a wait call

• Wait operation Condition Variables – When a thread executes a wait call on a condition variable, it is immediately suspended • It is now is waiting for the event that is represented by the condition variable to occur • Signal operation – Eventually, a thread will cause the event to occur after which it will call the signal method on the corresponding condition variable • If there are threads waiting on the signaled condition variable, the monitor will allow one of the waiting threads to resume its execution • If there is no waiting thread on the signaled condition variable, this signal is lost as if it never occured • Always used in conjunction with a mutex lock

Condition Variables • pthreads functions/data struct – pthread_cond_t condition = PTHREAD_COND_INITIALIZER; or pthread_cont_init (condition,

Condition Variables • pthreads functions/data struct – pthread_cond_t condition = PTHREAD_COND_INITIALIZER; or pthread_cont_init (condition, attr) – pthread_cond_wait (condition, mutex) – pthread_cond_signal (condition)

Semaphores Definition (Dijkstra) • ACK: Lot of material borrowed from “The Little Book of

Semaphores Definition (Dijkstra) • ACK: Lot of material borrowed from “The Little Book of Semaphores” by Allen B. Downey – Available online (free) at: http: //www. greenteapress. com/semaphores/

Semaphores Definition (contd. ) • Can only be accessed via two indivisible (atomic) operations

Semaphores Definition (contd. ) • Can only be accessed via two indivisible (atomic) operations – – wait (S) { /* also called decrement */ while S <= 0; // no-op S--; } signal (S) { /* also called increment */ S++; } Entry section Exit section • Note: Busy waiting in these definitions, we will see how they can be improved to avoid busy waiting

Semaphore Usage (Prelim. ) • Can only be accessed via two indivisible (atomic) operations

Semaphore Usage (Prelim. ) • Can only be accessed via two indivisible (atomic) operations – – wait (S) { /* also called decrement */ while S <= 0; // no-op S--; } signal (S) { /* also called increment */ S++; } • Provides mutual exclusion – Semaphore S; // initialized to 1 – wait (S); Critical Section signal (S);

Consequences of the definition • In general, there is no way to know before

Consequences of the definition • In general, there is no way to know before a thread decrements a semaphore whether it will block • After a thread increments a semaphore and another thread gets woken up, both threads continue running concurrently. There is no way to know which thread, if either, will continue immediately • When you signal a semaphore, you don’t necessarily know whether another thread is waiting, so the number of unblocked threads may be zero or one.

Meaning of Semaphore Values • If the value is +, it represents the number

Meaning of Semaphore Values • If the value is +, it represents the number of threads that can decrement without blocking • If the value is -, it represents the number of threads that are blocked and are waiting • If the value is 0, it means there are no threads waiting, but if a thread tries to decrement, it will block

Why Semaphores? • Semaphores impose deliberate constraints that help programmers avoid errors • Solutions

Why Semaphores? • Semaphores impose deliberate constraints that help programmers avoid errors • Solutions using semaphores are often clean and organized, making it easy to demonstrate their correctness • Semaphores can be implemented efficiently on many systems, so solutions that us semaphores are portable and efficient

Counting and Binary Semaphores • Counting semaphore – integer value can range over an

Counting and Binary Semaphores • Counting semaphore – integer value can range over an unrestricted domain • Binary semaphore – integer value can range only between 0 and 1; can be simpler to implement – Also known as mutex locks • Can implement a counting semaphore S as a binary semaphore - will return to this later

Semaphore Usage: Basic Synchronization Patterns • Not just for Mutex but many other purposes!

Semaphore Usage: Basic Synchronization Patterns • Not just for Mutex but many other purposes! – – – – Signaling Rendezvous Mutex Multiplex Barrier Re-usable barrier Queues FIFO Queue We will study these

Signaling • Initial value of sem = 0 • This ensures a 1 executes

Signaling • Initial value of sem = 0 • This ensures a 1 executes before b 1 • Why?

Rendezvous • We want a 1 before b 2 and b 1 before a

Rendezvous • We want a 1 before b 2 and b 1 before a 2 • Hint: Create two semaphores a. Arrived (indicating A has arrived at the rendevous) and b. Arrived both initialized to 0;

Rendezvous: Solution 1 • Initialization: – a. Arrived = 0; – b. Arrived =

Rendezvous: Solution 1 • Initialization: – a. Arrived = 0; – b. Arrived = 0;

Rendezvous: Solution 2 • Initialization: – a. Arrived = 0; – b. Arrived =

Rendezvous: Solution 2 • Initialization: – a. Arrived = 0; – b. Arrived = 0;

Rendezvous: Solutions 1 and 2 Compared • Initialization: – a. Arrived = 0; –

Rendezvous: Solutions 1 and 2 Compared • Initialization: – a. Arrived = 0; – b. Arrived = 0; • • • Which is likely more efficient? Hint: Solution 2 might require one extra context switch