















Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
The instructions and questions for an in-class exam on concurrency and synchronization for the 15-410 course at carnegie mellon university. The exam includes short answer questions, diagrams, and the implementation of condition variables and list locking using mutexes and rendezvous().
Typology: Exams
1 / 23
This page cannot be seen from the preview
Don't miss anything!
















think clearly about a problem, you will probably have time to write your answer legibly.
After I leave this exam session, I will not discuss the contents of this 15-410 midterm with anybody, whether or not in this class, whether or not present in this exam session with me, before 19:00 on Wednesday, October 6th.
Signature: Date
(b) 4 points What is a “kernel stack”? When is one used and why are they important?
Running Runnable
Sleeping Blocked
Zombie
Please declare a struct cond and implement cond init(), cond wait(), and cond signal() (you do not need to implement either cond broadcast() or cond destroy()). If you wish, you may also declare an auxiliary structure, struct aux, but this is strictly optional.
It is strongly recommended that you rough out an implementation on the scrap paper provided at the end of the exam, or on the back of some other page, before you write anything here. If we cannot understand the solution you provide on this page, your grade will suffer!
typedef struct cond {
} cond_t;
typedef struct aux {
} aux_t;
...space for cvar implementation...
Your friend Barry Hovik is writing some concurrent code using a shared linked list, and comes to you wondering about concurrency primitives. His code currently looks like this:
void list_insert_sorted(list_t *list, list_node_t *new) { list_node_t **p;
/* STEP 0: Prevent concurrent access. */ rwlock_lock(&list->lock, RWLOCK_WRITE);
/* STEP 1: Iterate down the list. / for (p = &list->head; p != NULL; p = &(p)->next) { if (list->compare((p)->data, new->data) >= 0) { /* Entry should be inserted after the current one. */ break; } }
/* STEP 2: Insert node. */ new->next = *p; *p = new;
rwlock_unlock(&list->lock); }
You should imagine that other list operations, such as list delete(), list count nodes(), etc., exist and are coded in sensible (correct) fashions. Naturally, operations that examine the list but do not modify it lock the list in RWLOCK READ mode.
Barry is worried that list insert sorted() will perform poorly because walking down the list takes O(n) time and his code will hold a RWLOCK WRITE (exclusive) lock during the entire operation. He explains that he briefly considered rewriting list insert sorted() as follows.
void list_insert_sorted(list_t *list, list_node_t *new) { list_node_t **p;
/* STEP 0: "Declare" that list shouldn’t change while we walk it. */ rwlock_lock(&list->lock, RWLOCK_READ);
/* STEP 1: Iterate down the list. / for (p = &list->head; p != NULL; p = &(p)->next) { int cmp; if ((cmp = list->compare((p)->data, new->data)) == 0) { /* We already have one of these / rwlock_unlock(&list->lock); free(new); return; } else if (cmp > 0) { / Entry should be inserted after the current one. */ break; } }
/* STEP 2: Promote READ lock to WRITE lock before modification. */ rwlock_unlock(&list->lock); rwlock_lock(&list->lock, RWLOCK_WRITE);
/* STEP 3: Insert node. */ new->next = *p; *p = new;
rwlock_unlock(&list->lock); }
Now that you and Barry are thinking along the same lines, he unveils a novel proposal. He has invented a new operation for readers/writers locks to support, called rwlock promote(), defined as follows. void rwlock promote(rwlock t *rwlock) - If the invoking thread does not already hold a RWLOCK READ lock on the specified rwlock, this constitutes a fatal error and the program immediately ends. Otherwise, the invoking thread is blocked until the RWLOCK READ lock can be “atomically upgraded” to an RWLOCK WRITE lock. While a thread is blocked in rwlock promote(), no other thread will obtain an RWLOCK WRITE or RWLOCK READ lock on the specified rwlock before the promotion to RWLOCK WRITE completes.
Barry proposes replacing the two lines of bad “STEP 2: Promote...” code above with one line of code, namely the invocation of rwlock promote(&list->lock);.
As Barry explains his proposal, you have a sinking feeling. Though Barry assures you that he has figured out how to rewrite his rwlock implementation to provide an rwlock promote() that fully complies with the specification above, you regretfully explain to him that this approach has a fatal flaw.
(b) 10 points Summarize the flaw in a sentence or two and also provide an execution trace which clearly and compellingly illustrates how this flaw will appear. Assume his rwlock promote() (and his other readers/writers lock code) works exactly according to specification, and also assume, for exam purposes, that necessary library and system call invocations aren’t forced to fail by unfortunate circumstances.
You may use this page as extra space for the rwlock question if you wish.
You may use this page as extra space for the critical-section protocol question if you wish.
(b) 5 points Show, with a clear and convincing trace, that a different critical-section algo- rithm requirement also does not hold.
You may use this page as extra space for the critical-section protocol question if you wish.
(a) Registers: eax 00000000 ebx 00000000 ecx 00000000 edx 00000004 edi 00000000 esi 00000000 ebp ffffffdd esp ffffffd5 ss 0000002b eip ffefffdd cs 00000023 ds 002b es 002b fs 002b gs 002b eflags 00210246
(b) Registers: eax 00000001 ebx 010000af ecx ffffffd1 edx 00000000 edi 00000000 esi 00000000 ebp ffffffdd esp 00002fbb ss 0000002b eip 0100000c cs 00000023 ds 002b es 002b fs 002b gs 002b eflags 00210282