Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/kern Fix waiting on a zero bitset.



details:   https://anonhg.NetBSD.org/src/rev/8cefffab26ca
branches:  trunk
changeset: 1009612:8cefffab26ca
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Tue Apr 28 16:22:25 2020 +0000

description:
Fix waiting on a zero bitset.

The logic in futex_wait assumes there are two paths out:

1. Error (signal or timeout), in which case we take ourselves off the
   queue.

2. Wakeup, in which case the waker takes us off the queue.

But if the user does FUTEX_WAIT_BITSET(bitset=0), as in the
futex_wait_pointless_bitset test, then we will never even go to
sleep, so there will be nobody to wake us as in (2), but it's not an
error as in (1) either.  As a result, we're left on the queue.

Instead, don't bother with any of the wait machinery in that case.
This does not actually match Linux semantics -- Linux returns EINVAL
if bitset is zero.  But let's make sure this passes the releng test
rig as the tests are written now, and then fix both the logic and the
tests -- this is a candidate fix for:

lib/libc/sys/t_futex_ops (277/847): 20 test cases
    futex_basic_wait_wake_private: [6.645189s] Passed.
    futex_basic_wait_wake_shared: [6.572692s] Passed.
    futex_cmp_requeue: [4.624082s] Passed.
    futex_requeue: [4.427191s] Passed.
    futex_wait_pointless_bitset: [0.202865s] Passed.
    futex_wait_timeout_deadline: [ 9074.4164779] panic: TAILQ_INSERT_TAIL 0xffff000056a1ad48 /tmp/bracket/build/2020.04.28.03.00.23-evbarm-aarch64/src/sys/kern/sys_futex.c:826
[ 9074.4340691] cpu0: Begin traceback...
[ 9074.4340691] trace fp ffffc0004ceffb40
[ 9074.4340691] fp ffffc0004ceffb60 vpanic() at ffffc000004aac58 netbsd:vpanic+0x160
[ 9074.4441432] fp ffffc0004ceffbd0 panic() at ffffc000004aad4c netbsd:panic+0x44
[ 9074.4441432] fp ffffc0004ceffc60 futex_wait_enqueue() at ffffc000004b7710 netbsd:futex_wait_enqueue+0x138
[ 9074.4555795] fp ffffc0004ceffc80 futex_func_wait.part.5() at ffffc000004b82f4 netbsd:futex_func_wait.part.5+0x17c
[ 9074.4660518] fp ffffc0004ceffd50 do_futex() at ffffc000004b8cd8 netbsd:do_futex+0x1d0
[ 9074.4660518] fp ffffc0004ceffdf0 sys___futex() at ffffc000004b9078 netbsd:sys___futex+0x50

diffstat:

 sys/kern/sys_futex.c |  15 +++++++++++++--
 1 files changed, 13 insertions(+), 2 deletions(-)

diffs (50 lines):

diff -r 77c26c7ec236 -r 8cefffab26ca sys/kern/sys_futex.c
--- a/sys/kern/sys_futex.c      Tue Apr 28 15:43:34 2020 +0000
+++ b/sys/kern/sys_futex.c      Tue Apr 28 16:22:25 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sys_futex.c,v 1.5 2020/04/28 00:54:24 riastradh Exp $  */
+/*     $NetBSD: sys_futex.c,v 1.6 2020/04/28 16:22:25 riastradh Exp $  */
 
 /*-
  * Copyright (c) 2018, 2019, 2020 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_futex.c,v 1.5 2020/04/28 00:54:24 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_futex.c,v 1.6 2020/04/28 16:22:25 riastradh Exp $");
 
 /*
  * Futexes
@@ -785,6 +785,8 @@
 futex_wait_init(struct futex_wait *fw, int bitset)
 {
 
+       KASSERT(bitset);
+
        mutex_init(&fw->fw_lock, MUTEX_DEFAULT, IPL_NONE);
        cv_init(&fw->fw_cv, "futex");
        fw->fw_futex = NULL;
@@ -802,6 +804,8 @@
 futex_wait_fini(struct futex_wait *fw)
 {
 
+       KASSERT(fw->fw_futex == NULL);
+
        cv_destroy(&fw->fw_cv);
        mutex_destroy(&fw->fw_lock);
 }
@@ -1193,6 +1197,13 @@
        const struct timespec *deadline;
        int error;
 
+       /*
+        * If there's nothing to wait for, and nobody will ever wake
+        * us, then don't set anything up to wait -- just stop here.
+        */
+       if (val3 == 0)
+               return 0;
+
        /* Optimistically test before anything else.  */
        if (!futex_test(uaddr, val))
                return EAGAIN;



Home | Main Index | Thread Index | Old Index