svn commit: r303549 - in stable/11: share/man/man9 sys/kern sys/sys

Konstantin Belousov kib at FreeBSD.org
Sat Jul 30 09:28:15 UTC 2016


Author: kib
Date: Sat Jul 30 09:28:13 2016
New Revision: 303549
URL: https://svnweb.freebsd.org/changeset/base/303549

Log:
  MFC r303211:
  Implement mtx_trylock_spin(9).
  
  Approved by:	re (gjb)

Modified:
  stable/11/share/man/man9/Makefile
  stable/11/share/man/man9/mutex.9
  stable/11/sys/kern/kern_mutex.c
  stable/11/sys/sys/mutex.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/share/man/man9/Makefile
==============================================================================
--- stable/11/share/man/man9/Makefile	Sat Jul 30 09:25:57 2016	(r303548)
+++ stable/11/share/man/man9/Makefile	Sat Jul 30 09:28:13 2016	(r303549)
@@ -1181,6 +1181,8 @@ MLINKS+=mutex.9 mtx_assert.9 \
 	mutex.9 MTX_SYSINIT.9 \
 	mutex.9 mtx_trylock.9 \
 	mutex.9 mtx_trylock_flags.9 \
+	mutex.9 mtx_trylock_spin.9 \
+	mutex.9 mtx_trylock_spin_flags.9 \
 	mutex.9 mtx_unlock.9 \
 	mutex.9 mtx_unlock_flags.9 \
 	mutex.9 mtx_unlock_spin.9 \

Modified: stable/11/share/man/man9/mutex.9
==============================================================================
--- stable/11/share/man/man9/mutex.9	Sat Jul 30 09:25:57 2016	(r303548)
+++ stable/11/share/man/man9/mutex.9	Sat Jul 30 09:28:13 2016	(r303549)
@@ -28,7 +28,7 @@
 .\"	from BSDI $Id: mutex.4,v 1.1.2.3 1998/04/27 22:53:13 ewv Exp $
 .\" $FreeBSD$
 .\"
-.Dd December 13, 2014
+.Dd July 18, 2016
 .Dt MUTEX 9
 .Os
 .Sh NAME
@@ -41,6 +41,8 @@
 .Nm mtx_lock_spin_flags ,
 .Nm mtx_trylock ,
 .Nm mtx_trylock_flags ,
+.Nm mtx_trylock_spin ,
+.Nm mtx_trylock_spin_flags ,
 .Nm mtx_unlock ,
 .Nm mtx_unlock_spin ,
 .Nm mtx_unlock_flags ,
@@ -73,6 +75,10 @@
 .Ft int
 .Fn mtx_trylock_flags "struct mtx *mutex" "int flags"
 .Ft void
+.Fn mtx_trylock_spin "struct mtx *mutex"
+.Ft int
+.Fn mtx_trylock_spin_flags "struct mtx *mutex" "int flags"
+.Ft void
 .Fn mtx_unlock "struct mtx *mutex"
 .Ft void
 .Fn mtx_unlock_spin "struct mtx *mutex"
@@ -249,26 +255,33 @@ argument, then the mutex can be acquired
 .Pp
 The
 .Fn mtx_trylock
-attempts to acquire the
+and
+.Fn mtx_trylock_spin
+functions attempt to acquire a
 .Dv MTX_DEF
-mutex pointed to by
+or
+.Dv MTX_SPIN
+mutex, respectively, pointed to by
 .Fa mutex .
-If the mutex cannot be immediately acquired
-.Fn mtx_trylock
-will return 0,
-otherwise the mutex will be acquired
-and a non-zero value will be returned.
+If the mutex cannot be immediately acquired, the functions will return 0,
+otherwise the mutex will be acquired and a non-zero value will be returned.
 .Pp
 The
 .Fn mtx_trylock_flags
-function has the same behavior as
+and
+.Fn mtx_trylock_spin_flags
+functions have the same behavior as
 .Fn mtx_trylock
-but should be used when the caller desires to pass in a
+and
+.Fn mtx_trylock_spin
+respectively, but should be used when the caller desires to pass in a
 .Fa flags
 value.
 Presently, the only valid value in the
 .Fn mtx_trylock
-case is
+and
+.Fn mtx_trylock_spin
+cases is
 .Dv MTX_QUIET ,
 and its effects are identical to those described for
 .Fn mtx_lock
@@ -447,6 +460,13 @@ while any spin lock is held.
 .It Dv MTX_RECURSE
 Specifies that the initialized mutex is allowed to recurse.
 This bit must be present if the mutex is permitted to recurse.
+.Pp
+Note that neither
+.Fn mtx_trylock
+nor
+.Fn mtx_trylock_spin
+support recursion;
+that is, attempting to acquire an already-owned mutex fails.
 .It Dv MTX_QUIET
 Do not log any mutex operations for this lock.
 .It Dv MTX_NOWITNESS
@@ -534,3 +554,7 @@ functions appeared in
 .Bsx 4.1
 and
 .Fx 5.0 .
+The
+.Fn mtx_trylock_spin
+function was added in
+.Fx 12.0 .

Modified: stable/11/sys/kern/kern_mutex.c
==============================================================================
--- stable/11/sys/kern/kern_mutex.c	Sat Jul 30 09:25:57 2016	(r303548)
+++ stable/11/sys/kern/kern_mutex.c	Sat Jul 30 09:28:13 2016	(r303549)
@@ -281,6 +281,34 @@ __mtx_lock_spin_flags(volatile uintptr_t
 	WITNESS_LOCK(&m->lock_object, opts | LOP_EXCLUSIVE, file, line);
 }
 
+int
+__mtx_trylock_spin_flags(volatile uintptr_t *c, int opts, const char *file,
+    int line)
+{
+	struct mtx *m;
+
+	if (SCHEDULER_STOPPED())
+		return (1);
+
+	m = mtxlock2mtx(c);
+
+	KASSERT(m->mtx_lock != MTX_DESTROYED,
+	    ("mtx_trylock_spin() of destroyed mutex @ %s:%d", file, line));
+	KASSERT(LOCK_CLASS(&m->lock_object) == &lock_class_mtx_spin,
+	    ("mtx_trylock_spin() of sleep mutex %s @ %s:%d",
+	    m->lock_object.lo_name, file, line));
+	KASSERT((opts & MTX_RECURSE) == 0,
+	    ("mtx_trylock_spin: unsupp. opt MTX_RECURSE on mutex %s @ %s:%d\n",
+	    m->lock_object.lo_name, file, line));
+	if (__mtx_trylock_spin(m, curthread, opts, file, line)) {
+		LOCK_LOG_TRY("LOCK", &m->lock_object, opts, 1, file, line);
+		WITNESS_LOCK(&m->lock_object, opts | LOP_EXCLUSIVE, file, line);
+		return (1);
+	}
+	LOCK_LOG_TRY("LOCK", &m->lock_object, opts, 0, file, line);
+	return (0);
+}
+
 void
 __mtx_unlock_spin_flags(volatile uintptr_t *c, int opts, const char *file,
     int line)

Modified: stable/11/sys/sys/mutex.h
==============================================================================
--- stable/11/sys/sys/mutex.h	Sat Jul 30 09:25:57 2016	(r303548)
+++ stable/11/sys/sys/mutex.h	Sat Jul 30 09:28:13 2016	(r303549)
@@ -112,6 +112,8 @@ void	__mtx_unlock_flags(volatile uintptr
 	    int line);
 void	__mtx_lock_spin_flags(volatile uintptr_t *c, int opts, const char *file,
 	     int line);
+int	__mtx_trylock_spin_flags(volatile uintptr_t *c, int opts,
+	     const char *file, int line);
 void	__mtx_unlock_spin_flags(volatile uintptr_t *c, int opts,
 	    const char *file, int line);
 #if defined(INVARIANTS) || defined(INVARIANT_SUPPORT)
@@ -152,6 +154,8 @@ void	thread_lock_flags_(struct thread *,
 	__mtx_unlock_flags(&(m)->mtx_lock, o, f, l)
 #define	_mtx_lock_spin_flags(m, o, f, l)				\
 	__mtx_lock_spin_flags(&(m)->mtx_lock, o, f, l)
+#define	_mtx_trylock_spin_flags(m, o, f, l)				\
+	__mtx_trylock_spin_flags(&(m)->mtx_lock, o, f, l)
 #define	_mtx_unlock_spin_flags(m, o, f, l)				\
 	__mtx_unlock_spin_flags(&(m)->mtx_lock, o, f, l)
 #if defined(INVARIANTS) || defined(INVARIANT_SUPPORT)
@@ -212,6 +216,21 @@ void	thread_lock_flags_(struct thread *,
 		LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(spin__acquire,	\
 		    mp, 0, 0, file, line);				\
 } while (0)
+#define __mtx_trylock_spin(mp, tid, opts, file, line) __extension__  ({	\
+	uintptr_t _tid = (uintptr_t)(tid);				\
+	int _ret;							\
+									\
+	spinlock_enter();						\
+	if (((mp)->mtx_lock != MTX_UNOWNED || !_mtx_obtain_lock((mp), _tid))) {\
+		spinlock_exit();					\
+		_ret = 0;						\
+	} else {							\
+		LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(spin__acquire,	\
+		    mp, 0, 0, file, line);				\
+		_ret = 1;						\
+	}								\
+	_ret;								\
+})
 #else /* SMP */
 #define __mtx_lock_spin(mp, tid, opts, file, line) do {			\
 	uintptr_t _tid = (uintptr_t)(tid);				\
@@ -224,6 +243,20 @@ void	thread_lock_flags_(struct thread *,
 		(mp)->mtx_lock = _tid;					\
 	}								\
 } while (0)
+#define __mtx_trylock_spin(mp, tid, opts, file, line) __extension__  ({	\
+	uintptr_t _tid = (uintptr_t)(tid);				\
+	int _ret;							\
+									\
+	spinlock_enter();						\
+	if ((mp)->mtx_lock != MTX_UNOWNED) {				\
+		spinlock_exit();					\
+		_ret = 0;						\
+	} else {							\
+		(mp)->mtx_lock = _tid;					\
+		_ret = 1;						\
+	}								\
+	_ret;								\
+})
 #endif /* SMP */
 
 /* Unlock a normal mutex. */
@@ -293,6 +326,10 @@ void	thread_lock_flags_(struct thread *,
  * mtx_trylock_flags(m, opts) is used the same way as mtx_trylock() but accepts
  *     relevant option flags `opts.'
  *
+ * mtx_trylock_spin(m) attempts to acquire MTX_SPIN mutex `m' but doesn't
+ *     spin if it cannot.  Rather, it returns 0 on failure and non-zero on
+ *     success.  It always returns failure for recursed lock attempts.
+ *
  * mtx_initialized(m) returns non-zero if the lock `m' has been initialized.
  *
  * mtx_owned(m) returns non-zero if the current thread owns the lock `m'
@@ -302,6 +339,7 @@ void	thread_lock_flags_(struct thread *,
 #define mtx_lock(m)		mtx_lock_flags((m), 0)
 #define mtx_lock_spin(m)	mtx_lock_spin_flags((m), 0)
 #define mtx_trylock(m)		mtx_trylock_flags((m), 0)
+#define mtx_trylock_spin(m)	mtx_trylock_spin_flags((m), 0)
 #define mtx_unlock(m)		mtx_unlock_flags((m), 0)
 #define mtx_unlock_spin(m)	mtx_unlock_spin_flags((m), 0)
 
@@ -335,6 +373,8 @@ extern struct mtx_pool *mtxpool_sleep;
 	_mtx_unlock_flags((m), (opts), (file), (line))
 #define	mtx_lock_spin_flags_(m, opts, file, line)			\
 	_mtx_lock_spin_flags((m), (opts), (file), (line))
+#define	mtx_trylock_spin_flags_(m, opts, file, line)			\
+	_mtx_trylock_spin_flags((m), (opts), (file), (line))
 #define	mtx_unlock_spin_flags_(m, opts, file, line)			\
 	_mtx_unlock_spin_flags((m), (opts), (file), (line))
 #else	/* LOCK_DEBUG == 0 && !MUTEX_NOINLINE */
@@ -344,6 +384,8 @@ extern struct mtx_pool *mtxpool_sleep;
 	__mtx_unlock((m), curthread, (opts), (file), (line))
 #define	mtx_lock_spin_flags_(m, opts, file, line)			\
 	__mtx_lock_spin((m), curthread, (opts), (file), (line))
+#define	mtx_trylock_spin_flags_(m, opts, file, line)			\
+	__mtx_trylock_spin((m), curthread, (opts), (file), (line))
 #define	mtx_unlock_spin_flags_(m, opts, file, line)			\
 	__mtx_unlock_spin((m))
 #endif	/* LOCK_DEBUG > 0 || MUTEX_NOINLINE */
@@ -369,6 +411,8 @@ extern struct mtx_pool *mtxpool_sleep;
 	mtx_unlock_spin_flags_((m), (opts), LOCK_FILE, LOCK_LINE)
 #define mtx_trylock_flags(m, opts)					\
 	mtx_trylock_flags_((m), (opts), LOCK_FILE, LOCK_LINE)
+#define mtx_trylock_spin_flags(m, opts)					\
+	mtx_trylock_spin_flags_((m), (opts), LOCK_FILE, LOCK_LINE)
 #define	mtx_assert(m, what)						\
 	mtx_assert_((m), (what), __FILE__, __LINE__)
 


More information about the svn-src-all mailing list