Module Name: src
Committed By: riastradh
Date: Sat Jan 18 07:26:06 UTC 2025
Modified Files:
src/sys/kern: sys_futex.c
src/tests/lib/libc/sys: t_futex_ops.c
Log Message:
futex(2): Fix FUTEX_CMP_REQUEUE to always compare even if no waiters.
It must always compare the futex value and fail with EAGAIN on
mismatch, even if there are no waiters.
FUTEX_CMP_REQUEUE (since Linux 2.6.7)
This operation first checks whether the location uaddr
still contains the value val3. If not, the operation
fails with the error EAGAIN. Otherwise, the operation [...]
https://man7.org/linux/man-pages/man2/futex.2.html
PR kern/56828: futex calls in Linux emulation sometimes hang
To generate a diff of this commit:
cvs rdiff -u -r1.20 -r1.21 src/sys/kern/sys_futex.c
cvs rdiff -u -r1.8 -r1.9 src/tests/lib/libc/sys/t_futex_ops.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/kern/sys_futex.c
diff -u src/sys/kern/sys_futex.c:1.20 src/sys/kern/sys_futex.c:1.21
--- src/sys/kern/sys_futex.c:1.20 Thu Apr 11 13:51:36 2024
+++ src/sys/kern/sys_futex.c Sat Jan 18 07:26:06 2025
@@ -1,4 +1,4 @@
-/* $NetBSD: sys_futex.c,v 1.20 2024/04/11 13:51:36 riastradh Exp $ */
+/* $NetBSD: sys_futex.c,v 1.21 2025/01/18 07:26:06 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.20 2024/04/11 13:51:36 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_futex.c,v 1.21 2025/01/18 07:26:06 riastradh Exp $");
/*
* Futexes
@@ -1336,14 +1336,23 @@ futex_func_requeue(bool shared, int op,
goto out;
}
- /* Look up the source futex, if any. */
- error = futex_lookup(uaddr, shared, &f);
+ /*
+ * Look up or create the source futex. For FUTEX_CMP_REQUEUE,
+ * we always create it, rather than bail if it has no waiters,
+ * because FUTEX_CMP_REQUEUE always tests the futex word in
+ * order to report EAGAIN.
+ */
+ error = (op == FUTEX_CMP_REQUEUE
+ ? futex_lookup_create(uaddr, shared, &f)
+ : futex_lookup(uaddr, shared, &f));
if (error)
goto out;
- /* If there is none, nothing to do. */
- if (f == NULL)
+ /* If there is none for FUTEX_REQUEUE, nothing to do. */
+ if (f == NULL) {
+ KASSERT(op != FUTEX_CMP_REQUEUE);
goto out;
+ }
/*
* We may need to create the destination futex because it's
Index: src/tests/lib/libc/sys/t_futex_ops.c
diff -u src/tests/lib/libc/sys/t_futex_ops.c:1.8 src/tests/lib/libc/sys/t_futex_ops.c:1.9
--- src/tests/lib/libc/sys/t_futex_ops.c:1.8 Sat Jan 18 07:05:15 2025
+++ src/tests/lib/libc/sys/t_futex_ops.c Sat Jan 18 07:26:06 2025
@@ -1,4 +1,4 @@
-/* $NetBSD: t_futex_ops.c,v 1.8 2025/01/18 07:05:15 riastradh Exp $ */
+/* $NetBSD: t_futex_ops.c,v 1.9 2025/01/18 07:26:06 riastradh Exp $ */
/*-
* Copyright (c) 2019, 2020 The NetBSD Foundation, Inc.
@@ -29,7 +29,7 @@
#include <sys/cdefs.h>
__COPYRIGHT("@(#) Copyright (c) 2019, 2020\
The NetBSD Foundation, inc. All rights reserved.");
-__RCSID("$NetBSD: t_futex_ops.c,v 1.8 2025/01/18 07:05:15 riastradh Exp $");
+__RCSID("$NetBSD: t_futex_ops.c,v 1.9 2025/01/18 07:26:06 riastradh Exp $");
#include <sys/fcntl.h>
#include <sys/mman.h>
@@ -927,13 +927,10 @@ ATF_TC_BODY(futex_cmp_requeue_trivial, t
futex_word = 123;
futex_word1 = 456; /* should be ignored */
- atf_tc_expect_fail("PR kern/56828:"
- " futex calls in Linux emulation sometimes hang");
ATF_CHECK_ERRNO(EAGAIN, __futex(&futex_word, FUTEX_CMP_REQUEUE,
/*nwake*/1, NULL, &futex_word1, /*nrequeue*/1, 0) == -1);
ATF_CHECK_ERRNO(EAGAIN, __futex(&futex_word, FUTEX_CMP_REQUEUE,
/*nwake*/1, NULL, &futex_word1, /*nrequeue*/1, 122) == -1);
- atf_tc_expect_pass();
nwoken = __futex(&futex_word, FUTEX_CMP_REQUEUE,
/*nwake*/1, NULL, &futex_word1, /*nrequeue*/1, 123);
ATF_CHECK_MSG(nwoken != -1, "errno=%d (%s)", errno, strerror(errno));