/3rd_party/llvm/lib/Support/Threading.cpp

https://code.google.com/p/softart/ · C++ · 147 lines · 94 code · 27 blank · 26 comment · 18 complexity · f98324331022726d95ad72c86cfbf43c MD5 · raw file

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