Skip to content

Commit f2aa291

Browse files
add raw_mutex tests
1 parent d213d08 commit f2aa291

File tree

4 files changed

+86
-0
lines changed

4 files changed

+86
-0
lines changed

libc/test/src/__support/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,3 +207,4 @@ add_subdirectory(FPUtil)
207207
add_subdirectory(fixed_point)
208208
add_subdirectory(HashTable)
209209
add_subdirectory(time)
210+
add_subdirectory(threads)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
add_custom_target(libc-support-threads-tests)
2+
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
3+
add_subdirectory(${LIBC_TARGET_OS})
4+
endif()
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
add_libc_test(
2+
raw_mutex_test
3+
SUITE
4+
libc-support-threads-tests
5+
SRCS
6+
raw_mutex_test.cpp
7+
DEPENDS
8+
libc.src.__support.threads.linux.raw_mutex
9+
libc.src.sys.mman.mmap
10+
libc.src.sys.mman.munmap
11+
libc.src.stdlib.exit
12+
)
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include "include/llvm-libc-macros/linux/time-macros.h"
2+
#include "src/__support/CPP/atomic.h"
3+
#include "src/__support/OSUtil/syscall.h"
4+
#include "src/__support/threads/linux/raw_mutex.h"
5+
#include "src/__support/threads/sleep.h"
6+
#include "src/__support/time/linux/clock_gettime.h"
7+
#include "src/stdlib/exit.h"
8+
#include "src/sys/mman/mmap.h"
9+
#include "src/sys/mman/munmap.h"
10+
#include "test/UnitTest/Test.h"
11+
#include <sys/syscall.h>
12+
13+
TEST(LlvmLibcSupportThreadsRawMutexTest, SmokeTest) {
14+
LIBC_NAMESPACE::internal::RawMutex mutex;
15+
ASSERT_TRUE(mutex.lock());
16+
ASSERT_TRUE(mutex.unlock());
17+
ASSERT_TRUE(mutex.try_lock());
18+
ASSERT_FALSE(mutex.try_lock());
19+
ASSERT_TRUE(mutex.unlock());
20+
ASSERT_FALSE(mutex.unlock());
21+
}
22+
23+
TEST(LlvmLibcSupportThreadsRawMutexTest, Timeout) {
24+
LIBC_NAMESPACE::internal::RawMutex mutex;
25+
ASSERT_TRUE(mutex.lock());
26+
timespec ts;
27+
LIBC_NAMESPACE::internal::clock_gettime(CLOCK_MONOTONIC, &ts);
28+
ts.tv_sec += 1;
29+
// Timeout will be respected when deadlock happens.
30+
auto timeout = LIBC_NAMESPACE::internal::AbsTimeout::from_timespec(ts, false);
31+
ASSERT_TRUE(timeout.has_value());
32+
ASSERT_FALSE(mutex.lock(*timeout));
33+
ASSERT_TRUE(mutex.unlock());
34+
ASSERT_TRUE(mutex.lock(*timeout));
35+
ASSERT_TRUE(mutex.unlock());
36+
// If a lock can be acquired directly, expired timeout will not count.
37+
ASSERT_TRUE(mutex.lock(*timeout));
38+
ASSERT_TRUE(mutex.unlock());
39+
}
40+
41+
TEST(LlvmLibcSupportThreadsRawMutexTest, PSharedLock) {
42+
struct SharedData {
43+
LIBC_NAMESPACE::internal::RawMutex mutex;
44+
LIBC_NAMESPACE::cpp::Atomic<size_t> finished;
45+
int data;
46+
};
47+
void *addr =
48+
LIBC_NAMESPACE::mmap(nullptr, sizeof(SharedData), PROT_READ | PROT_WRITE,
49+
MAP_ANONYMOUS | MAP_SHARED, -1, 0);
50+
ASSERT_NE(addr, MAP_FAILED);
51+
auto *shared = reinterpret_cast<SharedData *>(addr);
52+
shared->data = 0;
53+
LIBC_NAMESPACE::internal::RawMutex::init(&shared->mutex);
54+
// Avoid pull in our own implementation of pthread_t.
55+
long pid = LIBC_NAMESPACE::syscall_impl<long>(SYS_fork);
56+
for (int i = 0; i < 10000; ++i) {
57+
shared->mutex.lock(LIBC_NAMESPACE::cpp::nullopt, true);
58+
shared->data++;
59+
shared->mutex.unlock(true);
60+
}
61+
// Mark the thread as finished.
62+
shared->finished.fetch_add(1);
63+
// early exit to avoid output pollution
64+
if (pid == 0)
65+
LIBC_NAMESPACE::exit(0);
66+
while (shared->finished.load() != 2)
67+
LIBC_NAMESPACE::sleep_briefly();
68+
ASSERT_EQ(shared->data, 20000);
69+
}

0 commit comments

Comments
 (0)