[libc-commits] [libc] 70c8d12 - [libc] Add pthread_create and pthread_join functions.

Siva Chandra Reddy via libc-commits libc-commits at lists.llvm.org
Wed Jun 1 18:47:54 PDT 2022


Author: Siva Chandra Reddy
Date: 2022-06-02T01:47:24Z
New Revision: 70c8d12b79a58cf350256bb0a366f0e91000d82e

URL: https://github.com/llvm/llvm-project/commit/70c8d12b79a58cf350256bb0a366f0e91000d82e
DIFF: https://github.com/llvm/llvm-project/commit/70c8d12b79a58cf350256bb0a366f0e91000d82e.diff

LOG: [libc] Add pthread_create and pthread_join functions.

They do not yet support all the feature/attributes in pthread_attr_t.
Future changes will add such support.

Reviewed By: lntue

Differential Revision: https://reviews.llvm.org/D126718

Added: 
    libc/include/llvm-libc-types/__pthread_start_t.h
    libc/include/llvm-libc-types/__thread_type.h
    libc/include/llvm-libc-types/pthread_t.h
    libc/src/pthread/pthread_create.cpp
    libc/src/pthread/pthread_create.h
    libc/src/pthread/pthread_join.cpp
    libc/src/pthread/pthread_join.h
    libc/test/src/pthread/pthread_test.cpp

Modified: 
    libc/config/linux/api.td
    libc/config/linux/x86_64/entrypoints.txt
    libc/include/CMakeLists.txt
    libc/include/llvm-libc-types/CMakeLists.txt
    libc/include/llvm-libc-types/thrd_t.h
    libc/spec/posix.td
    libc/src/pthread/CMakeLists.txt
    libc/test/src/pthread/CMakeLists.txt
    libc/test/src/pthread/pthread_mutex_test.cpp

Removed: 
    


################################################################################
diff  --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index f8ca32133eea8..3ab2f3a63a724 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -244,9 +244,11 @@ def ThreadsAPI : PublicAPI<"threads.h"> {
 
 def PThreadAPI : PublicAPI<"pthread.h"> {
   let Types = [
+      "__pthread_start_t",
       "pthread_attr_t",
       "pthread_mutex_t",
-      "pthread_mutexattr_t"
+      "pthread_mutexattr_t",
+      "pthread_t",
   ];
 }
 

diff  --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 28607d615edcb..ed2e248d7652c 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -236,6 +236,8 @@ if(LLVM_LIBC_FULL_BUILD)
     libc.src.pthread.pthread_attr_setstack
     libc.src.pthread.pthread_attr_setstacksize
     libc.src.pthread.pthread_attr_init
+    libc.src.pthread.pthread_create
+    libc.src.pthread.pthread_join
     libc.src.pthread.pthread_mutex_destroy
     libc.src.pthread.pthread_mutex_init
     libc.src.pthread.pthread_mutex_lock

diff  --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 5ffef44cbc62e..afd4972120d4a 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -162,9 +162,11 @@ add_gen_header(
   GEN_HDR pthread.h
   DEPENDS
     .llvm_libc_common_h
+    .llvm-libc-types.__pthread_start_t
     .llvm-libc-types.pthread_attr_t
     .llvm-libc-types.pthread_mutex_t
     .llvm-libc-types.pthread_mutexattr_t
+    .llvm-libc-types.pthread_t
 )
 
 # TODO: Not all platforms will have a include/sys directory. Add the sys

diff  --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 681f7aa63fd28..9ca82ad811282 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -1,9 +1,11 @@
 add_header(__bsearchcompare_t HDR __bsearchcompare_t.h)
 add_header(__call_once_func_t HDR __call_once_func_t.h)
 add_header(__futex_word HDR __futex_word.h)
-add_header(__mutex_type HDR __mutex_type.h)
+add_header(__mutex_type HDR __mutex_type.h DEPENDS .__futex_word)
+add_header(__pthread_start_t HDR __pthread_start_t.h)
 add_header(__qsortcompare_t HDR __qsortcompare_t.h)
 add_header(__sighandler_t HDR __sighandler_t.h)
+add_header(__thread_type HDR __thread_type.h)
 add_header(cnd_t HDR cnd_t.h)
 add_header(cookie_io_functions_t HDR cookie_io_functions_t.h DEPENDS .off64_t)
 add_header(double_t HDR double_t.h)
@@ -22,12 +24,13 @@ add_header(off64_t HDR off64_t.h)
 add_header(once_flag HDR once_flag.h DEPENDS .__futex_word)
 add_header(pthread_attr_t HDR pthread_attr_t.h DEPENDS .size_t)
 add_header(pthread_mutex_t HDR pthread_mutex_t.h DEPENDS .__futex_word .__mutex_type)
+add_header(pthread_t HDR pthread_t.h DEPENDS .__thread_type)
 add_header(pthread_mutexattr_t HDR pthread_mutexattr_t.h)
 add_header(size_t HDR size_t.h)
 add_header(ssize_t HDR ssize_t.h)
 add_header(struct_sigaction HDR struct_sigaction.h)
 add_header(struct_tm HDR struct_tm.h)
 add_header(thrd_start_t HDR thrd_start_t.h)
-add_header(thrd_t HDR thrd_t.h)
+add_header(thrd_t HDR thrd_t.h DEPENDS .__thread_type)
 add_header(time_t HDR time_t.h)
 add_header(__atexithandler_t HDR __atexithandler_t.h)

diff  --git a/libc/include/llvm-libc-types/__pthread_start_t.h b/libc/include/llvm-libc-types/__pthread_start_t.h
new file mode 100644
index 0000000000000..1e05f9b497299
--- /dev/null
+++ b/libc/include/llvm-libc-types/__pthread_start_t.h
@@ -0,0 +1,14 @@
+//===-- Definition of __pthread_start_t type ------------------------------===//
+//
+// 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_TYPES_PTHREAD_START_T_H__
+#define __LLVM_LIBC_TYPES_PTHREAD_START_T_H__
+
+typedef void *(*__pthread_start_t)(void *);
+
+#endif // __LLVM_LIBC_TYPES_PTHREAD_START_T_H__

diff  --git a/libc/include/llvm-libc-types/__thread_type.h b/libc/include/llvm-libc-types/__thread_type.h
new file mode 100644
index 0000000000000..1d64f909bd809
--- /dev/null
+++ b/libc/include/llvm-libc-types/__thread_type.h
@@ -0,0 +1,17 @@
+//===-- Definition of thrd_t type -----------------------------------------===//
+//
+// 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_TYPES_THREAD_TYPE_H__
+#define __LLVM_LIBC_TYPES_THREAD_TYPE_H__
+
+typedef struct {
+  void *__attrib;
+  void *__platform_attrib;
+} __thread_type;
+
+#endif // __LLVM_LIBC_TYPES_THREAD_TYPE_H__

diff  --git a/libc/include/llvm-libc-types/pthread_t.h b/libc/include/llvm-libc-types/pthread_t.h
new file mode 100644
index 0000000000000..8130491274efb
--- /dev/null
+++ b/libc/include/llvm-libc-types/pthread_t.h
@@ -0,0 +1,16 @@
+//===-- Definition of pthread_t type --------------------------------------===//
+//
+// 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_TYPES_PTHREAD_T_H__
+#define __LLVM_LIBC_TYPES_PTHREAD_T_H__
+
+#include <llvm-libc-types/__thread_type.h>
+
+typedef __thread_type pthread_t;
+
+#endif // __LLVM_LIBC_TYPES_PTHREAD_T_H__

diff  --git a/libc/include/llvm-libc-types/thrd_t.h b/libc/include/llvm-libc-types/thrd_t.h
index 169f937042c6b..0743106c48c64 100644
--- a/libc/include/llvm-libc-types/thrd_t.h
+++ b/libc/include/llvm-libc-types/thrd_t.h
@@ -9,11 +9,8 @@
 #ifndef __LLVM_LIBC_TYPES_THRD_T_H__
 #define __LLVM_LIBC_TYPES_THRD_T_H__
 
-#include <llvm-libc-types/__futex_word.h>
+#include <llvm-libc-types/__thread_type.h>
 
-typedef struct {
-  void *__attribs;
-  void *__platform_attribs;
-} thrd_t;
+typedef __thread_type thrd_t;
 
 #endif // __LLVM_LIBC_TYPES_THRD_T_H__

diff  --git a/libc/spec/posix.td b/libc/spec/posix.td
index 2436d8eea4b1c..e53942dd850c4 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -10,6 +10,8 @@ def ConstStructSigactionPtr : ConstType<StructSigactionPtr>;
 def RestrictedStructSigactionPtr : RestrictedPtrType<StructSigaction>;
 def ConstRestrictedStructSigactionPtr : ConstType<RestrictedStructSigactionPtr>;
 
+def PThreadStartT : NamedType<"__pthread_start_t">;
+
 def POSIX : StandardSpec<"POSIX"> {
   PtrType CharPtr = PtrType<CharType>;
   RestrictedPtrType RestrictedCharPtr = RestrictedPtrType<CharType>;
@@ -39,6 +41,10 @@ def POSIX : StandardSpec<"POSIX"> {
   ConstType ConstPThreadMutexTPtr = ConstType<PThreadMutexTPtr>;
   ConstType ConstRestrictedPThreadMutexTPtr = ConstType<RestrictedPThreadMutexTPtr>;
 
+  NamedType PThreadTType = NamedType<"pthread_t">;
+  PtrType PThreadTPtr = PtrType<PThreadTType>;
+  RestrictedPtrType RestrictedPThreadTPtr = RestrictedPtrType<PThreadTType>;
+
   HeaderSpec Errno = HeaderSpec<
       "errno.h",
       [
@@ -392,7 +398,7 @@ def POSIX : StandardSpec<"POSIX"> {
   HeaderSpec PThread = HeaderSpec<
     "pthread.h",
     [], // Macros
-    [PThreadAttrTType, PThreadMutexAttrTType, PThreadMutexTType], // Types
+    [PThreadAttrTType, PThreadMutexAttrTType, PThreadMutexTType, PThreadStartT, PThreadTType], // Types
     [], // Enumerations
     [
       FunctionSpec<
@@ -445,6 +451,16 @@ def POSIX : StandardSpec<"POSIX"> {
           RetValSpec<IntType>,
           [ArgSpec<PThreadAttrTPtr>, ArgSpec<VoidPtr>, ArgSpec<SizeTType>]
       >,
+      FunctionSpec<
+          "pthread_create",
+          RetValSpec<IntType>,
+          [ArgSpec<RestrictedPThreadTPtr>, ArgSpec<ConstRestrictedPThreadAttrTPtr>, ArgSpec<PThreadStartT>, ArgSpec<VoidPtr>]
+      >,
+      FunctionSpec<
+          "pthread_join",
+          RetValSpec<IntType>,
+          [ArgSpec<PThreadTType>, ArgSpec<VoidPtrPtr>]
+      >,
       FunctionSpec<
           "pthread_mutexattr_init",
           RetValSpec<IntType>,

diff  --git a/libc/src/pthread/CMakeLists.txt b/libc/src/pthread/CMakeLists.txt
index ca5f0e0433cb5..828fee219a5c1 100644
--- a/libc/src/pthread/CMakeLists.txt
+++ b/libc/src/pthread/CMakeLists.txt
@@ -242,3 +242,26 @@ add_entrypoint_object(
     libc.include.pthread
     libc.src.__support.threads.mutex
 )
+
+add_entrypoint_object(
+  pthread_create
+  SRCS
+    pthread_create.cpp
+  HDRS
+    pthread_create.h
+  DEPENDS
+    libc.include.errno
+    libc.include.pthread
+    libc.src.__support.threads.thread
+)
+
+add_entrypoint_object(
+  pthread_join
+  SRCS
+    pthread_join.cpp
+  HDRS
+    pthread_join.h
+  DEPENDS
+    libc.include.pthread
+    libc.src.__support.threads.thread
+)

diff  --git a/libc/src/pthread/pthread_create.cpp b/libc/src/pthread/pthread_create.cpp
new file mode 100644
index 0000000000000..bc945a93984e9
--- /dev/null
+++ b/libc/src/pthread/pthread_create.cpp
@@ -0,0 +1,33 @@
+//===-- Linux implementation of the pthread_create function ---------------===//
+//
+// 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 "pthread_create.h"
+
+#include "src/__support/common.h"
+#include "src/__support/threads/thread.h"
+
+#include <errno.h>
+#include <pthread.h> // For pthread_* type definitions.
+
+namespace __llvm_libc {
+
+static_assert(sizeof(pthread_t) == sizeof(__llvm_libc::Thread<int>),
+              "Mismatch between pthread_t and internal Thread<int>.");
+
+LLVM_LIBC_FUNCTION(int, pthread_create,
+                   (pthread_t *__restrict th,
+                    const pthread_attr_t *__restrict attr,
+                    __pthread_start_t func, void *arg)) {
+  auto *thread = reinterpret_cast<__llvm_libc::Thread<void *> *>(th);
+  int result = thread->run(func, arg, nullptr, 0);
+  if (result != 0 && result != EPERM)
+    return EAGAIN;
+  return result;
+}
+
+} // namespace __llvm_libc

diff  --git a/libc/src/pthread/pthread_create.h b/libc/src/pthread/pthread_create.h
new file mode 100644
index 0000000000000..500aa6cc8138e
--- /dev/null
+++ b/libc/src/pthread/pthread_create.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for pthread_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_PTHREAD_CREATE_H
+#define LLVM_LIBC_SRC_THREADS_PTHREAD_CREATE_H
+
+#include <pthread.h>
+
+namespace __llvm_libc {
+
+int pthread_create(pthread_t *__restrict thread,
+                   const pthread_attr_t *__restrict attr,
+                   __pthread_start_t func, void *arg);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_THREADS_PTHREAD_CREATE_H

diff  --git a/libc/src/pthread/pthread_join.cpp b/libc/src/pthread/pthread_join.cpp
new file mode 100644
index 0000000000000..c3bf4adc6372e
--- /dev/null
+++ b/libc/src/pthread/pthread_join.cpp
@@ -0,0 +1,27 @@
+//===-- Linux implementation of the pthread_join function -----------------===//
+//
+// 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 "pthread_join.h"
+
+#include "src/__support/common.h"
+#include "src/__support/threads/thread.h"
+
+#include <pthread.h> // For pthread_* type definitions.
+
+namespace __llvm_libc {
+
+static_assert(sizeof(pthread_t) == sizeof(__llvm_libc::Thread<int>),
+              "Mismatch between pthread_t and internal Thread<int>.");
+
+LLVM_LIBC_FUNCTION(int, pthread_join, (pthread_t th, void **retval)) {
+  auto *thread = reinterpret_cast<Thread<void *> *>(&th);
+  int result = thread->join(retval);
+  return result;
+}
+
+} // namespace __llvm_libc

diff  --git a/libc/src/pthread/pthread_join.h b/libc/src/pthread/pthread_join.h
new file mode 100644
index 0000000000000..d659897b07377
--- /dev/null
+++ b/libc/src/pthread/pthread_join.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for pthread_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_PTHREAD_JOIN_H
+#define LLVM_LIBC_SRC_THREADS_PTHREAD_JOIN_H
+
+#include <pthread.h>
+
+namespace __llvm_libc {
+
+int pthread_join(pthread_t thread, void **retval);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_THREADS_PTHREAD_JOIN_H

diff  --git a/libc/test/src/pthread/CMakeLists.txt b/libc/test/src/pthread/CMakeLists.txt
index 5f3bbcbdd9a36..f69c77fd4c3ec 100644
--- a/libc/test/src/pthread/CMakeLists.txt
+++ b/libc/test/src/pthread/CMakeLists.txt
@@ -41,7 +41,7 @@ add_libc_unittest(
 )
 
 add_libc_unittest(
-  phtread_mutex_test
+  pthread_mutex_test
   SUITE
     libc_pthread_unittests
   SRCS
@@ -53,6 +53,18 @@ add_libc_unittest(
     libc.src.pthread.pthread_mutex_init
     libc.src.pthread.pthread_mutex_lock
     libc.src.pthread.pthread_mutex_unlock
-    libc.src.threads.thrd_create
-    libc.src.threads.thrd_join
+    libc.src.pthread.pthread_create
+    libc.src.pthread.pthread_join
+)
+
+add_libc_unittest(
+  pthread_test
+  SUITE
+    libc_pthread_unittests
+  SRCS
+    pthread_test.cpp
+  DEPENDS
+    libc.include.pthread
+    libc.src.pthread.pthread_create
+    libc.src.pthread.pthread_join
 )

diff  --git a/libc/test/src/pthread/pthread_mutex_test.cpp b/libc/test/src/pthread/pthread_mutex_test.cpp
index 8b06294169ed6..28c06b01eb1a1 100644
--- a/libc/test/src/pthread/pthread_mutex_test.cpp
+++ b/libc/test/src/pthread/pthread_mutex_test.cpp
@@ -11,10 +11,8 @@
 #include "src/pthread/pthread_mutex_lock.h"
 #include "src/pthread/pthread_mutex_unlock.h"
 
-// TODO: When pthread_t type is available, use it to spawn threads instead of
-// thrd_t.
-#include "src/threads/thrd_create.h"
-#include "src/threads/thrd_join.h"
+#include "src/pthread/pthread_create.h"
+#include "src/pthread/pthread_join.h"
 
 #include "utils/UnitTest/Test.h"
 
@@ -26,7 +24,7 @@ constexpr int MAX = 10000;
 pthread_mutex_t mutex;
 static int shared_int = START;
 
-int counter(void *arg) {
+void *counter(void *arg) {
   int last_count = START;
   while (true) {
     __llvm_libc::pthread_mutex_lock(&mutex);
@@ -38,7 +36,7 @@ int counter(void *arg) {
     if (last_count >= MAX)
       break;
   }
-  return 0;
+  return nullptr;
 }
 
 TEST(LlvmLibcMutexTest, RelayCounter) {
@@ -46,8 +44,8 @@ TEST(LlvmLibcMutexTest, RelayCounter) {
 
   // The idea of this test is that two competing threads will update
   // a counter only if the other thread has updated it.
-  thrd_t thread;
-  __llvm_libc::thrd_create(&thread, counter, nullptr);
+  pthread_t thread;
+  __llvm_libc::pthread_create(&thread, nullptr, counter, nullptr);
 
   int last_count = START;
   while (true) {
@@ -65,9 +63,9 @@ TEST(LlvmLibcMutexTest, RelayCounter) {
       break;
   }
 
-  int retval = 123;
-  __llvm_libc::thrd_join(&thread, &retval);
-  ASSERT_EQ(retval, 0);
+  void *retval = reinterpret_cast<void *>(123);
+  __llvm_libc::pthread_join(thread, &retval);
+  ASSERT_EQ(uintptr_t(retval), uintptr_t(nullptr));
 
   __llvm_libc::pthread_mutex_destroy(&mutex);
 }
@@ -75,7 +73,7 @@ TEST(LlvmLibcMutexTest, RelayCounter) {
 pthread_mutex_t start_lock, step_lock;
 bool started, step;
 
-int stepper(void *arg) {
+void *stepper(void *arg) {
   __llvm_libc::pthread_mutex_lock(&start_lock);
   started = true;
   __llvm_libc::pthread_mutex_unlock(&start_lock);
@@ -83,7 +81,7 @@ int stepper(void *arg) {
   __llvm_libc::pthread_mutex_lock(&step_lock);
   step = true;
   __llvm_libc::pthread_mutex_unlock(&step_lock);
-  return 0;
+  return nullptr;
 }
 
 TEST(LlvmLibcMutexTest, WaitAndStep) {
@@ -97,8 +95,8 @@ TEST(LlvmLibcMutexTest, WaitAndStep) {
   started = false;
   ASSERT_EQ(__llvm_libc::pthread_mutex_lock(&step_lock), 0);
 
-  thrd_t thread;
-  __llvm_libc::thrd_create(&thread, stepper, nullptr);
+  pthread_t thread;
+  __llvm_libc::pthread_create(&thread, nullptr, stepper, nullptr);
 
   while (true) {
     // Make sure the thread actually started.
@@ -123,9 +121,9 @@ TEST(LlvmLibcMutexTest, WaitAndStep) {
       break;
   }
 
-  int retval = 123;
-  __llvm_libc::thrd_join(&thread, &retval);
-  ASSERT_EQ(retval, 0);
+  void *retval = reinterpret_cast<void *>(123);
+  __llvm_libc::pthread_join(thread, &retval);
+  ASSERT_EQ(uintptr_t(retval), uintptr_t(nullptr));
 
   __llvm_libc::pthread_mutex_destroy(&start_lock);
   __llvm_libc::pthread_mutex_destroy(&step_lock);
@@ -136,7 +134,7 @@ static pthread_mutex_t multiple_waiter_lock;
 static pthread_mutex_t counter_lock;
 static int wait_count = 0;
 
-int waiter_func(void *) {
+void *waiter_func(void *) {
   __llvm_libc::pthread_mutex_lock(&counter_lock);
   ++wait_count;
   __llvm_libc::pthread_mutex_unlock(&counter_lock);
@@ -150,7 +148,7 @@ int waiter_func(void *) {
   --wait_count;
   __llvm_libc::pthread_mutex_unlock(&counter_lock);
 
-  return 0;
+  return nullptr;
 }
 
 TEST(LlvmLibcMutexTest, MultipleWaiters) {
@@ -158,9 +156,9 @@ TEST(LlvmLibcMutexTest, MultipleWaiters) {
   __llvm_libc::pthread_mutex_init(&counter_lock, nullptr);
 
   __llvm_libc::pthread_mutex_lock(&multiple_waiter_lock);
-  thrd_t waiters[THREAD_COUNT];
+  pthread_t waiters[THREAD_COUNT];
   for (int i = 0; i < THREAD_COUNT; ++i) {
-    __llvm_libc::thrd_create(waiters + i, waiter_func, nullptr);
+    __llvm_libc::pthread_create(waiters + i, nullptr, waiter_func, nullptr);
   }
 
   // Spin until the counter is incremented to the desired
@@ -176,9 +174,9 @@ TEST(LlvmLibcMutexTest, MultipleWaiters) {
 
   __llvm_libc::pthread_mutex_unlock(&multiple_waiter_lock);
 
-  int retval;
+  void *retval;
   for (int i = 0; i < THREAD_COUNT; ++i) {
-    __llvm_libc::thrd_join(waiters + i, &retval);
+    __llvm_libc::pthread_join(waiters[i], &retval);
   }
 
   ASSERT_EQ(wait_count, 0);

diff  --git a/libc/test/src/pthread/pthread_test.cpp b/libc/test/src/pthread/pthread_test.cpp
new file mode 100644
index 0000000000000..3a3d587ab5d51
--- /dev/null
+++ b/libc/test/src/pthread/pthread_test.cpp
@@ -0,0 +1,56 @@
+//===-- Unittests for pthread_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 "src/pthread/pthread_create.h"
+#include "src/pthread/pthread_join.h"
+#include "utils/UnitTest/Test.h"
+
+#include <pthread.h>
+
+static constexpr int thread_count = 1000;
+static int counter = 0;
+static void *thread_func(void *) {
+  ++counter;
+  return nullptr;
+}
+
+TEST(LlvmLibcThreadTest, CreateAndJoin) {
+  for (counter = 0; counter <= thread_count;) {
+    pthread_t thread;
+    int old_counter_val = counter;
+    ASSERT_EQ(
+        __llvm_libc::pthread_create(&thread, nullptr, thread_func, nullptr), 0);
+
+    // Start with a retval we dont expect.
+    void *retval = reinterpret_cast<void *>(thread_count + 1);
+    ASSERT_EQ(__llvm_libc::pthread_join(thread, &retval), 0);
+    ASSERT_EQ(uintptr_t(retval), uintptr_t(nullptr));
+    ASSERT_EQ(counter, old_counter_val + 1);
+  }
+}
+
+static void *return_arg(void *arg) { return arg; }
+
+TEST(LlvmLibcThreadTest, SpawnAndJoin) {
+  pthread_t thread_list[thread_count];
+  int args[thread_count];
+
+  for (int i = 0; i < thread_count; ++i) {
+    args[i] = i;
+    ASSERT_EQ(__llvm_libc::pthread_create(thread_list + i, nullptr, return_arg,
+                                          args + i),
+              0);
+  }
+
+  for (int i = 0; i < thread_count; ++i) {
+    // Start with a retval we dont expect.
+    void *retval = reinterpret_cast<void *>(thread_count + 1);
+    ASSERT_EQ(__llvm_libc::pthread_join(thread_list[i], &retval), 0);
+    ASSERT_EQ(*reinterpret_cast<int *>(retval), i);
+  }
+}


        


More information about the libc-commits mailing list