What will be printed by the following code snippet that creates two (2) threads to execute the function mythread and joins them to ensure they both finish?
void *mythread(void *arg) {
int result = 0;
result = result + 100;
printf("result %d\n", result);
}
thread_t p1, p2;
thread_create(&p1, mythread, NULL);
thread_create(&p2, mythread, NULL);
thread_join(p1);
thread_join(p2);
What will be the result of a thread executing the following C code snippet?
lock_t mutex;
.
.
.
lock(&mutex);
while(1){
myFunc();
}
unlock(&mutex);
Consider the following lock and unlock functions from class that puts threads to sleep instead of spin-waiting. Identify the bug(s) in the code. Assume TestAndSet runs atomically.
void lock(lock_t *m) {
while (TestAndSet(&m->guard, 1) == 1)
; // acquire guard lock by spinning
if (m->flag == 0){
m->flag = 1; // lock is acquired
m->guard = 0;} else {
queue_add(m->q, gettid());
m->guard = 0; park(); } } void unlock(lock_t *m) { while (TestAndSet(&m->guard, 1) == 1) ; // acquire guard lock by spinning if (queue_empty(m->q)) m->flag = 0; // let go of lock; no one wants it elseunpark(queue_remove(m->q)); // hold lock (for next thread!)
m->guard = 0;
}
Suppose three (3) threads each increment a shared variable 5 times that is initialized to 0 (so, the expected result then is 15). After all threads have finished, the main prints the value of the shared variable. Without locks (or any other way of enforcing mutual exclusion), which of the following will/could be printed by the main?
The following C code was our first attempt to make a lock using a flag to indicate if the lock was acquired.
typedef struct __lock_t { int flag; } lock_t;
void init(lock_t *mutex) {
mutex->flag = 0;
}
void lock(lock_t *mutex) {
while (mutex->flag == 1) // TEST the flag
; // spin-wait (do nothing)
mutex->flag = 1; // now SET it !
}
void unlock(lock_t *mutex) {
mutex->flag = 0;
}
How will this code perform in terms of correctness and efficiency?
For this question, refer to the following code:
mutex_t m;
int slot = -1;
int array[2] = { 0, 0 }; // initialize to 0, 0 contents
function1() {
mutex_acquire(&m);
slot++;
mutex_release(&m);
int tid = get_counter();
mutex_acquire(&m);
array[slot] = tid;
mutex_release(&m);
}
Assume that get_counter() has its own internal locking (not shown), and will return 1 when first called, and 2 when called next, etc. Assume that function1() is called by two threads at roughly the same time. What are the final contents of the array?
Consider the following code to initialize the concurrent Michael and Scott Queue from class.
void Queue_Init(queue_t *q) {
node_t *tmp = malloc(sizeof(node_t));
tmp->next = NULL;
q->head = q->tail = tmp;
pthread_mutex_init(&q->headLock, NULL);
pthread_mutex_init(&q->tailLock, NULL);
}
Why does an empty queue have a node allocated?
For this question, refer to the following code:
mutex_t m;
int slot = -1;
int array[2] = { 0, 0 }; // initialize to 0, 0 contents
function1() {
mutex_acquire(&m);
slot++;
int tid = get_counter();
array[slot] = tid;
mutex_release(&m);
}
Assume that get_counter() has its own internal locking (not shown), and will return 1 when first called, and 2 when called next, etc. Assume that function1() is called by two threads at roughly the same time. What are the final contents of the array?
Consider a system that has a 16KB address space and 64 byte pages in a two-level and that the page directory and the page table with entries as in the image below (taken from OSTEP ch. 20, Figure 20.5). Suppose also that PTEs and PDEs are 4 bytes each.
How much less memory is used for storing the multi-level page table, compared to a linear page table?