UNIVERSITY OF WISCONSIN-MADISON
Computer Sciences Department | ||
CS 537
Fall 2007 | A. Arpaci-Dusseau | |
Quiz #6: Take-home: Due Oct 18, 2007 |
Name: |
The following code specifies different implementations for a lock. Assume that the application calls lock_init() before using the lock and calls lock_acquire() before entering the critical section and lock_release() after exiting the critical section. Assume that the tid of each thread is either 0 or 1. Assume a uniprocessor.
typedef int lock_t; lock_init(lock_t *flag) { *flag = 0; } void lock_acquire(lock_t *flag) { while (*flag); *flag = 1; } void lock_release(lock_t *flag) { *flag = 0; } |
typedef struct { int turn; int flag[2]; } lock_t; lock_init(lock_t *myl) { myl->turn = 0; myl->flag[0] = myl->flag[1] = 0; } void lock_acquire(lock_t *myl) { myl->flag[tid] = 1; myl->turn = 1-tid; if (tid == 0) { while (myl->flag[1] && myl->turn == 1); } else { /* tid == 1 */ while (myl->flag[0]); } } void lock_release(lock_t *myl) { myl->flag[tid] = 0; } |
You should assume that locks and condition variables have been implemented correctly with Mesa semantics.
cv_t mayEat[5]; // How is this initialized? lock_t lock; // A monitor lock -- initialized to unlock'ed! volatile int state[5]; // Initialized to THINKING void take_chopsticks() { lock_acquire(&lock); state[tid] = HUNGRY; test(tid); while (state[tid] != EATING) { cv_wait(&mayEat[tid], &lock); } lock_release(&lock); } void put_chopsticks() { lock_acquire(&lock); state[tid] = THINKING; test(tid+1%5); test(tid+4%5); lock_release(&lock); } void test(int i) { if (state[i]==HUNGRY && state[i+1%5]!=EATING && state[i+4%5]!=EATING) { state[i] = EATING; cv_signal(&mayEat[i]); } } |
How should the condition variable elements of mayEat be initialized?
What is the maximum number of Philosophers that can be waiting on lock at any given time?
What is the maximum number of Philosophers that can be waiting on one condition variable element mayEat[i] in the array mayEat at any given time?
Why does the lock need to be passed to the routine cv_wait(&mayEat[tid], &lock)? Give an example execution where something would go wrong without it.
Does the code work correctly if the expression while (state[tid] != EATING) is removed before the statement cv_wait(&mayEat[tid], &lock)? Briefly describe why or why not.
Does the code work correctly if the expression while (state[tid] != EATING) is changed to if (state[tid] != EATING)? Briefly describe why or why not. Be sure to think this one through carefully!
Does the code work correctly if instead of an array of condition variables, mayEat[i], every philosopher waits and signals on one shared condition variable, someoneMayEat? Briefly describe why or why not.
Assume that in addition to using just one condition variable, someoneMayEat, the cv_signal(mayEat[i]) is changed to cv_broadcast(someoneMayEat). (Hint: cv_broadcast wakes all threads waiting on the specified condition variable.) Does the code work correctly? Briefly describe why or why not.