xref: /aosp_15_r20/external/llvm/lib/Support/Threading.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- llvm/Support/Threading.cpp- Control multithreading mode --*- C++ -*-==//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file defines helper functions for running LLVM in a multi-threaded
11*9880d681SAndroid Build Coastguard Worker // environment.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker 
15*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Threading.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/Config/config.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Atomic.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Mutex.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/thread.h"
20*9880d681SAndroid Build Coastguard Worker #include <cassert>
21*9880d681SAndroid Build Coastguard Worker 
22*9880d681SAndroid Build Coastguard Worker using namespace llvm;
23*9880d681SAndroid Build Coastguard Worker 
llvm_is_multithreaded()24*9880d681SAndroid Build Coastguard Worker bool llvm::llvm_is_multithreaded() {
25*9880d681SAndroid Build Coastguard Worker #if LLVM_ENABLE_THREADS != 0
26*9880d681SAndroid Build Coastguard Worker   return true;
27*9880d681SAndroid Build Coastguard Worker #else
28*9880d681SAndroid Build Coastguard Worker   return false;
29*9880d681SAndroid Build Coastguard Worker #endif
30*9880d681SAndroid Build Coastguard Worker }
31*9880d681SAndroid Build Coastguard Worker 
32*9880d681SAndroid Build Coastguard Worker #if LLVM_ENABLE_THREADS != 0 && defined(HAVE_PTHREAD_H)
33*9880d681SAndroid Build Coastguard Worker #include <pthread.h>
34*9880d681SAndroid Build Coastguard Worker 
35*9880d681SAndroid Build Coastguard Worker struct ThreadInfo {
36*9880d681SAndroid Build Coastguard Worker   void (*UserFn)(void *);
37*9880d681SAndroid Build Coastguard Worker   void *UserData;
38*9880d681SAndroid Build Coastguard Worker };
ExecuteOnThread_Dispatch(void * Arg)39*9880d681SAndroid Build Coastguard Worker static void *ExecuteOnThread_Dispatch(void *Arg) {
40*9880d681SAndroid Build Coastguard Worker   ThreadInfo *TI = reinterpret_cast<ThreadInfo*>(Arg);
41*9880d681SAndroid Build Coastguard Worker   TI->UserFn(TI->UserData);
42*9880d681SAndroid Build Coastguard Worker   return nullptr;
43*9880d681SAndroid Build Coastguard Worker }
44*9880d681SAndroid Build Coastguard Worker 
llvm_execute_on_thread(void (* Fn)(void *),void * UserData,unsigned RequestedStackSize)45*9880d681SAndroid Build Coastguard Worker void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
46*9880d681SAndroid Build Coastguard Worker                                   unsigned RequestedStackSize) {
47*9880d681SAndroid Build Coastguard Worker   ThreadInfo Info = { Fn, UserData };
48*9880d681SAndroid Build Coastguard Worker   pthread_attr_t Attr;
49*9880d681SAndroid Build Coastguard Worker   pthread_t Thread;
50*9880d681SAndroid Build Coastguard Worker 
51*9880d681SAndroid Build Coastguard Worker   // Construct the attributes object.
52*9880d681SAndroid Build Coastguard Worker   if (::pthread_attr_init(&Attr) != 0)
53*9880d681SAndroid Build Coastguard Worker     return;
54*9880d681SAndroid Build Coastguard Worker 
55*9880d681SAndroid Build Coastguard Worker   // Set the requested stack size, if given.
56*9880d681SAndroid Build Coastguard Worker   if (RequestedStackSize != 0) {
57*9880d681SAndroid Build Coastguard Worker     if (::pthread_attr_setstacksize(&Attr, RequestedStackSize) != 0)
58*9880d681SAndroid Build Coastguard Worker       goto error;
59*9880d681SAndroid Build Coastguard Worker   }
60*9880d681SAndroid Build Coastguard Worker 
61*9880d681SAndroid Build Coastguard Worker   // Construct and execute the thread.
62*9880d681SAndroid Build Coastguard Worker   if (::pthread_create(&Thread, &Attr, ExecuteOnThread_Dispatch, &Info) != 0)
63*9880d681SAndroid Build Coastguard Worker     goto error;
64*9880d681SAndroid Build Coastguard Worker 
65*9880d681SAndroid Build Coastguard Worker   // Wait for the thread and clean up.
66*9880d681SAndroid Build Coastguard Worker   ::pthread_join(Thread, nullptr);
67*9880d681SAndroid Build Coastguard Worker 
68*9880d681SAndroid Build Coastguard Worker  error:
69*9880d681SAndroid Build Coastguard Worker   ::pthread_attr_destroy(&Attr);
70*9880d681SAndroid Build Coastguard Worker }
71*9880d681SAndroid Build Coastguard Worker #elif LLVM_ENABLE_THREADS!=0 && defined(LLVM_ON_WIN32)
72*9880d681SAndroid Build Coastguard Worker #include "Windows/WindowsSupport.h"
73*9880d681SAndroid Build Coastguard Worker #include <process.h>
74*9880d681SAndroid Build Coastguard Worker 
75*9880d681SAndroid Build Coastguard Worker // Windows will at times define MemoryFence.
76*9880d681SAndroid Build Coastguard Worker #ifdef MemoryFence
77*9880d681SAndroid Build Coastguard Worker #undef MemoryFence
78*9880d681SAndroid Build Coastguard Worker #endif
79*9880d681SAndroid Build Coastguard Worker 
80*9880d681SAndroid Build Coastguard Worker struct ThreadInfo {
81*9880d681SAndroid Build Coastguard Worker   void (*func)(void*);
82*9880d681SAndroid Build Coastguard Worker   void *param;
83*9880d681SAndroid Build Coastguard Worker };
84*9880d681SAndroid Build Coastguard Worker 
ThreadCallback(void * param)85*9880d681SAndroid Build Coastguard Worker static unsigned __stdcall ThreadCallback(void *param) {
86*9880d681SAndroid Build Coastguard Worker   struct ThreadInfo *info = reinterpret_cast<struct ThreadInfo *>(param);
87*9880d681SAndroid Build Coastguard Worker   info->func(info->param);
88*9880d681SAndroid Build Coastguard Worker 
89*9880d681SAndroid Build Coastguard Worker   return 0;
90*9880d681SAndroid Build Coastguard Worker }
91*9880d681SAndroid Build Coastguard Worker 
llvm_execute_on_thread(void (* Fn)(void *),void * UserData,unsigned RequestedStackSize)92*9880d681SAndroid Build Coastguard Worker void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
93*9880d681SAndroid Build Coastguard Worker                                   unsigned RequestedStackSize) {
94*9880d681SAndroid Build Coastguard Worker   struct ThreadInfo param = { Fn, UserData };
95*9880d681SAndroid Build Coastguard Worker 
96*9880d681SAndroid Build Coastguard Worker   HANDLE hThread = (HANDLE)::_beginthreadex(NULL,
97*9880d681SAndroid Build Coastguard Worker                                             RequestedStackSize, ThreadCallback,
98*9880d681SAndroid Build Coastguard Worker                                             &param, 0, NULL);
99*9880d681SAndroid Build Coastguard Worker 
100*9880d681SAndroid Build Coastguard Worker   if (hThread) {
101*9880d681SAndroid Build Coastguard Worker     // We actually don't care whether the wait succeeds or fails, in
102*9880d681SAndroid Build Coastguard Worker     // the same way we don't care whether the pthread_join call succeeds
103*9880d681SAndroid Build Coastguard Worker     // or fails.  There's not much we could do if this were to fail. But
104*9880d681SAndroid Build Coastguard Worker     // on success, this call will wait until the thread finishes executing
105*9880d681SAndroid Build Coastguard Worker     // before returning.
106*9880d681SAndroid Build Coastguard Worker     (void)::WaitForSingleObject(hThread, INFINITE);
107*9880d681SAndroid Build Coastguard Worker     ::CloseHandle(hThread);
108*9880d681SAndroid Build Coastguard Worker   }
109*9880d681SAndroid Build Coastguard Worker }
110*9880d681SAndroid Build Coastguard Worker #else
111*9880d681SAndroid Build Coastguard Worker // Support for non-Win32, non-pthread implementation.
llvm_execute_on_thread(void (* Fn)(void *),void * UserData,unsigned RequestedStackSize)112*9880d681SAndroid Build Coastguard Worker void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
113*9880d681SAndroid Build Coastguard Worker                                   unsigned RequestedStackSize) {
114*9880d681SAndroid Build Coastguard Worker   (void) RequestedStackSize;
115*9880d681SAndroid Build Coastguard Worker   Fn(UserData);
116*9880d681SAndroid Build Coastguard Worker }
117*9880d681SAndroid Build Coastguard Worker 
118*9880d681SAndroid Build Coastguard Worker #endif
119