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