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                                            &param, 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