Semaphores, Condition Variables, Readers/Writers

Semaphores, Condition Variables, Readers/Writers

Review: Synchronization problem with Threads CS162 • One thread per transaction, each running: Operating Systems and Deposit(acctId, amount) { acct = GetAccount(actId); /* May use disk I/O */ Systems Programming acct->balance += amount; Lecture 8 StoreAccount(acct); /* Involves disk I/O */ } • Unfortunately, shared state can get corrupted: Semaphores, Monitors, and Thread 1 Thread 2 Readers/Writers load r1, acct->balance load r1, acct->balance add r1, amount2 February 18th, 2015 store r1, acct->balance add r1, amount1 Prof. John Kubiatowicz store r1, acct->balance http://cs162.eecs.Berkeley.edu • Atomic Operation: an operation that always runs to completion or not at all – It is indivisible: it cannot be stopped in the middle and state cannot be modified by someone else in the middle 2/18/15 Kubiatowicz CS162 ©UCB Spring 2015 Lec 8.2 Review: Too Much Milk Solution #3 Review: Too Much Milk: Solution #4 • Here is a possible two-note solution: • Suppose we have some sort of implementation of a Thread A Thread B lock (more in a moment). leave note A; leave note B; – Acquire(&mylock) – wait until lock is free, then grab while (note B) {\\X if (noNote A) {\\Y – Release(&mylock) – Unlock, waking up anyone waiting do nothing; if (noMilk) { } buy milk; – These must be atomic operations – if two threads are if (noMilk) { } waiting for the lock and both see it’s free, only one buy milk; } succeeds to grab the lock } remove note B; remove note A; • Then, our milk problem is easy: • Does this work? Yes. Both can guarantee that: Acquire(&milklock); – It is safe to buy, or if (nomilk) – Other will buy, ok to quit buy milk; Release(&milklock); • At X: – if no note B, safe for A to buy, • Once again, section of code between Acquire() and Release() called a “Critical Section” – otherwise wait to find out what will happen • Of course, you can make this even simpler: suppose • At Y: you are out of ice cream instead of milk – if no note A, safe for B to buy – Skip the test since you always need more ice cream. – Otherwise, A is either buying or waiting for B to quit 2/18/15 Kubiatowicz CS162 ©UCB Spring 2015 Lec 8.3 2/18/15 Kubiatowicz CS162 ©UCB Spring 2015 Lec 8.4 Recall: Better Implementation of Locks Goals for Today by Disabling Interrupts • Continue with Synchronization Abstractions • Key idea: maintain a lock variable and impose mutual exclusion only during operations on that variable – Semaphores, Monitors, and Condition variables int mylock = FREE; • Readers-Writers problem and solution Acquire(&mylock) – wait until lock is free, then grab • Introduction to scheduling Release(&mylock) – Unlock, waking up anyone waiting Acquire(int *lock) { Release(int *lock) { disable interrupts; disable interrupts; if (*lock == BUSY) { if (anyone on wait queue) { put thread on wait queue; take thread off wait queue Go to sleep(); Place on ready queue; } else { // Enable interrupts? *lock = FREE; } else { } *lock = BUSY; enable interrupts; } } Note: Some slides and/or pictures in the following are enable interrupts; adapted from slides ©2005 Silberschatz, Galvin, and GagneGagne. } Many slides generated from my lecture notes by Kubiatowicz. • Really only works in kernel – why? 2/18/15 Kubiatowicz CS162 ©UCB Spring 2015 Lec 8.5 2/18/15 Kubiatowicz CS162 ©UCB Spring 2015 Lec 8.6 Recall: How to Re-enable After Sleep()? Review: Examples of Read-Modify-Write • test&set (&address) { /* most architectures */ • Interrupts are disabled when you call sleep: result = M[address]; – Responsibility of the next thread to re-enable ints M[address] = 1; return result; – When the sleeping thread wakes up, returns to acquire } and re-enables interrupts • swap (&address, register) { /* x86 */ temp = M[address]; Thread A Thread B M[address] = register; . register = temp; . } disable ints • compare&swap (&address, reg1, reg2) { /* 68000 */ sleep if (reg1 == M[address]) { sleep return M[address] = reg2; return success; enable ints } else { . return failure; . } . } disable int • load-linked&store conditional(&address) { sleep /* R4000, alpha */ loop: sleep return ll r1, M[address]; enable ints movi r2, 1; /* Can do arbitrary comp */ . sc r2, M[address]; . beqz r2, loop; • Why must Interrupts be disabled during context switch? } 2/18/15 Kubiatowicz CS162 ©UCB Spring 2015 Lec 8.7 2/18/15 Kubiatowicz CS162 ©UCB Spring 2015 Lec 8.8 Implementing Locks with test&set Problem: Busy-Waiting for Lock • A flawed, but simple solution (that works at user-level!) • Positives for this solution – Machine can receive interrupts int mylock = 0; // Free – User code can use this lock Acquire() { while (test&set(&mylock)); // while busy – Works on a multiprocessor } • Negatives Release() { – This is very inefficient because the busy-waiting mylock = 0; thread will consume cycles waiting } – Waiting thread may take cycles away from thread • Simple explanation: holding lock (no one wins!) – If lock is free, test&set reads 0 and sets value=1, so lock – Priority Inversion: If busy-waiting thread has higher is now busy. It returns 0 so while exits. priority than thread holding lock no progress! – If lock is busy, test&set reads 1 and sets value=1 (no • Priority Inversion problem with original Martian rover change). It returns 1, so while loop continues • For semaphores and monitors, waiting thread may – When we set value = 0, someone else can get lock wait for an arbitrary length of time! • Issues with this solution – Thus even if busy-waiting was OK for locks, definitely not ok for other primitives – Busy-Waiting: thread consumes cycles while waiting – Homework/exam solutions should not have busy-waiting! – Does not take advantage of multi-core/processor caches! 2/18/15 Kubiatowicz CS162 ©UCB Spring 2015 Lec 8.9 2/18/15 Kubiatowicz CS162 ©UCB Spring 2015 Lec 8.10 Multiprocessor Spin Locks: test&test&set Better Locks using test&set • A better solution for multiprocessors: • Can we build test&set locks without busy-waiting? int mylock = 0; // Free – Can’t entirely, but can minimize! Acquire() { – Idea: only busy-wait to atomically check lock value do { int guard = 0; int mylock = FREE; while(mylock); // Wait until might be free } while(test&set(&mylock)); // exit if get lock Acquire(&mylock) – wait until lock is free, then grab Release(&mylock) – Unlock, waking up anyone waiting } Acquire(int *lock) { Release(int *lock) { Release() { // Short busy-wait time // Short busy-wait time mylock = 0; while (test&set(&guard)); while (test&set(&guard)); } if (*lock == BUSY) { if anyone on wait queue { • Simple explanation: put thread on wait queue; take thread off wait queue – Wait until lock might be free (only reading – stays in cache) go to sleep() & guard = 0; Place on ready queue; } else { } else { – Then, try to grab lock with test&set *lock = FREE; *lock = BUSY; – Repeat if fail to actually get lock } guard = 0; guard = 0; • Issues with this solution: } – Busy-Waiting: thread still consumes cycles while waiting } » However, it does not impact other processors! • Note: sleep has to be sure to reset the guard variable – Why can’t we do it just before or just after the sleep? 2/18/15 Kubiatowicz CS162 ©UCB Spring 2015 Lec 8.11 2/18/15 Kubiatowicz CS162 ©UCB Spring 2015 Lec 8.12 Administrivia Using of Compare&Swap for queues • compare&swap (&address, reg1, reg2) { /* 68000 */ • First Checkpoint due this Friday 11:59pm PST if (reg1 == M[address]) { – Yes this is graded! M[address] = reg2; return success; – Assume design document is high level! } else { » You should think of this as a document for a manager return failure; (your TA) } } • Do your own work! – Please do not try to find solutions from previous terms Here is an atomic add to linked-list function: – We will be look out for this… addToQueue(&object) { do { // repeat until no conflict • Basic semaphores work in PintOS! ld r1, M[root] // Get ptr to current head – However, you will need to implement priority scheduling st r1, M[object] // Save link in new object behavior both in semaphore and ready queue } until (compare&swap(&root,r1,object)); } • Still could use more folks in Thursday 12-1 and root next next Friday 10-1 sections! – Much better next – Try to attend the section with your project TA…? New Object 2/18/15 Kubiatowicz CS162 ©UCB Spring 2015 Lec 8.13 2/18/15 Kubiatowicz CS162 ©UCB Spring 2015 Lec 8.14 Higher-level Primitives than Locks Semaphores • Goal of last couple of lectures: • Semaphores are a kind of generalized lock – What is the right abstraction for synchronizing threads – First defined by Dijkstra in late 60s that share memory? – Main synchronization primitive used in original UNIX – Want as high a level primitive as possible • Definition: a Semaphore has a non-negative integer • Good primitives and practices important! value and supports the following two operations: – Since execution is not entirely sequential, really hard to – P(): an atomic operation that waits for semaphore to find bugs, since they happen rarely become positive, then decrements it by 1 – UNIX is pretty stable now, but up until about mid-80s » Think of this as the wait() operation (10 years after started), systems running UNIX would – V(): an atomic operation that increments the semaphore crash every week or so – concurrency bugs by 1, waking up a waiting P, if any • Synchronization is a way of coordinating multiple » This of this as the signal() operation concurrent activities that are using shared state – Note that P() stands for “proberen” (to test) and V() stands for “verhogen” (to increment) in Dutch – This lecture and the next presents a couple of ways of structuring the sharing 2/18/15 Kubiatowicz CS162 ©UCB Spring 2015 Lec 8.15 2/18/15 Kubiatowicz CS162 ©UCB Spring 2015 Lec 8.16 Semaphores Like Integers Except Two Uses of Semaphores • Semaphores are like integers, except • Mutual Exclusion (initial value = 1) – No negative values – Also called “Binary Semaphore”.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    15 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us