2 Dining Puppies Mutex Failure 1 Outline for

  • Slides: 43
Download presentation
2 -Dining Puppies Mutex Failure 1

2 -Dining Puppies Mutex Failure 1

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

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

Readers/Writers Problem Synchronizing access to a file or data record in a database such

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. 3

Template for Readers/Writers Reader() {while (true) { Writer() {while (true) { /*request r access*/

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

Template for Readers/Writers Reader() {while (true) { Writer() {while (true) { fd = open(foo,

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

Template for Readers/Writers Reader() {while (true) { Writer() {while (true) { start. Read(); start.

Template for Readers/Writers Reader() {while (true) { Writer() {while (true) { start. Read(); start. Write(); read write end. Read(); end. Write(); } } 6

R/W - Monitor Style Boolean busy = false; int num. Readers = 0; Lock

R/W - Monitor Style Boolean busy = false; int num. Readers = 0; Lock files. Mutex; Condition OKto. Write, OKto. Read; void start. Read () { files. Mutex. Acquire( ); while ( busy ) OKto. Read. Wait(&files. Mutex); num. Readers++; files. Mutex. Release( ); } void end. Read () { files. Mutex. Acquire( ); num. Readers--; if (num. Readers == 0) OKto. Write. Signal(&files. Mutex); files. Mutex. Release( ); } void start. Write() { files. Mutex. Acquire( ); while (busy || num. Readers != 0) OKto. Write. Wait(&files. Mutex); busy = true; files. Mutex. Release( ); } void end. Write() { files. Mutex. Acquire( ); busy = false; OKto. Read. Broadcast(&files. Mutex); OKto. Write. Signal(&files. Mutex); files. Mutex. Release( ); } 7

Guidelines for Choosing Lock Granularity 1. Keep critical sections short. Push “noncritical” statements outside

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!” 8

Semaphore Solution int read. Count = 0; semaphore mutex = 1; semaphore write. Block

Semaphore Solution int read. Count = 0; semaphore mutex = 1; semaphore write. Block = 1; 9

Reader(){ while (TRUE) { other stuff; P(mutex); read. Count = read. Count +1; if(read.

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

Attempt at Writer Priority int read. Count = 0, write. Count = 0; semaphore

Attempt at Writer Priority int read. Count = 0, write. Count = 0; semaphore mutex 1 = 1, mutex 2 = 1; semaphore read. Block = 1; semaphore write. Block = 1; 11

Reader 2 Reader(){ Writer(){ while (TRUE) { while(TRUE){ other stuff; Reader 1 P(read. Block);

Reader 2 Reader(){ Writer(){ while (TRUE) { while(TRUE){ other stuff; Reader 1 P(read. Block); P(mutex 2); P(mutex 1); write. Count = write. Count +1; read. Count = read. Count +1; if (write. Count == 1) Writer 1 if(read. Count == 1) P(read. Block); P(write. Block); V(mutex 2); V(mutex 1); P(write. Block); V(read. Block); access resource; V(write. Block); P(mutex 1); P(mutex 2); read. Count = read. Count -1; write. Count - 1; if(read. Count == 0) if (write. Count == 0) V(write. Block); V(read. Block); V(mutex 1); }} V(mutex 2); }} 12

Reader 2 Reader(){ while (TRUE) { other stuff; P(read. Block); P(mutex 1); read. Count

Reader 2 Reader(){ while (TRUE) { other stuff; P(read. Block); P(mutex 1); read. Count = read. Count +1; if(read. Count == 1) Reader 1 P(write. Block); V(mutex 1); V(read. Block); access resource; P(mutex 1); read. Count = read. Count -1; if(read. Count == 0) V(write. Block); V(mutex 1); }} Writer(){ while(TRUE){ other stuff; P(mutex 2); write. Count = write. Count +1; if (write. Count == 1) Writer 1 P(read. Block); V(mutex 2); P(write. Block); access resource; V(write. Block); P(mutex 2); write. Count - 1; if (write. Count == 0) V(read. Block); V(mutex 2); }} 13

Reader(){ while (TRUE) { other stuff; P(write. Pending); P(read. Block); P(mutex 1); read. Count

Reader(){ while (TRUE) { other stuff; P(write. Pending); P(read. Block); P(mutex 1); read. Count = read. Count +1; if(read. Count == 1) P(write. Block); V(mutex 1); V(read. Block); V(write. Pending); access resource; P(mutex 1); read. Count = read. Count -1; if(read. Count == 0) V(write. Block); V(mutex 1); }} Writer(){ while(TRUE){ other stuff; P(mutex 2); write. Count = write. Count +1; if (write. Count == 1) P(read. Block); V(mutex 2); P(write. Block); access resource; V(write. Block); P(mutex 2); write. Count - 1; if (write. Count == 0) V(read. Block); V(mutex 2); }} 14

Reader 2 Reader(){ Writer(){ while (TRUE) { while(TRUE){ other stuff; P(write. Pending); P(mutex 2);

Reader 2 Reader(){ Writer(){ while (TRUE) { while(TRUE){ other stuff; P(write. Pending); P(mutex 2); P(read. Block); write. Count = write. Count +1; P(mutex 1); if (write. Count == 1) Writer 1 read. Count = read. Count +1; P(read. Block); if(read. Count == 1) Reader 1 V(mutex 2); P(write. Block); V(mutex 1); V(read. Block); access resource; V(write. Pending); V(write. Block); access resource; P(mutex 2); P(mutex 1); write. Count - 1; read. Count = read. Count -1; if (write. Count == 0) if(read. Count == 0) V(read. Block); V(write. Block); V(mutex 2); V(mutex 1); }} }} Assumptions about semaphore semantics? 15

Reader(){ Writer(){ while (TRUE) { while(TRUE){ Reader 2 other stuff; P(write. Pending); P(mutex 2);

Reader(){ Writer(){ while (TRUE) { while(TRUE){ Reader 2 other stuff; P(write. Pending); P(mutex 2); P(read. Block); write. Count = write. Count +1; P(mutex 1); if (write. Count == 1) Writer 1 read. Count = read. Count +1; P(read. Block); if(read. Count == 1) Reader 1 V(mutex 2); P(write. Block); V(mutex 1); V(read. Block); access resource; V(write. Pending); V(write. Block); access resource; P(mutex 2); P(mutex 1); write. Count - 1; read. Count = read. Count -1; if (write. Count == 0) if(read. Count == 0) V(read. Block); V(write. Block); V(mutex 2); V(mutex 1); }} }} Assume the write. Pending semaphore was omitted. What would 16 happen?

Assume the write. Pending semaphore was omitted in the solution just given. What would

Assume the write. Pending 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(read. Block); Reader 1 executes P(mutex 1); Writer 1 arrives, waits at P(read. Block); Reader 2 arrives, waits at P(read. Block); Reader 1 executes V(mutex 1); then V(read. Block); Reader 2 may now proceed…wrong 17

Linux Reader/Writer Spinlocks • Class of reader/writer problems • Multiple readers OK • Mutual

Linux Reader/Writer Spinlocks • 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 18

Linux Reader/Writer Semaphores • All reader / writer semaphores are mutexes (usage count 1)

Linux Reader/Writer Semaphores • 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 19

Message-Passing 20

Message-Passing 20

Interprocess Communication Messages • Assume no explicit sharing of data elements in the address

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. 21

Issues • System calls for sending and receiving messages with the OS(s) acting as

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? 22

Send and Receive 23

Send and Receive 23

UNIX Sockets for Client/ Server Message Passing Server 1. Create a named socket syscalls:

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

5 DP – Direct Send/Receive Message Passing Between Philosophers Fork please? Philosopher 0 (thinking)

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

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

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

Fork please? Philosopher 0 (thinking) Philosopher 4 Philosopher 1 Philosopher 3 (eating) Philosopher 2

Fork please? Philosopher 0 (thinking) Philosopher 4 Philosopher 1 Philosopher 3 (eating) Philosopher 2 27

Fork please? Philosopher 0 (thinking) Philosopher 4 I’ll ignore that request until I’m done

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

Philosopher 0 (thinking) Philosopher 4 Fork please? Philosopher 1 Philosopher 3 (eating) Fork please?

Philosopher 0 (thinking) Philosopher 4 Fork please? Philosopher 1 Philosopher 3 (eating) Fork please? Philosopher 2 29

Start here Client / Server server-> 30

Start here Client / Server server-> 30

Example: Time Service 31

Example: Time Service 31

Example: Time Service via Messages 32

Example: Time Service via Messages 32

Client / Server with Threads 33

Client / Server with Threads 33

Hiding Message-Passing: RPC 34

Hiding Message-Passing: RPC 34

Remote Procedure Call - RPC • Looks like a nice familiar procedure call P

Remote Procedure Call - RPC • Looks like a nice familiar procedure call P 0 result = foo(param); P 1 Receive 35

Remote Procedure Call - RPC • Looks like a nice familiar procedure call P

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

Remote Procedure Call - RPC • Looks like a nice familiar procedure call P

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

Remote Procedure Call - RPC • Looks like a nice familiar procedure call P

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

Remote Procedure Call - RPC • Looks like a nice familiar procedure call P

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

Remote Procedure Call - RPC • Looks like a nice familiar procedure call P

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

5 DP via RPC with Fork Manager • Looks like a nice familiar procedure

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

Example: Time Service via RPC 42

Example: Time Service via RPC 42

RPC Issues 44

RPC Issues 44