CS241 System ProgrammingProcess Synchronization (4) Klara Nahrstedt Lecture 9 2/8/2006
Content • Example: Producer and Consumer Implementation Using Mutex and Semaphores • Other Synchronization Primitives • Barriers • Message Passing • Classical IPC Problems • Dining Philosophers • Reader and Writer • Summary CS 241 - System Programming, Klara Nahrstedt
Administrative • Read: T: Chapter 2.2 and 2.3 • Read: R&R: 16.1-16.3 (Producer and Consumer implementation using mutex and semaphores) • Read: R&R: 13.6 (Readers and Writers) • MP1 is running • Quiz 2: Friday, February 10, 2006 (topic – processes, threads and synchronization) CS 241 - System Programming, Klara Nahrstedt
Bounded Buffer Consumer Producer Implementation Using Mutex and Semaphores(R: Ch 16 pp 549-563) • A consumer must not remove an item • That a producer is busy inserting • That is not there • That has already been removed • A producer must not insert an item • When there are no free slots • Overwrite an item that has not been removed CS 241 - System Programming, Klara Nahrstedt
Producer Consumer Problem bufin bufout #include <pthread.h> #include "buffer.h" static buffer_t buffer[BUFSIZE]; static pthread_mutex_t bufferlock = PTHREAD_MUTEX_INITIALIZER; static int bufin = 0; static int bufout = 0; CS 241 - System Programming, Klara Nahrstedt
Producer Consumer Problem int getitem(buffer_t *itemp) { /* remove item from buffer and put in *itemp */ int error; if (error = pthread_mutex_lock(&bufferlock)) /*no mutex, give up*/ return error; *itemp = buffer[bufout]; bufout = (bufout + 1) % BUFSIZE; return pthread_mutex_unlock(&bufferlock); } int putitem(buffer_t item) { /* insert item in the buffer */ int error; if (error = pthread_mutex_lock(&bufferlock)) /*no mutex, give up*/ return error; buffer[bufin] = item; bufin = (bufin + 1) % BUFSIZE; return pthread_mutex_unlock(&bufferlock); } CS 241 - System Programming, Klara Nahrstedt
Producer Consumer using Semaphores bufin bufout #include <errno.h> #include <pthread.h> #include <semaphore.h> #include "buffer.h" static buffer_t buffer[BUFSIZE]; static pthread_mutex_t bufferlock = PTHREAD_MUTEX_INITIALIZER; static int bufin = 0; static int bufout = 0; static sem_t semitems; static sem_t semslots; Note: #semitems+#semslots=BUFSIZE CS 241 - System Programming, Klara Nahrstedt
Producer Consumer Semaphores int bufferinit(void) { /*call this exactly once BEFORE getitem and putitem */ int error; if (sem_init(&semitems, 0, 0)) return errno; if (sem_init(&semslots, 0, BUFSIZE)) { error = errno; sem_destroy(&semitems); /* free the other semaphore */ return error; } return 0; } CS 241 - System Programming, Klara Nahrstedt
Producer Consumer Semaphores int getitem(buffer_t *itemp) { /* remove item from buffer and put in *itemp */ int error; while (((error = sem_wait(&semitems)) == -1) && (errno == EINTR)) ; if (error) return errno; if (error = pthread_mutex_lock(&bufferlock)) return error; *itemp = buffer[bufout]; bufout = (bufout + 1) % BUFSIZE; if (error = pthread_mutex_unlock(&bufferlock)) return error; if (sem_post(&semslots) == -1) return errno; return 0; } CS 241 - System Programming, Klara Nahrstedt
Producer Consumer Semaphores int putitem(buffer_t item) { /* insert item in the buffer */ int error; while (((error = sem_wait(&semslots)) == -1) && (errno == EINTR)) ; if (error) return errno; if (error = pthread_mutex_lock(&bufferlock)) return error; buffer[bufin] = item; bufin = (bufin + 1) % BUFSIZE; if (error = pthread_mutex_unlock(&bufferlock)) return error; if (sem_post(&semitems) == -1) return errno; return 0; } CS 241 - System Programming, Klara Nahrstedt
Barriers • Use of a barrier • processes approaching a barrier • all processes but one blocked at barrier • last process arrives, all are let through • Problem: • Waste CPU if workloads are unbalanced CS 241 - System Programming, Klara Nahrstedt
Barriers CS 241 - System Programming, Klara Nahrstedt
Message Passing • Send (destination, &message) • Receive (source, &message) • Message size: Fixed or Variable size. • Real life analogy: conversation CS 241 - System Programming, Klara Nahrstedt
Producer/Consumer Implementation using Message Passing CS 241 - System Programming, Klara Nahrstedt
Indirect Communication send(A,message) /* send a message to mailbox A */ receive(A,message) /* receive a message from mailbox A */ • Mailbox is an abstract object into which a message can be placed to or removed from. CS 241 - System Programming, Klara Nahrstedt
Rendezvous Communication • No buffering – all buffering between sender and receiver is eliminated • Rendezvous Protocol: • If ‘send’ is done before ‘receive’, the sending process blocks until ‘receive happens, and only then a message is copied directly from sender to receiver • If ‘receive’ happens before ‘send’, receiver blocks until ‘send’ happens CS 241 - System Programming, Klara Nahrstedt
Dining Philosophers (1) • Philosophers eat/think • Eating needs 2 forks • Pick one fork at a time • How to prevent deadlock CS 241 - System Programming, Klara Nahrstedt
A nonsolution to the dining philosophers problem Dining Philosophers (2) Does This Work? CS 241 - System Programming, Klara Nahrstedt
binary semaphore s[N]; /* one semaphore per philosopher */ Initialize s[N] to 1 void take_fork(int i) { Down(&s[i]); } void put_fork(int i) {Up(&s[i]); } void philosopher(int i) { while(TRUE) { think(); take_fork(i); take_fork((i+1)%N); eat(); put_fork(i); put_fork((i+1)%N); } } Implementation of Non-solution Problem: Possible Deadlock if each philosopher (in circular manner) takes one fork CS 241 - System Programming, Klara Nahrstedt
To break the deadlock possibility, break the circular waiting, e.g., allow only N-1 philosophers to participate Introduce another counting semaphore for coordination and allow only N-1 philosophers to access the forks semaphore F; /* counting semaphore*/ Initialize F to N-1; void philosopher(int i) { while(TRUE) { think(); down(&F); take_fork(i); take_fork((i+1)%N); eat(); put_fork(i); put_fork((i+1)%N); up(&F); } } Simple Solution to the Deadlock Situation CS 241 - System Programming, Klara Nahrstedt
Dining Philosophers (3) A Solution to dining philosophers problem (part 1) Using Semaphores CS 241 - System Programming, Klara Nahrstedt
Dining Philosophers (3) CS 241 - System Programming, Klara Nahrstedt
Dining Philosophers (4) A Solution to dining philosophers problem (part 2) Using Semaphores CS 241 - System Programming, Klara Nahrstedt
Dining Philosophers (4) CS 241 - System Programming, Klara Nahrstedt
First Readers-Writers Problem • Let processes reading do so concurrently • Let processes writing do so one at a time Typedef in semaphore; Semaphore mutex = 1; Semaphore wrt = 1; Int readc = 0; CS 241 - System Programming, Klara Nahrstedt
Writer While (TRUE) { Think_up_data(); /*noncritical section*/ down(&wrt); do writing up(&wrt); } Reader While (TRUE) { down(&mutex); readc:=readc+1; if readc == 1 then down(&wrt); up(&mutex); do reading down&mutex) readc:=readc-1; if readc == 0 then up(&wrt); up(&mutex); Use read data } First Readers-Writers Problem CS 241 - System Programming, Klara Nahrstedt
Reminder • MP1 due February 13 • Quiz 2 on February 10 CS 241 - System Programming, Klara Nahrstedt