153ca1f3190680f3e86aebe0f72f7918d63f71e0dCharles Davis//===-- llvm/Support/Threading.cpp- Control multithreading mode --*- C++ -*-==//
24c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson//
34c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson//                     The LLVM Compiler Infrastructure
44c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson//
54c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson// This file is distributed under the University of Illinois Open Source
64c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson// License. See LICENSE.TXT for details.
74c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson//
84c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson//===----------------------------------------------------------------------===//
94c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson//
10c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines// This file defines helper functions for running LLVM in a multi-threaded
11c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines// environment.
124c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson//
134c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson//===----------------------------------------------------------------------===//
144c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson
151f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Threading.h"
16d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Config/config.h"
171f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Atomic.h"
181f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Mutex.h"
19de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/Support/thread.h"
204c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson#include <cassert>
21643dda1d625d286dc53283d22152ba56926a1f25Owen Anderson
224c7ac18fc9e9af51ea6362871589c13263526d7aOwen Andersonusing namespace llvm;
234c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson
24c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesbool llvm::llvm_is_multithreaded() {
2508b73a30bbb6407c7b48a734a29f65f4c8ddd782Dylan Noblesmith#if LLVM_ENABLE_THREADS != 0
264c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson  return true;
274c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson#else
284c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson  return false;
294c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson#endif
304c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson}
314c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson
3208b73a30bbb6407c7b48a734a29f65f4c8ddd782Dylan Noblesmith#if LLVM_ENABLE_THREADS != 0 && defined(HAVE_PTHREAD_H)
33ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar#include <pthread.h>
34ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar
35ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbarstruct ThreadInfo {
36ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar  void (*UserFn)(void *);
37ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar  void *UserData;
38ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar};
39ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbarstatic void *ExecuteOnThread_Dispatch(void *Arg) {
40ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar  ThreadInfo *TI = reinterpret_cast<ThreadInfo*>(Arg);
41ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar  TI->UserFn(TI->UserData);
42dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  return nullptr;
43ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar}
44ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar
45ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbarvoid llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
46ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar                                  unsigned RequestedStackSize) {
47ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar  ThreadInfo Info = { Fn, UserData };
48ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar  pthread_attr_t Attr;
49ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar  pthread_t Thread;
50ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar
51ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar  // Construct the attributes object.
52ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar  if (::pthread_attr_init(&Attr) != 0)
53ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar    return;
54ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar
55ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar  // Set the requested stack size, if given.
56ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar  if (RequestedStackSize != 0) {
57ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar    if (::pthread_attr_setstacksize(&Attr, RequestedStackSize) != 0)
58ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar      goto error;
59ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar  }
60ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar
61ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar  // Construct and execute the thread.
62ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar  if (::pthread_create(&Thread, &Attr, ExecuteOnThread_Dispatch, &Info) != 0)
63ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar    goto error;
64ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar
65ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar  // Wait for the thread and clean up.
66dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  ::pthread_join(Thread, nullptr);
671f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer
68ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar error:
69ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar  ::pthread_attr_destroy(&Attr);
70ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar}
7108b73a30bbb6407c7b48a734a29f65f4c8ddd782Dylan Noblesmith#elif LLVM_ENABLE_THREADS!=0 && defined(LLVM_ON_WIN32)
7236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "Windows/WindowsSupport.h"
7392ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi#include <process.h>
74ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar
75de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Windows will at times define MemoryFence.
76de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#ifdef MemoryFence
77de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#undef MemoryFence
78de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#endif
79de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
8092ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumistruct ThreadInfo {
8192ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi  void (*func)(void*);
8292ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi  void *param;
8392ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi};
84ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar
8592ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumistatic unsigned __stdcall ThreadCallback(void *param) {
8692ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi  struct ThreadInfo *info = reinterpret_cast<struct ThreadInfo *>(param);
8792ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi  info->func(info->param);
8892ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi
8992ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi  return 0;
9092ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi}
91ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar
92ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbarvoid llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
93ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar                                  unsigned RequestedStackSize) {
9492ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi  struct ThreadInfo param = { Fn, UserData };
9592ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi
9692ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi  HANDLE hThread = (HANDLE)::_beginthreadex(NULL,
9792ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi                                            RequestedStackSize, ThreadCallback,
9892ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi                                            &param, 0, NULL);
9992ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi
10092ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi  if (hThread) {
10192ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi    // We actually don't care whether the wait succeeds or fails, in
10292ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi    // the same way we don't care whether the pthread_join call succeeds
10392ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi    // or fails.  There's not much we could do if this were to fail. But
10492ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi    // on success, this call will wait until the thread finishes executing
10592ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi    // before returning.
10692ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi    (void)::WaitForSingleObject(hThread, INFINITE);
10792ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi    ::CloseHandle(hThread);
10892ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi  }
10992ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi}
11092ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi#else
11192ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi// Support for non-Win32, non-pthread implementation.
11292ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumivoid llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
11392ec8e1427e595d540f2238c7a1bb05fbd013013NAKAMURA Takumi                                  unsigned RequestedStackSize) {
114ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar  (void) RequestedStackSize;
115ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar  Fn(UserData);
116ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar}
117ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar
118ea8e20696e0bc8313b9459484797614a769a5e0cDaniel Dunbar#endif
119