summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Pitre <nicolas.pitre@linaro.org>2017-08-01 00:31:32 -0400
committerThomas Gleixner <tglx@linutronix.de>2017-08-01 08:36:35 -0400
commitbc2eecd7ecce40af43b6eb3d256b6076257df846 (patch)
treed4189369c4484b144f9cb3d72455ac3a5207dd37
parentf06e8c584fa0d05312c11ea66194f3d2efb93c21 (diff)
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
-rw-r--r--include/linux/futex.h7
-rw-r--r--init/Kconfig7
-rw-r--r--kernel/futex.c22
-rw-r--r--kernel/locking/rtmutex_common.h29
4 files changed, 63 insertions, 2 deletions
diff --git a/include/linux/futex.h b/include/linux/futex.h
index 7c5b694864cd..f36bfd26f998 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -54,7 +54,6 @@ union futex_key {
54 54
55#ifdef CONFIG_FUTEX 55#ifdef CONFIG_FUTEX
56extern void exit_robust_list(struct task_struct *curr); 56extern void exit_robust_list(struct task_struct *curr);
57extern void exit_pi_state_list(struct task_struct *curr);
58#ifdef CONFIG_HAVE_FUTEX_CMPXCHG 57#ifdef CONFIG_HAVE_FUTEX_CMPXCHG
59#define futex_cmpxchg_enabled 1 58#define futex_cmpxchg_enabled 1
60#else 59#else
@@ -64,8 +63,14 @@ extern int futex_cmpxchg_enabled;
64static inline void exit_robust_list(struct task_struct *curr) 63static inline void exit_robust_list(struct task_struct *curr)
65{ 64{
66} 65}
66#endif
67
68#ifdef CONFIG_FUTEX_PI
69extern void exit_pi_state_list(struct task_struct *curr);
70#else
67static inline void exit_pi_state_list(struct task_struct *curr) 71static inline void exit_pi_state_list(struct task_struct *curr)
68{ 72{
69} 73}
70#endif 74#endif
75
71#endif 76#endif
diff --git a/init/Kconfig b/init/Kconfig
index 8514b25db21c..5f0ef850e808 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1275,12 +1275,17 @@ config BASE_FULL
1275config FUTEX 1275config FUTEX
1276 bool "Enable futex support" if EXPERT 1276 bool "Enable futex support" if EXPERT
1277 default y 1277 default y
1278 select RT_MUTEXES 1278 imply RT_MUTEXES
1279 help 1279 help
1280 Disabling this option will cause the kernel to be built without 1280 Disabling this option will cause the kernel to be built without
1281 support for "fast userspace mutexes". The resulting kernel may not 1281 support for "fast userspace mutexes". The resulting kernel may not
1282 run glibc-based applications correctly. 1282 run glibc-based applications correctly.
1283 1283
1284config FUTEX_PI
1285 bool
1286 depends on FUTEX && RT_MUTEXES
1287 default y
1288
1284config HAVE_FUTEX_CMPXCHG 1289config HAVE_FUTEX_CMPXCHG
1285 bool 1290 bool
1286 depends on FUTEX 1291 depends on FUTEX
diff --git a/kernel/futex.c b/kernel/futex.c
index 16dbe4c93895..ad0af4df1b9d 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -875,6 +875,8 @@ static struct task_struct *futex_find_get_task(pid_t pid)
875 return p; 875 return p;
876} 876}
877 877
878#ifdef CONFIG_FUTEX_PI
879
878/* 880/*
879 * This task is holding PI mutexes at exit time => bad. 881 * This task is holding PI mutexes at exit time => bad.
880 * Kernel cleans up PI-state, but userspace is likely hosed. 882 * Kernel cleans up PI-state, but userspace is likely hosed.
@@ -932,6 +934,8 @@ void exit_pi_state_list(struct task_struct *curr)
932 raw_spin_unlock_irq(&curr->pi_lock); 934 raw_spin_unlock_irq(&curr->pi_lock);
933} 935}
934 936
937#endif
938
935/* 939/*
936 * We need to check the following states: 940 * We need to check the following states:
937 * 941 *
@@ -1799,6 +1803,15 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
1799 struct futex_q *this, *next; 1803 struct futex_q *this, *next;
1800 DEFINE_WAKE_Q(wake_q); 1804 DEFINE_WAKE_Q(wake_q);
1801 1805
1806 /*
1807 * When PI not supported: return -ENOSYS if requeue_pi is true,
1808 * consequently the compiler knows requeue_pi is always false past
1809 * this point which will optimize away all the conditional code
1810 * further down.
1811 */
1812 if (!IS_ENABLED(CONFIG_FUTEX_PI) && requeue_pi)
1813 return -ENOSYS;
1814
1802 if (requeue_pi) { 1815 if (requeue_pi) {
1803 /* 1816 /*
1804 * Requeue PI only works on two distinct uaddrs. This 1817 * Requeue PI only works on two distinct uaddrs. This
@@ -2594,6 +2607,9 @@ static int futex_lock_pi(u32 __user *uaddr, unsigned int flags,
2594 struct futex_q q = futex_q_init; 2607 struct futex_q q = futex_q_init;
2595 int res, ret; 2608 int res, ret;
2596 2609
2610 if (!IS_ENABLED(CONFIG_FUTEX_PI))
2611 return -ENOSYS;
2612
2597 if (refill_pi_state_cache()) 2613 if (refill_pi_state_cache())
2598 return -ENOMEM; 2614 return -ENOMEM;
2599 2615
@@ -2773,6 +2789,9 @@ static int futex_unlock_pi(u32 __user *uaddr, unsigned int flags)
2773 struct futex_q *top_waiter; 2789 struct futex_q *top_waiter;
2774 int ret; 2790 int ret;
2775 2791
2792 if (!IS_ENABLED(CONFIG_FUTEX_PI))
2793 return -ENOSYS;
2794
2776retry: 2795retry:
2777 if (get_user(uval, uaddr)) 2796 if (get_user(uval, uaddr))
2778 return -EFAULT; 2797 return -EFAULT;
@@ -2983,6 +3002,9 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
2983 struct futex_q q = futex_q_init; 3002 struct futex_q q = futex_q_init;
2984 int res, ret; 3003 int res, ret;
2985 3004
3005 if (!IS_ENABLED(CONFIG_FUTEX_PI))
3006 return -ENOSYS;
3007
2986 if (uaddr == uaddr2) 3008 if (uaddr == uaddr2)
2987 return -EINVAL; 3009 return -EINVAL;
2988 3010
diff --git a/kernel/locking/rtmutex_common.h b/kernel/locking/rtmutex_common.h
index 72ad45a9a794..8d039b928d61 100644
--- a/kernel/locking/rtmutex_common.h
+++ b/kernel/locking/rtmutex_common.h
@@ -40,6 +40,9 @@ struct rt_mutex_waiter {
40/* 40/*
41 * Various helpers to access the waiters-tree: 41 * Various helpers to access the waiters-tree:
42 */ 42 */
43
44#ifdef CONFIG_RT_MUTEXES
45
43static inline int rt_mutex_has_waiters(struct rt_mutex *lock) 46static inline int rt_mutex_has_waiters(struct rt_mutex *lock)
44{ 47{
45 return !RB_EMPTY_ROOT(&lock->waiters); 48 return !RB_EMPTY_ROOT(&lock->waiters);
@@ -69,6 +72,32 @@ task_top_pi_waiter(struct task_struct *p)
69 pi_tree_entry); 72 pi_tree_entry);
70} 73}
71 74
75#else
76
77static inline int rt_mutex_has_waiters(struct rt_mutex *lock)
78{
79 return false;
80}
81
82static inline struct rt_mutex_waiter *
83rt_mutex_top_waiter(struct rt_mutex *lock)
84{
85 return NULL;
86}
87
88static inline int task_has_pi_waiters(struct task_struct *p)
89{
90 return false;
91}
92
93static inline struct rt_mutex_waiter *
94task_top_pi_waiter(struct task_struct *p)
95{
96 return NULL;
97}
98
99#endif
100
72/* 101/*
73 * lock->owner state tracking: 102 * lock->owner state tracking:
74 */ 103 */