[libc-commits] [libc] 8dc4280 - [libc] Add implementations of pthread_equal and pthread_self.

Siva Chandra Reddy via libc-commits libc-commits at lists.llvm.org
Thu Jul 14 13:12:55 PDT 2022


Author: Siva Chandra Reddy
Date: 2022-07-14T20:12:35Z
New Revision: 8dc42802f7052d2eed4f2267851b94578c0152fc

URL: https://github.com/llvm/llvm-project/commit/8dc42802f7052d2eed4f2267851b94578c0152fc
DIFF: https://github.com/llvm/llvm-project/commit/8dc42802f7052d2eed4f2267851b94578c0152fc.diff

LOG: [libc] Add implementations of pthread_equal and pthread_self.

Reviewed By: michaelrj, lntue

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

Added: 
    libc/src/pthread/pthread_equal.cpp
    libc/src/pthread/pthread_equal.h
    libc/src/pthread/pthread_self.cpp
    libc/src/pthread/pthread_self.h
    libc/src/threads/thrd_current.cpp
    libc/src/threads/thrd_current.h
    libc/src/threads/thrd_equal.cpp
    libc/src/threads/thrd_equal.h
    libc/test/integration/src/pthread/pthread_equal_test.cpp
    libc/test/integration/src/threads/thrd_equal_test.cpp

Modified: 
    libc/config/linux/x86_64/entrypoints.txt
    libc/loader/linux/aarch64/start.cpp
    libc/loader/linux/x86_64/CMakeLists.txt
    libc/loader/linux/x86_64/start.cpp
    libc/spec/posix.td
    libc/spec/stdc.td
    libc/src/__support/threads/linux/thread.cpp
    libc/src/__support/threads/thread.cpp
    libc/src/__support/threads/thread.h
    libc/src/pthread/CMakeLists.txt
    libc/src/pthread/pthread_join.cpp
    libc/src/threads/CMakeLists.txt
    libc/test/integration/src/pthread/CMakeLists.txt
    libc/test/integration/src/threads/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 06258688b254d..93c76b305e1c9 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -241,7 +241,9 @@ if(LLVM_LIBC_FULL_BUILD)
     libc.src.pthread.pthread_attr_init
     libc.src.pthread.pthread_create
     libc.src.pthread.pthread_detach
+    libc.src.pthread.pthread_equal
     libc.src.pthread.pthread_join
+    libc.src.pthread.pthread_self
     libc.src.pthread.pthread_mutex_destroy
     libc.src.pthread.pthread_mutex_init
     libc.src.pthread.pthread_mutex_lock
@@ -310,7 +312,9 @@ if(LLVM_LIBC_FULL_BUILD)
     libc.src.threads.mtx_lock
     libc.src.threads.mtx_unlock
     libc.src.threads.thrd_create
+    libc.src.threads.thrd_current
     libc.src.threads.thrd_detach
+    libc.src.threads.thrd_equal
     libc.src.threads.thrd_join
 
     # time.h entrypoints

diff  --git a/libc/loader/linux/aarch64/start.cpp b/libc/loader/linux/aarch64/start.cpp
index 5835c838078c3..6c977860a28bd 100644
--- a/libc/loader/linux/aarch64/start.cpp
+++ b/libc/loader/linux/aarch64/start.cpp
@@ -8,6 +8,7 @@
 
 #include "config/linux/app.h"
 #include "src/__support/OSUtil/syscall.h"
+#include "src/__support/threads/thread.h"
 #include "src/string/memory_utils/memcpy_implementations.h"
 
 #include <arm_acle.h>
@@ -35,6 +36,8 @@ static constexpr long MMAP_SYSCALL_NUMBER = SYS_mmap;
 
 AppProperties app;
 
+static ThreadAttributes main_thread_attrib;
+
 void init_tls(TLSDescriptor &tls_descriptor) {
   if (app.tls.size == 0) {
     tls_descriptor.size = 0;
@@ -105,6 +108,11 @@ extern "C" void _start() {
   app.args = reinterpret_cast<__llvm_libc::Args *>(
       reinterpret_cast<uintptr_t *>(__builtin_frame_address(0)) + 2);
 
+  auto tid = __llvm_libc::syscall(SYS_gettid);
+  if (tid <= 0)
+    __llvm_libc::syscall(SYS_exit, 1);
+  __llvm_libc::main_thread_attrib.tid = tid;
+
   // After the argv array, is a 8-byte long NULL value before the array of env
   // values. The end of the env values is marked by another 8-byte long NULL
   // value. We step over it (the "+ 1" below) to get to the env values.
@@ -151,6 +159,8 @@ extern "C" void _start() {
   if (tls.size != 0)
     __llvm_libc::set_thread_ptr(tls.tp);
 
+  __llvm_libc::self.attrib = &__llvm_libc::main_thread_attrib;
+
   int retval = main(app.args->argc, reinterpret_cast<char **>(app.args->argv),
                     reinterpret_cast<char **>(env_ptr));
   __llvm_libc::cleanup_tls(tls.addr, tls.size);

diff  --git a/libc/loader/linux/x86_64/CMakeLists.txt b/libc/loader/linux/x86_64/CMakeLists.txt
index 47c3d38e24e8e..238364ee21820 100644
--- a/libc/loader/linux/x86_64/CMakeLists.txt
+++ b/libc/loader/linux/x86_64/CMakeLists.txt
@@ -6,6 +6,7 @@ add_loader_object(
     libc.config.linux.app_h
     libc.include.sys_mman
     libc.include.sys_syscall
+    libc.src.__support.threads.thread
     libc.src.__support.OSUtil.osutil
     libc.src.string.memory_utils.memcpy_implementation
   COMPILE_OPTIONS

diff  --git a/libc/loader/linux/x86_64/start.cpp b/libc/loader/linux/x86_64/start.cpp
index 514caaf4dca63..03382065dd35c 100644
--- a/libc/loader/linux/x86_64/start.cpp
+++ b/libc/loader/linux/x86_64/start.cpp
@@ -8,6 +8,7 @@
 
 #include "config/linux/app.h"
 #include "src/__support/OSUtil/syscall.h"
+#include "src/__support/threads/thread.h"
 #include "src/string/memory_utils/memcpy_implementations.h"
 
 #include <asm/prctl.h>
@@ -31,6 +32,8 @@ static constexpr long mmapSyscallNumber = SYS_mmap;
 
 AppProperties app;
 
+static ThreadAttributes main_thread_attrib;
+
 // TODO: The function is x86_64 specific. Move it to config/linux/app.h
 // and generalize it. Also, dynamic loading is not handled currently.
 void init_tls(TLSDescriptor &tls_descriptor) {
@@ -118,6 +121,11 @@ extern "C" void _start() {
   __asm__ __volatile__("andq $0xfffffffffffffff0, %%rsp\n\t" ::: "%rsp");
   __asm__ __volatile__("andq $0xfffffffffffffff0, %%rbp\n\t" ::: "%rbp");
 
+  auto tid = __llvm_libc::syscall(SYS_gettid);
+  if (tid <= 0)
+    __llvm_libc::syscall(SYS_exit, 1);
+  __llvm_libc::main_thread_attrib.tid = tid;
+
   // After the argv array, is a 8-byte long NULL value before the array of env
   // values. The end of the env values is marked by another 8-byte long NULL
   // value. We step over it (the "+ 1" below) to get to the env values.
@@ -165,6 +173,8 @@ extern "C" void _start() {
   if (tls.size != 0 && !__llvm_libc::set_thread_ptr(tls.tp))
     __llvm_libc::syscall(SYS_exit, 1);
 
+  __llvm_libc::self.attrib = &__llvm_libc::main_thread_attrib;
+
   int retval = main(app.args->argc, reinterpret_cast<char **>(app.args->argv),
                     reinterpret_cast<char **>(env_ptr));
   __llvm_libc::cleanup_tls(tls.addr, tls.size);

diff  --git a/libc/spec/posix.td b/libc/spec/posix.td
index 915a177913402..2840b5d911421 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -466,6 +466,16 @@ def POSIX : StandardSpec<"POSIX"> {
           RetValSpec<IntType>,
           [ArgSpec<PThreadTType>]
       >,
+      FunctionSpec<
+          "pthread_self",
+          RetValSpec<PThreadTType>,
+          [ArgSpec<VoidType>]
+      >,
+      FunctionSpec<
+          "pthread_equal",
+          RetValSpec<IntType>,
+          [ArgSpec<PThreadTType>, ArgSpec<PThreadTType>]
+      >,
       FunctionSpec<
           "pthread_mutexattr_init",
           RetValSpec<IntType>,

diff  --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 72809cc694cf2..b998c0da3aa20 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -810,6 +810,16 @@ def StdC : StandardSpec<"stdc"> {
               "thrd_detach",
               RetValSpec<IntType>,
               [ArgSpec<ThrdTType>]
+          >,
+          FunctionSpec<
+              "thrd_current",
+              RetValSpec<ThrdTType>,
+              [ArgSpec<VoidType>]
+          >,
+          FunctionSpec<
+              "thrd_equal",
+              RetValSpec<IntType>,
+              [ArgSpec<ThrdTType>, ArgSpec<ThrdTType>]
           >
       ]
   >;

diff  --git a/libc/src/__support/threads/linux/thread.cpp b/libc/src/__support/threads/linux/thread.cpp
index e5b73d43c0a4b..83c85f9b5128b 100644
--- a/libc/src/__support/threads/linux/thread.cpp
+++ b/libc/src/__support/threads/linux/thread.cpp
@@ -111,6 +111,8 @@ __attribute__((noinline))
 static void start_thread() {
   auto *start_args = reinterpret_cast<StartArgs *>(get_start_args_addr());
   auto *attrib = start_args->thread_attrib;
+  self.attrib = attrib;
+
   long retval;
   if (attrib->style == ThreadStyle::POSIX) {
     attrib->retval.posix_retval =
@@ -272,4 +274,8 @@ void Thread::wait() {
   }
 }
 
+bool Thread::operator==(const Thread &thread) const {
+  return attrib->tid == thread.attrib->tid;
+}
+
 } // namespace __llvm_libc

diff  --git a/libc/src/__support/threads/thread.cpp b/libc/src/__support/threads/thread.cpp
index 1ca78ece703dd..6149f7724fca6 100644
--- a/libc/src/__support/threads/thread.cpp
+++ b/libc/src/__support/threads/thread.cpp
@@ -6,5 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 
-// This file is currently emtpy. In future, declaration of a self thread object
-// etc. will be added here.
+#include "thread.h"
+
+namespace __llvm_libc {
+
+thread_local Thread self;
+
+} // namespace __llvm_libc

diff  --git a/libc/src/__support/threads/thread.h b/libc/src/__support/threads/thread.h
index 7f965923391d1..2ca17aa08dcfc 100644
--- a/libc/src/__support/threads/thread.h
+++ b/libc/src/__support/threads/thread.h
@@ -162,8 +162,13 @@ struct Thread {
   // NOTE: This function is to be used for testing only. There is no standard
   // which requires exposing it via a public API.
   void wait();
+
+  // Return true if this thread is equal to the other thread.
+  bool operator==(const Thread &other) const;
 };
 
+extern thread_local Thread self;
+
 } // namespace __llvm_libc
 
 #endif // LLVM_LIBC_SRC_SUPPORT_THREADS_THREAD_H

diff  --git a/libc/src/pthread/CMakeLists.txt b/libc/src/pthread/CMakeLists.txt
index d786a35155492..4c45cc53a3e82 100644
--- a/libc/src/pthread/CMakeLists.txt
+++ b/libc/src/pthread/CMakeLists.txt
@@ -279,3 +279,25 @@ add_entrypoint_object(
     libc.include.pthread
     libc.src.__support.threads.thread
 )
+
+add_entrypoint_object(
+  pthread_equal
+  SRCS
+    pthread_equal.cpp
+  HDRS
+    pthread_equal.h
+  DEPENDS
+    libc.include.pthread
+    libc.src.__support.threads.thread
+)
+
+add_entrypoint_object(
+  pthread_self
+  SRCS
+    pthread_self.cpp
+  HDRS
+    pthread_self.h
+  DEPENDS
+    libc.include.pthread
+    libc.src.__support.threads.thread
+)

diff  --git a/libc/src/pthread/pthread_equal.cpp b/libc/src/pthread/pthread_equal.cpp
new file mode 100644
index 0000000000000..29460204ae1d9
--- /dev/null
+++ b/libc/src/pthread/pthread_equal.cpp
@@ -0,0 +1,27 @@
+//===-- Implementation of the pthread_equal 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_equal.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),
+              "Mismatch between pthread_t and internal Thread.");
+
+LLVM_LIBC_FUNCTION(int, pthread_equal, (pthread_t lhs, pthread_t rhs)) {
+  auto *lhs_internal = reinterpret_cast<Thread *>(&lhs);
+  auto *rhs_internal = reinterpret_cast<Thread *>(&rhs);
+  return *lhs_internal == *rhs_internal;
+}
+
+} // namespace __llvm_libc

diff  --git a/libc/src/pthread/pthread_equal.h b/libc/src/pthread/pthread_equal.h
new file mode 100644
index 0000000000000..a4518d179e78c
--- /dev/null
+++ b/libc/src/pthread/pthread_equal.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for pthread_equal 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_EQUAL_H
+#define LLVM_LIBC_SRC_THREADS_PTHREAD_EQUAL_H
+
+#include <pthread.h>
+
+namespace __llvm_libc {
+
+int pthread_equal(pthread_t lhs, pthread_t rhs);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_THREADS_PTHREAD_EQUAL_H

diff  --git a/libc/src/pthread/pthread_join.cpp b/libc/src/pthread/pthread_join.cpp
index 0774d02680526..b888260247cd8 100644
--- a/libc/src/pthread/pthread_join.cpp
+++ b/libc/src/pthread/pthread_join.cpp
@@ -1,4 +1,4 @@
-//===-- Linux implementation of the pthread_join function -----------------===//
+//===-- 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.

diff  --git a/libc/src/pthread/pthread_self.cpp b/libc/src/pthread/pthread_self.cpp
new file mode 100644
index 0000000000000..5b3145f34930c
--- /dev/null
+++ b/libc/src/pthread/pthread_self.cpp
@@ -0,0 +1,27 @@
+//===-- Implementation of the pthread_self 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_self.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),
+              "Mismatch between pthread_t and internal Thread.");
+
+LLVM_LIBC_FUNCTION(pthread_t, pthread_self, ()) {
+  pthread_t th;
+  th.__attrib = self.attrib;
+  return th;
+}
+
+} // namespace __llvm_libc

diff  --git a/libc/src/pthread/pthread_self.h b/libc/src/pthread/pthread_self.h
new file mode 100644
index 0000000000000..dd4b920a0b04b
--- /dev/null
+++ b/libc/src/pthread/pthread_self.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for pthread_self 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_SELF_H
+#define LLVM_LIBC_SRC_THREADS_PTHREAD_SELF_H
+
+#include <pthread.h>
+
+namespace __llvm_libc {
+
+pthread_t pthread_self();
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_THREADS_PTHREAD_SELF_H

diff  --git a/libc/src/threads/CMakeLists.txt b/libc/src/threads/CMakeLists.txt
index bdbb32d81e1c1..179d1e56205b8 100644
--- a/libc/src/threads/CMakeLists.txt
+++ b/libc/src/threads/CMakeLists.txt
@@ -46,6 +46,28 @@ add_entrypoint_object(
     libc.src.__support.threads.thread
 )
 
+add_entrypoint_object(
+  thrd_current
+  SRCS
+    thrd_current.cpp
+  HDRS
+    thrd_current.h
+  DEPENDS
+    libc.include.threads
+    libc.src.__support.threads.thread
+)
+
+add_entrypoint_object(
+  thrd_equal
+  SRCS
+    thrd_equal.cpp
+  HDRS
+    thrd_equal.h
+  DEPENDS
+    libc.include.threads
+    libc.src.__support.threads.thread
+)
+
 add_entrypoint_object(
   mtx_init
   SRCS

diff  --git a/libc/src/threads/thrd_current.cpp b/libc/src/threads/thrd_current.cpp
new file mode 100644
index 0000000000000..e8afd7bf6c49a
--- /dev/null
+++ b/libc/src/threads/thrd_current.cpp
@@ -0,0 +1,26 @@
+//===-- Implementation of the thrd_current 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 "src/threads/thrd_current.h"
+#include "src/__support/common.h"
+#include "src/__support/threads/thread.h"
+
+#include <threads.h> // For thrd_* type definitions.
+
+namespace __llvm_libc {
+
+static_assert(sizeof(thrd_t) == sizeof(__llvm_libc::Thread),
+              "Mismatch between thrd_t and internal Thread.");
+
+LLVM_LIBC_FUNCTION(thrd_t, thrd_current, ()) {
+  thrd_t th;
+  th.__attrib = self.attrib;
+  return th;
+}
+
+} // namespace __llvm_libc

diff  --git a/libc/src/threads/thrd_current.h b/libc/src/threads/thrd_current.h
new file mode 100644
index 0000000000000..774b445aa339b
--- /dev/null
+++ b/libc/src/threads/thrd_current.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for thrd_current 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_THRD_CURRENT_H
+#define LLVM_LIBC_SRC_THREADS_THRD_CURRENT_H
+
+#include "include/threads.h"
+
+namespace __llvm_libc {
+
+thrd_t thrd_current();
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_THREADS_THRD_CURRENT_H

diff  --git a/libc/src/threads/thrd_equal.cpp b/libc/src/threads/thrd_equal.cpp
new file mode 100644
index 0000000000000..aac220ec9adb4
--- /dev/null
+++ b/libc/src/threads/thrd_equal.cpp
@@ -0,0 +1,26 @@
+//===-- Implementation of the thrd_equal 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 "src/threads/thrd_equal.h"
+#include "src/__support/common.h"
+#include "src/__support/threads/thread.h"
+
+#include <threads.h> // For thrd_* type definitions.
+
+namespace __llvm_libc {
+
+static_assert(sizeof(thrd_t) == sizeof(__llvm_libc::Thread),
+              "Mismatch between thrd_t and internal Thread.");
+
+LLVM_LIBC_FUNCTION(int, thrd_equal, (thrd_t lhs, thrd_t rhs)) {
+  auto *lhs_internal = reinterpret_cast<Thread *>(&lhs);
+  auto *rhs_internal = reinterpret_cast<Thread *>(&rhs);
+  return *lhs_internal == *rhs_internal;
+}
+
+} // namespace __llvm_libc

diff  --git a/libc/src/threads/thrd_equal.h b/libc/src/threads/thrd_equal.h
new file mode 100644
index 0000000000000..123563ea71247
--- /dev/null
+++ b/libc/src/threads/thrd_equal.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for thrd_equal 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_THRD_EQUAL_H
+#define LLVM_LIBC_SRC_THREADS_THRD_EQUAL_H
+
+#include "include/threads.h"
+
+namespace __llvm_libc {
+
+int thrd_equal(thrd_t lhs, thrd_t rhs);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_THREADS_THRD_EQUAL_H

diff  --git a/libc/test/integration/src/pthread/CMakeLists.txt b/libc/test/integration/src/pthread/CMakeLists.txt
index 0f52d8ac28e63..e751318bb0012 100644
--- a/libc/test/integration/src/pthread/CMakeLists.txt
+++ b/libc/test/integration/src/pthread/CMakeLists.txt
@@ -32,3 +32,24 @@ add_integration_test(
     libc.src.pthread.pthread_create
     libc.src.pthread.pthread_join
 )
+
+add_integration_test(
+  pthread_equal_test
+  SUITE
+    libc-pthread-integration-tests
+  SRCS
+    pthread_equal_test.cpp
+  LOADER
+    libc.loader.linux.crt1
+  DEPENDS
+    libc.include.pthread
+    libc.src.errno.errno
+    libc.src.pthread.pthread_mutex_destroy
+    libc.src.pthread.pthread_mutex_init
+    libc.src.pthread.pthread_mutex_lock
+    libc.src.pthread.pthread_mutex_unlock
+    libc.src.pthread.pthread_create
+    libc.src.pthread.pthread_equal
+    libc.src.pthread.pthread_join
+    libc.src.pthread.pthread_self
+)

diff  --git a/libc/test/integration/src/pthread/pthread_equal_test.cpp b/libc/test/integration/src/pthread/pthread_equal_test.cpp
new file mode 100644
index 0000000000000..2f1ff6a8c8730
--- /dev/null
+++ b/libc/test/integration/src/pthread/pthread_equal_test.cpp
@@ -0,0 +1,67 @@
+//===-- Tests for pthread_equal -------------------------------------------===//
+//
+// 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_equal.h"
+#include "src/pthread/pthread_join.h"
+#include "src/pthread/pthread_mutex_destroy.h"
+#include "src/pthread/pthread_mutex_init.h"
+#include "src/pthread/pthread_mutex_lock.h"
+#include "src/pthread/pthread_mutex_unlock.h"
+#include "src/pthread/pthread_self.h"
+
+#include "utils/IntegrationTest/test.h"
+
+#include <pthread.h>
+
+pthread_t child_thread;
+pthread_mutex_t mutex;
+
+static void *child_func(void *arg) {
+  __llvm_libc::pthread_mutex_lock(&mutex);
+  int *ret = reinterpret_cast<int *>(arg);
+  auto self = __llvm_libc::pthread_self();
+  *ret = __llvm_libc::pthread_equal(child_thread, self);
+  __llvm_libc::pthread_mutex_unlock(&mutex);
+  return nullptr;
+}
+
+int main() {
+  // We init and lock the mutex so that we guarantee that the child thread is
+  // waiting after startup.
+  ASSERT_EQ(__llvm_libc::pthread_mutex_init(&mutex, nullptr), 0);
+  ASSERT_EQ(__llvm_libc::pthread_mutex_lock(&mutex), 0);
+
+  auto main_thread = __llvm_libc::pthread_self();
+
+  // The idea here is that, we start a child thread which will immediately
+  // wait on |mutex|. The main thread will update the global |child_thread| var
+  // and unlock |mutex|. This will give the child thread a chance to compare
+  // the result of pthread_self with the |child_thread|. The result of the
+  // comparison is returned in the thread arg.
+  int result = 0;
+  pthread_t th;
+  ASSERT_EQ(__llvm_libc::pthread_create(&th, nullptr, child_func, &result), 0);
+  // This new thread should of course not be equal to the main thread.
+  ASSERT_EQ(__llvm_libc::pthread_equal(th, main_thread), 0);
+
+  // Set the |child_thread| global var and unlock to allow the child to perform
+  // the comparison.
+  child_thread = th;
+  ASSERT_EQ(__llvm_libc::pthread_mutex_unlock(&mutex), 0);
+
+  void *retval;
+  ASSERT_EQ(__llvm_libc::pthread_join(th, &retval), 0);
+  ASSERT_EQ(uintptr_t(retval), uintptr_t(nullptr));
+  // The child thread should see that pthread_self return value is the same as
+  // |child_thread|.
+  ASSERT_NE(result, 0);
+
+  __llvm_libc::pthread_mutex_destroy(&mutex);
+  return 0;
+}

diff  --git a/libc/test/integration/src/threads/CMakeLists.txt b/libc/test/integration/src/threads/CMakeLists.txt
index 05acc7f1da456..34dc47127005d 100644
--- a/libc/test/integration/src/threads/CMakeLists.txt
+++ b/libc/test/integration/src/threads/CMakeLists.txt
@@ -19,6 +19,26 @@ add_integration_test(
     libc.src.threads.thrd_join
 )
 
+add_integration_test(
+  thrd_equal_test
+  SUITE
+    libc-threads-integration-tests
+  SRCS
+    thrd_equal_test.cpp
+  LOADER
+    libc.loader.linux.crt1
+  DEPENDS
+    libc.include.threads
+    libc.src.threads.mtx_destroy
+    libc.src.threads.mtx_init
+    libc.src.threads.mtx_lock
+    libc.src.threads.mtx_unlock
+    libc.src.threads.thrd_create
+    libc.src.threads.thrd_current
+    libc.src.threads.thrd_equal
+    libc.src.threads.thrd_join
+)
+
 add_integration_test(
   thrd_test
   SUITE

diff  --git a/libc/test/integration/src/threads/thrd_equal_test.cpp b/libc/test/integration/src/threads/thrd_equal_test.cpp
new file mode 100644
index 0000000000000..4058d0d141815
--- /dev/null
+++ b/libc/test/integration/src/threads/thrd_equal_test.cpp
@@ -0,0 +1,68 @@
+//===-- Tests for thrd_equal ----------------------------------------------===//
+//
+// 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/threads/mtx_destroy.h"
+#include "src/threads/mtx_init.h"
+#include "src/threads/mtx_lock.h"
+#include "src/threads/mtx_unlock.h"
+#include "src/threads/thrd_create.h"
+#include "src/threads/thrd_current.h"
+#include "src/threads/thrd_equal.h"
+#include "src/threads/thrd_join.h"
+
+#include "utils/IntegrationTest/test.h"
+
+#include <threads.h>
+
+thrd_t child_thread;
+mtx_t mutex;
+
+static int child_func(void *arg) {
+  __llvm_libc::mtx_lock(&mutex);
+  int *ret = reinterpret_cast<int *>(arg);
+  auto self = __llvm_libc::thrd_current();
+  *ret = __llvm_libc::thrd_equal(child_thread, self);
+  __llvm_libc::mtx_unlock(&mutex);
+  return 0;
+}
+
+int main() {
+  // We init and lock the mutex so that we guarantee that the child thread is
+  // waiting after startup.
+  ASSERT_EQ(__llvm_libc::mtx_init(&mutex, mtx_plain), int(thrd_success));
+  ASSERT_EQ(__llvm_libc::mtx_lock(&mutex), int(thrd_success));
+
+  auto main_thread = __llvm_libc::thrd_current();
+
+  // The idea here is that, we start a child thread which will immediately
+  // wait on |mutex|. The main thread will update the global |child_thread| var
+  // and unlock |mutex|. This will give the child thread a chance to compare
+  // the result of thrd_self with the |child_thread|. The result of the
+  // comparison is returned in the thread arg.
+  int result = 0;
+  thrd_t th;
+  ASSERT_EQ(__llvm_libc::thrd_create(&th, child_func, &result),
+            int(thrd_success));
+  // This new thread should of course not be equal to the main thread.
+  ASSERT_EQ(__llvm_libc::thrd_equal(th, main_thread), 0);
+
+  // Set the |child_thread| global var and unlock to allow the child to perform
+  // the comparison.
+  child_thread = th;
+  ASSERT_EQ(__llvm_libc::mtx_unlock(&mutex), int(thrd_success));
+
+  int retval;
+  ASSERT_EQ(__llvm_libc::thrd_join(&th, &retval), int(thrd_success));
+  ASSERT_EQ(retval, 0);
+  // The child thread should see that thrd_current return value is the same as
+  // |child_thread|.
+  ASSERT_NE(result, 0);
+
+  __llvm_libc::mtx_destroy(&mutex);
+  return 0;
+}


        


More information about the libc-commits mailing list