47 changes: 47 additions & 0 deletions libc/src/__support/threads/thread.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//===--- A platform independent indirection for a thread class --*- 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_SUPPORT_THREADS_THREAD_H
#define LLVM_LIBC_SRC_SUPPORT_THREADS_THREAD_H

#include <stddef.h>

// 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:
//
// 1. Has a defaulted default constructor (not a default constructor).
//
// 2. Has a "run" method with the following signature:
//
// int run(ThreadRunner *f, void *arg, void *stack, size_t size);
//
// Returns:
// 0 on success and an error value on failure.
// Args:
// 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.
//
// If callers pass a non-null |stack| value, then it will 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();
// 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.
//
// 4. Has an operator== for comparison between two threads.
#ifdef __unix__
#include "linux/thread.h"
#endif // __unix__

#endif // LLVM_LIBC_SRC_SUPPORT_THREADS_THREAD_H
29 changes: 29 additions & 0 deletions libc/src/__support/threads/thread_attrib.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//===--- A data type for thread attributes ----------------------*- 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_SUPPORT_THREADS_THREAD_ATTRIB_H
#define LLVM_LIBC_SRC_SUPPORT_THREADS_THREAD_ATTRIB_H

namespace __llvm_libc {

// A data type to hold common thread attributes which have to be stored as
// thread state. A platform thread implementation should store the attrib object
// in its Thread data structure. Note that this is different from public
// attribute types like pthread_attr which contain information which need not
// be saved as part of a thread's state. For example, the stack guard size.
template <typename ReturnType> struct ThreadAttributes {
void *stack; // Pointer to the thread stack
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;
};

} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_SUPPORT_THREADS_THREAD_ATTRIB_H
20 changes: 16 additions & 4 deletions libc/src/threads/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,28 @@ add_entrypoint_object(

add_entrypoint_object(
thrd_create
ALIAS
SRCS
thrd_create.cpp
HDRS
thrd_create.h
DEPENDS
.${LIBC_TARGET_OS}.thrd_create
libc.src.__support.threads.thread
libc.include.threads
COMPILE_OPTIONS
-O3
-fno-omit-frame-pointer # This allows us to sniff out the thread args from
# the new thread's stack reliably.
)

add_entrypoint_object(
thrd_join
ALIAS
SRCS
thrd_join.cpp
HDRS
thrd_join.h
DEPENDS
.${LIBC_TARGET_OS}.thrd_join
libc.include.threads
libc.src.__support.threads.thread
)

add_entrypoint_object(
Expand Down
37 changes: 1 addition & 36 deletions libc/src/threads/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,48 +17,13 @@ add_header_library(
HDRS
CndVar.h
Futex.h
Thread.h
DEPENDS
libc.include.sys_syscall
libc.include.threads
libc.src.__support.CPP.atomic
libc.src.__support.OSUtil.osutil
libc.src.__support.threads.mutex
)

add_entrypoint_object(
thrd_create
SRCS
thrd_create.cpp
HDRS
../thrd_create.h
DEPENDS
.threads_utils
libc.include.errno
libc.include.sys_mman
libc.include.sys_syscall
libc.include.threads
libc.src.__support.common
libc.src.__support.OSUtil.osutil
COMPILE_OPTIONS
-O3
-fno-omit-frame-pointer # This allows us to sniff out the thread args from
# the new thread's stack reliably.
)

add_entrypoint_object(
thrd_join
SRCS
thrd_join.cpp
HDRS
../thrd_join.h
DEPENDS
.threads_utils
libc.include.sys_syscall
libc.include.threads
libc.src.__support.CPP.atomic
libc.src.__support.common
libc.src.__support.OSUtil.osutil
libc.src.__support.threads.linux.futex_word_type
)

add_entrypoint_object(
Expand Down
3 changes: 2 additions & 1 deletion libc/src/threads/linux/CndVar.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "include/threads.h" // For values like thrd_success etc.
#include "src/__support/CPP/atomic.h"
#include "src/__support/OSUtil/syscall.h" // For syscall functions.
#include "src/__support/threads/linux/futex_word.h"
#include "src/__support/threads/mutex.h"

#include <linux/futex.h> // For futex operations.
Expand Down Expand Up @@ -106,7 +107,7 @@ struct CndVar {
if (waitq_front == nullptr)
waitq_back = nullptr;

qmtx.futex_word = Mutex::FutexWordType(Mutex::LockState::Free);
qmtx.futex_word = FutexWordType(Mutex::LockState::Free);

__llvm_libc::syscall(
SYS_futex, &qmtx.futex_word.val, FUTEX_WAKE_OP, 1, 1,
Expand Down
23 changes: 0 additions & 23 deletions libc/src/threads/linux/Thread.h

This file was deleted.

153 changes: 0 additions & 153 deletions libc/src/threads/linux/thrd_create.cpp

This file was deleted.

46 changes: 0 additions & 46 deletions libc/src/threads/linux/thrd_join.cpp

This file was deleted.

33 changes: 33 additions & 0 deletions libc/src/threads/thrd_create.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//===-- Linux implementation of the thrd_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 "src/threads/thrd_create.h"
#include "src/__support/common.h"
#include "src/__support/threads/thread.h"

#include <errno.h>
#include <threads.h> // For thrd_* type definitions.

namespace __llvm_libc {

static_assert(sizeof(thrd_t) == sizeof(__llvm_libc::Thread<int>),
"Mismatch between thrd_t and internal Thread<int>.");

LLVM_LIBC_FUNCTION(int, thrd_create,
(thrd_t * th, thrd_start_t func, void *arg)) {
auto *thread = reinterpret_cast<__llvm_libc::Thread<int> *>(th);
int result = thread->run(func, arg, nullptr, 0);
if (result == 0)
return thrd_success;
else if (result == ENOMEM)
return thrd_nomem;
else
return thrd_error;
}

} // namespace __llvm_libc
2 changes: 1 addition & 1 deletion libc/src/threads/thrd_create.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#ifndef LLVM_LIBC_SRC_THREADS_THRD_CREATE_H
#define LLVM_LIBC_SRC_THREADS_THRD_CREATE_H

#include "include/threads.h"
#include <threads.h>

namespace __llvm_libc {

Expand Down
30 changes: 30 additions & 0 deletions libc/src/threads/thrd_join.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//===-- Linux implementation of the thrd_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 "src/threads/thrd_join.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<int>),
"Mismatch between thrd_t and internal Thread<int>.");

LLVM_LIBC_FUNCTION(int, thrd_join, (thrd_t * th, int *retval)) {
auto *thread = reinterpret_cast<Thread<int> *>(th);
int result = thread->join();
if (result == 0) {
*retval = thread->return_value();
return thrd_success;
}
return thrd_error;
}

} // namespace __llvm_libc