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.