1 / 43

2-Dining Puppies Mutex Failure

This text discusses the readers/writers problem and outlines different solutions using mutexes and semaphores. It covers the concepts of message passing and administrative details of the problem.

harrill
Download Presentation

2-Dining Puppies Mutex Failure

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. 2-Dining Puppies Mutex Failure

  2. Outline for Today • Objective: • Reader-writer problem • Message Passing • Administrative details:

  3. Readers/Writers Problem Synchronizing access to a file or data record in a database such that any number of threads requesting read-only access are allowed but only one thread requesting write access is allowed, excluding all readers.

  4. Reader() {while (true) { read } } Writer() {while (true) { write } } Template for Readers/Writers /*request r access*/ /*request w access*/ /*release r access*/ /*release w access*/

  5. Reader() {while (true) { read } } Writer() {while (true) { write } } Template for Readers/Writers fd = open(foo, 0); fd = open(foo, 1); close(fd); close(fd);

  6. Reader() {while (true) { read } } Writer() {while (true) { write } } Template for Readers/Writers startRead(); startWrite(); endRead(); endWrite();

  7. Boolean busy = false; int numReaders = 0; Lock filesMutex; Condition OKtoWrite, OKtoRead; void startRead () { filesMutex.Acquire( ); while ( busy ) OKtoRead.Wait(&filesMutex); numReaders++; filesMutex.Release( );} void endRead () { filesMutex.Acquire( ); numReaders--; if (numReaders == 0) OKtoWrite.Signal(&filesMutex); filesMutex.Release( );} void startWrite() { filesMutex.Acquire( ); while (busy || numReaders != 0) OKtoWrite.Wait(&filesMutex); busy = true; filesMutex.Release( );} void endWrite() { filesMutex.Acquire( ); busy = false; OKtoRead.Broadcast(&filesMutex); OKtoWrite.Signal(&filesMutex); filesMutex.Release( );} R/W - Monitor Style

  8. Guidelines for Choosing Lock Granularity 1. Keep critical sections short. Push “noncritical” statements outside of critical sections to reduce contention. 2. Limit lock overhead. Keep to a minimum the number of times mutexes are acquired and released. Note tradeoff between contention and lock overhead. 3. Use as few mutexes as possible, but no fewer. Choose lock scope carefully: if the operations on two different data structures can be separated, it may be more efficient to synchronize those structures with separate locks. Add new locks only as needed to reduce contention. “Correctness first, performance second!”

  9. Semaphore Solution int readCount = 0; semaphore mutex = 1; semaphore writeBlock = 1;

  10. Reader(){ while (TRUE) { other stuff; P(mutex); readCount = readCount +1; if(readCount == 1) P(writeBlock); V(mutex); access resource; P(mutex); readCount = readCount -1; if(readCount == 0) V(writeBlock); V(mutex); }} Writer(){ while(TRUE){ other stuff; P(writeBlock); access resource; V(writeBlock); }}

  11. Attempt at Writer Priority int readCount = 0, writeCount = 0; semaphore mutex1 = 1, mutex2 = 1; semaphore readBlock = 1; semaphore writeBlock = 1;

  12. Reader(){ while (TRUE) { other stuff; P(readBlock); P(mutex1); readCount = readCount +1; if(readCount == 1) P(writeBlock); V(mutex1); V(readBlock); access resource; P(mutex1); readCount = readCount -1; if(readCount == 0) V(writeBlock); V(mutex1); }} Writer(){ while(TRUE){ other stuff; P(mutex2); writeCount = writeCount +1; if (writeCount == 1) P(readBlock); V(mutex2); P(writeBlock); access resource; V(writeBlock); P(mutex2); writeCount - writeCount - 1; if (writeCount == 0) V(readBlock); V(mutex2); }} Reader2 Reader1 Writer1

  13. Reader(){ while (TRUE) { other stuff; P(readBlock); P(mutex1); readCount = readCount +1; if(readCount == 1) P(writeBlock); V(mutex1); V(readBlock); access resource; P(mutex1); readCount = readCount -1; if(readCount == 0) V(writeBlock); V(mutex1); }} Writer(){ while(TRUE){ other stuff; P(mutex2); writeCount = writeCount +1; if (writeCount == 1) P(readBlock); V(mutex2); P(writeBlock); access resource; V(writeBlock); P(mutex2); writeCount - writeCount - 1; if (writeCount == 0) V(readBlock); V(mutex2); }} Reader2 Reader1 Writer1

  14. Reader(){ while (TRUE) { other stuff; P(writePending); P(readBlock); P(mutex1); readCount = readCount +1; if(readCount == 1) P(writeBlock); V(mutex1); V(readBlock); V(writePending); access resource; P(mutex1); readCount = readCount -1; if(readCount == 0) V(writeBlock); V(mutex1); }} Writer(){ while(TRUE){ other stuff; P(mutex2); writeCount = writeCount +1; if (writeCount == 1) P(readBlock); V(mutex2); P(writeBlock); access resource; V(writeBlock); P(mutex2); writeCount - writeCount - 1; if (writeCount == 0) V(readBlock); V(mutex2); }}

  15. Reader(){ while (TRUE) { other stuff; P(writePending); P(readBlock); P(mutex1); readCount = readCount +1; if(readCount == 1) P(writeBlock); V(mutex1); V(readBlock); V(writePending); access resource; P(mutex1); readCount = readCount -1; if(readCount == 0) V(writeBlock); V(mutex1); }} Writer(){ while(TRUE){ other stuff; P(mutex2); writeCount = writeCount +1; if (writeCount == 1) P(readBlock); V(mutex2); P(writeBlock); access resource; V(writeBlock); P(mutex2); writeCount - writeCount - 1; if (writeCount == 0) V(readBlock); V(mutex2); }} Reader2 Writer1 Reader1 Assumptions about semaphore semantics?

  16. Reader(){ while (TRUE) { other stuff; P(writePending); P(readBlock); P(mutex1); readCount = readCount +1; if(readCount == 1) P(writeBlock); V(mutex1); V(readBlock); V(writePending); access resource; P(mutex1); readCount = readCount -1; if(readCount == 0) V(writeBlock); V(mutex1); }} Writer(){ while(TRUE){ other stuff; P(mutex2); writeCount = writeCount +1; if (writeCount == 1) P(readBlock); V(mutex2); P(writeBlock); access resource; V(writeBlock); P(mutex2); writeCount - writeCount - 1; if (writeCount == 0) V(readBlock); V(mutex2); }} Reader2 Writer1 Reader1 Assume the writePending semaphore was omitted. What would happen?

  17. Assume the writePending semaphore was omitted in the solution just given.What would happen? This is supposed to give writers priority. However, consider the following sequence: Reader 1 arrives, executes thro’ P(readBlock); Reader 1 executes P(mutex1); Writer 1 arrives, waits at P(readBlock); Reader 2 arrives, waits at P(readBlock); Reader 1 executes V(mutex1); then V(readBlock); Reader 2 may now proceed…wrong

  18. Class of reader/writer problems Multiple readers OK Mutual exclusion for writers No upgrade from reader lock to writer lock Favors readers – starvation of writers possible rwlock_t read_lock,read_unlock read_lock_irq // also unlock read_lock_irqsave read_unlock_irqrestore write_lock,write_unlock //_irq,_irqsave,_irqrestore write_trylock rw_is_locked Linux Reader/Writer Spinlocks

  19. All reader / writer semaphores are mutexes (usage count 1) Multiple readers, solo writer Uninterruptible sleep Possible to downgrade writer to reader down_read down_write up_read up_write downgrade_writer down_read_trylock down_write_trylock Linux Reader/Writer Semaphores

  20. Message-Passing

  21. Interprocess Communication - Messages • Assume no explicit sharing of data elements in the address spaces of processes wishing to cooperate/communicate. • Essence of message-passing is copying(although implementations may avoid actual copies whenever possible). • Problem-solving with messages - has a feel of more active involvement by participants.

  22. Issues • System calls for sending and receiving messages with the OS(s) acting as courier. • Variations on exact semantics of primitives and in the definition of what comprises a message. • Naming - direct (to/from pids), indirect (to distinct objects - e.g., mailboxes, ports, sockets) • How do unrelated processes “find” each other? • Buffering - capacity and blocking semantics. • Guarantees - in-order delivery? no lost messages?

  23. Send and Receive

  24. Server 1. Create a named socketsyscalls:sfd = socket(…)bind (sfd, ptr,len) 2. Listen for clientslisten(sfd,numpend) 4. Connection made and continue listeningcfd=accept(sfd, …) 5. Exchange datawrite(cfd, …) 6. Done: close(cfd); 7. Really done: close(sfd); Client 3. Create unnamed socket & ask for connectionsyscalls:cfd=socket(…)err=connect(cfd, ptr, …) 5. Exchange data read(cfd, …) 6. Done: close(cfd); In a child process of server UNIX Sockets for Client/ Server Message Passing name name

  25. 5 DP – Direct Send/Receive Message Passing Between Philosophers Forkplease? Philosopher 0(thinking) Philosopher 4 Philosopher 1 Philosopher 3 (eating) Philosopher 2

  26. Umm. Oh yeah. Philosopher 0(thinking) Philosopher 4 Philosopher 1 Philosopher 3 (eating) Philosopher 2

  27. Forkplease? Philosopher 0(thinking) Philosopher 4 Philosopher 1 Philosopher 3 (eating) Philosopher 2

  28. Forkplease? Philosopher 0(thinking) Philosopher 4 I’ll ignore that request until I’m done Philosopher 1 Philosopher 3 (eating) Philosopher 2

  29. Philosopher 0(thinking) Philosopher 4 Forkplease? Philosopher 1 Philosopher 3 (eating) Forkplease? Philosopher 2

  30. Start here Client / Server server->

  31. Example: Time Service

  32. Example: Time Service via Messages

  33. Client / Server with Threads

  34. Hiding Message-Passing: RPC

  35. Remote Procedure Call - RPC • Looks like a nice familiar procedure call P1 P0 Receive result = foo(param);

  36. Remote Procedure Call - RPC • Looks like a nice familiar procedure call P1 P0 please do foo for P0 with param Receive result = foo(param); blocked here

  37. Remote Procedure Call - RPC • Looks like a nice familiar procedure call P1 P0 please do foo for P0 with param Receive result = foo(param); r = foo(param); // actual call blocked here

  38. Remote Procedure Call - RPC • Looks like a nice familiar procedure call P1 P0 Receive result = foo(param); r = foo(param); // actual call blocked here Reply returning r to P0

  39. Remote Procedure Call - RPC • Looks like a nice familiar procedure call P1 P0 Receive result = foo(param); r = foo(param); // actual call Reply returning r to P0

  40. Remote Procedure Call - RPC • Looks like a nice familiar procedure call P1 P0 Receive result = foo(param); r = foo(param); // actual call Reply

  41. 5DP via RPC with Fork Manager • Looks like a nice familiar procedure call Fork Server Philosopher0 Receive result = PickupForks (0); r = proc(param); // explicit queuing when necessary Reply

  42. Example: Time Service via RPC

  43. RPC Issues

More Related