LLVM API Documentation

Threading.cpp
Go to the documentation of this file.
00001 //===-- llvm/Support/Threading.cpp- Control multithreading mode --*- C++ -*-==//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements llvm_start_multithreaded() and friends.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "llvm/Support/Threading.h"
00015 #include "llvm/Config/config.h"
00016 #include "llvm/Support/Atomic.h"
00017 #include "llvm/Support/Mutex.h"
00018 #include <cassert>
00019 
00020 using namespace llvm;
00021 
00022 static bool multithreaded_mode = false;
00023 
00024 static sys::Mutex* global_lock = 0;
00025 
00026 bool llvm::llvm_start_multithreaded() {
00027 #if LLVM_ENABLE_THREADS != 0
00028   assert(!multithreaded_mode && "Already multithreaded!");
00029   multithreaded_mode = true;
00030   global_lock = new sys::Mutex(true);
00031 
00032   // We fence here to ensure that all initialization is complete BEFORE we
00033   // return from llvm_start_multithreaded().
00034   sys::MemoryFence();
00035   return true;
00036 #else
00037   return false;
00038 #endif
00039 }
00040 
00041 void llvm::llvm_stop_multithreaded() {
00042 #if LLVM_ENABLE_THREADS != 0
00043   assert(multithreaded_mode && "Not currently multithreaded!");
00044 
00045   // We fence here to insure that all threaded operations are complete BEFORE we
00046   // return from llvm_stop_multithreaded().
00047   sys::MemoryFence();
00048 
00049   multithreaded_mode = false;
00050   delete global_lock;
00051 #endif
00052 }
00053 
00054 bool llvm::llvm_is_multithreaded() {
00055   return multithreaded_mode;
00056 }
00057 
00058 void llvm::llvm_acquire_global_lock() {
00059   if (multithreaded_mode) global_lock->acquire();
00060 }
00061 
00062 void llvm::llvm_release_global_lock() {
00063   if (multithreaded_mode) global_lock->release();
00064 }
00065 
00066 #if LLVM_ENABLE_THREADS != 0 && defined(HAVE_PTHREAD_H)
00067 #include <pthread.h>
00068 
00069 struct ThreadInfo {
00070   void (*UserFn)(void *);
00071   void *UserData;
00072 };
00073 static void *ExecuteOnThread_Dispatch(void *Arg) {
00074   ThreadInfo *TI = reinterpret_cast<ThreadInfo*>(Arg);
00075   TI->UserFn(TI->UserData);
00076   return 0;
00077 }
00078 
00079 void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
00080                                   unsigned RequestedStackSize) {
00081   ThreadInfo Info = { Fn, UserData };
00082   pthread_attr_t Attr;
00083   pthread_t Thread;
00084 
00085   // Construct the attributes object.
00086   if (::pthread_attr_init(&Attr) != 0)
00087     return;
00088 
00089   // Set the requested stack size, if given.
00090   if (RequestedStackSize != 0) {
00091     if (::pthread_attr_setstacksize(&Attr, RequestedStackSize) != 0)
00092       goto error;
00093   }
00094 
00095   // Construct and execute the thread.
00096   if (::pthread_create(&Thread, &Attr, ExecuteOnThread_Dispatch, &Info) != 0)
00097     goto error;
00098 
00099   // Wait for the thread and clean up.
00100   ::pthread_join(Thread, 0);
00101 
00102  error:
00103   ::pthread_attr_destroy(&Attr);
00104 }
00105 #elif LLVM_ENABLE_THREADS!=0 && defined(LLVM_ON_WIN32)
00106 #include "Windows/Windows.h"
00107 #include <process.h>
00108 
00109 struct ThreadInfo {
00110   void (*func)(void*);
00111   void *param;
00112 };
00113 
00114 static unsigned __stdcall ThreadCallback(void *param) {
00115   struct ThreadInfo *info = reinterpret_cast<struct ThreadInfo *>(param);
00116   info->func(info->param);
00117 
00118   return 0;
00119 }
00120 
00121 void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
00122                                   unsigned RequestedStackSize) {
00123   struct ThreadInfo param = { Fn, UserData };
00124 
00125   HANDLE hThread = (HANDLE)::_beginthreadex(NULL,
00126                                             RequestedStackSize, ThreadCallback,
00127                                             &param, 0, NULL);
00128 
00129   if (hThread) {
00130     // We actually don't care whether the wait succeeds or fails, in
00131     // the same way we don't care whether the pthread_join call succeeds
00132     // or fails.  There's not much we could do if this were to fail. But
00133     // on success, this call will wait until the thread finishes executing
00134     // before returning.
00135     (void)::WaitForSingleObject(hThread, INFINITE);
00136     ::CloseHandle(hThread);
00137   }
00138 }
00139 #else
00140 // Support for non-Win32, non-pthread implementation.
00141 void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
00142                                   unsigned RequestedStackSize) {
00143   (void) RequestedStackSize;
00144   Fn(UserData);
00145 }
00146 
00147 #endif