Browse Source

futex: Allow for compiling out PI support

This makes it possible to preserve basic futex support and compile out the
PI support when RT mutexes are not available.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Darren Hart <dvhart@infradead.org>
Link: http://lkml.kernel.org/r/alpine.LFD.2.20.1708010024190.5981@knanqh.ubzr
Nicolas Pitre 8 năm trước cách đây
mục cha
commit
bc2eecd7ec

+ 6 - 1
include/linux/futex.h

@@ -54,7 +54,6 @@ union futex_key {
 
 
 #ifdef CONFIG_FUTEX
 #ifdef CONFIG_FUTEX
 extern void exit_robust_list(struct task_struct *curr);
 extern void exit_robust_list(struct task_struct *curr);
-extern void exit_pi_state_list(struct task_struct *curr);
 #ifdef CONFIG_HAVE_FUTEX_CMPXCHG
 #ifdef CONFIG_HAVE_FUTEX_CMPXCHG
 #define futex_cmpxchg_enabled 1
 #define futex_cmpxchg_enabled 1
 #else
 #else
@@ -64,8 +63,14 @@ extern int futex_cmpxchg_enabled;
 static inline void exit_robust_list(struct task_struct *curr)
 static inline void exit_robust_list(struct task_struct *curr)
 {
 {
 }
 }
+#endif
+
+#ifdef CONFIG_FUTEX_PI
+extern void exit_pi_state_list(struct task_struct *curr);
+#else
 static inline void exit_pi_state_list(struct task_struct *curr)
 static inline void exit_pi_state_list(struct task_struct *curr)
 {
 {
 }
 }
 #endif
 #endif
+
 #endif
 #endif

+ 6 - 1
init/Kconfig

@@ -1275,12 +1275,17 @@ config BASE_FULL
 config FUTEX
 config FUTEX
 	bool "Enable futex support" if EXPERT
 	bool "Enable futex support" if EXPERT
 	default y
 	default y
-	select RT_MUTEXES
+	imply RT_MUTEXES
 	help
 	help
 	  Disabling this option will cause the kernel to be built without
 	  Disabling this option will cause the kernel to be built without
 	  support for "fast userspace mutexes".  The resulting kernel may not
 	  support for "fast userspace mutexes".  The resulting kernel may not
 	  run glibc-based applications correctly.
 	  run glibc-based applications correctly.
 
 
+config FUTEX_PI
+	bool
+	depends on FUTEX && RT_MUTEXES
+	default y
+
 config HAVE_FUTEX_CMPXCHG
 config HAVE_FUTEX_CMPXCHG
 	bool
 	bool
 	depends on FUTEX
 	depends on FUTEX

+ 22 - 0
kernel/futex.c

@@ -875,6 +875,8 @@ static struct task_struct *futex_find_get_task(pid_t pid)
 	return p;
 	return p;
 }
 }
 
 
+#ifdef CONFIG_FUTEX_PI
+
 /*
 /*
  * This task is holding PI mutexes at exit time => bad.
  * This task is holding PI mutexes at exit time => bad.
  * Kernel cleans up PI-state, but userspace is likely hosed.
  * Kernel cleans up PI-state, but userspace is likely hosed.
@@ -932,6 +934,8 @@ void exit_pi_state_list(struct task_struct *curr)
 	raw_spin_unlock_irq(&curr->pi_lock);
 	raw_spin_unlock_irq(&curr->pi_lock);
 }
 }
 
 
+#endif
+
 /*
 /*
  * We need to check the following states:
  * We need to check the following states:
  *
  *
@@ -1799,6 +1803,15 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
 	struct futex_q *this, *next;
 	struct futex_q *this, *next;
 	DEFINE_WAKE_Q(wake_q);
 	DEFINE_WAKE_Q(wake_q);
 
 
+	/*
+	 * When PI not supported: return -ENOSYS if requeue_pi is true,
+	 * consequently the compiler knows requeue_pi is always false past
+	 * this point which will optimize away all the conditional code
+	 * further down.
+	 */
+	if (!IS_ENABLED(CONFIG_FUTEX_PI) && requeue_pi)
+		return -ENOSYS;
+
 	if (requeue_pi) {
 	if (requeue_pi) {
 		/*
 		/*
 		 * Requeue PI only works on two distinct uaddrs. This
 		 * Requeue PI only works on two distinct uaddrs. This
@@ -2594,6 +2607,9 @@ static int futex_lock_pi(u32 __user *uaddr, unsigned int flags,
 	struct futex_q q = futex_q_init;
 	struct futex_q q = futex_q_init;
 	int res, ret;
 	int res, ret;
 
 
+	if (!IS_ENABLED(CONFIG_FUTEX_PI))
+		return -ENOSYS;
+
 	if (refill_pi_state_cache())
 	if (refill_pi_state_cache())
 		return -ENOMEM;
 		return -ENOMEM;
 
 
@@ -2773,6 +2789,9 @@ static int futex_unlock_pi(u32 __user *uaddr, unsigned int flags)
 	struct futex_q *top_waiter;
 	struct futex_q *top_waiter;
 	int ret;
 	int ret;
 
 
+	if (!IS_ENABLED(CONFIG_FUTEX_PI))
+		return -ENOSYS;
+
 retry:
 retry:
 	if (get_user(uval, uaddr))
 	if (get_user(uval, uaddr))
 		return -EFAULT;
 		return -EFAULT;
@@ -2983,6 +3002,9 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
 	struct futex_q q = futex_q_init;
 	struct futex_q q = futex_q_init;
 	int res, ret;
 	int res, ret;
 
 
+	if (!IS_ENABLED(CONFIG_FUTEX_PI))
+		return -ENOSYS;
+
 	if (uaddr == uaddr2)
 	if (uaddr == uaddr2)
 		return -EINVAL;
 		return -EINVAL;
 
 

+ 29 - 0
kernel/locking/rtmutex_common.h

@@ -40,6 +40,9 @@ struct rt_mutex_waiter {
 /*
 /*
  * Various helpers to access the waiters-tree:
  * Various helpers to access the waiters-tree:
  */
  */
+
+#ifdef CONFIG_RT_MUTEXES
+
 static inline int rt_mutex_has_waiters(struct rt_mutex *lock)
 static inline int rt_mutex_has_waiters(struct rt_mutex *lock)
 {
 {
 	return !RB_EMPTY_ROOT(&lock->waiters);
 	return !RB_EMPTY_ROOT(&lock->waiters);
@@ -69,6 +72,32 @@ task_top_pi_waiter(struct task_struct *p)
 			pi_tree_entry);
 			pi_tree_entry);
 }
 }
 
 
+#else
+
+static inline int rt_mutex_has_waiters(struct rt_mutex *lock)
+{
+	return false;
+}
+
+static inline struct rt_mutex_waiter *
+rt_mutex_top_waiter(struct rt_mutex *lock)
+{
+	return NULL;
+}
+
+static inline int task_has_pi_waiters(struct task_struct *p)
+{
+	return false;
+}
+
+static inline struct rt_mutex_waiter *
+task_top_pi_waiter(struct task_struct *p)
+{
+	return NULL;
+}
+
+#endif
+
 /*
 /*
  * lock->owner state tracking:
  * lock->owner state tracking:
  */
  */