This test item has extremely high requirements for timing and can only
pass the test under specific conditions. The following situations will
lead to test failure:
MainThread Thread1
|
pthread_create--------------------
| |
futex_cmp_requeue |
| futex_wait
| |
If the child thread is not waiting in the futex_wait function when the
main thread reaches the futex_cmp_requeue function, the test will fail.
An attempt is made to avoid this problem by checking whether the child
thread is in a sleeping state in the main thread.
Fixes: 7cb5dd8e2c8c ("selftests: futex: Add futex compare requeue test")
Signed-off-by: Yuwen Chen <[email protected]>
Co-developed-by: Edward Liaw <[email protected]>
Signed-off-by: Edward Liaw <[email protected]>
---
.../futex/functional/futex_requeue.c | 40 +++++++++++++------
1 file changed, 27 insertions(+), 13 deletions(-)
diff --git a/tools/testing/selftests/futex/functional/futex_requeue.c
b/tools/testing/selftests/futex/functional/futex_requeue.c
index dcf0d5f2f3122..ce10030e6f657 100644
--- a/tools/testing/selftests/futex/functional/futex_requeue.c
+++ b/tools/testing/selftests/futex/functional/futex_requeue.c
@@ -9,50 +9,60 @@
#include <limits.h>
#include "futextest.h"
+#include "futex_thread.h"
#include "kselftest_harness.h"
-#define timeout_ns 30000000
-#define WAKE_WAIT_US 10000
+#define FUTEX_WAIT_TIMEOUT_SECS 1
+#define WAIT_THREAD_CREATE_TIMEOUT_USECS (USEC_PER_SEC)
volatile futex_t *f1;
-void *waiterfn(void *arg)
+static int waiterfn(void *arg)
{
struct timespec to;
- to.tv_sec = 0;
- to.tv_nsec = timeout_ns;
+ to.tv_sec = FUTEX_WAIT_TIMEOUT_SECS;
+ to.tv_nsec = 0;
- if (futex_wait(f1, *f1, &to, 0))
+ if (futex_wait(f1, *f1, &to, 0)) {
printf("waiter failed errno %d\n", errno);
+ return -errno;
+ }
- return NULL;
+ return 0;
}
TEST(requeue_single)
{
+ struct futex_thread waiter;
volatile futex_t _f1 = 0;
volatile futex_t f2 = 0;
- pthread_t waiter[10];
f1 = &_f1;
/*
* Requeue a waiter from f1 to f2, and wake f2.
*/
- ASSERT_EQ(0, pthread_create(&waiter[0], NULL, waiterfn, NULL));
+ ASSERT_EQ(0, futex_thread_create(&waiter, waiterfn, NULL));
- usleep(WAKE_WAIT_US);
+ /*
+ * Even if the waiting fails because the proc file system is not
mounted, this
+ * test item can still succeed. Therefore, there is no need to check the
+ * return value here.
+ */
+ futex_wait_for_thread(&waiter, WAIT_THREAD_CREATE_TIMEOUT_USECS);
EXPECT_EQ(1, futex_cmp_requeue(f1, 0, &f2, 0, 1, 0));
EXPECT_EQ(1, futex_wake(&f2, 1, 0));
+
+ EXPECT_EQ(0, futex_thread_destroy(&waiter));
}
TEST(requeue_multiple)
{
+ struct futex_thread waiter[10];
volatile futex_t _f1 = 0;
volatile futex_t f2 = 0;
- pthread_t waiter[10];
int i;
f1 = &_f1;
@@ -62,12 +72,16 @@ TEST(requeue_multiple)
* At futex_wake, wake INT_MAX (should be exactly 7).
*/
for (i = 0; i < 10; i++)
- ASSERT_EQ(0, pthread_create(&waiter[i], NULL, waiterfn, NULL));
+ ASSERT_EQ(0, futex_thread_create(&waiter[i], waiterfn, NULL));
- usleep(WAKE_WAIT_US);
+ for (i = 0; i < 10; i++)
+ futex_wait_for_thread(&waiter[i],
WAIT_THREAD_CREATE_TIMEOUT_USECS / 10);
EXPECT_EQ(10, futex_cmp_requeue(f1, 0, &f2, 3, 7, 0));
EXPECT_EQ(7, futex_wake(&f2, INT_MAX, 0));
+
+ for (i = 0; i < 10; i++)
+ EXPECT_EQ(0, futex_thread_destroy(&waiter[i]));
}
TEST_HARNESS_MAIN
--
2.34.1