This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
rwlocks writer preference patch
- To: GLIBC List <libc-alpha at sources dot redhat dot com>
- Subject: rwlocks writer preference patch
- From: Momchil Velikov <velco at fadata dot bg>
- Date: Thu, 09 Nov 2000 12:52:44 +0000
- CC: Joel Klecker <debian-glibc at lists dot debian dot org>
Hi,
The 2.1.3 implementation of rwlocks (and the current CVS, FWIW)
still allows for excessive starvation for writers, no matter
if writer preference is set. The attached patch makes a waiting
writer the owner of the lock upon wakeup.
Regards,
-velco
PS. Joel, note this hunk from the patch, this bug is already fixed in
the CVS, but you might still want to add it to the Debian patches
(along with the rest).
@@ -362,7 +364,8 @@
}
rwlock->__rw_writer = NULL;
- if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP
+ if ((rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP
+ && !queue_is_empty(&rwlock->__rw_read_waiting))
|| (th = dequeue (&rwlock->__rw_write_waiting)) == NULL)
{
/* Restart all waiting readers. */
-velco
--- rwlock.c~ Fri Jan 21 01:40:19 2000
+++ rwlock.c Thu Nov 9 10:39:37 2000
@@ -313,7 +313,9 @@
while(1)
{
__pthread_lock (&rwlock->__rw_lock, self);
- if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL)
+ if (rwlock->__rw_readers == 0
+ && (rwlock->__rw_writer == NULL
+ || rwlock->__rw_writer == self))
{
rwlock->__rw_writer = self;
__pthread_unlock (&rwlock->__rw_lock);
@@ -362,7 +364,8 @@
}
rwlock->__rw_writer = NULL;
- if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP
+ if ((rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP
+ && !queue_is_empty(&rwlock->__rw_read_waiting))
|| (th = dequeue (&rwlock->__rw_write_waiting)) == NULL)
{
/* Restart all waiting readers. */
@@ -375,6 +378,7 @@
else
{
/* Restart one waiting writer. */
+ rwlock->__rw_writer = th;
__pthread_unlock (&rwlock->__rw_lock);
restart (th);
}
@@ -390,8 +394,11 @@
--rwlock->__rw_readers;
if (rwlock->__rw_readers == 0)
- /* Restart one waiting writer, if any. */
- th = dequeue (&rwlock->__rw_write_waiting);
+ {
+ /* Restart one waiting writer, if any. */
+ th = dequeue (&rwlock->__rw_write_waiting);
+ rwlock->__rw_writer = th;
+ }
else
th = NULL;