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