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 defines helper functions for running LLVM in a multi-threaded
00011 // environment.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "llvm/Support/Threading.h"
00016 #include "llvm/Config/config.h"
00017 #include "llvm/Support/Atomic.h"
00018 #include "llvm/Support/Mutex.h"
00019 #include <cassert>
00020 
00021 using namespace llvm;
00022 
00023 bool llvm::llvm_is_multithreaded() {
00024 #if LLVM_ENABLE_THREADS != 0
00025   return true;
00026 #else
00027   return false;
00028 #endif
00029 }
00030 
00031 #if LLVM_ENABLE_THREADS != 0 && defined(HAVE_PTHREAD_H)
00032 #include <pthread.h>
00033 
00034 struct ThreadInfo {
00035   void (*UserFn)(void *);
00036   void *UserData;
00037 };
00038 static void *ExecuteOnThread_Dispatch(void *Arg) {
00039   ThreadInfo *TI = reinterpret_cast<ThreadInfo*>(Arg);
00040   TI->UserFn(TI->UserData);
00041   return nullptr;
00042 }
00043 
00044 void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
00045                                   unsigned RequestedStackSize) {
00046   ThreadInfo Info = { Fn, UserData };
00047   pthread_attr_t Attr;
00048   pthread_t Thread;
00049 
00050   // Construct the attributes object.
00051   if (::pthread_attr_init(&Attr) != 0)
00052     return;
00053 
00054   // Set the requested stack size, if given.
00055   if (RequestedStackSize != 0) {
00056     if (::pthread_attr_setstacksize(&Attr, RequestedStackSize) != 0)
00057       goto error;
00058   }
00059 
00060   // Construct and execute the thread.
00061   if (::pthread_create(&Thread, &Attr, ExecuteOnThread_Dispatch, &Info) != 0)
00062     goto error;
00063 
00064   // Wait for the thread and clean up.
00065   ::pthread_join(Thread, nullptr);
00066 
00067  error:
00068   ::pthread_attr_destroy(&Attr);
00069 }
00070 #elif LLVM_ENABLE_THREADS!=0 && defined(LLVM_ON_WIN32)
00071 #include "Windows/WindowsSupport.h"
00072 #include <process.h>
00073 
00074 struct ThreadInfo {
00075   void (*func)(void*);
00076   void *param;
00077 };
00078 
00079 static unsigned __stdcall ThreadCallback(void *param) {
00080   struct ThreadInfo *info = reinterpret_cast<struct ThreadInfo *>(param);
00081   info->func(info->param);
00082 
00083   return 0;
00084 }
00085 
00086 void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
00087                                   unsigned RequestedStackSize) {
00088   struct ThreadInfo param = { Fn, UserData };
00089 
00090   HANDLE hThread = (HANDLE)::_beginthreadex(NULL,
00091                                             RequestedStackSize, ThreadCallback,
00092                                             &param, 0, NULL);
00093 
00094   if (hThread) {
00095     // We actually don't care whether the wait succeeds or fails, in
00096     // the same way we don't care whether the pthread_join call succeeds
00097     // or fails.  There's not much we could do if this were to fail. But
00098     // on success, this call will wait until the thread finishes executing
00099     // before returning.
00100     (void)::WaitForSingleObject(hThread, INFINITE);
00101     ::CloseHandle(hThread);
00102   }
00103 }
00104 #else
00105 // Support for non-Win32, non-pthread implementation.
00106 void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
00107                                   unsigned RequestedStackSize) {
00108   (void) RequestedStackSize;
00109   Fn(UserData);
00110 }
00111 
00112 #endif