Commit bc2eecd7 authored by Nicolas Pitre's avatar Nicolas Pitre Committed by Thomas Gleixner
Browse files

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: default avatarNicolas Pitre <nico@linaro.org>
Signed-off-by: default avatarThomas 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
parent f06e8c58
Loading
Loading
Loading
Loading
+6 −1
Original line number Original line Diff line number Diff line
@@ -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
Original line number Original line Diff line number Diff line
@@ -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
Original line number Original line Diff line number Diff line
@@ -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
Original line number Original line Diff line number Diff line
@@ -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:
 */
 */