Skip to content

Commit

Permalink
kernel: Enable waitpid() for futex2
Browse files Browse the repository at this point in the history
To make pthreads works as expected if they are using futex2, wake
clear_child_tid with futex2 as well. This is make applications that uses
waitpid() (and clone(CLONE_CHILD_SETTID)) wake while waiting for the
child to terminate. Given that apps should not mix futex() and futex2(),
any correct app will trigger a harmless noop wakeup on the interface
that it isn't using.

Signed-off-by: André Almeida <andrealmeid@collabora.com>
  • Loading branch information
andrealmeid authored and xanmod committed Oct 2, 2021
1 parent e5a1578 commit 442d05a
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 12 deletions.
2 changes: 2 additions & 0 deletions include/linux/syscalls.h
Expand Up @@ -1326,6 +1326,8 @@ int ksys_ipc(unsigned int call, int first, unsigned long second,
unsigned long third, void __user * ptr, long fifth);
int compat_ksys_ipc(u32 call, int first, int second,
u32 third, u32 ptr, u32 fifth);
long ksys_futex_wake(void __user *uaddr, unsigned long nr_wake,
unsigned int flags);

/*
* The following kernel syscall equivalents are just wrappers to fs-internal
Expand Down
2 changes: 2 additions & 0 deletions kernel/fork.c
Expand Up @@ -1337,6 +1337,8 @@ static void mm_release(struct task_struct *tsk, struct mm_struct *mm)
put_user(0, tsk->clear_child_tid);
do_futex(tsk->clear_child_tid, FUTEX_WAKE,
1, NULL, NULL, 0, 0);
ksys_futex_wake(tsk->clear_child_tid, 1,
FUTEX_32 | FUTEX_SHARED_FLAG);
}
tsk->clear_child_tid = NULL;
}
Expand Down
30 changes: 18 additions & 12 deletions kernel/futex2.c
Expand Up @@ -940,18 +940,8 @@ static inline bool futex_match(struct futex_key key1, struct futex_key key2)
key1.offset == key2.offset);
}

/**
* sys_futex_wake - Wake a number of futexes waiting on an address
* @uaddr: Address of futex to be woken up
* @nr_wake: Number of futexes waiting in uaddr to be woken up
* @flags: Flags for size and shared
*
* Wake `nr_wake` threads waiting at uaddr.
*
* Returns the number of woken threads on success, error code otherwise.
*/
SYSCALL_DEFINE3(futex_wake, void __user *, uaddr, unsigned int, nr_wake,
unsigned int, flags)
long ksys_futex_wake(void __user *uaddr, unsigned long nr_wake,
unsigned int flags)
{
bool shared = (flags & FUTEX_SHARED_FLAG) ? true : false;
unsigned int size = flags & FUTEX_SIZE_MASK;
Expand Down Expand Up @@ -988,6 +978,22 @@ SYSCALL_DEFINE3(futex_wake, void __user *, uaddr, unsigned int, nr_wake,
return ret;
}

/**
* sys_futex_wake - Wake a number of futexes waiting on an address
* @uaddr: Address of futex to be woken up
* @nr_wake: Number of futexes waiting in uaddr to be woken up
* @flags: Flags for size and shared
*
* Wake `nr_wake` threads waiting at uaddr.
*
* Returns the number of woken threads on success, error code otherwise.
*/
SYSCALL_DEFINE3(futex_wake, void __user *, uaddr, unsigned int, nr_wake,
unsigned int, flags)
{
return ksys_futex_wake(uaddr, nr_wake, flags);
}

static void futex_double_unlock(struct futex_bucket *b1, struct futex_bucket *b2)
{
spin_unlock(&b1->lock);
Expand Down

0 comments on commit 442d05a

Please sign in to comment.