I can't find any evidence online of pthread_cond_wait
being strange on Mac OS X, but it seems to be failing the simplest test for me.
The function
int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t * );
is supposed to unlock the mutex argument #2 and then wait for a signal to be sent on the condition argument #1. I wrote a simple program to test this, and also test for spurious wakeups:
#include <stdio.h>
#include <pthread.h>
pthread_t spin_thread;
pthread_mutex_t spin_mutex;
pthread_cond_t spin_cond;
int actual = 0;
void *condspin( void *v ) {
int expected = 0;
for ( ;; ) {
if ( actual != expected ) printf( "unexpected %d\n", actual );
else printf( "expected %d\n", actual );
pthread_mutex_lock( &spin_mutex );
printf( "locked\n" );
expected = actual + 1;
pthread_cond_wait( &spin_cond, &spin_mutex );
}
return NULL;
}
int main( int argc, char ** argv ) {
pthread_mutex_init( &spin_mutex, NULL );
pthread_cond_init( &spin_cond, NULL );
pthread_create( &spin_thread, NULL, &condspin, NULL );
for ( ;; ) {
getchar();
pthread_cond_signal( &spin_cond );
printf( "signaled\n" );
++ actual;
}
return 0;
}
But it only acquires the lock once. The main thread doesn't even try to acquire the lock just to keep things simple.
Shadow:~ dkrauss$ cc condwait.c -o condwait
Shadow:~ dkrauss$ ./condwait
expected 0
locked
signaled
expected 1
signaled
signaled
If I add a pthread_mutex_unlock
after the pthread_cond_wait
, it behaves as expected. (Or as well as you'd expect with only half a locking mechanism.) So, what gives?
pthread_cond_wait
re-acquires the mutex when it is awoken. The standard pattern for using pthreads mutexes is:
pthread_mutex_lock(&mutex);
// init work...
while (!some_condition)
pthread_cond_wait(&cond, &mutex);
// finishing work...
pthread_mutex_unlock(&mutex);
This behavior is described in the SUS documentation for pthread_cond_wait
as:
Upon successful return, the mutex has been locked and is owned by the calling thread.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With