I have following sample code (see code below) that does by thread:
A: rd-lock
B: wr-lock (waiting)
A: rd-lock (recursive)
A: rd-unlock (recursive)
A: rd-unlock
B: wr-locked (wake after wait)
B: wr-unlock.
Basically read-lock is recursive. It it required by POSIX standards (requires read locks to be recursive, but not specified for write locks). This works on Linux, FreeBSD, Solaris, however it does not work on Darwin/Mac OS X.
The sample below gives following output on Linux:
read locking
read locked
write locking
read locking 2
read locked 2
read unlocked 2
read unlocked
write locked
write unlocked 2
While on Darwin it prints:
read locking
read locked
write locking
read locking 2
And deadlocks here (does not continue), basically it does not respect recursive read lock.
Is there anything that possible to do (flag, defined, link with a special library version) that it would work as expected?
Sample code
#include <pthread.h>
#include <stdio.h>
pthread_rwlock_t lock;
void *thread_r(void *p)
{
printf("read locking\n");
pthread_rwlock_rdlock(&lock);
printf("read locked\n");
usleep(500*1000);
printf("read locking 2\n");
pthread_rwlock_rdlock(&lock);
printf("read locked 2\n");
usleep(500*1000);
pthread_rwlock_unlock(&lock);
printf("read unlocked 2\n");
usleep(500*1000);
pthread_rwlock_unlock(&lock);
printf("read unlocked\n");
}
void *thread_w(void *p)
{
usleep(250*1000);
printf("write locking\n");
pthread_rwlock_wrlock(&lock);
printf("write locked\n");
pthread_rwlock_unlock(&lock);
printf("write unlocked 2\n");
}
int main()
{
pthread_t a,b;
pthread_rwlock_init(&lock,NULL);
pthread_create(&a,NULL,thread_r,0);
pthread_create(&b,NULL,thread_w,0);
pthread_join(a,NULL);
pthread_join(b,NULL);
return 0;
}
Yes, the locks are read locks on rwlocks are indeed recursive, up to a point. But there is a line in the POSIX docs for
pthread_rwlock_rdlock
, SUSv2 since that's what Apple suports:Nothing at all in there about letting a thread with an existing read lock relock for read. Just that the read lock request will block if a writer is blocked (implementations often give preference to write lock to avoid writer starvation).
Apple's own online docs also support this:
And, later:
Again. no mention of allowing recursive read locks while a write lock is in the queue.