1 //===-- Tests for pthread_mutex_t -----------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "src/pthread/pthread_mutex_destroy.h"
10 #include "src/pthread/pthread_mutex_init.h"
11 #include "src/pthread/pthread_mutex_lock.h"
12 #include "src/pthread/pthread_mutex_unlock.h"
14 #include "src/pthread/pthread_create.h"
15 #include "src/pthread/pthread_join.h"
17 #include "test/IntegrationTest/test.h"
20 #include <stdint.h> // uintptr_t
22 constexpr int START
= 0;
23 constexpr int MAX
= 10000;
25 pthread_mutex_t mutex
;
26 static int shared_int
= START
;
28 void *counter(void *arg
) {
29 int last_count
= START
;
31 LIBC_NAMESPACE::pthread_mutex_lock(&mutex
);
32 if (shared_int
== last_count
+ 1) {
34 last_count
= shared_int
;
36 LIBC_NAMESPACE::pthread_mutex_unlock(&mutex
);
37 if (last_count
>= MAX
)
43 void relay_counter() {
44 ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_init(&mutex
, nullptr), 0);
46 // The idea of this test is that two competing threads will update
47 // a counter only if the other thread has updated it.
49 LIBC_NAMESPACE::pthread_create(&thread
, nullptr, counter
, nullptr);
51 int last_count
= START
;
53 ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_lock(&mutex
), 0);
54 if (shared_int
== START
) {
56 last_count
= shared_int
;
57 } else if (shared_int
!= last_count
) {
58 ASSERT_EQ(shared_int
, last_count
+ 1);
60 last_count
= shared_int
;
62 ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_unlock(&mutex
), 0);
67 void *retval
= reinterpret_cast<void *>(123);
68 LIBC_NAMESPACE::pthread_join(thread
, &retval
);
69 ASSERT_EQ(uintptr_t(retval
), uintptr_t(nullptr));
71 LIBC_NAMESPACE::pthread_mutex_destroy(&mutex
);
74 pthread_mutex_t start_lock
, step_lock
;
77 void *stepper(void *arg
) {
78 LIBC_NAMESPACE::pthread_mutex_lock(&start_lock
);
80 LIBC_NAMESPACE::pthread_mutex_unlock(&start_lock
);
82 LIBC_NAMESPACE::pthread_mutex_lock(&step_lock
);
84 LIBC_NAMESPACE::pthread_mutex_unlock(&step_lock
);
88 void wait_and_step() {
89 ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_init(&start_lock
, nullptr), 0);
90 ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_init(&step_lock
, nullptr), 0);
92 // In this test, we start a new thread but block it before it can make a
93 // step. Once we ensure that the thread is blocked, we unblock it.
94 // After unblocking, we then verify that the thread was indeed unblocked.
97 ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_lock(&step_lock
), 0);
100 LIBC_NAMESPACE::pthread_create(&thread
, nullptr, stepper
, nullptr);
103 // Make sure the thread actually started.
104 ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_lock(&start_lock
), 0);
106 ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_unlock(&start_lock
), 0);
111 // Since |step_lock| is still locked, |step| should be false.
114 // Unlock the step lock and wait until the step is made.
115 ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_unlock(&step_lock
), 0);
118 ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_lock(&step_lock
), 0);
119 bool current_step_value
= step
;
120 ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_unlock(&step_lock
), 0);
121 if (current_step_value
)
125 void *retval
= reinterpret_cast<void *>(123);
126 LIBC_NAMESPACE::pthread_join(thread
, &retval
);
127 ASSERT_EQ(uintptr_t(retval
), uintptr_t(nullptr));
129 LIBC_NAMESPACE::pthread_mutex_destroy(&start_lock
);
130 LIBC_NAMESPACE::pthread_mutex_destroy(&step_lock
);
133 static constexpr int THREAD_COUNT
= 10;
134 static pthread_mutex_t multiple_waiter_lock
;
135 static pthread_mutex_t counter_lock
;
136 static int wait_count
= 0;
138 void *waiter_func(void *) {
139 LIBC_NAMESPACE::pthread_mutex_lock(&counter_lock
);
141 LIBC_NAMESPACE::pthread_mutex_unlock(&counter_lock
);
143 // Block on the waiter lock until the main
145 LIBC_NAMESPACE::pthread_mutex_lock(&multiple_waiter_lock
);
146 LIBC_NAMESPACE::pthread_mutex_unlock(&multiple_waiter_lock
);
148 LIBC_NAMESPACE::pthread_mutex_lock(&counter_lock
);
150 LIBC_NAMESPACE::pthread_mutex_unlock(&counter_lock
);
155 void multiple_waiters() {
156 LIBC_NAMESPACE::pthread_mutex_init(&multiple_waiter_lock
, nullptr);
157 LIBC_NAMESPACE::pthread_mutex_init(&counter_lock
, nullptr);
159 LIBC_NAMESPACE::pthread_mutex_lock(&multiple_waiter_lock
);
160 pthread_t waiters
[THREAD_COUNT
];
161 for (int i
= 0; i
< THREAD_COUNT
; ++i
) {
162 LIBC_NAMESPACE::pthread_create(waiters
+ i
, nullptr, waiter_func
, nullptr);
165 // Spin until the counter is incremented to the desired
168 LIBC_NAMESPACE::pthread_mutex_lock(&counter_lock
);
169 if (wait_count
== THREAD_COUNT
) {
170 LIBC_NAMESPACE::pthread_mutex_unlock(&counter_lock
);
173 LIBC_NAMESPACE::pthread_mutex_unlock(&counter_lock
);
176 LIBC_NAMESPACE::pthread_mutex_unlock(&multiple_waiter_lock
);
179 for (int i
= 0; i
< THREAD_COUNT
; ++i
) {
180 LIBC_NAMESPACE::pthread_join(waiters
[i
], &retval
);
183 ASSERT_EQ(wait_count
, 0);
185 LIBC_NAMESPACE::pthread_mutex_destroy(&multiple_waiter_lock
);
186 LIBC_NAMESPACE::pthread_mutex_destroy(&counter_lock
);