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));

Reply via email to