[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

rwlocks writer preference patch



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;
 

Reply to: