Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/llvm/llvm-project.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
authorSiva Chandra <sivachandra@google.com>2022-03-31 09:44:57 +0300
committerSiva Chandra <sivachandra@google.com>2022-03-31 18:42:07 +0300
commit97417e0300719f4bc9e8599ecc68ef97170524f8 (patch)
tree46e06cfe3ff3da72646495241e9bbbf02fee6acf /libc
parent4dfec37037f5f96db8898b79601c7a1d19177027 (diff)
[libc] Enable threads.h functions on aarch64.
Reviewed By: lntue Differential Revision: https://reviews.llvm.org/D122788
Diffstat (limited to 'libc')
-rw-r--r--libc/config/linux/aarch64/entrypoints.txt18
-rw-r--r--libc/src/threads/linux/CMakeLists.txt11
-rw-r--r--libc/src/threads/linux/Thread.h2
-rw-r--r--libc/src/threads/linux/thrd_create.cpp50
-rw-r--r--libc/src/threads/linux/x86_64/thread_start_args.h.in24
5 files changed, 61 insertions, 44 deletions
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index cd2b52f18a90..72919c1b81e4 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -213,6 +213,24 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.sys.mman.munmap
)
+if(LLVM_LIBC_FULL_BUILD)
+ list(APPEND TARGET_LIBC_ENTRYPOINTS
+ # threads.h entrypoints
+ libc.src.threads.call_once
+ libc.src.threads.cnd_broadcast
+ libc.src.threads.cnd_destroy
+ libc.src.threads.cnd_init
+ libc.src.threads.cnd_signal
+ libc.src.threads.cnd_wait
+ 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_join
+ )
+endif()
+
set(TARGET_LLVMLIBC_ENTRYPOINTS
${TARGET_LIBC_ENTRYPOINTS}
${TARGET_LIBM_ENTRYPOINTS}
diff --git a/libc/src/threads/linux/CMakeLists.txt b/libc/src/threads/linux/CMakeLists.txt
index 6706c422934b..0941711432c2 100644
--- a/libc/src/threads/linux/CMakeLists.txt
+++ b/libc/src/threads/linux/CMakeLists.txt
@@ -1,13 +1,3 @@
-add_gen_header(
- thread_start_args_h
- DEF_FILE thread_start_args.h.def
- GEN_HDR thread_start_args.h
- PARAMS
- thread_start_args=${LIBC_TARGET_ARCHITECTURE}/thread_start_args.h.in
- DATA_FILES
- ${LIBC_TARGET_ARCHITECTURE}/thread_start_args.h.in
-)
-
add_entrypoint_object(
call_once
SRCS
@@ -29,7 +19,6 @@ add_header_library(
Futex.h
Thread.h
DEPENDS
- .thread_start_args_h
libc.include.sys_syscall
libc.include.threads
libc.src.__support.CPP.atomic
diff --git a/libc/src/threads/linux/Thread.h b/libc/src/threads/linux/Thread.h
index a14ed49c33b1..de58ae4c64c6 100644
--- a/libc/src/threads/linux/Thread.h
+++ b/libc/src/threads/linux/Thread.h
@@ -9,8 +9,6 @@
#ifndef LLVM_LIBC_SRC_THREADS_LINUX_THREAD_UTILS_H
#define LLVM_LIBC_SRC_THREADS_LINUX_THREAD_UTILS_H
-#include "thread_start_args.h"
-
#include <stdint.h>
namespace __llvm_libc {
diff --git a/libc/src/threads/linux/thrd_create.cpp b/libc/src/threads/linux/thrd_create.cpp
index 34b50399b98c..e89337471fca 100644
--- a/libc/src/threads/linux/thrd_create.cpp
+++ b/libc/src/threads/linux/thrd_create.cpp
@@ -13,6 +13,7 @@
#include "include/sys/syscall.h" // For syscall numbers.
#include "include/threads.h" // For thrd_* type definitions.
#include "src/__support/OSUtil/syscall.h" // For syscall function.
+#include "src/__support/architectures.h"
#include "src/__support/common.h"
#include "src/errno/llvmlibc_errno.h"
#include "src/sys/mman/mmap.h"
@@ -25,12 +26,31 @@
namespace __llvm_libc {
-struct StartArgs {
+// 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 different architecture in future requires higher alignment, then we
+// can add a platform specific alignment spec.
+struct alignas(16) StartArgs {
thrd_t *thread;
thrd_start_t func;
void *arg;
};
+__attribute__((always_inline)) inline uintptr_t get_start_args_addr() {
+ // NOTE: For __builtin_frame_address to work reliably across compilers,
+ // architectures and various optimization levels, the TU including this file
+ // should be compiled with -fno-omit-frame-pointer.
+ return reinterpret_cast<uintptr_t>(__builtin_frame_address(0))
+ // The x86_64 call instruction pushes resume address on to the stack.
+ // Next, The x86_64 SysV ABI requires that the frame pointer be pushed
+ // on to the stack. Similarly on aarch64, previous frame pointer and
+ // the value of the link register are pushed on to the stack. So, in
+ // both these cases, we have to step past two 64-bit values to get
+ // to the start args.
+ + sizeof(uintptr_t) * 2;
+}
+
static __attribute__((noinline)) void start_thread() {
StartArgs *start_args = reinterpret_cast<StartArgs *>(get_start_args_addr());
__llvm_libc::syscall(SYS_exit, start_args->thread->__retval =
@@ -79,13 +99,29 @@ LLVM_LIBC_FUNCTION(int, thrd_create,
start_args->func = func;
start_args->arg = arg;
- // TODO: The arguments to the clone syscall below is correct for x86_64
- // but it might differ for other architectures. So, make this call
- // architecture independent. May be implement a glibc like wrapper for clone
- // and use it here.
+ // The clone syscall takes arguments in an architecture specific order.
+ // Also, we want the result of the syscall to be in a register as the child
+ // thread gets a completely different stack after it is created. The stack
+ // variables from this function will not be availalbe to the child thread.
+#ifdef LLVM_LIBC_ARCH_X86_64
long register clone_result asm("rax");
- clone_result = __llvm_libc::syscall(SYS_clone, clone_flags, adjusted_stack,
- &thread->__tid, clear_tid_address, 0);
+ clone_result = __llvm_libc::syscall(
+ SYS_clone, clone_flags, adjusted_stack,
+ &thread->__tid, // The address where the child tid is written
+ clear_tid_address, // The futex where the child thread status is signalled
+ 0 // Set TLS to null for now.
+ );
+#elif defined(LLVM_LIBC_ARCH_AARCH64)
+ long register clone_result asm("x0");
+ clone_result = __llvm_libc::syscall(
+ SYS_clone, clone_flags, adjusted_stack,
+ &thread->__tid, // The address where the child tid is written
+ 0, // Set TLS to null for now.
+ clear_tid_address // The futex where the child thread status is signalled
+ );
+#else
+#error "Unsupported architecture for the clone syscall."
+#endif
if (clone_result == 0) {
start_thread();
diff --git a/libc/src/threads/linux/x86_64/thread_start_args.h.in b/libc/src/threads/linux/x86_64/thread_start_args.h.in
deleted file mode 100644
index 36365b98bb21..000000000000
--- a/libc/src/threads/linux/x86_64/thread_start_args.h.in
+++ /dev/null
@@ -1,24 +0,0 @@
-//===- x86_64 implementation of the get_start_args_addr 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
-//
-//===----------------------------------------------------------------------===//
-
-%%begin()
-
-namespace __llvm_libc {
-
-__attribute__((always_inline)) inline uintptr_t get_start_args_addr() {
- // NOTE: For __builtin_frame_address to work reliably across compilers,
- // architectures and various optimization levels, the TU including this file
- // should be compiled with -fno-omit-frame-pointer.
- return reinterpret_cast<uintptr_t>(__builtin_frame_address(0)) +
- // The x86_64 call instruction pushes resume address on to the stack.
- // Next, The x86_64 SysV ABI also pushes the frame pointer on the
- // stack. Hence, we look past these items to get to the start args.
- sizeof(uintptr_t) * 2;
-}
-
-} // namespace __llvm_libc