Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 19 Feb 2017 16:28:47 +0000 (UTC)
From:      Mateusz Guzik <mjg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r313944 - head/sys/kern
Message-ID:  <201702191628.v1JGSlTX076985@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);



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