Author: kib
Date: Sat Jul 30 14:47:04 2016
New Revision: 303552
URL: https://svnweb.freebsd.org/changeset/base/303552

Log:
  MFC r303211:
  Implement mtx_trylock_spin(9).

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

Modified: stable/10/share/man/man9/Makefile
==============================================================================
--- stable/10/share/man/man9/Makefile   Sat Jul 30 10:32:28 2016        
(r303551)
+++ stable/10/share/man/man9/Makefile   Sat Jul 30 14:47:04 2016        
(r303552)
@@ -994,6 +994,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/10/share/man/man9/mutex.9
==============================================================================
--- stable/10/share/man/man9/mutex.9    Sat Jul 30 10:32:28 2016        
(r303551)
+++ stable/10/share/man/man9/mutex.9    Sat Jul 30 14:47:04 2016        
(r303552)
@@ -28,7 +28,7 @@
 .\"    from BSDI $Id: mutex.4,v 1.1.2.3 1998/04/27 22:53:13 ewv Exp $
 .\" $FreeBSD$
 .\"
-.Dd November 16, 2011
+.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"
@@ -245,26 +251,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
@@ -443,6 +456,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
@@ -528,3 +548,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/10/sys/kern/kern_mutex.c
==============================================================================
--- stable/10/sys/kern/kern_mutex.c     Sat Jul 30 10:32:28 2016        
(r303551)
+++ stable/10/sys/kern/kern_mutex.c     Sat Jul 30 14:47:04 2016        
(r303552)
@@ -285,6 +285,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/10/sys/sys/mutex.h
==============================================================================
--- stable/10/sys/sys/mutex.h   Sat Jul 30 10:32:28 2016        (r303551)
+++ stable/10/sys/sys/mutex.h   Sat Jul 30 14:47:04 2016        (r303552)
@@ -111,6 +111,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)
@@ -151,6 +153,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)
@@ -211,6 +215,21 @@ void       thread_lock_flags_(struct thread *,
                LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(LS_MTX_SPIN_LOCK_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(LS_MTX_SPIN_LOCK_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);                              \
@@ -223,6 +242,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. */
@@ -292,6 +325,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'
@@ -301,6 +338,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)
 
@@ -338,6 +376,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 */
@@ -347,6 +387,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 */
@@ -372,6 +414,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__)
 
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to