From cdd39dd2457ac57622339669db0536a580374bd3 Mon Sep 17 00:00:00 2001 From: Chunwei Chen Date: Tue, 12 Apr 2016 12:05:14 -0700 Subject: [PATCH] Use kernel provided mutex owner 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 Signed-off-by: Brian Behlendorf Closes #540 --- config/spl-build.m4 | 29 +++++++++++++++++++++++++++++ include/sys/mutex.h | 15 +++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/config/spl-build.m4 b/config/spl-build.m4 index b9c04a9..55453c8 100644 --- a/config/spl-build.m4 +++ b/config/spl-build.m4 @@ -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 + ],[ + 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" +]) diff --git a/include/sys/mutex.h b/include/sys/mutex.h index fba35f3..3192352 100644 --- a/include/sys/mutex.h +++ b/include/sys/mutex.h @@ -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)) -- 2.39.2