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
This commit is contained in:
Nicolas Pitre 2017-08-01 00:31:32 -04:00 committed by Thomas Gleixner
parent f06e8c584f
commit bc2eecd7ec
4 changed files with 63 additions and 2 deletions

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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:
*/ */