1 / 34

Operating Systems Design (CS 423)

Learn about implementing producer-consumer systems using monitors, locks, and condition variables for efficient synchronization in operating system design. Understand scenarios, bug fixes, and reader-writer locks implementation.

ljudy
Download Presentation

Operating Systems Design (CS 423)

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Operating Systems Design (CS 423) Elsa L Gunter 2112 SC, UIUC http://www.cs.illinois.edu/class/cs423/ Based on slides by Roy Campbell, Sam King, and Andrew S Tanenbaum

  2. Producer-consumer: Example • Coke machine • Delivery person (producer) • Customers buy cokes (consumer) • Coke machine has finite space (buffer)

  3. Producer-consumer using monitors • Operations • Add coke to machine • Take coke out of machine • Variables • Shared data for the coke machine • maxCokes (capacity of machine) • numCokes (number of cokes in machine)

  4. Producer-consumer using monitors • One lock (cokeLock) to protect shared data • Fewer locks easier to program, less concur. • Ordering constraints • Consumer must wait for producer to fill buffer if all buffers are empty (hasCoke) • Producer must wait for consumer to take from buffer if buffer is completely full (hasRoom)

  5. Basic behavior – What’s wrong? producer() consumer: lock(cokeLock); lock(cokeLock); put one coke take one coke out in machine; of machine; unlock(cokeLock); unlock(cokeLock); } }

  6. Basic behavior producer() consumer() lock(cokeLock); lock(cokeLock); while (numCokes == while(numCokes == 0){ maxCokes){ wait(cokrLock,hasCoke); wait(cokeLock,hasRoom); put one coke take one coke out in machine; of machine; signal(cokeLock;hasCoke); signal(cokeLock,hasRoom); unlock(cokeLock); unlock(cokeLock); } }

  7. What if producer loops? Is it OK? Producer() { lock(cokeLock); while(1) { while(numCokes == max) { wait(cokeLock, hasRoom); } add coke to machine; signal(hasCoke); } unlock(cokeLock); }

  8. What if we add sleep? Producer() { lock(cokeLock); while(1) { sleep(1 hour); while(numCokes == max) { wait(cokeLock, hasRoom); } add coke to machine; signal(hasCoke); } unlock(cokeLock); }

  9. What is wrong here? (hard) producer() consumer() lock(cokeLock); lock(cokeLock); while (numCokes while(numCokes == 0){ == maxCokes){ wait(cokeLock,condVar); wait(cokeLock,condVar)}; put one coke take one coke out in machine; of machine; signal(cokeLock;condVar); signal(cokeLock,condVar); unlock(cokeLock); unlock(cokeLock); } }

  10. Problem Scenario (max = 1) P1 P2 C1 C2 lock numC == 0 wait lock numC == 0 wait lock numC < max numC ++ signal -------------------------- unlock lock numC=max wait !numC==0 numC— signal ---- numC == 0 wait Bug!

  11. Solution to too few Cond Vars • Use broadcast • Will wake everyone up • Each will check its own progress condition • First one to check and get true will go • Much more inefficient than signal and multiple condition variables

  12. Reader – Writer Locks • Problem: With standard locks, threads acquire lock to read shared data • Prevents other reader threads from accessing data • Can we allow more concurrency?

  13. Reader – Writer Locks • Problem definition: • Shared data that will be read and written by multiple threads • Allow multiple readers to access shared data when no threads are writing data • A thread can write shared data only when no other thread is reading or writing the shared data

  14. Interface • readerStart() • readerFinish() • writerStart() • writerFinish() • Many threads can be in between a readStart and readerFinish • Only one thread can be between writerStart and writierFinish

  15. Example: Calendar • Goal: online calendar for a class • Lots of people may read it at the same time • Only one person updates it (prof, Tas) • Shared data • map<date, listOfEvents> EventMap • listOfEvents GetEvents(date) • AddEvent(data, newEvent)

  16. Basic Code – Single Threaded GetEvents(date) { List events = EventMap.find(date).copy(); return events; } AddEvent(data, newEvent) { EventMap.find(date) += newEvent; }

  17. Inefficient Multi-threaded code GetEvents(date) { lock(mapLock); List events = EventMap.find(date).copy(); unlock(mapLock); return events; } AddEvent(data, newEvent) { lock(mapLock); EventMap.find(date) += newEvent; unlock(mapLock); }

  18. How to do with reader – write locks? GetEvents(date) { List events = EventMap.find(date).copy(); return events; } AddEvent(data, newEvent) { EventMap.find(date) += newEvent; }

  19. How to do with reader – write locks? GetEvents(date) { readerStart(maRWLock); List events = EventMap.find(date).copy(); readerFinish(mapRWLock); return events; } AddEvent(data, newEvent) { writerStart(maRWLock); EventMap.find(date) += newEvent; writerFinish(mapRWLock); }

  20. Additional Layer of Synchronization Concurrent programs Even higher-level synchronization High-level synchronization provided by software Low-level atomic operations provided by hardware

  21. Reader – Writer Locks using Monitors • Note: Implement Reader/Writer Locks as an abstractions, not as an integrated part of code • Central Questions: • Shared Data? • Ordering Constraints? • How many Condition Variables?

  22. Reader – Writer Locks using Monitors • Note: Implement Reader/Writer Locks as an abstractions, not as an integrated part of code • Central Questions: • Shared Data? NumReaders NumWriters • Ordering Constraints? • How many Condition Variables?

  23. Reader – Writer Locks using Monitors • Note: Implement Reader/Writer Locks as an abstractions, not as an integrated part of code • Central Questions: • Shared Data? NumReaders NumWriters • Ordering Constraints? • readerStart must wait if there are writers • writerStart must wait if there are readers or writes • How many Condition Variables?

  24. Reader – Writer Locks using Monitors • Note: Implement Reader/Writer Locks as an abstractions, not as an integrated part of code • Central Questions: • Shared Data? NumReaders NumWriters • Ordering Constraints? • readerStart must wait if there are writers • writerStart must wait if there are readers or writes • How many Condition Variables? • One: condRW (no readers or writers)

  25. Basic Implementation readerStart() { } readerFinish() { }

  26. Basic Implementation readerStart() { lock(lockRW); while(numWriters > 0){ wait(lockRW,condRW); }; numReaders++; unlock(lockRW); } readerFinish() { lock(lockRW); numReaders--; broadcast(lockRW,condWR); unlock(lockRW); }

  27. Basic Implementation writerStart() { lock(lockRW); while(numReaders > 0|| numWriters >0){ wait(lockRW,condRW); }; numWriters++; unlock(lockRW); } writerFinish() { lock(lockRW); numWriters--; broadcast(lockRW,condWR); unlock(lockRW); }

  28. Better Implementation readerStart() { lock(lockRW); while(numWriters > 0){ wait(lockRW,condRW); }; numReaders++; unlock(lockRW); } readerFinish() { lock(lockRW); numReaders--. if(numReaders == 0){ signal(lockRW,condWR); }; unlock(lockRW); }

  29. Better Implementation • Can we change broadcast to signal in writerFinish() in a similar way? • Many Readers at a time, but only one Writer • How long will one writer wait? • Starvation – process never gets a turn • How to give priority to writer?

  30. Write Priority readerStart() { lock(lockRW); while(activeWriters + waitingWriters > 0){ wait(lockRW,condRW); }; numReaders++; unlock(lockRW); }

  31. Write Priority writerStart() { lock(lockRW); waitingWriters ++; while(numReaders > 0|| numWriters >0){ wait(lockRW,condRW); }; waitingWriters--; numWriters++; unlock(lockRW); }

  32. Lock and Reader / Writer Locks • Reader-writer functions are similar to standard locks • Call readerStart before read shared data • Call readerFinish after done reading data • Call writerStart before writing shared data • Call writerFinish after done writing data • These are known as “reader-writer locks” • Thread in between readerStart and readerFinish “holds a read lock” • Thread in between writerStart and writerFinish “holds a write lock” • Compare reader-writer locks with standard locks

  33. Semaphores (not used in this class) • Like a generalized lock • Semaphore has a non-negative integer value (>= 0) and supports • Down(): wait for semaphore to become positive, decrement semaphore by 1 (originally called “P” for Dutch “proberen”) • Up(): increment semaphore by 1 (originally called “V” for Dutch “verhogen”). This wakes up a thread waiting in down(), if there are any. • Can also set the initial value for the semaphore

  34. Semaphores – Quick Review • The key parts in down() and up() are atomic • Two down calls at the same time cannot decrement the value below 0 • Binary semaphore • Value is either 0 or 1 • Down() waits for value to become 1, then sets to 0 • Up() sets value to 1, waking up waiting down

More Related