* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Download CS 519 -- Operating Systems -
Survey
Document related concepts
Transcript
Processes, Threads, Synchronization CS 519: Operating System Theory Computer Science, Rutgers University Instructor: Thu D. Nguyen TA: Xiaoyan Li Spring 2002 Von Neuman Model Both text (program) and data reside in memory Execution cycle Fetch instruction Decode instruction CPU Execute instruction Memory Computer Science, Rutgers 2 CS 519: Operating System Theory Image of Executing Program 100 load R1, R2 104 add R1, 4, R1 108 load R1, R3 112 add R2, R3, R3 R1: 2000 R2: R3: PC: 100 CPU … 2000 4 2004 8 Memory Computer Science, Rutgers 3 CS 519: Operating System Theory How Do We Write Programs Now? public class foo { static private int yv = 0; static private int nv = 0; public static void main() { foo foo_obj = new foo; foo_obj->cheat(); } How to map a program like this to a Von Neuman machine? Where to keep yv, nv? What about foo_obj and tyv? public cheat() { int tyv = yv; yv = yv + 1; if (tyv < 10) { cheat(); } } How to do foo->cheat()? } Computer Science, Rutgers 4 CS 519: Operating System Theory Global Variables Dealing with “global” variables like yv and nv is easy Let’s just allocate some space in memory for them This is done by the compiler at compile time A reference to yv is then just an access to yv’s location in memory Suppose g is stored at location 2000 Then, yv = yv + 1 might be compiled to something like loadi load add store 2000, R1 R1, R2 R2, 1, R2 R1, R2 Computer Science, Rutgers 5 CS 519: Operating System Theory Local Variables What about foo_obj defined in main() and tyv defined in cheat()? 1st option you might think of is just to allocate some space in memory for these variables as well (as shown to the right) 2000 yv 2004 2008 nv foo_obj tyv What is the problem with this approach? How can we deal with this problem? Computer Science, Rutgers 6 CS 519: Operating System Theory Local Variable foo->cheat(); tyv = yv; … foo->cheat(); tyv = yv; … yv globals tyv tyv’ tyv’’ stack Allocate a new memory location to tyv every time cheat() is called at runtime Convention is to allocate storage in a stack (often called the control stack) Pop stack when returning from a method: storage is no longer needed Code for allocating/deallocating space on the stack is generated by compiler at compile time Computer Science, Rutgers 7 CS 519: Operating System Theory What About “new” Objects? foo foo_obj = new foo; foo_obj is really a pointer to a foo object As just explained, a memory location is allocated for foo_obj from the stack whenever main() is invoked Where does the object created by the “new foo” actually live? Is the stack an appropriate place to keep this object? Why not? Computer Science, Rutgers 8 CS 519: Operating System Theory Memory Image Suppose we have executed the following: yv = 0 nv = 0 main() foo_obj = new foo foo->cheat() tyv = yv yv = yv + 1 foo->cheat() tyv = yv yv = yv + 1 foo->cheat() tyv = yv yv = yv + 1 Computer Science, Rutgers yv foo_obj tyv tyv’ tyv’’ globals stack heap 9 CS 519: Operating System Theory Data Access How to find data allocated dynamically on stack? By convention, designate one register as the stack pointer Stack pointer always point at current activation record Stack pointer is set at entry to a method Code for setting stack pointer is generated by compiler Local variables and parameters are referenced as offsets from sp activation record for cheat_yes() PC SP tyv CPU Computer Science, Rutgers 10 CS 519: Operating System Theory Data Access The statement tyv = tyv + 1 Would then translate into something like addi 0, sp, R1 load R1, R2 addi 1, R2 store R1, R2 Computer Science, Rutgers # tyv is the only variable so offset is 0 11 CS 519: Operating System Theory Activation Record We have only talked about allocation of local variables on the stack Other stuff The activation record is also used to store: Local variables Parameters The beginning of the previous activation record The return address … Computer Science, Rutgers 12 CS 519: Operating System Theory Run Time Storage Organization Code Globals Stack Each variable must be assigned a storage class Global (static) variables Allocated in globals region at compiletime Method local variables and parameters Allocate dynamically on stack Heap Memory Dynamically created objects (using new) Allocate from heap Objects live beyond invocation of a method Garbage collected when no longer “live” Computer Science, Rutgers 13 CS 519: Operating System Theory Why Did We Talk About All That Stuff? Process = system abstraction for the set of resources required for executing a program = a running instance of a program = memory image + registers’ content (+ I/O state) The stack + registers’ content represent the execution context or thread of control Computer Science, Rutgers 14 CS 519: Operating System Theory What About The OS? Recall that one of the function of an OS is to provide a virtual machine interface that makes programming the machine easier So, a process memory image must also contain the OS Code Globals Memory OS Stack Code Globals Heap Stack OS data space is used to store things like file descriptors for files being accessed by the process, status of I/O devices, etc. Heap Computer Science, Rutgers 15 CS 519: Operating System Theory What Happens When There Are More Than One Running Process? OS Code Globals Stack P0 Heap P1 P2 Computer Science, Rutgers 16 CS 519: Operating System Theory Process Control Block Each process has per-process state maintained by the OS Identification: process, parent process, user, group, etc. Execution contexts: threads Address space: virtual memory I/O state: file handles (file system), communication endpoints (network), etc. Accounting information For each process, this state is maintained in a process control block (PCB) This is just data in the OS data space Think of it as objects of a class Computer Science, Rutgers 17 CS 519: Operating System Theory Process Creation How to create a process? System call. In UNIX, a process can create another process using the fork() system call int pid = fork(); /* this is in C */ The creating process is called the parent and the new process is called the child The child process is created as a copy of the parent process (process image and process control structure) except for the identification and scheduling state Parent and child processes run in two different address spaces By default, there’s no memory sharing Process creation is expensive because of this copying The exec() call is provided for the newly created process to run a different program than that of the parent Computer Science, Rutgers 18 CS 519: Operating System Theory System Call In Monolithic OS interrupt vector for trap instruction PC PSW in-kernel file system(monolithic OS) code for fork system call kernel mode trap iret user mode id = fork() Computer Science, Rutgers 19 CS 519: Operating System Theory Process Creation fork() code PCBs fork() exec() Computer Science, Rutgers 20 CS 519: Operating System Theory Example of Process Creation Using Fork The UNIX shell is command-line interpreter whose basic purpose is for user to run applications on a UNIX system cmd arg1 arg2 ... argn Computer Science, Rutgers 21 CS 519: Operating System Theory Process Death (or Murder) One process can wait for another process to finish using the wait() system call Can wait for a child to finish as shown in the example Can also wait for an arbitrary process if know its PID Can kill another process using the kill() system call What all happens when kill() is invoked? What if the victim process doesn’t want to die? Computer Science, Rutgers 22 CS 519: Operating System Theory Process Swapping May want to swap out entire process Thrashing if too many processes competing for resources To swap out a process Suspend all of its threads Must keep track of whether thread was blocked or ready Copy all of its information to backing store (except for PCB) To swap a process back in Copy needed information back into memory, e.g. page table, thread control blocks Restore each thread to blocked or ready Must check whether event(s) has (have) already occurred Computer Science, Rutgers 23 CS 519: Operating System Theory Process State Diagram ready (in memory) swap in swap out suspended (swapped out) Computer Science, Rutgers 24 CS 519: Operating System Theory Signals OS may need to “upcall” into user processes Signals UNIX mechanism to upcall when an event of interest occurs Potentially interesting events are predefined: e.g., segmentation violation, message arrival, kill, etc. When interested in “handling” a particular event (signal), a process indicates its interest to the OS and gives the OS a procedure that should be invoked in the upcall. Computer Science, Rutgers 25 CS 519: Operating System Theory Signals (Cont’d) When an event of interest occurs the kernel handles the event first, then modifies the process’s stack to look as if the process’s code made a procedure call to the signal handler. When the user process is scheduled next it executes the handler first From the handler the user process returns to where it was when the event occurred Computer Science, Rutgers 26 Handler B B A A CS 519: Operating System Theory Inter-Process Communication Most operating systems provide several abstractions for inter-process communication: message passing, shared memory, etc Communication requires synchronization between processes (i.e. data must be produced before it is consumed) Synchronization can be implicit (message passing) or explicit (shared memory) Explicit synchronization can be provided by the OS (semaphores, monitors, etc) or can be achieved exclusively in user-mode (if processes share memory) Computer Science, Rutgers 27 CS 519: Operating System Theory Inter-Process Communication More on shared memory and message passing later Synchronization after we talk about threads Computer Science, Rutgers 28 CS 519: Operating System Theory A Tree of Processes On A Typical UNIX System Computer Science, Rutgers 29 CS 519: Operating System Theory Process: Summary System abstraction – the set of resources required for executing a program (an instantiation of a program) Execution context(s) Address space File handles, communication endpoints, etc. Historically, all of the above “lumped” into a single abstraction More recently, split into several abstractions Threads, address space, protection domain, etc. OS process management: Supports creation of processes and interprocess communication (IPC) Allocates resources to processes according to specific policies Interleaves the execution of multiple processes to increase system utilization Computer Science, Rutgers 30 CS 519: Operating System Theory Threads Thread of execution: stack + registers (which includes the PC) Informally: where an execution stream is currently at in the program and the method invocation chain that brought the execution stream to the current place Example: A called B which called C which called B which called C The PC should be pointing somewhere inside C at this point The stack should contain 5 activation records: A/B/C/B/C Thread for short Process model discussed thus far implies a single thread Computer Science, Rutgers 31 CS 519: Operating System Theory Multi-Threading Why limit ourselves to a single thread? Think of a web server that must service a large stream of requests If only have one thread, can only process one request at a time What to do when reading a file from disk? Multi-threading model Each process can have multiple threads Each thread has a private stack Registers are also private All threads of a process share the code and heap Objects to be shared across multiple threads should be allocated on the heap Computer Science, Rutgers 32 CS 519: Operating System Theory Process Address Space Revisited OS OS Code Code Globals Globals Stack Stack Stack Heap Heap (a) Single-threaded address space (b) Multi-threaded address space Computer Science, Rutgers 33 CS 519: Operating System Theory Multi-Threading (cont) Implementation Each thread is described by a thread-control block (TCB) A TCB typically contains Thread ID Space for saving registers Pointer to thread-specific data not on stack Observation Although the model is that each thread has a private stack, threads actually share the process address space There’s no memory protection! Threads could potentially write into each other’s stack Computer Science, Rutgers 34 CS 519: Operating System Theory Thread Creation PC SP thread_create() code PCBs TCBs thread_create() new_thread_starts_here stacks Computer Science, Rutgers 35 CS 519: Operating System Theory Context Switching Suppose a process has multiple threads …uh oh … a uniprocessor machine only has 1 CPU … what to do? In fact, even if we only had one thread per process, we would have to do something about running multiple processes … We multiplex the multiple threads on the single CPU At any instance in time, only one thread is running At some point in time, the OS may decide to stop the currently running thread and allow another thread to run This switching from one running thread to another is called context switching Computer Science, Rutgers 36 CS 519: Operating System Theory Diagram of Thread State Computer Science, Rutgers 37 CS 519: Operating System Theory Context Switching (cont) How to do a context switch? Save state of currently executing thread Copy all “live” registers to thread control block For register-only machines, need at least 1 scratch register points to area of memory in thread control block that registers should be saved to Restore state of thread to run next Copy values of live registers from thread control block to registers When does context switching take place? Computer Science, Rutgers 38 CS 519: Operating System Theory Context Switching (cont) When does context switching occur? When the OS decides that a thread has run long enough and that another thread should be given the CPU Remember how the OS gets control of the CPU back when it is executing user code? When a thread performs an I/O operation and needs to block to wait for the completion of this operation To wait for some other thread Thread synchronization: we’ll talk about this lots in a couple of lectures Computer Science, Rutgers 39 CS 519: Operating System Theory How Is the Switching Code Invoked? user thread executing clock interrupt PC modified by hardware to “vector” to interrupt handler user thread state is saved for restart clock interrupt handler is invoked disable interrupt checking check whether current thread has run “long enough” if yes, post asynchronous software trap (AST) enable interrupt checking exit interrupt handler enter “return-to-user” code check whether AST was posted if not, restore user thread state and return to executing user thread; if AST was posted, call context switch code Why need AST? Computer Science, Rutgers 40 CS 519: Operating System Theory How Is the Switching Code Invoked? (cont) user thread executing system call to perform I/O user thread state is saved for restart OS code to perform system call is invoked I/O operation started (by invoking I/O driver) set thread status to waiting move thread’s TCB from run queue to wait queue associated with specific device call context switching code Computer Science, Rutgers 41 CS 519: Operating System Theory Context Switching BC CS BC UC BC BC CS Computer Science, Rutgers At entry to CS, the return address is either in a register or on the stack (in the current activation record) CS saves this return address to the TCB instead of the current PC To thread, it looks like CS just took a while to return! If the context switch was initiated from an interrupt, the thread never knows that it has been context switched out and back in unless it looking at the “wall” clock 42 CS 519: Operating System Theory Context Switching (cont) Even that is not quite the whole story When a thread is switched out, what happens to it? How do we find it to switch it back in? This is what the TCB is for. System typically has A run queue that points to the TCBs of threads ready to run A blocked queue per device to hold the TCBs of threads blocked waiting for an I/O operation on that device to complete When a thread is switched out at a timer interrupt, it is still ready to run so its TCB stays on the run queue When a thread is switched out because it is blocking on an I/O operation, its TCB is moved to the blocked queue of the device Computer Science, Rutgers 43 CS 519: Operating System Theory Ready Queue And Various I/O Device Queues Computer Science, Rutgers 44 CS 519: Operating System Theory Switching Between Threads of Different Processes What if switching to a thread of a different process? Caches, TLB, page table, etc.? Caches Physical addresses: no problem Virtual addresses: cache must either have process tag or must flush cache on context switch TLB Each entry must have process tag or must flush TLB on context switch Page table Typically have page table pointer (register) that must be reloaded on context switch Computer Science, Rutgers 45 CS 519: Operating System Theory Threads & Signals What happens if kernel wants to signal a process when all of its threads are blocked? When there are multiple threads, which thread should the kernel deliver the signal to? OS writes into process control block that a signal should be delivered Next time any thread from this process is allowed to run, the signal is delivered to that thread as part of the context switch What happens if kernel needs to deliver multiple signals? Computer Science, Rutgers 46 CS 519: Operating System Theory Thread Implementation Kernel-level threads (lightweight processes) Kernel sees multiple execution context Thread management done by the kernel User-level threads Implemented as a thread library which contains the code for thread creation, termination, scheduling and switching Kernel sees one execution context and is unaware of thread activity Can be preemptive or not Computer Science, Rutgers 47 CS 519: Operating System Theory User-Level vs. Kernel-Level Threads Advantages of user-level threads Performance: low-cost thread operations (do not require crossing protection domains) Flexibility: scheduling can be application specific Portability: user-level thread library easy to port Disadvantages of user-level threads If a user-level thread is blocked in the kernel, the entire process (all threads of that process) are blocked Cannot take advantage of multiprocessing (the kernel assigns one process to only one processor) Computer Science, Rutgers 48 CS 519: Operating System Theory User-Level vs. Kernel-Level Threads user-level threads kernel-level threads threads thread scheduling user kernel threads process thread scheduling process scheduling processor processor Computer Science, Rutgers process scheduling 49 CS 519: Operating System Theory User-Level vs. Kernel-Level Threads No reason why we shouldn’t have both user-level threads Most systems now support kernel threads thread scheduling User-level threads are available as linkable libraries user kernel kernel-level threads thread scheduling process scheduling processor Computer Science, Rutgers 50 CS 519: Operating System Theory Threads vs. Processes Why multiple threads? Can’t we use multiple processes to do whatever that is that we do with multiple threads? Of course, we need to be able to share memory (and other resources) between multiple processes … But this sharing is already supported – see later in the lecture Operations on threads (creation, termination, scheduling, etc..) are cheaper than the corresponding operations on processes This is because thread operations do not involve manipulations of other resources associated with processes Inter-thread communication is supported through shared memory without kernel intervention Why not? Have multiple other resources, why not threads Computer Science, Rutgers 51 CS 519: Operating System Theory Thread/Process Operation Latencies Operation User-level Threads (s) Kernel Threads (s) Processes (s) Null fork 34 948 11,300 Signal-wait 37 441 1,840 Computer Science, Rutgers 52 CS 519: Operating System Theory Synchronization Synchronization Problem Threads must share data Data consistency must be maintained Example Suppose my wife wants to withdraw $5 from our account and I want to deposit $10 What should the balance be after the two transactions have been completed? What might happen instead if the two transactions were executed concurrently? Computer Science, Rutgers 54 CS 519: Operating System Theory Synchronization (cont) The balance might be SB – 5 W reads SB I read SB I compute SB + 10 and save new balance W computes SB – 5 and save new balance The balance might be SB + 10 How? Ensure the orderly execution of cooperating threads/processes Computer Science, Rutgers 55 CS 519: Operating System Theory Terminologies Critical section: a section of code which reads or writes shared data Race condition: potential for interleaved execution of a critical section by multiple threads Results are non-deterministic Mutual exclusion: synchronization mechanism to avoid race conditions by ensuring exclusive execution of critical sections Deadlock: permanent blocking of threads Starvation: execution but no progress Computer Science, Rutgers 56 CS 519: Operating System Theory Requirements for ME No assumptions on hardware: speed, # of processors Mutual exclusion is maintained – that is, only one thread at a time can be executing inside a CS Execution of CS takes a finite time A thread/process not in CS cannot prevent other threads/processes to enter the CS Entering CS cannot de delayed indefinitely: no deadlock or starvation Computer Science, Rutgers 57 CS 519: Operating System Theory Synchronization Primitives Most common primitives Locks (mutual exclusion) Condition variables Semaphores Monitors Need Semaphores, or Locks and condition variables, or Monitors Computer Science, Rutgers 58 CS 519: Operating System Theory Locks Mutual exclusion want to be the only thread modifying a set of data items Can look at it as exclusive access to data items or to a piece of code Have three components: Acquire, Release, Waiting Computer Science, Rutgers 59 CS 519: Operating System Theory Example public class BankAccount { Lock aLock = new Lock; int balance = 0; ... public void deposit(int amount) { aLock.acquire(); balance = balance + amount; aLock.release(); } Computer Science, Rutgers 60 public void withdrawal(int amount) { aLock.acquire(); balance = balance - amount; aLock.release(); } } CS 519: Operating System Theory Implementing Locks Inside OS Kernel From Nachos (with some simplifications) public class Lock { private KThread lockHolder = null; private ThreadQueue waitQueue = ThreadedKernel.scheduler.newThreadQueue(true); public void acquire() { KThread thread = KThread.currentThread(); if (lockHolder != null) { waitQueue.waitForAccess(thread); KThread.sleep(); } else { lockHolder = thread; } } Computer Science, Rutgers 61 // Get thread object (TCB) // Gotta wait // Put thread on wait queue // Context switch // Got the lock CS 519: Operating System Theory Implementing Locks Inside OS Kernel (cont) public void release() { if ((lockHolder = waitQueue.nextThread()) != null) lockHolder.ready(); // Wake up a waiting thread } This implementation is not quite right … what’s missing? Computer Science, Rutgers 62 CS 519: Operating System Theory Implementing Locks Inside OS Kernel (cont) public void release() { boolean intStatus = Machine.interrupt().disable(); if ((lockHolder = waitQueue.nextThread()) != null) lockHolder.ready(); Machine.interrupt().restore(intStatus); } Computer Science, Rutgers 63 CS 519: Operating System Theory Implementing Locks At User-Level Why? Expensive to enter the kernel Parallel programs on multiprocessor systems What’s the problem? Can’t disable interrupt … Many software algorithms for mutual exclusion See any OS book Disadvantages: very difficult to get correct So what do we do? Computer Science, Rutgers 64 CS 519: Operating System Theory Implementing Locks At User-Level Simple with a “little bit” of help from the hardware Atomic read-modify-write instructions Test-and-set Atomically read a variable and, if the value of the variable is currently 0, set it to 1 Fetch-and-increment Compare-and-swap Computer Science, Rutgers 65 CS 519: Operating System Theory Atomic Read-Modify-Write Instructions Test-and-set Read a memory location and, if the value is currently 0, set it to 1 Fetch-and-increment Return the value of of a memory location Increment the value by 1 (in memory, not the value returned) Compare-and-swap Compare the value of a memory location with an old value If the same, replace with a new value Computer Science, Rutgers 66 CS 519: Operating System Theory Simple Spin Lock Test-and-set Spin_lock(lock) { while (test-and-set(lock) == 0); } Spin_unlock(lock) { lock = 0; } Computer Science, Rutgers 67 CS 519: Operating System Theory What To Do While Waiting? Spinning Waiting threads keep testing location until it changes value Doesn’t work on uniprocessor system Blocking OS or RT system deschedules waiting threads Spinning vs. blocking becomes an issue in multiprocessor systems (with > 1 thread/processor) What is the main trade-off? How can we implement a blocking lock? Computer Science, Rutgers 68 CS 519: Operating System Theory Deadlock Computer Science, Rutgers Lock A Lock B A B 69 CS 519: Operating System Theory Deadlock Computer Science, Rutgers Lock A Lock B A B 70 CS 519: Operating System Theory Deadlock Computer Science, Rutgers Lock A Lock B A B 71 CS 519: Operating System Theory Deadlock (Cont’d) Deadlock can occur whenever multiple parties are competing for exclusive access to multiple resources How can we deal deadlocks? Deadlock prevention Design a system without one of mutual exclusion, hold and wait, no preemption or circular wait (four necessary conditions) To prevent circular wait, impose a strict ordering on resources. For instance, if need to lock variables A and B, always lock A first, then lock B Deadlock avoidance Deny requests that may lead to unsafe states (Banker’s algorithm) Running the algorithm on all resource requests is expensive Deadlock detection and recovery Check for circular wait periodically. If circular wait is found, abort all deadlocked processes (extreme solution but very common) Checking for circular wait is expensive Computer Science, Rutgers 72 CS 519: Operating System Theory Condition Variables A condition variable is always associated with: A condition A lock Typically used to wait for the condition to take on a given value Three operations: Computer Science, Rutgers public class CondVar { public Wait(Lock lock); public Signal(); public Broadcast(); // ... other stuff } 73 CS 519: Operating System Theory Condition Variables Wait(Lock lock) Release the lock Put thread object on wait queue of this CondVar object Yield the CPU to another thread When waken by the system, reacquire the lock and return Signal() If at least 1 thread is sleeping on cond_var, wake 1 up. Otherwise, no effect Waking up a thread means changing its state to Ready and moving the thread object to the run queue Broadcast() If 1 or more threads are sleeping on cond_var, wake everyone up Otherwise, no effect Computer Science, Rutgers 74 CS 519: Operating System Theory Producer/Consumer Example Imagine a web server with the following architecture: One “producer” thread listens for client http requests When a request is received, the producer enqueues it on a circular request queue with finite capacity (if there is room) A number of “consumer” threads services the queue as follows Remove the 1st request from the queue (if there is a request) Read data from disk to service the request How can the producer and consumers synchronize? Computer Science, Rutgers 75 CS 519: Operating System Theory Producer/Consumer (cont) public class SyncQueue { public boolean IsEmpty(); public boolean IsFull(); public boolean Enqueue(Request r); public Request Dequeue(); public LockVar lock = new Lock; public CondVar waitForNotEmpty = new CondVar; public CondVar waitForNotFull = new CondVar; ... } Computer Science, Rutgers 76 CS 519: Operating System Theory Producer public class Producer extends Thread { private SyncQueue requestQ; public Producer(SyncQueue q) {requestQ = q;} public void run() { // Accept a request from some client. // The request is stored in the object newRequest. requestQ.lock.Acquire(); while (requestQ.IsFull()) { waitForNotFull.Wait(); } requestQ.Enqueue(newRequest); waitForNotEmpty.Signal(); requestQ.lock.Release(); } } Computer Science, Rutgers 77 CS 519: Operating System Theory Consumer public class Consumer extends Thread { private SyncQueue requestQ; public Consumer(SyncQueue q) {requestQ = q;} public void run() { requestQ.lock.Acquire(); while (requestQ.IsEmpty()) { waitForNotEmpty.Wait(); } Request r = requestQ.Dequeue(); waitForNotFull.Signal() requestQ.lock.Release(); // Process the request } } Computer Science, Rutgers 78 CS 519: Operating System Theory Implementing Condition Variables Can you see how to do this from our discussion of how to implement locks? You will need to understand how for a later assignment Computer Science, Rutgers 79 CS 519: Operating System Theory Semaphore Synchronized counting variables Formally, a semaphore is comprised of: An integer value Two operations: P() and V() P() While value = 0, sleep Decrement value and return V() Increments value If there are any threads sleeping waiting for value to become non-zero, wakeup at least 1 thread Computer Science, Rutgers 80 CS 519: Operating System Theory Implementing Semaphores Let’s do this together on the board Can you see how to implement semaphores given locks and condition variables? Can you see how to implement locks and condition variables given semaphores? Hint: if not, learn how Computer Science, Rutgers 81 CS 519: Operating System Theory Monitors Semaphores have a few limitations: unstructured, difficult to program correctly. Monitors eliminate these limitations and are as powerful as semaphores A monitor consists of a software module with one or more procedures, an initialization sequence, and local data (can only be accessed by procedures) Only one process can execute within the monitor at any one time (mutual exclusion) Synchronization within the monitor implemented with condition variables (wait/signal) => one queue per condition variable Computer Science, Rutgers 82 CS 519: Operating System Theory Lock and Wait-free Synchronization (or Mutual Exclusion Considered Harmful) Problem: Critical sections If a process is delayed or halted in a critical section, hard or impossible for other processes to make progress Lock-free (aka non-blocking) concurrent objects Some process will complete an operation on the object in a finite number of steps Wait-free concurrent objects Each process attempting to perform an operation on the concurrent object will complete it in a finite number of steps Essential difference between these two? Computer Science, Rutgers 83 CS 519: Operating System Theory Herlihy’s Paper What’s the point? Lock and wait-free synchronization can be very useful for building multiprocessor systems; they provide progress guarantees Building lock and wait-free concurrent objects is HARD, so a methodology for implementing these objects is required Lock and wait-free synchronization provide guarantees but can be rather expensive – lots of copying M. Greenwald and D. Cheriton. The Synergy between Non-blocking Synchronization and Operating System Structure. In Proceedings of OSDI ’96, Oct, 1996. Computer Science, Rutgers 84 CS 519: Operating System Theory Single Word Protocol Fetch_and_add_sync(obj: integer, v: integer) returns(integer) success: boolean := false loop exit when success old: integer := obj new: integer := old+v success := compare_and_swap(obj, old, new) end loop return old end Fetch_and_add_sync Lock-free but not wait-free!! Computer Science, Rutgers 85 CS 519: Operating System Theory Small Objects Small object: occupies 1 block (or less) Basic idea of lock-free object implementation Allocate a new block Copy object to new block, making sure copy is consistent Modify copied block, i.e. perform operation on copied block Try to atomically replace pointer to old block with new one Basic idea of wait-free object implementation Same as before, except that processes should announce their operations in a shared data structure Any process in step 3 should perform all previously announced operations, not just its own operations Computer Science, Rutgers 86 CS 519: Operating System Theory Large Objects I’ll leave for you to read Basic idea is to make local changes in the data structure using small object protocol Complicated but not different than locking: e.g., if you lock an entire tree to modify some nodes, performance will go down the drain Computer Science, Rutgers 87 CS 519: Operating System Theory