UNIVERSITY OF WISCONSIN-MADISON
Computer Sciences Department | ||
CS 537
Fall 2007 | A. Arpaci-Dusseau | |
Sample Quiz #3 -- Critical Sections, Locks, and Semaphores |
The following code samples each specify different implementations for a
lock; in all cases, the lock structure is defined, as well as the
lock_init(), lock_acquire(), and lock_release() procedures. You should
assume that the application calls lock_init() before using the lock and
call lock_acquire() before entering the critical section and
lock_release() after exiting the critical section. For the
implementations that require a
For each code sample, answer the following questions:
typedef struct { int turn; } lock_t; lock_init(lock_t *l) { l->turn = 0; } void lock_acquire(lock_t *l) { while (l->turn == (1 - tid)); } void lock_release(lock_t *l) { l->turn = (1 - tid); } |
typedef struct { } lock_t; lock_init(lock_t *l) { } void lock_acquire(lock_t *l) { disableInterrupts(); } void lock_release(lock_t *l) { enableInterrupts(); } |
typedef struct { int turn; int lock[2]; } lock_t; lock_init(lock_t *l) { l->turn = 0; l->lock[0] = l->lock[1] = 0; } void lock_acquire(lock_t *l) { l->lock[tid] = 1; l->turn = 1 - tid; while (l->lock[1-tid] && l->turn == (1 - tid)); } void lock_release(lock_t *l) { l->lock[tid] = 0; } |
typedef struct { int lock; } lock_t; lock_init(lock_t *l) { l->lock = 1; } void lock_acquire(lock_t *l) { while (TestAndSet(lock, 1); } void lock_release(lock_t *l) { l->lock = 0; } |
// Global variables, shared across reader and writer threads volatile int sharedBuffer[] = new int[1000]; sem_t mutex; sem_t OKToRead; sem_t OKToWrite; volatile int ActiveWriters = 0; volatile int WaitingWriters = 0; volatile int ActiveReaders = 0; volatile int WaitingReaders = 0; | |
void reader() { sem_wait(&mutex); if ((ActiveWriters + WaitingWriters) == 0){ sem_signal(&OKToRead); ActiveReaders++; } else { WaitingReaders++; } sem_signal(&mutex); sem_wait(&OKToRead); // Perform read of sharedBuffer sem_wait(&mutex); ActiveReaders--; if ((ActiveReaders == 0) && (WaitingWriters > 0)) { sem_signal(&OKToWrite); ActiveWriters++; WaitingWriters--; } sem_signal(&mutex); } | |
private void writer() { sem_wait(&mutex); if ((ActiveWriters + ActiveReaders + WaitingWriters) == 0) { sem_signal(&OKToWrite); ActiveWriters++; } else { WaitingWriters++; } sem_signal(&mutex); sem_wait(&OKToWrite); // Perform write of dataBuffer sem_wait(&mutex); ActiveWriters--; if (WaitingWriters > 0) { sem_signal(&OKToWrite); ActiveWriters++; WaitingWriters--; } else { while (WaitingReaders > 0) { sem_signal(&OKToRead); ActiveReaders++; WaitingReaders--; } } sem_signal(&mutex); } |
You should assume that semaphores have been implemented in a reasonable way. You should assume that all semaphores are implemented with a First-in-First-out (FIFO) list of threads; that is, the thread that has been waiting the longest for a semaphore will be the next one woken up.
You need to answer five questions about this code segment. Each will be worth the same number of points.
b) Is the first writer to execute sem_wait(&OKToWrite)
guaranteed to be the first writer to use the buffer?