svn commit: r313270 - in head/sys: kern sys

Mateusz Guzik mjg at FreeBSD.org
Sun Feb 5 04:53:15 UTC 2017


Author: mjg
Date: Sun Feb  5 04:53:13 2017
New Revision: 313270
URL: https://svnweb.freebsd.org/changeset/base/313270

Log:
  rwlock: switch to fcmpset
  
  Discussed with:	jhb
  Tested by:	pho

Modified:
  head/sys/kern/kern_rwlock.c
  head/sys/sys/rwlock.h

Modified: head/sys/kern/kern_rwlock.c
==============================================================================
--- head/sys/kern/kern_rwlock.c	Sun Feb  5 03:26:34 2017	(r313269)
+++ head/sys/kern/kern_rwlock.c	Sun Feb  5 04:53:13 2017	(r313270)
@@ -440,7 +440,7 @@ __rw_rlock(volatile uintptr_t *c, const 
 			 * if the lock has been unlocked and write waiters
 			 * were present.
 			 */
-			if (atomic_cmpset_acq_ptr(&rw->rw_lock, v,
+			if (atomic_fcmpset_acq_ptr(&rw->rw_lock, &v,
 			    v + RW_ONE_READER)) {
 				if (LOCK_LOG_TEST(&rw->lock_object, 0))
 					CTR4(KTR_LOCK,
@@ -449,7 +449,6 @@ __rw_rlock(volatile uintptr_t *c, const 
 					    (void *)(v + RW_ONE_READER));
 				break;
 			}
-			v = RW_READ_VALUE(rw);
 			continue;
 		}
 #ifdef KDTRACE_HOOKS
@@ -675,7 +674,7 @@ _rw_runlock_cookie(volatile uintptr_t *c
 		 * just drop one and return.
 		 */
 		if (RW_READERS(x) > 1) {
-			if (atomic_cmpset_rel_ptr(&rw->rw_lock, x,
+			if (atomic_fcmpset_rel_ptr(&rw->rw_lock, &x,
 			    x - RW_ONE_READER)) {
 				if (LOCK_LOG_TEST(&rw->lock_object, 0))
 					CTR4(KTR_LOCK,
@@ -684,7 +683,6 @@ _rw_runlock_cookie(volatile uintptr_t *c
 					    (void *)(x - RW_ONE_READER));
 				break;
 			}
-			x = RW_READ_VALUE(rw);
 			continue;
 		}
 		/*
@@ -694,14 +692,13 @@ _rw_runlock_cookie(volatile uintptr_t *c
 		if (!(x & RW_LOCK_WAITERS)) {
 			MPASS((x & ~RW_LOCK_WRITE_SPINNER) ==
 			    RW_READERS_LOCK(1));
-			if (atomic_cmpset_rel_ptr(&rw->rw_lock, x,
+			if (atomic_fcmpset_rel_ptr(&rw->rw_lock, &x,
 			    RW_UNLOCKED)) {
 				if (LOCK_LOG_TEST(&rw->lock_object, 0))
 					CTR2(KTR_LOCK, "%s: %p last succeeded",
 					    __func__, rw);
 				break;
 			}
-			x = RW_READ_VALUE(rw);
 			continue;
 		}
 		/*
@@ -769,8 +766,8 @@ _rw_runlock_cookie(volatile uintptr_t *c
  * read or write lock.
  */
 void
-__rw_wlock_hard(volatile uintptr_t *c, uintptr_t tid, const char *file,
-    int line)
+__rw_wlock_hard(volatile uintptr_t *c, uintptr_t v, uintptr_t tid,
+    const char *file, int line)
 {
 	struct rwlock *rw;
 	struct turnstile *ts;
@@ -779,7 +776,7 @@ __rw_wlock_hard(volatile uintptr_t *c, u
 	int spintries = 0;
 	int i;
 #endif
-	uintptr_t v, x;
+	uintptr_t x;
 #ifdef LOCK_PROFILING
 	uint64_t waittime = 0;
 	int contested = 0;
@@ -803,7 +800,6 @@ __rw_wlock_hard(volatile uintptr_t *c, u
 	lock_delay_arg_init(&lda, NULL);
 #endif
 	rw = rwlock2rw(c);
-	v = RW_READ_VALUE(rw);
 
 	if (__predict_false(lv_rw_wowner(v) == (struct thread *)tid)) {
 		KASSERT(rw->lock_object.lo_flags & LO_RECURSABLE,
@@ -825,9 +821,8 @@ __rw_wlock_hard(volatile uintptr_t *c, u
 #endif
 	for (;;) {
 		if (v == RW_UNLOCKED) {
-			if (_rw_write_lock(rw, tid))
+			if (_rw_write_lock_fetch(rw, &v, tid))
 				break;
-			v = RW_READ_VALUE(rw);
 			continue;
 		}
 #ifdef KDTRACE_HOOKS

Modified: head/sys/sys/rwlock.h
==============================================================================
--- head/sys/sys/rwlock.h	Sun Feb  5 03:26:34 2017	(r313269)
+++ head/sys/sys/rwlock.h	Sun Feb  5 04:53:13 2017	(r313270)
@@ -84,6 +84,11 @@
 #define	_rw_write_lock(rw, tid)						\
 	atomic_cmpset_acq_ptr(&(rw)->rw_lock, RW_UNLOCKED, (tid))
 
+#define	_rw_write_lock_fetch(rw, vp, tid) ({				\
+	*vp = RW_UNLOCKED;						\
+	atomic_fcmpset_acq_ptr(&(rw)->rw_lock, vp, (tid));		\
+})
+
 /* Release a write lock quickly if there are no waiters. */
 #define	_rw_write_unlock(rw, tid)					\
 	atomic_cmpset_rel_ptr(&(rw)->rw_lock, (tid), RW_UNLOCKED)
@@ -97,9 +102,10 @@
 /* Acquire a write lock. */
 #define	__rw_wlock(rw, tid, file, line) do {				\
 	uintptr_t _tid = (uintptr_t)(tid);				\
+	uintptr_t _v;							\
 									\
-	if ((rw)->rw_lock != RW_UNLOCKED || !_rw_write_lock((rw), _tid))\
-		_rw_wlock_hard((rw), _tid, (file), (line));		\
+	if (!_rw_write_lock_fetch((rw), &_v, _tid))			\
+		_rw_wlock_hard((rw), _v, _tid, (file), (line));		\
 	else 								\
 		LOCKSTAT_PROFILE_OBTAIN_RWLOCK_SUCCESS(rw__acquire, rw,	\
 		    0, 0, file, line, LOCKSTAT_WRITER);			\
@@ -114,7 +120,7 @@
 	else {								\
 		LOCKSTAT_PROFILE_RELEASE_RWLOCK(rw__release, rw,	\
 		    LOCKSTAT_WRITER);					\
-		if ((rw)->rw_lock != _tid || !_rw_write_unlock((rw), _tid))\
+		if (!_rw_write_unlock((rw), _tid))			\
 			_rw_wunlock_hard((rw), _tid, (file), (line));	\
 	}								\
 } while (0)
@@ -135,8 +141,8 @@ void	_rw_wunlock_cookie(volatile uintptr
 void	__rw_rlock(volatile uintptr_t *c, const char *file, int line);
 int	__rw_try_rlock(volatile uintptr_t *c, const char *file, int line);
 void	_rw_runlock_cookie(volatile uintptr_t *c, const char *file, int line);
-void	__rw_wlock_hard(volatile uintptr_t *c, uintptr_t tid, const char *file,
-	    int line);
+void	__rw_wlock_hard(volatile uintptr_t *c, uintptr_t v, uintptr_t tid,
+	    const char *file, int line);
 void	__rw_wunlock_hard(volatile uintptr_t *c, uintptr_t tid,
 	    const char *file, int line);
 int	__rw_try_upgrade(volatile uintptr_t *c, const char *file, int line);
@@ -171,8 +177,8 @@ void	__rw_assert(const volatile uintptr_
 	__rw_try_rlock(&(rw)->rw_lock, f, l)
 #define	_rw_runlock(rw, f, l)						\
 	_rw_runlock_cookie(&(rw)->rw_lock, f, l)
-#define	_rw_wlock_hard(rw, t, f, l)					\
-	__rw_wlock_hard(&(rw)->rw_lock, t, f, l)
+#define	_rw_wlock_hard(rw, v, t, f, l)					\
+	__rw_wlock_hard(&(rw)->rw_lock, v, t, f, l)
 #define	_rw_wunlock_hard(rw, t, f, l)					\
 	__rw_wunlock_hard(&(rw)->rw_lock, t, f, l)
 #define	_rw_try_upgrade(rw, f, l)					\


More information about the svn-src-head mailing list