Threading.cpp 3.9 KB

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