Tom Kelliher, CS42
Sept. 30, 1996
Critical section code:
int turn = 0; /* shared control variable */ Pi: /* i is 0 or 1 */ while (turn != i) ; /* busy wait */ CSi; turn = 1 - i;
Remove strict alternation requirement
int flag[2] = { FALSE, FALSE } /* flag[i] indicates that Pi is in its */ /* critical section */ while (flag[1 - i]) ; flag[i] = TRUE; CSi; flag[i] = FALSE;
Restore mutual exclusion
int flag[2] = { FALSE, FALSE } /* flag[i] indicates that Pi wants to */ /* enter its critical section */ flag[i] = TRUE; while (flag[1 - i]) ; CSi; flag[i] = FALSE;
Attempt to remove the deadlock
int flag[2] = { FALSE, FALSE } /* flag[i] indicates that Pi wants to */ /* enter its critical section */ flag[i] = TRUE; while (flag[1 - i]) { flag[i] = FALSE; delay; /* sleep for some time */ flag[i] = TRUE; } CSi; flag[i] = FALSE;
int flag[2] = { FALSE, FALSE } /* flag[i] indicates that Pi wants to */ /* enter its critical section */ int turn = 0; /* turn indicates which process has */ /* priority in entering its critical */ /* section flag[i] = TRUE; turn = 1 - i; while (flag[1 - i] && turn == 1 - i) ; CSi; flag[i] = FALSE;
Lamport's Bakery algorithm
int choosing[NPROCS] = { FALSE } /* cheating initializer */ int number[NPROCS] = { 0 } choosing[i] = TRUE; number[i] = max(number) + 1; choosing[i] = FALSE; for (j = 0; j < NPROCS; j++) { while (choosing[j]) ; while (number[j] != 0 && (number[j] < number[i] || number[j] == number[i] && j < i) ) ; } CSi; number[i] = 0;
wait(s) { while (s == 0) ; s--; }
Test and (possible) decrement executed atomically.
signal(s) { s++; }
semaphore mutex = 1; mutexbegin: wait(mutex); mutexend: signal(mutex);
semaphore sig = 0; int_hndl: signal(sig); driver: startread(); wait(sig);
Producer/Consumer problem:
semaphore count = N; semaphore mutex = 1; getbuf: wait(count); /* order important here */ wait(mutex); <find empty buffer> signal(mutex); return(buffer); relbuf: wait(mutex); <link released buffer> signal(mutex); signal(count);
Associate a ``blocked'' queue with each semaphore.
typedef struct semaphore { int value; pcb *head; }
Semaphore creation:
semaphore *createsem(int value) { semaphore *sem; sem = get_next_sem(); sem->value = value; sem->head = NULL; return (sem); } void wait(semaphore *sem) { /* need mutex goo here */ if (--sem->value < 0) { <update status of current process> insqu(sem->head->prev, current); scheduler(); } } void signal(semaphore *sem) { /* mutex */ pcb *proc; if (++sem->value <= 0) { proc = remqu(sem->head->next); <update status of proc> ordinsqu(ready, proc); if (proc->prio > current->prio) scheduler(); } }
Write a semaphore solution to the producer/consumer problem when you have N buffers.