xref: /linux/include/vdso/futex.h (revision 00599d4841790d05401820a96cf7edb193888b00)
1*7010c39dSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0 */
2*7010c39dSThomas Gleixner #ifndef _VDSO_FUTEX_H
3*7010c39dSThomas Gleixner #define _VDSO_FUTEX_H
4*7010c39dSThomas Gleixner 
5*7010c39dSThomas Gleixner #include <uapi/linux/types.h>
6*7010c39dSThomas Gleixner 
7*7010c39dSThomas Gleixner /**
8*7010c39dSThomas Gleixner  * __vdso_futex_robust_list64_try_unlock - Try to unlock an uncontended robust futex
9*7010c39dSThomas Gleixner  *					   with a 64-bit pending op pointer
10*7010c39dSThomas Gleixner  * @lock:	Pointer to the futex lock object
11*7010c39dSThomas Gleixner  * @tid:	The TID of the calling task
12*7010c39dSThomas Gleixner  * @pop:	Pointer to the task's robust_list_head::list_pending_op
13*7010c39dSThomas Gleixner  *
14*7010c39dSThomas Gleixner  * Return: The content of *@lock. On success this is the same as @tid.
15*7010c39dSThomas Gleixner  *
16*7010c39dSThomas Gleixner  * The function implements:
17*7010c39dSThomas Gleixner  *	if (atomic_try_cmpxchg(lock, &tid, 0))
18*7010c39dSThomas Gleixner  *		*op = NULL;
19*7010c39dSThomas Gleixner  *	return tid;
20*7010c39dSThomas Gleixner  *
21*7010c39dSThomas Gleixner  * There is a race between a successful unlock and clearing the pending op
22*7010c39dSThomas Gleixner  * pointer in the robust list head. If the calling task is interrupted in the
23*7010c39dSThomas Gleixner  * race window and has to handle a (fatal) signal on return to user space then
24*7010c39dSThomas Gleixner  * the kernel handles the clearing of @pending_op before attempting to deliver
25*7010c39dSThomas Gleixner  * the signal. That ensures that a task cannot exit with a potentially invalid
26*7010c39dSThomas Gleixner  * pending op pointer.
27*7010c39dSThomas Gleixner  *
28*7010c39dSThomas Gleixner  * User space uses it in the following way:
29*7010c39dSThomas Gleixner  *
30*7010c39dSThomas Gleixner  * if (__vdso_futex_robust_list64_try_unlock(lock, tid, &pending_op) != tid)
31*7010c39dSThomas Gleixner  *	err = sys_futex($OP | FUTEX_ROBUST_UNLOCK,....);
32*7010c39dSThomas Gleixner  *
33*7010c39dSThomas Gleixner  * If the unlock attempt fails due to the FUTEX_WAITERS bit set in the lock,
34*7010c39dSThomas Gleixner  * then the syscall does the unlock, clears the pending op pointer and wakes the
35*7010c39dSThomas Gleixner  * requested number of waiters.
36*7010c39dSThomas Gleixner  */
37*7010c39dSThomas Gleixner __u32 __vdso_futex_robust_list64_try_unlock(__u32 *lock, __u32 tid, __u64 *pop);
38*7010c39dSThomas Gleixner 
39*7010c39dSThomas Gleixner /**
40*7010c39dSThomas Gleixner  * __vdso_futex_robust_list32_try_unlock - Try to unlock an uncontended robust futex
41*7010c39dSThomas Gleixner  *					   with a 32-bit pending op pointer
42*7010c39dSThomas Gleixner  * @lock:	Pointer to the futex lock object
43*7010c39dSThomas Gleixner  * @tid:	The TID of the calling task
44*7010c39dSThomas Gleixner  * @pop:	Pointer to the task's robust_list_head::list_pending_op
45*7010c39dSThomas Gleixner  *
46*7010c39dSThomas Gleixner  * Return: The content of *@lock. On success this is the same as @tid.
47*7010c39dSThomas Gleixner  *
48*7010c39dSThomas Gleixner  * Same as __vdso_futex_robust_list64_try_unlock() just with a 32-bit @pop pointer.
49*7010c39dSThomas Gleixner  */
50*7010c39dSThomas Gleixner __u32 __vdso_futex_robust_list32_try_unlock(__u32 *lock, __u32 tid, __u32 *pop);
51*7010c39dSThomas Gleixner 
52*7010c39dSThomas Gleixner #endif
53