]> granicus.if.org Git - spl/commitdiff
Use kernel provided mutex owner
authorChunwei Chen <david.chen@osnexus.com>
Tue, 12 Apr 2016 19:05:14 +0000 (12:05 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 26 Apr 2016 00:04:07 +0000 (17:04 -0700)
To reduce mutex footprint, we detect the existence of owner in kernel mutex,
and rely on it if it exists.

Note that before Linux 3.0, mutex owner is of type thread_info. Also note
that, in Linux 3.18, the condition for owner is changed from
CONFIG_DEBUG_MUTEXES || CONFIG_SMP to
CONFIG_DEBUG_MUTEXES || CONFIG_MUTEX_SPIN_ON_OWNER

Signed-off-by: Chunwei Chen <david.chen@osnexus.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #540

config/spl-build.m4
include/sys/mutex.h

index b9c04a95e01d60aa6d92d81e49836d200085f542..55453c822e7d5d6d680c87c3029839a8e1682fd0 100644 (file)
@@ -44,6 +44,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [
        SPL_AC_USLEEP_RANGE
        SPL_AC_KMEM_CACHE_ALLOCFLAGS
        SPL_AC_WAIT_ON_BIT
+       SPL_AC_MUTEX_OWNER
 ])
 
 AC_DEFUN([SPL_AC_MODULE_SYMVERS], [
@@ -1447,3 +1448,31 @@ AC_DEFUN([SPL_AC_WAIT_ON_BIT], [
                AC_MSG_RESULT(no)
        ])
 ])
+
+dnl #
+dnl # Check whether mutex has owner with task_struct type.
+dnl #
+dnl # Note that before Linux 3.0, mutex owner is of type thread_info.
+dnl #
+dnl # Note that in Linux 3.18, the condition for owner is changed from
+dnl # defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_SMP) to
+dnl # defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_MUTEX_SPIN_ON_OWNER)
+dnl #
+AC_DEFUN([SPL_AC_MUTEX_OWNER], [
+       AC_MSG_CHECKING([whether mutex has owner])
+       tmp_flags="$EXTRA_KCFLAGS"
+       EXTRA_KCFLAGS="-Werror"
+       SPL_LINUX_TRY_COMPILE([
+               #include <linux/mutex.h>
+       ],[
+               DEFINE_MUTEX(m);
+               struct task_struct *t __attribute__ ((unused));
+               t = m.owner;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_MUTEX_OWNER, 1, [yes])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+       EXTRA_KCFLAGS="$tmp_flags"
+])
index fba35f3f9813b0bcb695d48b2c1a86bf1e4f0f68..31923522308e8391ad2e2ba6dec94345f9eb7a98 100644 (file)
@@ -40,7 +40,10 @@ typedef enum {
 typedef struct {
        struct mutex            m_mutex;
        spinlock_t              m_lock; /* used for serializing mutex_exit */
+#ifndef HAVE_MUTEX_OWNER
+       /* only when kernel doesn't have owner */
        kthread_t               *m_owner;
+#endif
 #ifdef CONFIG_LOCKDEP
        kmutex_type_t           m_type;
 #endif /* CONFIG_LOCKDEP */
@@ -51,16 +54,28 @@ typedef struct {
 static inline void
 spl_mutex_set_owner(kmutex_t *mp)
 {
+       /*
+        * kernel will handle its owner, so we don't need to do anything if it
+        * is defined.
+        */
+#ifndef HAVE_MUTEX_OWNER
        mp->m_owner = current;
+#endif
 }
 
 static inline void
 spl_mutex_clear_owner(kmutex_t *mp)
 {
+#ifndef HAVE_MUTEX_OWNER
        mp->m_owner = NULL;
+#endif
 }
 
+#ifdef HAVE_MUTEX_OWNER
+#define        mutex_owner(mp)         (ACCESS_ONCE(MUTEX(mp)->owner))
+#else
 #define        mutex_owner(mp)         (ACCESS_ONCE((mp)->m_owner))
+#endif
 #define        mutex_owned(mp)         (mutex_owner(mp) == current)
 #define        MUTEX_HELD(mp)          mutex_owned(mp)
 #define        MUTEX_NOT_HELD(mp)      (!MUTEX_HELD(mp))