To make it more generically useful, augment it with allowing the caller to pass in the wake handler and wake data. Convert the futex_waitv() syscall, passing in the default handlers. Since we now provide a way to pass in a wake handler and data, ensure we use __futex_queue() to avoid having futex_queue() overwrite our wait data. Signed-off-by: Jens Axboe <axboe@xxxxxxxxx> --- kernel/futex/futex.h | 5 +++++ kernel/futex/syscalls.c | 14 ++++++++++---- kernel/futex/waitwake.c | 3 ++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/kernel/futex/futex.h b/kernel/futex/futex.h index 75dec2ec7469..ed5a7ccd2e99 100644 --- a/kernel/futex/futex.h +++ b/kernel/futex/futex.h @@ -284,6 +284,11 @@ struct futex_vector { struct futex_q q; }; +extern int futex_parse_waitv(struct futex_vector *futexv, + struct futex_waitv __user *uwaitv, + unsigned int nr_futexes, futex_wake_fn *wake, + void *wake_data); + extern int futex_wait_multiple(struct futex_vector *vs, unsigned int count, struct hrtimer_sleeper *to); diff --git a/kernel/futex/syscalls.c b/kernel/futex/syscalls.c index 75ca8c41cc94..8ac70bfb89fc 100644 --- a/kernel/futex/syscalls.c +++ b/kernel/futex/syscalls.c @@ -184,12 +184,15 @@ SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val, * @futexv: Kernel side list of waiters to be filled * @uwaitv: Userspace list to be parsed * @nr_futexes: Length of futexv + * @wake: Wake to call when futex is woken + * @wake_data: Data for the wake handler * * Return: Error code on failure, 0 on success */ -static int futex_parse_waitv(struct futex_vector *futexv, - struct futex_waitv __user *uwaitv, - unsigned int nr_futexes) +int futex_parse_waitv(struct futex_vector *futexv, + struct futex_waitv __user *uwaitv, + unsigned int nr_futexes, futex_wake_fn *wake, + void *wake_data) { struct futex_waitv aux; unsigned int i; @@ -208,6 +211,8 @@ static int futex_parse_waitv(struct futex_vector *futexv, futexv[i].w.val = aux.val; futexv[i].w.uaddr = aux.uaddr; futexv[i].q = futex_q_init; + futexv[i].q.wake = wake; + futexv[i].q.wake_data = wake_data; } return 0; @@ -284,7 +289,8 @@ SYSCALL_DEFINE5(futex_waitv, struct futex_waitv __user *, waiters, goto destroy_timer; } - ret = futex_parse_waitv(futexv, waiters, nr_futexes); + ret = futex_parse_waitv(futexv, waiters, nr_futexes, futex_wake_mark, + NULL); if (!ret) ret = futex_wait_multiple(futexv, nr_futexes, timeout ? &to : NULL); diff --git a/kernel/futex/waitwake.c b/kernel/futex/waitwake.c index 3471af87cb7d..dfd02ca5ecfa 100644 --- a/kernel/futex/waitwake.c +++ b/kernel/futex/waitwake.c @@ -446,7 +446,8 @@ static int futex_wait_multiple_setup(struct futex_vector *vs, int count, int *wo * next futex. Queue each futex at this moment so hb can * be unlocked. */ - futex_queue(q, hb); + __futex_queue(q, hb); + spin_unlock(&hb->lock); continue; } -- 2.40.1