diff options
author | Sam McCall <sammccall@google.com> | 2019-10-23 12:36:36 +0200 |
---|---|---|
committer | Sam McCall <sammccall@google.com> | 2019-10-23 12:48:38 +0200 |
commit | 40668abca4d307e02b33345cfdb7271549ff48d0 (patch) | |
tree | 8a5fcbf77abeb5a2d362182cef542215e742c0d4 /llvm/lib/Support/Unix/Threading.inc | |
parent | 4b63ca1379a8a6399c3d29560623ee832c818919 (diff) | |
download | llvm-40668abca4d307e02b33345cfdb7271549ff48d0.zip llvm-40668abca4d307e02b33345cfdb7271549ff48d0.tar.gz llvm-40668abca4d307e02b33345cfdb7271549ff48d0.tar.bz2 |
[Support] Add a way to run a function on a detached thread
This roughly mimics `std::thread(...).detach()` except it allows to
customize the stack size. Required for https://reviews.llvm.org/D50993.
I've decided against reusing the existing `llvm_execute_on_thread` because
it's not obvious what to do with the ownership of the passed
function/arguments:
1. If we pass possibly owning functions data to `llvm_execute_on_thread`,
we'll lose the ability to pass small non-owning non-allocating functions
for the joining case (as it's used now). Is it important enough?
2. If we use the non-owning interface in the new use case, we'll force
clients to transfer ownership to the spawned thread manually, but
similar code would still have to exist inside
`llvm_execute_on_thread(_async)` anyway (as we can't just pass the same
non-owning pointer to pthreads and Windows implementations, and would be
forced to wrap it in some structure, and deal with its ownership.
Patch by Dmitry Kozhevnikov!
Differential Revision: https://reviews.llvm.org/D51103
Diffstat (limited to 'llvm/lib/Support/Unix/Threading.inc')
-rw-r--r-- | llvm/lib/Support/Unix/Threading.inc | 63 |
1 files changed, 37 insertions, 26 deletions
diff --git a/llvm/lib/Support/Unix/Threading.inc b/llvm/lib/Support/Unix/Threading.inc index ed9a965..afb887f 100644 --- a/llvm/lib/Support/Unix/Threading.inc +++ b/llvm/lib/Support/Unix/Threading.inc @@ -10,6 +10,8 @@ // //===----------------------------------------------------------------------===// +#include "Unix.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" @@ -40,47 +42,56 @@ #include <unistd.h> // For syscall() #endif -namespace { - struct ThreadInfo { - void(*UserFn)(void *); - void *UserData; - }; +static void *threadFuncSync(void *Arg) { + SyncThreadInfo *TI = static_cast<SyncThreadInfo *>(Arg); + TI->UserFn(TI->UserData); + return nullptr; } -static void *ExecuteOnThread_Dispatch(void *Arg) { - ThreadInfo *TI = reinterpret_cast<ThreadInfo*>(Arg); - TI->UserFn(TI->UserData); +static void *threadFuncAsync(void *Arg) { + std::unique_ptr<AsyncThreadInfo> Info(static_cast<AsyncThreadInfo *>(Arg)); + (*Info)(); return nullptr; } -void llvm::llvm_execute_on_thread(void(*Fn)(void*), void *UserData, - unsigned RequestedStackSize) { - ThreadInfo Info = { Fn, UserData }; - pthread_attr_t Attr; - pthread_t Thread; +static void +llvm_execute_on_thread_impl(void *(*ThreadFunc)(void *), void *Arg, + llvm::Optional<unsigned> StackSizeInBytes, + JoiningPolicy JP) { + int errnum; // Construct the attributes object. - if (::pthread_attr_init(&Attr) != 0) - return; + pthread_attr_t Attr; + if ((errnum = ::pthread_attr_init(&Attr)) != 0) { + ReportErrnumFatal("pthread_attr_init failed", errnum); + } + + auto AttrGuard = llvm::make_scope_exit([&] { + if ((errnum = ::pthread_attr_destroy(&Attr)) != 0) { + ReportErrnumFatal("pthread_attr_destroy failed", errnum); + } + }); // Set the requested stack size, if given. - if (RequestedStackSize != 0) { - if (::pthread_attr_setstacksize(&Attr, RequestedStackSize) != 0) - goto error; + if (StackSizeInBytes) { + if ((errnum = ::pthread_attr_setstacksize(&Attr, *StackSizeInBytes)) != 0) { + ReportErrnumFatal("pthread_attr_setstacksize failed", errnum); + } } // Construct and execute the thread. - if (::pthread_create(&Thread, &Attr, ExecuteOnThread_Dispatch, &Info) != 0) - goto error; - - // Wait for the thread and clean up. - ::pthread_join(Thread, nullptr); + pthread_t Thread; + if ((errnum = ::pthread_create(&Thread, &Attr, ThreadFunc, Arg)) != 0) + ReportErrnumFatal("pthread_create failed", errnum); -error: - ::pthread_attr_destroy(&Attr); + if (JP == JoiningPolicy::Join) { + // Wait for the thread + if ((errnum = ::pthread_join(Thread, nullptr)) != 0) { + ReportErrnumFatal("pthread_join failed", errnum); + } + } } - uint64_t llvm::get_threadid() { #if defined(__APPLE__) // Calling "mach_thread_self()" bumps the reference count on the thread |