How to implement readers-writer lock with timeout, a hard question.
Chen(陈)Jun(军)
chjfth@gmail.com
Wed Jan 16 05:46:00 GMT 2008
Steve Munroe åé:
> libc-alpha-owner@sourceware.org wrote on 01/15/2008 07:52:15 PM:
>
>
>> Hello everyone, I'm new to mailing list. I think this list is the proper
>> place to ask my question.
>>
>> Is there an implementation of readers-writer lock with timeout support
>> on Linux(no doubt, using glibc). I've known quite some implementation of
>> readers-writer lock without timeout, like that in boost and ACE(by
>> Douglas C. Schmidt). By saying "timeout support", I mean, if some thread
>> acquires read or write lock but fails to get it before "timeout"
>> elapses, the calling thread returns as if the thread has never acquired
>> lock.
>>
>> I had not seen an implementation on Windows 2000/XP either, but I
>> managed to implement it some months ago, with help of the great
>> QueueUserAPC Win32 function. Now, I'd like to know how to implement
>> readers-writer lock with timeout on Linux. Can it be implemented with
>> glibc or some more kernel functions must be added to fulfill this?
>> Searching on google for weeks and no luck. Does anyone have an idea.
>> Thanks in advance.
>>
>>
>
> look at the posix documentation for pthread_rwlock_*. This API supports
> read/write locks with and without time-out.
>
> You can find lots of references using google. For example:
>
> http://www.linuxhowtos.org/manpages/3p/pthread_rwlock_timedrdlock.htm
>
>
Thank you very much for your answer, I tried it with a simple program on
SuSE 10.1(glibc 2.4 perhaps) and it works as expected.
However, I really want to know how it is implemented, since I'd like to
made some improvement. Such as:
* Recursively acquire the same type of lock should be allowed.
* Write-waiters should have more priority over read-waiters. This
introduces a new behavior: when a write-waiter times out, it should
check whether there have been some read-waiters waiting, if so, wake up
those read-waiters.
* Read-lock owners can upgrade to writer-lock owners without first
release read lock.
I look into the definition of pthread_rwlock_timedrdlock, there is a
mysterious lll_futex_timed_wait to carry out the wait operation. And in
pthread_rwlock_unlock, there is lll_futex_wake to do the wakeup. What
are those futex operations, are they documented somewhere?
My simple test code :
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <assert.h>
#include <pthread.h>
struct SThreadParam
{
pthread_rwlock_t *prwl;
int hold_seconds;
};
void * _thread_lock_write(void *param)
{
SThreadParam *ptp = (SThreadParam*)param;
pthread_rwlock_t *prwl = ptp->prwl;
int ret = pthread_rwlock_wrlock(prwl);
printf("pthread_rwlock_wrlock()=%d\n", ret);
if(ret!=0)
return NULL;
// hold the lock for some seconds
sleep(ptp->hold_seconds);
ret = pthread_rwlock_unlock(prwl);
printf("pthread_rwlock_unlock()=%d\n", ret);
return NULL;
}
void DoTest()
{
int re;
pthread_rwlock_t rwl, *prwl = &rwl;
re = pthread_rwlock_init(&rwl, NULL);
assert(re==0);
SThreadParam tp = {0};
tp.prwl = &rwl;
tp.hold_seconds = 5; // hold read-lock for this much seconds.
pthread_t thrd;
memset(&thrd, 0, sizeof(thrd));
re = pthread_create(&thrd, NULL, _thread_lock_write, &tp);
assert(re==0);
sleep(2); // !! hopes that _thread_lock_write() has acquired the lock
// try acquire read lock for 1 second, should fail due to timeout
time_t endtime = time(NULL)+1;
timespec end_abstime = { endtime, 0 };
re = pthread_rwlock_timedrdlock(prwl, &end_abstime);
if(re==ETIMEDOUT)
{
printf("Good, first timedrdlock return ETIMEDOUT(%d)\n", ETIMEDOUT);
}
else
printf("Unexpected first timedrdlock ret(%d)\n", re);
// second try read-lock acquire, should success.
end_abstime.tv_sec = time(NULL)+5;
end_abstime.tv_nsec = 0;
re = pthread_rwlock_timedrdlock(prwl, &end_abstime);
if(re==0)
{
printf("Good, second timedrdlock return success(0)\n");
pthread_rwlock_unlock(prwl);
}
else
printf("Unexpected second timedrdlock ret(%d)\n", re);
void *thrd_ret;
pthread_join(thrd, &thrd_ret);
pthread_rwlock_destroy(&rwl);
}
int main()
{
DoTest();
return 0;
}
More information about the Libc-alpha
mailing list