projects/linux·blob master · refs

96 lines · 2.2 KiB

1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright Collabora Ltd., 2021
4 *
5 * futex cmp requeue test by André Almeida <[email protected]>
6 */
7
8#include <limits.h>
9#include <pthread.h>
10#include <string.h>
11
12#include "futextest.h"
13#include "futex_thread.h"
14#include "kselftest_harness.h"
15
16struct waiter_args {
17 struct __test_metadata *_metadata;
18 unsigned int n_threads;
19};
20
21volatile futex_t *f1;
22
23static int waiterfn(void *arg)
24{
25 struct __test_metadata *_metadata;
26 struct waiter_args *wargs = arg;
27 struct timespec to = { };
28 int res;
29
30 _metadata = wargs->_metadata;
31 to.tv_sec = (wargs->n_threads + 1) * WAIT_FOR_THREAD_SECS;
32
33 res = futex_wait(f1, *f1, &to, 0);
34 if (res) {
35 EXPECT_EQ(res, 0)
36 TH_LOG("waiter failed errno %d: %s", errno, strerror(errno));
37 }
38
39 return 0;
40}
41
42TEST(requeue_single)
43{
44 struct waiter_args wargs = { ._metadata = _metadata, .n_threads = 1 };
45 struct futex_thread waiter;
46 volatile futex_t _f1 = 0;
47 volatile futex_t f2 = 0;
48
49 f1 = &_f1;
50
51 /*
52 * Requeue a waiter from f1 to f2, and wake f2.
53 */
54 ASSERT_EQ(futex_thread_create(&waiter, waiterfn, &wargs), 0)
55 TH_LOG("pthread_create failed");
56
57 ASSERT_EQ(futex_wait_for_thread(&waiter, _metadata), 0)
58 TH_LOG("Wait for thread failed");
59
60 EXPECT_EQ(futex_cmp_requeue(f1, 0, &f2, 0, 1, 0), 1);
61 EXPECT_EQ(futex_wake(&f2, 1, 0), 1);
62
63 EXPECT_EQ(futex_thread_destroy(&waiter), 0);
64}
65
66TEST(requeue_multiple)
67{
68 struct waiter_args wargs = { ._metadata = _metadata, .n_threads = 10 };
69 struct futex_thread waiter[10];
70 volatile futex_t _f1 = 0;
71 volatile futex_t f2 = 0;
72
73 f1 = &_f1;
74
75 /*
76 * Create 10 waiters at f1. At futex_requeue, wake 3 and requeue 7.
77 * At futex_wake, wake INT_MAX (should be exactly 7).
78 */
79 for (int i = 0; i < 10; i++) {
80 ASSERT_EQ(futex_thread_create(&waiter[i], waiterfn, &wargs), 0)
81 TH_LOG("pthread_create failed for waiter %d", i);
82 }
83
84 for (int i = 0; i < 10; i++) {
85 ASSERT_EQ(futex_wait_for_thread(&waiter[i], _metadata), 0)
86 TH_LOG("Wait for waiter thread %d failed", i);
87 }
88
89 EXPECT_EQ(futex_cmp_requeue(f1, 0, &f2, 3, 7, 0), 10);
90 EXPECT_EQ(futex_wake(&f2, INT_MAX, 0), 7);
91
92 for (int i = 0; i < 10; i++)
93 EXPECT_EQ(futex_thread_destroy(&waiter[i]), 0);
94}
95
96TEST_HARNESS_MAIN