20 changes: 20 additions & 0 deletions libc/src/threads/thrd_create.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===------- Implementation header for thrd_create function ------ *-C++-* ===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_THREADS_LINUX_THRD_CREATE_H
#define LLVM_LIBC_SRC_THREADS_LINUX_THRD_CREATE_H

#include "include/threads.h"

namespace __llvm_libc {

int thrd_create(thrd_t *thread, thrd_start_t func, void *arg);

} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_THREADS_LINUX_THRD_CREATE_H
20 changes: 20 additions & 0 deletions libc/src/threads/thrd_join.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-------- Implementation header for thrd_join function ------- *-C++-* ===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_THREADS_LINUX_THRD_JOIN_H
#define LLVM_LIBC_SRC_THREADS_LINUX_THRD_JOIN_H

#include "include/threads.h"

namespace __llvm_libc {

int thrd_join(thrd_t *thread, int *retval);

} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_THREADS_LINUX_THRD_JOIN_H
1 change: 1 addition & 0 deletions libc/test/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ add_subdirectory(signal)
add_subdirectory(stdlib)
add_subdirectory(string)
add_subdirectory(sys)
add_subdirectory(threads)
16 changes: 16 additions & 0 deletions libc/test/src/threads/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
add_libc_testsuite(libc_threads_unittests)

add_libc_unittest(
thrd_test
SUITE
libc_threads_unittests
SRCS
thrd_test.cpp
DEPENDS
__errno_location
mmap
munmap
threads_h
thrd_create
thrd_join
)
52 changes: 52 additions & 0 deletions libc/test/src/threads/thrd_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//===---------------------- Unittests for thrd_t --------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "include/threads.h"
#include "src/threads/thrd_create.h"
#include "src/threads/thrd_join.h"
#include "utils/UnitTest/Test.h"

static constexpr int thread_count = 1000;
static int counter = 0;
static int thread_func(void *) {
++counter;
return 0;
}

TEST(ThreadTest, CreateAndJoin) {
for (counter = 0; counter <= thread_count;) {
thrd_t thread;
int old_counter_val = counter;
ASSERT_EQ(__llvm_libc::thrd_create(&thread, thread_func, nullptr),
(int)thrd_success);
int retval = thread_count + 1; // Start with a retval we dont expect.
ASSERT_EQ(__llvm_libc::thrd_join(&thread, &retval), (int)thrd_success);
ASSERT_EQ(retval, 0);
ASSERT_EQ(counter, old_counter_val + 1);
}
}

static int return_arg(void *arg) { return *reinterpret_cast<int *>(arg); }

TEST(ThreadTest, SpawnAndJoin) {
thrd_t thread_list[thread_count];
int args[thread_count];

for (int i = 0; i < thread_count; ++i) {
args[i] = i;
ASSERT_EQ(__llvm_libc::thrd_create(thread_list + i, return_arg, args + i),
(int)thrd_success);
}

for (int i = 0; i < thread_count; ++i) {
int retval = thread_count + 1; // Start with a retval we dont expect.
ASSERT_EQ(__llvm_libc::thrd_join(&thread_list[i], &retval),
(int)thrd_success);
ASSERT_EQ(retval, i);
}
}