[libc-commits] [libc] f4580c6 - [libc][NFC] Remove the templatization from the linux implementation of thread.

Siva Chandra Reddy via libc-commits libc-commits at lists.llvm.org
Fri Jun 24 01:23:25 PDT 2022


Author: Siva Chandra Reddy
Date: 2022-06-24T08:22:53Z
New Revision: f4580c6d5a44379f3b1be033f39ec7af78dbbbfa

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

LOG: [libc][NFC] Remove the templatization from the linux implementation of thread.

This enables setting up a single "self" thread object to be returned by
API like thrd_self and pthread_self.

Added: 
    

Modified: 
    libc/src/__support/threads/linux/thread.h
    libc/src/__support/threads/thread.h
    libc/src/__support/threads/thread_attrib.h
    libc/src/pthread/pthread_create.cpp
    libc/src/pthread/pthread_detach.cpp
    libc/src/pthread/pthread_join.cpp
    libc/src/threads/thrd_create.cpp
    libc/src/threads/thrd_detach.cpp
    libc/src/threads/thrd_join.cpp

Removed: 
    


################################################################################
diff  --git a/libc/src/__support/threads/linux/thread.h b/libc/src/__support/threads/linux/thread.h
index a947613ea5e27..365f0fc55979b 100644
--- a/libc/src/__support/threads/linux/thread.h
+++ b/libc/src/__support/threads/linux/thread.h
@@ -27,8 +27,6 @@
 
 namespace __llvm_libc {
 
-template <typename ReturnType> struct Thread;
-
 #ifdef SYS_mmap2
 static constexpr long MMAP_SYSCALL_NUMBER = SYS_mmap2;
 #elif SYS_mmap
@@ -72,16 +70,16 @@ static inline void free_stack(void *stack, size_t size) {
   __llvm_libc::syscall(SYS_munmap, stack, size);
 }
 
-template <typename ReturnType> using ThreadRunner = ReturnType(void *);
+struct Thread;
 
 // We align the start args to 16-byte boundary as we adjust the allocated
 // stack memory with its size. We want the adjusted address to be at a
 // 16-byte boundary to satisfy the x86_64 and aarch64 ABI requirements.
 // If 
diff erent architecture in future requires higher alignment, then we
 // can add a platform specific alignment spec.
-template <typename ReturnType> struct alignas(STACK_ALIGNMENT) StartArgs {
-  Thread<ReturnType> *thread;
-  ThreadRunner<ReturnType> *func;
+struct alignas(STACK_ALIGNMENT) StartArgs {
+  Thread *thread;
+  ThreadRunner runner;
   void *arg;
 };
 
@@ -104,19 +102,57 @@ __attribute__((always_inline)) inline uintptr_t get_start_args_addr() {
 #endif
 }
 
-template <typename ReturnType> struct Thread {
+struct Thread {
 private:
-  ThreadAttributes<ReturnType> *attrib;
+  ThreadAttributes *attrib;
   cpp::Atomic<FutexWordType> *clear_tid;
 
 public:
   Thread() = default;
 
-  static void start_thread() __attribute__((noinline));
+  static void start_thread() __attribute__((noinline)) {
+    auto *start_args = reinterpret_cast<StartArgs *>(get_start_args_addr());
+    auto *thread = start_args->thread;
+    auto *attrib = thread->attrib;
+    long retval;
+    if (attrib->style == ThreadStyle::POSIX) {
+      attrib->retval.posix_retval =
+          start_args->runner.posix_runner(start_args->arg);
+      retval = long(attrib->retval.posix_retval);
+    } else {
+      attrib->retval.stdc_retval =
+          start_args->runner.stdc_runner(start_args->arg);
+      retval = long(attrib->retval.stdc_retval);
+    }
 
-  // Return 0 on success or an error value on failure.
-  int run(ThreadRunner<ReturnType> *f, void *arg, void *stack, size_t size,
+    uint32_t joinable_state = uint32_t(DetachState::JOINABLE);
+    if (!thread->attrib->detach_state.compare_exchange_strong(
+            joinable_state, uint32_t(DetachState::EXITING))) {
+      // Thread is detached so cleanup the resources.
+      if (thread->attrib->owned_stack)
+        free_stack(thread->attrib->stack, thread->attrib->stack_size);
+    }
+
+    __llvm_libc::syscall(SYS_exit, retval);
+  }
+
+  int run(ThreadRunnerPosix *func, void *arg, void *stack, size_t size,
+          bool detached = false) {
+    ThreadRunner runner;
+    runner.posix_runner = func;
+    return run(ThreadStyle::POSIX, runner, arg, stack, size, detached);
+  }
+
+  int run(ThreadRunnerStdc *func, void *arg, void *stack, size_t size,
           bool detached = false) {
+    ThreadRunner runner;
+    runner.stdc_runner = func;
+    return run(ThreadStyle::STDC, runner, arg, stack, size, detached);
+  }
+
+  // Return 0 on success or an error value on failure.
+  int run(ThreadStyle style, ThreadRunner runner, void *arg, void *stack,
+          size_t size, bool detached) {
     bool owned_stack = false;
     if (stack == nullptr) {
       if (size == 0)
@@ -139,19 +175,18 @@ template <typename ReturnType> struct Thread {
     // Likewise, the actual thread state information is also stored on the
     // stack memory.
     uintptr_t adjusted_stack = reinterpret_cast<uintptr_t>(stack) + size -
-                               sizeof(StartArgs<ReturnType>) -
-                               sizeof(ThreadAttributes<ReturnType>) -
+                               sizeof(StartArgs) - sizeof(ThreadAttributes) -
                                sizeof(cpp::Atomic<FutexWordType>);
     adjusted_stack &= ~(uintptr_t(STACK_ALIGNMENT) - 1);
 
-    auto *start_args =
-        reinterpret_cast<StartArgs<ReturnType> *>(adjusted_stack);
+    auto *start_args = reinterpret_cast<StartArgs *>(adjusted_stack);
     start_args->thread = this;
-    start_args->func = f;
+    start_args->runner = runner;
     start_args->arg = arg;
 
-    attrib = reinterpret_cast<ThreadAttributes<ReturnType> *>(
-        adjusted_stack + sizeof(StartArgs<ReturnType>));
+    attrib = reinterpret_cast<ThreadAttributes *>(adjusted_stack +
+                                                  sizeof(StartArgs));
+    attrib->style = style;
     attrib->detach_state =
         uint32_t(detached ? DetachState::DETACHED : DetachState::JOINABLE);
     attrib->stack = stack;
@@ -159,8 +194,7 @@ template <typename ReturnType> struct Thread {
     attrib->owned_stack = owned_stack;
 
     clear_tid = reinterpret_cast<cpp::Atomic<FutexWordType> *>(
-        adjusted_stack + sizeof(StartArgs<ReturnType>) +
-        sizeof(ThreadAttributes<ReturnType>));
+        adjusted_stack + sizeof(StartArgs) + sizeof(ThreadAttributes));
     clear_tid->val = CLEAR_TID_VALUE;
 
     // The clone syscall takes arguments in an architecture specific order.
@@ -203,10 +237,32 @@ template <typename ReturnType> struct Thread {
     return 0;
   }
 
-  int join(ReturnType *retval) {
+  int join(int *val) {
+    ThreadReturnValue retval;
+    int status = join(retval);
+    if (status != 0)
+      return status;
+    *val = retval.stdc_retval;
+    return 0;
+  }
+
+  int join(void **val) {
+    ThreadReturnValue retval;
+    int status = join(retval);
+    if (status != 0)
+      return status;
+    *val = retval.posix_retval;
+    return 0;
+  }
+
+  int join(ThreadReturnValue &retval) {
     wait();
 
-    *retval = attrib->retval;
+    if (attrib->style == ThreadStyle::POSIX)
+      retval.posix_retval = attrib->retval.posix_retval;
+    else
+      retval.stdc_retval = attrib->retval.stdc_retval;
+
     if (attrib->owned_stack)
       free_stack(attrib->stack, attrib->stack_size);
 
@@ -258,25 +314,6 @@ template <typename ReturnType> struct Thread {
   }
 };
 
-template <typename ReturnType>
-__attribute__((noinline)) void Thread<ReturnType>::start_thread() {
-  auto *start_args =
-      reinterpret_cast<StartArgs<ReturnType> *>(get_start_args_addr());
-  auto *thread = start_args->thread;
-  ReturnType retval = thread->attrib->retval =
-      start_args->func(start_args->arg);
-
-  uint32_t joinable_state = uint32_t(DetachState::JOINABLE);
-  if (!thread->attrib->detach_state.compare_exchange_strong(
-          joinable_state, uint32_t(DetachState::EXITING))) {
-    // Thread is detached so cleanup the resources.
-    if (thread->attrib->owned_stack)
-      free_stack(thread->attrib->stack, thread->attrib->stack_size);
-  }
-
-  __llvm_libc::syscall(SYS_exit, retval);
-}
-
 } // namespace __llvm_libc
 
 #endif // LLVM_LIBC_SRC_SUPPORT_THREADS_LINUX_THREAD_H

diff  --git a/libc/src/__support/threads/thread.h b/libc/src/__support/threads/thread.h
index 2d38c37d060e0..368df2bda9860 100644
--- a/libc/src/__support/threads/thread.h
+++ b/libc/src/__support/threads/thread.h
@@ -11,6 +11,19 @@
 
 #include <stddef.h>
 
+using ThreadRunnerPosix = void *(void *);
+using ThreadRunnerStdc = int(void *);
+
+union ThreadRunner {
+  ThreadRunnerPosix *posix_runner;
+  ThreadRunnerStdc *stdc_runner;
+};
+
+union ThreadReturnValue {
+  void *posix_retval;
+  int stdc_retval;
+};
+
 // The platform specific implemnetations are pulled via the following include.
 // The idea is for the platform implementation to implement a class named Thread
 // in the namespace __llvm_libc with the following properties:
@@ -19,22 +32,25 @@
 //
 // 2. Has a "run" method with the following signature:
 //
-//        int run(ThreadRunner *f, void *arg, void *stack, size_t size);
+//        int run(ThreadRunner runner, void *arg, void *stack, size_t size,
+//                bool detached);
 //
 //    Returns:
 //        0 on success and an error value on failure.
 //    Args:
+//        runner - The function to execute in the new thread.
 //        arg - The argument to be passed to the thread runner after the thread
 //              is created.
 //        stack - The stack to use for the thread.
 //        size - The stack size.
+//        detached - The detached state of the thread at startup.
 //
-//    If callers pass a non-null |stack| value, then it will assumed that
+//    If callers pass a non-null |stack| value, then it will be assumed that
 //      1. The clean up the stack memory is their responsibility
 //      2. The guard area is setup appropriately by the caller.
 //
 // 3. Has a "join" method with the following signature:
-//      ErrorOr<ReturnType> join();
+//      int join(ThreadReturnValue &retval);
 //    The "join" method should return 0 on success and set retcode to the
 //    threads return value. On failure, an appropriate errno value should be
 //    returned.

diff  --git a/libc/src/__support/threads/thread_attrib.h b/libc/src/__support/threads/thread_attrib.h
index 31d97acd3fb90..c4deabd4c5898 100644
--- a/libc/src/__support/threads/thread_attrib.h
+++ b/libc/src/__support/threads/thread_attrib.h
@@ -27,6 +27,8 @@ enum class DetachState : uint32_t {
   DETACHED = 0x33
 };
 
+enum class ThreadStyle : uint8_t { POSIX = 0x1, STDC = 0x2 };
+
 // Detach type is useful in testing the detach operation.
 enum class DetachType : int {
   // Indicates that the detach operation just set the detach state to DETACHED
@@ -44,7 +46,6 @@ enum class DetachType : int {
 //
 // Thread attributes are typically stored on the stack. So, we align as required
 // for the target architecture.
-template <typename ReturnType>
 struct alignas(STACK_ALIGNMENT) ThreadAttributes {
   // We want the "detach_state" attribute to be an atomic value as it could be
   // updated by one thread while the self thread is reading it. It is a tristate
@@ -66,12 +67,13 @@ struct alignas(STACK_ALIGNMENT) ThreadAttributes {
   //          exits.
   cpp::Atomic<uint32_t> detach_state;
   void *stack;                   // Pointer to the thread stack
+  void *tls;
   unsigned long long stack_size; // Size of the stack
   unsigned char owned_stack; // Indicates if the thread owns this stack memory
-  ReturnType retval;         // The return value of thread runner is saved here
   int tid;
+  ThreadStyle style;
+  ThreadReturnValue retval;
 };
-
 } // namespace __llvm_libc
 
 #endif // LLVM_LIBC_SRC_SUPPORT_THREADS_THREAD_ATTRIB_H

diff  --git a/libc/src/pthread/pthread_create.cpp b/libc/src/pthread/pthread_create.cpp
index bc945a93984e9..ec1e0e331ae04 100644
--- a/libc/src/pthread/pthread_create.cpp
+++ b/libc/src/pthread/pthread_create.cpp
@@ -16,14 +16,14 @@
 
 namespace __llvm_libc {
 
-static_assert(sizeof(pthread_t) == sizeof(__llvm_libc::Thread<int>),
-              "Mismatch between pthread_t and internal Thread<int>.");
+static_assert(sizeof(pthread_t) == sizeof(__llvm_libc::Thread),
+              "Mismatch between pthread_t and internal Thread.");
 
 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);
+  auto *thread = reinterpret_cast<__llvm_libc::Thread *>(th);
   int result = thread->run(func, arg, nullptr, 0);
   if (result != 0 && result != EPERM)
     return EAGAIN;

diff  --git a/libc/src/pthread/pthread_detach.cpp b/libc/src/pthread/pthread_detach.cpp
index c71b12fbdcda5..009438e16c4c3 100644
--- a/libc/src/pthread/pthread_detach.cpp
+++ b/libc/src/pthread/pthread_detach.cpp
@@ -15,11 +15,11 @@
 
 namespace __llvm_libc {
 
-static_assert(sizeof(pthread_t) == sizeof(__llvm_libc::Thread<void *>),
-              "Mismatch between pthread_t and internal Thread<void *>.");
+static_assert(sizeof(pthread_t) == sizeof(__llvm_libc::Thread),
+              "Mismatch between pthread_t and internal Thread.");
 
 LLVM_LIBC_FUNCTION(int, pthread_detach, (pthread_t th)) {
-  auto *thread = reinterpret_cast<Thread<void *> *>(&th);
+  auto *thread = reinterpret_cast<Thread *>(&th);
   thread->detach();
   return 0;
 }

diff  --git a/libc/src/pthread/pthread_join.cpp b/libc/src/pthread/pthread_join.cpp
index c3bf4adc6372e..0774d02680526 100644
--- a/libc/src/pthread/pthread_join.cpp
+++ b/libc/src/pthread/pthread_join.cpp
@@ -15,11 +15,11 @@
 
 namespace __llvm_libc {
 
-static_assert(sizeof(pthread_t) == sizeof(__llvm_libc::Thread<int>),
-              "Mismatch between pthread_t and internal Thread<int>.");
+static_assert(sizeof(pthread_t) == sizeof(__llvm_libc::Thread),
+              "Mismatch between pthread_t and internal Thread.");
 
 LLVM_LIBC_FUNCTION(int, pthread_join, (pthread_t th, void **retval)) {
-  auto *thread = reinterpret_cast<Thread<void *> *>(&th);
+  auto *thread = reinterpret_cast<Thread *>(&th);
   int result = thread->join(retval);
   return result;
 }

diff  --git a/libc/src/threads/thrd_create.cpp b/libc/src/threads/thrd_create.cpp
index 91b36a71f8239..9e81f0fdf78c1 100644
--- a/libc/src/threads/thrd_create.cpp
+++ b/libc/src/threads/thrd_create.cpp
@@ -15,12 +15,12 @@
 
 namespace __llvm_libc {
 
-static_assert(sizeof(thrd_t) == sizeof(__llvm_libc::Thread<int>),
-              "Mismatch between thrd_t and internal Thread<int>.");
+static_assert(sizeof(thrd_t) == sizeof(__llvm_libc::Thread),
+              "Mismatch between thrd_t and internal Thread.");
 
 LLVM_LIBC_FUNCTION(int, thrd_create,
                    (thrd_t * th, thrd_start_t func, void *arg)) {
-  auto *thread = reinterpret_cast<__llvm_libc::Thread<int> *>(th);
+  auto *thread = reinterpret_cast<__llvm_libc::Thread *>(th);
   int result = thread->run(func, arg, nullptr, 0);
   if (result == 0)
     return thrd_success;

diff  --git a/libc/src/threads/thrd_detach.cpp b/libc/src/threads/thrd_detach.cpp
index e3c4301709cdf..20c6540faa17c 100644
--- a/libc/src/threads/thrd_detach.cpp
+++ b/libc/src/threads/thrd_detach.cpp
@@ -14,11 +14,11 @@
 
 namespace __llvm_libc {
 
-static_assert(sizeof(thrd_t) == sizeof(__llvm_libc::Thread<int>),
-              "Mismatch between thrd_t and internal Thread<int>.");
+static_assert(sizeof(thrd_t) == sizeof(__llvm_libc::Thread),
+              "Mismatch between thrd_t and internal Thread.");
 
 LLVM_LIBC_FUNCTION(int, thrd_detach, (thrd_t th)) {
-  auto *thread = reinterpret_cast<Thread<int> *>(&th);
+  auto *thread = reinterpret_cast<Thread *>(&th);
   thread->detach();
   return 0;
 }

diff  --git a/libc/src/threads/thrd_join.cpp b/libc/src/threads/thrd_join.cpp
index fbdfa78fec2b9..4c3ecac34a4e9 100644
--- a/libc/src/threads/thrd_join.cpp
+++ b/libc/src/threads/thrd_join.cpp
@@ -14,11 +14,11 @@
 
 namespace __llvm_libc {
 
-static_assert(sizeof(thrd_t) == sizeof(__llvm_libc::Thread<int>),
-              "Mismatch between thrd_t and internal Thread<int>.");
+static_assert(sizeof(thrd_t) == sizeof(__llvm_libc::Thread),
+              "Mismatch between thrd_t and internal Thread.");
 
 LLVM_LIBC_FUNCTION(int, thrd_join, (thrd_t * th, int *retval)) {
-  auto *thread = reinterpret_cast<Thread<int> *>(th);
+  auto *thread = reinterpret_cast<Thread *>(th);
   int result = thread->join(retval);
   return result == 0 ? thrd_success : thrd_error;
 }


        


More information about the libc-commits mailing list