Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 25 Sep 2009 00:03:13 +0000 (UTC)
From:      David Xu <davidxu@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r197476 - head/sys/kern
Message-ID:  <200909250003.n8P03Dgx011115@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: davidxu
Date: Fri Sep 25 00:03:13 2009
New Revision: 197476
URL: http://svn.freebsd.org/changeset/base/197476

Log:
  In function do_rw_wrlock, when a writer got an error and before returning,
  check if there are readers blocked by us via URWLOCK_WRITE_WAITERS flag,
  and resume the readers. The error must be EAGAIN, otherwise there must
  have memory problem, and nobody can rescue the buggy application.
  
  The revision 197445 might be reverted.

Modified:
  head/sys/kern/kern_umtx.c

Modified: head/sys/kern/kern_umtx.c
==============================================================================
--- head/sys/kern/kern_umtx.c	Thu Sep 24 22:42:35 2009	(r197475)
+++ head/sys/kern/kern_umtx.c	Fri Sep 25 00:03:13 2009	(r197476)
@@ -2556,6 +2556,7 @@ do_rw_wrlock(struct thread *td, struct u
 	uint32_t flags;
 	int32_t state, oldstate;
 	int32_t blocked_writers;
+	int32_t blocked_readers;
 	int error;
 
 	uq = td->td_umtxq;
@@ -2564,6 +2565,7 @@ do_rw_wrlock(struct thread *td, struct u
 	if (error != 0)
 		return (error);
 
+	blocked_readers = 0;
 	for (;;) {
 		state = fuword32(__DEVOLATILE(int32_t *, &rwlock->rw_state));
 		while (!(state & URWLOCK_WRITE_OWNER) && URWLOCK_READER_COUNT(state) == 0) {
@@ -2575,8 +2577,18 @@ do_rw_wrlock(struct thread *td, struct u
 			state = oldstate;
 		}
 
-		if (error)
+		if (error) {
+			if (!(state & (URWLOCK_WRITE_OWNER|URWLOCK_WRITE_WAITERS)) &&
+			    blocked_readers != 0) {
+				umtxq_lock(&uq->uq_key);
+				umtxq_busy(&uq->uq_key);
+				umtxq_signal_queue(&uq->uq_key, INT_MAX, UMTX_SHARED_QUEUE);
+				umtxq_unbusy(&uq->uq_key);
+				umtxq_unlock(&uq->uq_key);
+			}
+
 			break;
+		}
 
 		/* grab monitor lock */
 		umtxq_lock(&uq->uq_key);
@@ -2627,7 +2639,9 @@ sleep:
 					break;
 				state = oldstate;
 			}
-		}
+			blocked_readers = fuword32(&rwlock->rw_blocked_readers);
+		} else
+			blocked_readers = 0;
 
 		umtxq_lock(&uq->uq_key);
 		umtxq_unbusy(&uq->uq_key);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200909250003.n8P03Dgx011115>