2
0

ManagedStatic.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. //===-- ManagedStatic.cpp - Static Global wrapper -------------------------===//
  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 the ManagedStatic class and llvm_shutdown().
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/Support/ManagedStatic.h"
  14. #include "llvm/Config/config.h"
  15. #include "llvm/Support/Atomic.h"
  16. #include "llvm/Support/Mutex.h"
  17. #include "llvm/Support/MutexGuard.h"
  18. #include <cassert>
  19. using namespace llvm;
  20. static const ManagedStaticBase *StaticList = nullptr;
  21. static sys::Mutex& getManagedStaticMutex() {
  22. // We need to use a function local static here, since this can get called
  23. // during a static constructor and we need to guarantee that it's initialized
  24. // correctly.
  25. static sys::Mutex ManagedStaticMutex;
  26. return ManagedStaticMutex;
  27. }
  28. void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
  29. void (*Deleter)(void*)) const {
  30. assert(Creator);
  31. if (llvm_is_multithreaded()) {
  32. MutexGuard Lock(getManagedStaticMutex());
  33. if (!Ptr) {
  34. void* tmp = Creator();
  35. TsanHappensBefore(this);
  36. sys::MemoryFence();
  37. // This write is racy against the first read in the ManagedStatic
  38. // accessors. The race is benign because it does a second read after a
  39. // memory fence, at which point it isn't possible to get a partial value.
  40. TsanIgnoreWritesBegin();
  41. Ptr = tmp;
  42. TsanIgnoreWritesEnd();
  43. DeleterFn = Deleter;
  44. // Add to list of managed statics.
  45. Next = StaticList;
  46. StaticList = this;
  47. }
  48. } else {
  49. assert(!Ptr && !DeleterFn && !Next &&
  50. "Partially initialized ManagedStatic!?");
  51. Ptr = Creator();
  52. DeleterFn = Deleter;
  53. // Add to list of managed statics.
  54. Next = StaticList;
  55. StaticList = this;
  56. }
  57. }
  58. void ManagedStaticBase::destroy() const {
  59. assert(DeleterFn && "ManagedStatic not initialized correctly!");
  60. assert(StaticList == this &&
  61. "Not destroyed in reverse order of construction?");
  62. // Unlink from list.
  63. StaticList = Next;
  64. Next = nullptr;
  65. // Destroy memory.
  66. DeleterFn(Ptr);
  67. // Cleanup.
  68. Ptr = nullptr;
  69. DeleterFn = nullptr;
  70. }
  71. /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
  72. void llvm::llvm_shutdown() {
  73. MutexGuard Lock(getManagedStaticMutex());
  74. while (StaticList)
  75. StaticList->destroy();
  76. }