1139825Simp//===-- llvm/Support/Threading.cpp- Control multithreading mode --*- C++ -*-==// 21541Srgrimes// 31541Srgrimes// The LLVM Compiler Infrastructure 41541Srgrimes// 51541Srgrimes// This file is distributed under the University of Illinois Open Source 61541Srgrimes// License. See LICENSE.TXT for details. 71541Srgrimes// 81541Srgrimes//===----------------------------------------------------------------------===// 91541Srgrimes// 101541Srgrimes// This file implements llvm_start_multithreaded() and friends. 111541Srgrimes// 121541Srgrimes//===----------------------------------------------------------------------===// 131541Srgrimes 141541Srgrimes#include "llvm/Support/Threading.h" 151541Srgrimes#include "llvm/Config/config.h" 161541Srgrimes#include "llvm/Support/Atomic.h" 171541Srgrimes#include "llvm/Support/Mutex.h" 181541Srgrimes#include <cassert> 191541Srgrimes 201541Srgrimesusing namespace llvm; 211541Srgrimes 221541Srgrimesstatic bool multithreaded_mode = false; 231541Srgrimes 241541Srgrimesstatic sys::Mutex* global_lock = 0; 251541Srgrimes 261541Srgrimesbool llvm::llvm_start_multithreaded() { 271541Srgrimes#if LLVM_ENABLE_THREADS != 0 281541Srgrimes assert(!multithreaded_mode && "Already multithreaded!"); 291541Srgrimes multithreaded_mode = true; 301541Srgrimes global_lock = new sys::Mutex(true); 311541Srgrimes 32116226Sobrien // We fence here to ensure that all initialization is complete BEFORE we 33116226Sobrien // return from llvm_start_multithreaded(). 34116226Sobrien sys::MemoryFence(); 351541Srgrimes return true; 361541Srgrimes#else 371541Srgrimes return false; 3876166Smarkm#endif 3976166Smarkm} 4076166Smarkm 4134924Sbdevoid llvm::llvm_stop_multithreaded() { 42248084Sattilio#if LLVM_ENABLE_THREADS != 0 4374927Sjhb assert(multithreaded_mode && "Not currently multithreaded!"); 4412662Sdg 4593823Sdillon // We fence here to insure that all threaded operations are complete BEFORE we 4612662Sdg // return from llvm_stop_multithreaded(). 471541Srgrimes sys::MemoryFence(); 4840794Speter 4912726Sbde multithreaded_mode = false; 5012662Sdg delete global_lock; 5112662Sdg#endif 5212662Sdg} 5312662Sdg 541541Srgrimesbool llvm::llvm_is_multithreaded() { 551541Srgrimes return multithreaded_mode; 56170170Sattilio} 571541Srgrimes 5862622Sjhbvoid llvm::llvm_acquire_global_lock() { 59228449Seadler if (multithreaded_mode) global_lock->acquire(); 6062622Sjhb} 61228449Seadler 6262622Sjhbvoid llvm::llvm_release_global_lock() { 63228449Seadler if (multithreaded_mode) global_lock->release(); 6462622Sjhb} 65228449Seadler 6662622Sjhb#if LLVM_ENABLE_THREADS != 0 && defined(HAVE_PTHREAD_H) 67228449Seadler#include <pthread.h> 6862622Sjhb 69228449Seadlerstruct ThreadInfo { 7062622Sjhb void (*UserFn)(void *); 71228449Seadler void *UserData; 7262622Sjhb}; 73228449Seadlerstatic void *ExecuteOnThread_Dispatch(void *Arg) { 7412286Sphk ThreadInfo *TI = reinterpret_cast<ThreadInfo*>(Arg); 75136404Speter TI->UserFn(TI->UserData); 76136404Speter return 0; 77136404Speter} 78181887Sjulian 79136404Spetervoid llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData, 80136404Speter unsigned RequestedStackSize) { 811541Srgrimes ThreadInfo Info = { Fn, UserData }; 82136404Speter pthread_attr_t Attr; 83136404Speter pthread_t Thread; 84136404Speter 85136404Speter // Construct the attributes object. 86136404Speter if (::pthread_attr_init(&Attr) != 0) 87136404Speter return; 88136404Speter 89136404Speter // Set the requested stack size, if given. 90136404Speter if (RequestedStackSize != 0) { 91136404Speter if (::pthread_attr_setstacksize(&Attr, RequestedStackSize) != 0) 92187658Sjhb goto error; 93187658Sjhb } 94187658Sjhb 95136404Speter // Construct and execute the thread. 9612286Sphk if (::pthread_create(&Thread, &Attr, ExecuteOnThread_Dispatch, &Info) != 0) 9762573Sphk goto error; 981541Srgrimes 9912286Sphk // Wait for the thread and clean up. 100164437Sru ::pthread_join(Thread, 0); 10112286Sphk 10212286Sphk error: 10312286Sphk ::pthread_attr_destroy(&Attr); 1041541Srgrimes} 10599072Sjulian#elif LLVM_ENABLE_THREADS!=0 && defined(LLVM_ON_WIN32) 106159054Stegge#include "Windows/Windows.h" 1071541Srgrimes#include <process.h> 108164437Sru 1091541Srgrimesstruct ThreadInfo { 1101541Srgrimes void (*func)(void*); 1111541Srgrimes void *param; 11295112Salc}; 113108551Salc 114248084Sattiliostatic unsigned __stdcall ThreadCallback(void *param) { 115124083Salc struct ThreadInfo *info = reinterpret_cast<struct ThreadInfo *>(param); 116124083Salc info->func(info->param); 117124083Salc 118124083Salc return 0; 119124083Salc} 120124083Salc 121124083Salcvoid llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData, 12238517Sdfr unsigned RequestedStackSize) { 123248084Sattilio struct ThreadInfo param = { Fn, UserData }; 124108551Salc 12595112Salc HANDLE hThread = (HANDLE)::_beginthreadex(NULL, 1261541Srgrimes RequestedStackSize, ThreadCallback, 1271541Srgrimes ¶m, 0, NULL); 1281541Srgrimes 12974927Sjhb if (hThread) { 13083366Sjulian // We actually don't care whether the wait succeeds or fails, in 1311541Srgrimes // the same way we don't care whether the pthread_join call succeeds 1321541Srgrimes // or fails. There's not much we could do if this were to fail. But 133177368Sjeff // on success, this call will wait until the thread finishes executing 13499072Sjulian // before returning. 13599072Sjulian (void)::WaitForSingleObject(hThread, INFINITE); 136177368Sjeff ::CloseHandle(hThread); 1371541Srgrimes } 1381541Srgrimes} 13999072Sjulian#else 14099072Sjulian// Support for non-Win32, non-pthread implementation. 141170307Sjeffvoid llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData, 14299072Sjulian unsigned RequestedStackSize) { 143103216Sjulian (void) RequestedStackSize; 144177085Sjeff Fn(UserData); 145164437Sru} 146177085Sjeff 147177085Sjeff#endif 148177085Sjeff