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 <cassert>
20
21using namespace llvm;
22
23bool llvm::llvm_is_multithreaded() {
24#if LLVM_ENABLE_THREADS != 0
25  return true;
26#else
27  return false;
28#endif
29}
30
31#if LLVM_ENABLE_THREADS != 0 && defined(HAVE_PTHREAD_H)
32#include <pthread.h>
33
34struct ThreadInfo {
35  void (*UserFn)(void *);
36  void *UserData;
37};
38static void *ExecuteOnThread_Dispatch(void *Arg) {
39  ThreadInfo *TI = reinterpret_cast<ThreadInfo*>(Arg);
40  TI->UserFn(TI->UserData);
41  return nullptr;
42}
43
44void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
45                                  unsigned RequestedStackSize) {
46  ThreadInfo Info = { Fn, UserData };
47  pthread_attr_t Attr;
48  pthread_t Thread;
49
50  // Construct the attributes object.
51  if (::pthread_attr_init(&Attr) != 0)
52    return;
53
54  // Set the requested stack size, if given.
55  if (RequestedStackSize != 0) {
56    if (::pthread_attr_setstacksize(&Attr, RequestedStackSize) != 0)
57      goto error;
58  }
59
60  // Construct and execute the thread.
61  if (::pthread_create(&Thread, &Attr, ExecuteOnThread_Dispatch, &Info) != 0)
62    goto error;
63
64  // Wait for the thread and clean up.
65  ::pthread_join(Thread, nullptr);
66
67 error:
68  ::pthread_attr_destroy(&Attr);
69}
70#elif LLVM_ENABLE_THREADS!=0 && defined(LLVM_ON_WIN32)
71#include "Windows/WindowsSupport.h"
72#include <process.h>
73
74struct ThreadInfo {
75  void (*func)(void*);
76  void *param;
77};
78
79static unsigned __stdcall ThreadCallback(void *param) {
80  struct ThreadInfo *info = reinterpret_cast<struct ThreadInfo *>(param);
81  info->func(info->param);
82
83  return 0;
84}
85
86void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
87                                  unsigned RequestedStackSize) {
88  struct ThreadInfo param = { Fn, UserData };
89
90  HANDLE hThread = (HANDLE)::_beginthreadex(NULL,
91                                            RequestedStackSize, ThreadCallback,
92                                            &param, 0, NULL);
93
94  if (hThread) {
95    // We actually don't care whether the wait succeeds or fails, in
96    // the same way we don't care whether the pthread_join call succeeds
97    // or fails.  There's not much we could do if this were to fail. But
98    // on success, this call will wait until the thread finishes executing
99    // before returning.
100    (void)::WaitForSingleObject(hThread, INFINITE);
101    ::CloseHandle(hThread);
102  }
103}
104#else
105// Support for non-Win32, non-pthread implementation.
106void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
107                                  unsigned RequestedStackSize) {
108  (void) RequestedStackSize;
109  Fn(UserData);
110}
111
112#endif
113