svn commit: r313944 - head/sys/kern

Mateusz Guzik mjg at FreeBSD.org
Sun Feb 19 16:28:48 UTC 2017


Author: mjg
Date: Sun Feb 19 16:28:46 2017
New Revision: 313944
URL: https://svnweb.freebsd.org/changeset/base/313944

Log:
  locks: make trylock routines check for 'unowned' value
  
  Since fcmpset can fail without lock contention e.g. on arm, it was possible
  to get spurious failures when the caller was expecting the primitive to succeed.
  
  Reported by:	mmel

Modified:
  head/sys/kern/kern_mutex.c
  head/sys/kern/kern_rwlock.c
  head/sys/kern/kern_sx.c

Modified: head/sys/kern/kern_mutex.c
==============================================================================
--- head/sys/kern/kern_mutex.c	Sun Feb 19 16:08:58 2017	(r313943)
+++ head/sys/kern/kern_mutex.c	Sun Feb 19 16:28:46 2017	(r313944)
@@ -402,16 +402,21 @@ _mtx_trylock_flags_(volatile uintptr_t *
 	rval = 1;
 	recursed = false;
 	v = MTX_UNOWNED;
-	if (!_mtx_obtain_lock_fetch(m, &v, tid)) {
+	for (;;) {
+		if (_mtx_obtain_lock_fetch(m, &v, tid))
+			break;
+		if (v == MTX_UNOWNED)
+			continue;
 		if (v == tid &&
 		    ((m->lock_object.lo_flags & LO_RECURSABLE) != 0 ||
 		    (opts & MTX_RECURSE) != 0)) {
-			 m->mtx_recurse++;
-			 atomic_set_ptr(&m->mtx_lock, MTX_RECURSED);
-			 recursed = true;
-		} else {
-			rval = 0;
+				 m->mtx_recurse++;
+				 atomic_set_ptr(&m->mtx_lock, MTX_RECURSED);
+				 recursed = true;
+				 break;
 		}
+		rval = 0;
+		break;
 	}
 
 	opts &= ~MTX_RECURSE;

Modified: head/sys/kern/kern_rwlock.c
==============================================================================
--- head/sys/kern/kern_rwlock.c	Sun Feb 19 16:08:58 2017	(r313943)
+++ head/sys/kern/kern_rwlock.c	Sun Feb 19 16:28:46 2017	(r313944)
@@ -314,13 +314,18 @@ __rw_try_wlock(volatile uintptr_t *c, co
 	rval = 1;
 	recursed = false;
 	v = RW_UNLOCKED;
-	if (!atomic_fcmpset_acq_ptr(&rw->rw_lock, &v, tid)) {
+	for (;;) {
+		if (atomic_fcmpset_acq_ptr(&rw->rw_lock, &v, tid))
+			break;
+		if (v == RW_UNLOCKED)
+			continue;
 		if (v == tid && (rw->lock_object.lo_flags & LO_RECURSABLE)) {
 			rw->rw_recurse++;
 			atomic_set_ptr(&rw->rw_lock, RW_LOCK_WRITER_RECURSED);
-		} else {
-			rval = 0;
+			break;
 		}
+		rval = 0;
+		break;
 	}
 
 	LOCK_LOG_TRY("WLOCK", &rw->lock_object, 0, rval, file, line);

Modified: head/sys/kern/kern_sx.c
==============================================================================
--- head/sys/kern/kern_sx.c	Sun Feb 19 16:08:58 2017	(r313943)
+++ head/sys/kern/kern_sx.c	Sun Feb 19 16:28:46 2017	(r313944)
@@ -341,13 +341,18 @@ sx_try_xlock_(struct sx *sx, const char 
 	rval = 1;
 	recursed = false;
 	x = SX_LOCK_UNLOCKED;
-	if (!atomic_fcmpset_acq_ptr(&sx->sx_lock, &x, tid)) {
+	for (;;) {
+		if (atomic_fcmpset_acq_ptr(&sx->sx_lock, &x, tid))
+			break;
+		if (x == SX_LOCK_UNLOCKED)
+			continue;
 		if (x == tid && (sx->lock_object.lo_flags & LO_RECURSABLE)) {
 			sx->sx_recurse++;
 			atomic_set_ptr(&sx->sx_lock, SX_LOCK_RECURSED);
-		} else {
-			rval = 0;
+			break;
 		}
+		rval = 0;
+		break;
 	}
 
 	LOCK_LOG_TRY("XLOCK", &sx->lock_object, 0, rval, file, line);


More information about the svn-src-head mailing list