Pthread Synchronization Operating Systems Hebrew University Spring 2004
What’s the problem Process thread1 { foo = 1; bar = 2; } Process thread2 { foo = 3; bar = 4; } What are the possible results?
Race condition Two threads racing to perform the same task Interleaving of operations can cause incorrect behavior
Atomic Updates Perform the following items as a single unit When we are done, exactly (A or B) is true –not (A and B) –not part of A and part of B Critical Section!
Mutex Enter and Exit critical section #include int pthread_mutex_lock(mutex); int pthread_mutex_unlock(mutex); mutex_var Thread AThread B lock block var access
No problem Process thread1 { pthread_mutex_lock(l); foo = 1; bar = 2; pthread_mutex_unlock(l); } Process thread2 { pthread_mutex_lock(l); foo = 3; bar = 4; pthread_mutex_unlock(l); } What are the possible results?
What’s the problem? Process producer { while(1) { while(count == 1) no_op; data = c; count = 1; } Process consumer { while(1) { while(count == 0) no_op; c = data; count = 0; // consume c }
Try it with a mutex
One solution Process producer { while(1) { lock(mutex); if (count == 0){ // produce c data = c; count = 1; } unlock(mutex); } Process consumer { while(1) { lock(mutex); if (count == 1){ c = data; count = 0; } unlock(mutex); // consume c } Problems Produce inside of lock Starvation Busy wait
Better solution Process producer { while(1) { // produce c lock(empty); lock(mutex); data = c; unlock(mutex); unlock(full); } Process consumer { while(1) { lock(full); lock(mutex); c = data; unlock(mutex); unlock(empty); // consume c } How many mutexs are in use? What is the initial state of the mutexs?
Condition Signals Wait on a condition Associated with mutex to prevent race condition #include pthread_mutex_t m; pthread_cond_t c; int pthread_cond_wait(&c, &m) int pthread_cond_signal(&c); int pthread_cond_broadcast(&c);
Solution using conditions void producer() { int i = 1; while (1) { pthread_mutex_lock(&mutex); while (count == 1) { pthread_cond_wait(&control, &mutex); } data = i; count = 1; pthread_cond_signal(&control); pthread_mutex_unlock(&mutex); } void consumer() { int i = 0; while (1) { pthread_mutex_lock(&mutex); while (count == 0) { pthread_cond_wait(&control, &mutex); } i = data; count = 0; pthread_cond_signal(&control); pthread_mutex_unlock(&mutex); }
Counting Mutex Linux Extension PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; A Partial Semaphore Can be called recursively in a single thread Counts number of calls and unlocks once count is zero
Error Checking Mutex Linux Extension: PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; If called recursively, return an error! Very helpful for debugging deadlocks
Mutex Maintenance int pthread_mutex_init(&m, &flags) int pthread_mutex_trylock(&m); int pthread_mutex_destroy(&m);
Condition Maintenance PTHREAD_COND_INITIALIZER int pthread_cond_init(&c) int pthread_cond_timedwait(&c, &m, &t); int pthread_cond_destroy(&c)
Problems with Solutions Barrier –Wait until all have registered –Wait until at least one has registered –Insure that a function is called exactly once
Two Phase locking Get all the locks in a consistent order Do the work Release the locks in the inverse order Reduces Deadlocks