xref: /openbmc/linux/kernel/futex/futex.h (revision 807ff7ed)
1af8cc960SPeter Zijlstra /* SPDX-License-Identifier: GPL-2.0 */
2af8cc960SPeter Zijlstra #ifndef _FUTEX_H
3af8cc960SPeter Zijlstra #define _FUTEX_H
4af8cc960SPeter Zijlstra 
585dc28faSPeter Zijlstra #include <linux/futex.h>
6*807ff7edSChristian König #include <linux/rtmutex.h>
7e5c68284SPeter Zijlstra #include <linux/sched/wake_q.h>
8e5c68284SPeter Zijlstra 
94d381673SPeter Zijlstra #ifdef CONFIG_PREEMPT_RT
104d381673SPeter Zijlstra #include <linux/rcuwait.h>
114d381673SPeter Zijlstra #endif
124d381673SPeter Zijlstra 
13af8cc960SPeter Zijlstra #include <asm/futex.h>
14af8cc960SPeter Zijlstra 
15af8cc960SPeter Zijlstra /*
16af8cc960SPeter Zijlstra  * Futex flags used to encode options to functions and preserve them across
17af8cc960SPeter Zijlstra  * restarts.
18af8cc960SPeter Zijlstra  */
19af8cc960SPeter Zijlstra #ifdef CONFIG_MMU
20af8cc960SPeter Zijlstra # define FLAGS_SHARED		0x01
21af8cc960SPeter Zijlstra #else
22af8cc960SPeter Zijlstra /*
23af8cc960SPeter Zijlstra  * NOMMU does not have per process address space. Let the compiler optimize
24af8cc960SPeter Zijlstra  * code away.
25af8cc960SPeter Zijlstra  */
26af8cc960SPeter Zijlstra # define FLAGS_SHARED		0x00
27af8cc960SPeter Zijlstra #endif
28af8cc960SPeter Zijlstra #define FLAGS_CLOCKRT		0x02
29af8cc960SPeter Zijlstra #define FLAGS_HAS_TIMEOUT	0x04
30af8cc960SPeter Zijlstra 
31af8cc960SPeter Zijlstra #ifdef CONFIG_FAIL_FUTEX
32af8cc960SPeter Zijlstra extern bool should_fail_futex(bool fshared);
33af8cc960SPeter Zijlstra #else
should_fail_futex(bool fshared)34af8cc960SPeter Zijlstra static inline bool should_fail_futex(bool fshared)
35af8cc960SPeter Zijlstra {
36af8cc960SPeter Zijlstra 	return false;
37af8cc960SPeter Zijlstra }
38af8cc960SPeter Zijlstra #endif
39af8cc960SPeter Zijlstra 
4085dc28faSPeter Zijlstra /*
4185dc28faSPeter Zijlstra  * Hash buckets are shared by all the futex_keys that hash to the same
4285dc28faSPeter Zijlstra  * location.  Each key may have multiple futex_q structures, one for each task
4385dc28faSPeter Zijlstra  * waiting on a futex.
4485dc28faSPeter Zijlstra  */
4585dc28faSPeter Zijlstra struct futex_hash_bucket {
4685dc28faSPeter Zijlstra 	atomic_t waiters;
4785dc28faSPeter Zijlstra 	spinlock_t lock;
4885dc28faSPeter Zijlstra 	struct plist_head chain;
4985dc28faSPeter Zijlstra } ____cacheline_aligned_in_smp;
5085dc28faSPeter Zijlstra 
5185dc28faSPeter Zijlstra /*
5285dc28faSPeter Zijlstra  * Priority Inheritance state:
5385dc28faSPeter Zijlstra  */
5485dc28faSPeter Zijlstra struct futex_pi_state {
5585dc28faSPeter Zijlstra 	/*
5685dc28faSPeter Zijlstra 	 * list of 'owned' pi_state instances - these have to be
5785dc28faSPeter Zijlstra 	 * cleaned up in do_exit() if the task exits prematurely:
5885dc28faSPeter Zijlstra 	 */
5985dc28faSPeter Zijlstra 	struct list_head list;
6085dc28faSPeter Zijlstra 
6185dc28faSPeter Zijlstra 	/*
6285dc28faSPeter Zijlstra 	 * The PI object:
6385dc28faSPeter Zijlstra 	 */
6485dc28faSPeter Zijlstra 	struct rt_mutex_base pi_mutex;
6585dc28faSPeter Zijlstra 
6685dc28faSPeter Zijlstra 	struct task_struct *owner;
6785dc28faSPeter Zijlstra 	refcount_t refcount;
6885dc28faSPeter Zijlstra 
6985dc28faSPeter Zijlstra 	union futex_key key;
7085dc28faSPeter Zijlstra } __randomize_layout;
7185dc28faSPeter Zijlstra 
7285dc28faSPeter Zijlstra /**
7385dc28faSPeter Zijlstra  * struct futex_q - The hashed futex queue entry, one per waiting task
7485dc28faSPeter Zijlstra  * @list:		priority-sorted list of tasks waiting on this futex
7585dc28faSPeter Zijlstra  * @task:		the task waiting on the futex
7685dc28faSPeter Zijlstra  * @lock_ptr:		the hash bucket lock
7785dc28faSPeter Zijlstra  * @key:		the key the futex is hashed on
7885dc28faSPeter Zijlstra  * @pi_state:		optional priority inheritance state
7985dc28faSPeter Zijlstra  * @rt_waiter:		rt_waiter storage for use with requeue_pi
8085dc28faSPeter Zijlstra  * @requeue_pi_key:	the requeue_pi target futex key
8185dc28faSPeter Zijlstra  * @bitset:		bitset for the optional bitmasked wakeup
8285dc28faSPeter Zijlstra  * @requeue_state:	State field for futex_requeue_pi()
8385dc28faSPeter Zijlstra  * @requeue_wait:	RCU wait for futex_requeue_pi() (RT only)
8485dc28faSPeter Zijlstra  *
8585dc28faSPeter Zijlstra  * We use this hashed waitqueue, instead of a normal wait_queue_entry_t, so
8685dc28faSPeter Zijlstra  * we can wake only the relevant ones (hashed queues may be shared).
8785dc28faSPeter Zijlstra  *
8885dc28faSPeter Zijlstra  * A futex_q has a woken state, just like tasks have TASK_RUNNING.
8985dc28faSPeter Zijlstra  * It is considered woken when plist_node_empty(&q->list) || q->lock_ptr == 0.
9085dc28faSPeter Zijlstra  * The order of wakeup is always to make the first condition true, then
9185dc28faSPeter Zijlstra  * the second.
9285dc28faSPeter Zijlstra  *
9385dc28faSPeter Zijlstra  * PI futexes are typically woken before they are removed from the hash list via
9485dc28faSPeter Zijlstra  * the rt_mutex code. See futex_unqueue_pi().
9585dc28faSPeter Zijlstra  */
9685dc28faSPeter Zijlstra struct futex_q {
9785dc28faSPeter Zijlstra 	struct plist_node list;
9885dc28faSPeter Zijlstra 
9985dc28faSPeter Zijlstra 	struct task_struct *task;
10085dc28faSPeter Zijlstra 	spinlock_t *lock_ptr;
10185dc28faSPeter Zijlstra 	union futex_key key;
10285dc28faSPeter Zijlstra 	struct futex_pi_state *pi_state;
10385dc28faSPeter Zijlstra 	struct rt_mutex_waiter *rt_waiter;
10485dc28faSPeter Zijlstra 	union futex_key *requeue_pi_key;
10585dc28faSPeter Zijlstra 	u32 bitset;
10685dc28faSPeter Zijlstra 	atomic_t requeue_state;
10785dc28faSPeter Zijlstra #ifdef CONFIG_PREEMPT_RT
10885dc28faSPeter Zijlstra 	struct rcuwait requeue_wait;
10985dc28faSPeter Zijlstra #endif
11085dc28faSPeter Zijlstra } __randomize_layout;
11185dc28faSPeter Zijlstra 
11285dc28faSPeter Zijlstra extern const struct futex_q futex_q_init;
11385dc28faSPeter Zijlstra 
11485dc28faSPeter Zijlstra enum futex_access {
11585dc28faSPeter Zijlstra 	FUTEX_READ,
11685dc28faSPeter Zijlstra 	FUTEX_WRITE
11785dc28faSPeter Zijlstra };
11885dc28faSPeter Zijlstra 
11985dc28faSPeter Zijlstra extern int get_futex_key(u32 __user *uaddr, bool fshared, union futex_key *key,
12085dc28faSPeter Zijlstra 			 enum futex_access rw);
12185dc28faSPeter Zijlstra 
12285dc28faSPeter Zijlstra extern struct hrtimer_sleeper *
12385dc28faSPeter Zijlstra futex_setup_timer(ktime_t *time, struct hrtimer_sleeper *timeout,
12485dc28faSPeter Zijlstra 		  int flags, u64 range_ns);
12585dc28faSPeter Zijlstra 
126e5c68284SPeter Zijlstra extern struct futex_hash_bucket *futex_hash(union futex_key *key);
127e5c68284SPeter Zijlstra 
128e5c68284SPeter Zijlstra /**
129e5c68284SPeter Zijlstra  * futex_match - Check whether two futex keys are equal
130e5c68284SPeter Zijlstra  * @key1:	Pointer to key1
131e5c68284SPeter Zijlstra  * @key2:	Pointer to key2
132e5c68284SPeter Zijlstra  *
133e5c68284SPeter Zijlstra  * Return 1 if two futex_keys are equal, 0 otherwise.
134e5c68284SPeter Zijlstra  */
futex_match(union futex_key * key1,union futex_key * key2)135e5c68284SPeter Zijlstra static inline int futex_match(union futex_key *key1, union futex_key *key2)
136e5c68284SPeter Zijlstra {
137e5c68284SPeter Zijlstra 	return (key1 && key2
138e5c68284SPeter Zijlstra 		&& key1->both.word == key2->both.word
139e5c68284SPeter Zijlstra 		&& key1->both.ptr == key2->both.ptr
140e5c68284SPeter Zijlstra 		&& key1->both.offset == key2->both.offset);
141e5c68284SPeter Zijlstra }
142e5c68284SPeter Zijlstra 
143e5c68284SPeter Zijlstra extern int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
144e5c68284SPeter Zijlstra 			    struct futex_q *q, struct futex_hash_bucket **hb);
145e5c68284SPeter Zijlstra extern void futex_wait_queue(struct futex_hash_bucket *hb, struct futex_q *q,
146e5c68284SPeter Zijlstra 				   struct hrtimer_sleeper *timeout);
147e5c68284SPeter Zijlstra extern void futex_wake_mark(struct wake_q_head *wake_q, struct futex_q *q);
148e5c68284SPeter Zijlstra 
14985dc28faSPeter Zijlstra extern int fault_in_user_writeable(u32 __user *uaddr);
15085dc28faSPeter Zijlstra extern int futex_cmpxchg_value_locked(u32 *curval, u32 __user *uaddr, u32 uval, u32 newval);
15185dc28faSPeter Zijlstra extern int futex_get_value_locked(u32 *dest, u32 __user *from);
15285dc28faSPeter Zijlstra extern struct futex_q *futex_top_waiter(struct futex_hash_bucket *hb, union futex_key *key);
15385dc28faSPeter Zijlstra 
154e5c68284SPeter Zijlstra extern void __futex_unqueue(struct futex_q *q);
15585dc28faSPeter Zijlstra extern void __futex_queue(struct futex_q *q, struct futex_hash_bucket *hb);
156a046f1a0SPeter Zijlstra extern int futex_unqueue(struct futex_q *q);
157a046f1a0SPeter Zijlstra 
158a046f1a0SPeter Zijlstra /**
159a046f1a0SPeter Zijlstra  * futex_queue() - Enqueue the futex_q on the futex_hash_bucket
160a046f1a0SPeter Zijlstra  * @q:	The futex_q to enqueue
161a046f1a0SPeter Zijlstra  * @hb:	The destination hash bucket
162a046f1a0SPeter Zijlstra  *
163a046f1a0SPeter Zijlstra  * The hb->lock must be held by the caller, and is released here. A call to
164a046f1a0SPeter Zijlstra  * futex_queue() is typically paired with exactly one call to futex_unqueue().  The
165a046f1a0SPeter Zijlstra  * exceptions involve the PI related operations, which may use futex_unqueue_pi()
166a046f1a0SPeter Zijlstra  * or nothing if the unqueue is done as part of the wake process and the unqueue
167a046f1a0SPeter Zijlstra  * state is implicit in the state of woken task (see futex_wait_requeue_pi() for
168a046f1a0SPeter Zijlstra  * an example).
169a046f1a0SPeter Zijlstra  */
futex_queue(struct futex_q * q,struct futex_hash_bucket * hb)170a046f1a0SPeter Zijlstra static inline void futex_queue(struct futex_q *q, struct futex_hash_bucket *hb)
171a046f1a0SPeter Zijlstra 	__releases(&hb->lock)
172a046f1a0SPeter Zijlstra {
173a046f1a0SPeter Zijlstra 	__futex_queue(q, hb);
174a046f1a0SPeter Zijlstra 	spin_unlock(&hb->lock);
175a046f1a0SPeter Zijlstra }
176a046f1a0SPeter Zijlstra 
17785dc28faSPeter Zijlstra extern void futex_unqueue_pi(struct futex_q *q);
17885dc28faSPeter Zijlstra 
17985dc28faSPeter Zijlstra extern void wait_for_owner_exiting(int ret, struct task_struct *exiting);
18085dc28faSPeter Zijlstra 
181e5c68284SPeter Zijlstra /*
182e5c68284SPeter Zijlstra  * Reflects a new waiter being added to the waitqueue.
183e5c68284SPeter Zijlstra  */
futex_hb_waiters_inc(struct futex_hash_bucket * hb)184e5c68284SPeter Zijlstra static inline void futex_hb_waiters_inc(struct futex_hash_bucket *hb)
185e5c68284SPeter Zijlstra {
186e5c68284SPeter Zijlstra #ifdef CONFIG_SMP
187e5c68284SPeter Zijlstra 	atomic_inc(&hb->waiters);
188e5c68284SPeter Zijlstra 	/*
189e5c68284SPeter Zijlstra 	 * Full barrier (A), see the ordering comment above.
190e5c68284SPeter Zijlstra 	 */
191e5c68284SPeter Zijlstra 	smp_mb__after_atomic();
192e5c68284SPeter Zijlstra #endif
193e5c68284SPeter Zijlstra }
194e5c68284SPeter Zijlstra 
195e5c68284SPeter Zijlstra /*
196e5c68284SPeter Zijlstra  * Reflects a waiter being removed from the waitqueue by wakeup
197e5c68284SPeter Zijlstra  * paths.
198e5c68284SPeter Zijlstra  */
futex_hb_waiters_dec(struct futex_hash_bucket * hb)199e5c68284SPeter Zijlstra static inline void futex_hb_waiters_dec(struct futex_hash_bucket *hb)
200e5c68284SPeter Zijlstra {
201e5c68284SPeter Zijlstra #ifdef CONFIG_SMP
202e5c68284SPeter Zijlstra 	atomic_dec(&hb->waiters);
203e5c68284SPeter Zijlstra #endif
204e5c68284SPeter Zijlstra }
205e5c68284SPeter Zijlstra 
futex_hb_waiters_pending(struct futex_hash_bucket * hb)206a046f1a0SPeter Zijlstra static inline int futex_hb_waiters_pending(struct futex_hash_bucket *hb)
207a046f1a0SPeter Zijlstra {
208a046f1a0SPeter Zijlstra #ifdef CONFIG_SMP
209a046f1a0SPeter Zijlstra 	/*
210a046f1a0SPeter Zijlstra 	 * Full barrier (B), see the ordering comment above.
211a046f1a0SPeter Zijlstra 	 */
212a046f1a0SPeter Zijlstra 	smp_mb();
213a046f1a0SPeter Zijlstra 	return atomic_read(&hb->waiters);
214a046f1a0SPeter Zijlstra #else
215a046f1a0SPeter Zijlstra 	return 1;
216a046f1a0SPeter Zijlstra #endif
217a046f1a0SPeter Zijlstra }
218a046f1a0SPeter Zijlstra 
21985dc28faSPeter Zijlstra extern struct futex_hash_bucket *futex_q_lock(struct futex_q *q);
22085dc28faSPeter Zijlstra extern void futex_q_unlock(struct futex_hash_bucket *hb);
22185dc28faSPeter Zijlstra 
22285dc28faSPeter Zijlstra 
22385dc28faSPeter Zijlstra extern int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb,
22485dc28faSPeter Zijlstra 				union futex_key *key,
22585dc28faSPeter Zijlstra 				struct futex_pi_state **ps,
22685dc28faSPeter Zijlstra 				struct task_struct *task,
22785dc28faSPeter Zijlstra 				struct task_struct **exiting,
22885dc28faSPeter Zijlstra 				int set_waiters);
22985dc28faSPeter Zijlstra 
23085dc28faSPeter Zijlstra extern int refill_pi_state_cache(void);
23185dc28faSPeter Zijlstra extern void get_pi_state(struct futex_pi_state *pi_state);
23285dc28faSPeter Zijlstra extern void put_pi_state(struct futex_pi_state *pi_state);
23385dc28faSPeter Zijlstra extern int fixup_pi_owner(u32 __user *uaddr, struct futex_q *q, int locked);
23485dc28faSPeter Zijlstra 
235e5c68284SPeter Zijlstra /*
236e5c68284SPeter Zijlstra  * Express the locking dependencies for lockdep:
237e5c68284SPeter Zijlstra  */
238e5c68284SPeter Zijlstra static inline void
double_lock_hb(struct futex_hash_bucket * hb1,struct futex_hash_bucket * hb2)239e5c68284SPeter Zijlstra double_lock_hb(struct futex_hash_bucket *hb1, struct futex_hash_bucket *hb2)
240e5c68284SPeter Zijlstra {
241bff7c57cSPeter Zijlstra 	if (hb1 > hb2)
242bff7c57cSPeter Zijlstra 		swap(hb1, hb2);
243bff7c57cSPeter Zijlstra 
244e5c68284SPeter Zijlstra 	spin_lock(&hb1->lock);
245bff7c57cSPeter Zijlstra 	if (hb1 != hb2)
246e5c68284SPeter Zijlstra 		spin_lock_nested(&hb2->lock, SINGLE_DEPTH_NESTING);
247e5c68284SPeter Zijlstra }
248e5c68284SPeter Zijlstra 
249e5c68284SPeter Zijlstra static inline void
double_unlock_hb(struct futex_hash_bucket * hb1,struct futex_hash_bucket * hb2)250e5c68284SPeter Zijlstra double_unlock_hb(struct futex_hash_bucket *hb1, struct futex_hash_bucket *hb2)
251e5c68284SPeter Zijlstra {
252e5c68284SPeter Zijlstra 	spin_unlock(&hb1->lock);
253e5c68284SPeter Zijlstra 	if (hb1 != hb2)
254e5c68284SPeter Zijlstra 		spin_unlock(&hb2->lock);
255e5c68284SPeter Zijlstra }
256e5c68284SPeter Zijlstra 
25785dc28faSPeter Zijlstra /* syscalls */
25885dc28faSPeter Zijlstra 
259af8cc960SPeter Zijlstra extern int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, u32
260af8cc960SPeter Zijlstra 				 val, ktime_t *abs_time, u32 bitset, u32 __user
261af8cc960SPeter Zijlstra 				 *uaddr2);
262af8cc960SPeter Zijlstra 
263af8cc960SPeter Zijlstra extern int futex_requeue(u32 __user *uaddr1, unsigned int flags,
264af8cc960SPeter Zijlstra 			 u32 __user *uaddr2, int nr_wake, int nr_requeue,
265af8cc960SPeter Zijlstra 			 u32 *cmpval, int requeue_pi);
266af8cc960SPeter Zijlstra 
267af8cc960SPeter Zijlstra extern int futex_wait(u32 __user *uaddr, unsigned int flags, u32 val,
268af8cc960SPeter Zijlstra 		      ktime_t *abs_time, u32 bitset);
269af8cc960SPeter Zijlstra 
270bf69bad3SAndré Almeida /**
271bf69bad3SAndré Almeida  * struct futex_vector - Auxiliary struct for futex_waitv()
272bf69bad3SAndré Almeida  * @w: Userspace provided data
273bf69bad3SAndré Almeida  * @q: Kernel side data
274bf69bad3SAndré Almeida  *
275bf69bad3SAndré Almeida  * Struct used to build an array with all data need for futex_waitv()
276bf69bad3SAndré Almeida  */
277bf69bad3SAndré Almeida struct futex_vector {
278bf69bad3SAndré Almeida 	struct futex_waitv w;
279bf69bad3SAndré Almeida 	struct futex_q q;
280bf69bad3SAndré Almeida };
281bf69bad3SAndré Almeida 
282bf69bad3SAndré Almeida extern int futex_wait_multiple(struct futex_vector *vs, unsigned int count,
283bf69bad3SAndré Almeida 			       struct hrtimer_sleeper *to);
284bf69bad3SAndré Almeida 
285af8cc960SPeter Zijlstra extern int futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset);
286af8cc960SPeter Zijlstra 
287af8cc960SPeter Zijlstra extern int futex_wake_op(u32 __user *uaddr1, unsigned int flags,
288af8cc960SPeter Zijlstra 			 u32 __user *uaddr2, int nr_wake, int nr_wake2, int op);
289af8cc960SPeter Zijlstra 
290af8cc960SPeter Zijlstra extern int futex_unlock_pi(u32 __user *uaddr, unsigned int flags);
291af8cc960SPeter Zijlstra 
292af8cc960SPeter Zijlstra extern int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int trylock);
293af8cc960SPeter Zijlstra 
294af8cc960SPeter Zijlstra #endif /* _FUTEX_H */
295