Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 13 Oct 2009 13:47:30 +0000 (UTC)
From:      Attilio Rao <attilio@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org
Subject:   svn commit: r198032 - in stable/7/sys: . contrib/pf kern
Message-ID:  <200910131347.n9DDlUcE007223@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: attilio
Date: Tue Oct 13 13:47:30 2009
New Revision: 198032
URL: http://svn.freebsd.org/changeset/base/198032

Log:
  MFC r197476:
  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.
  
  Approved by:	davidxu

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/kern/kern_umtx.c

Modified: stable/7/sys/kern/kern_umtx.c
==============================================================================
--- stable/7/sys/kern/kern_umtx.c	Tue Oct 13 13:08:05 2009	(r198031)
+++ stable/7/sys/kern/kern_umtx.c	Tue Oct 13 13:47:30 2009	(r198032)
@@ -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?200910131347.n9DDlUcE007223>