memory.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. //===------------------------ memory.cpp ----------------------------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is dual licensed under the MIT and the University of Illinois Open
  6. // Source Licenses. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #define _LIBCPP_BUILDING_MEMORY
  10. #include "memory"
  11. #if !defined(_LIBCPP_HAS_NO_THREADS) || defined(_LIBCPP_SGX_CONFIG)
  12. #include "mutex"
  13. #include "thread"
  14. #endif
  15. #include "include/atomic_support.h"
  16. _LIBCPP_BEGIN_NAMESPACE_STD
  17. namespace
  18. {
  19. // NOTE: Relaxed and acq/rel atomics (for increment and decrement respectively)
  20. // should be sufficient for thread safety.
  21. // See https://llvm.org/bugs/show_bug.cgi?id=22803
  22. template <class T>
  23. inline T
  24. increment(T& t) _NOEXCEPT
  25. {
  26. return __libcpp_atomic_add(&t, 1, _AO_Relaxed);
  27. }
  28. template <class T>
  29. inline T
  30. decrement(T& t) _NOEXCEPT
  31. {
  32. return __libcpp_atomic_add(&t, -1, _AO_Acq_Rel);
  33. }
  34. } // namespace
  35. const allocator_arg_t allocator_arg = allocator_arg_t();
  36. bad_weak_ptr::~bad_weak_ptr() _NOEXCEPT {}
  37. const char*
  38. bad_weak_ptr::what() const _NOEXCEPT
  39. {
  40. return "bad_weak_ptr";
  41. }
  42. __shared_count::~__shared_count()
  43. {
  44. }
  45. void
  46. __shared_count::__add_shared() _NOEXCEPT
  47. {
  48. increment(__shared_owners_);
  49. }
  50. bool
  51. __shared_count::__release_shared() _NOEXCEPT
  52. {
  53. if (decrement(__shared_owners_) == -1)
  54. {
  55. __on_zero_shared();
  56. return true;
  57. }
  58. return false;
  59. }
  60. __shared_weak_count::~__shared_weak_count()
  61. {
  62. }
  63. void
  64. __shared_weak_count::__add_shared() _NOEXCEPT
  65. {
  66. __shared_count::__add_shared();
  67. }
  68. void
  69. __shared_weak_count::__add_weak() _NOEXCEPT
  70. {
  71. increment(__shared_weak_owners_);
  72. }
  73. void
  74. __shared_weak_count::__release_shared() _NOEXCEPT
  75. {
  76. if (__shared_count::__release_shared())
  77. __release_weak();
  78. }
  79. void
  80. __shared_weak_count::__release_weak() _NOEXCEPT
  81. {
  82. if (decrement(__shared_weak_owners_) == -1)
  83. __on_zero_shared_weak();
  84. }
  85. __shared_weak_count*
  86. __shared_weak_count::lock() _NOEXCEPT
  87. {
  88. long object_owners = __libcpp_atomic_load(&__shared_owners_);
  89. while (object_owners != -1)
  90. {
  91. if (__libcpp_atomic_compare_exchange(&__shared_owners_,
  92. &object_owners,
  93. object_owners+1))
  94. return this;
  95. }
  96. return 0;
  97. }
  98. #if !defined(_LIBCPP_NO_RTTI) || !defined(_LIBCPP_BUILD_STATIC)
  99. const void*
  100. __shared_weak_count::__get_deleter(const type_info&) const _NOEXCEPT
  101. {
  102. return 0;
  103. }
  104. #endif // _LIBCPP_NO_RTTI
  105. #if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER) || defined(_LIBCPP_SGX_HAS_CXX_ATOMIC)
  106. static const std::size_t __sp_mut_count = 16;
  107. #if defined(_LIBCPP_SGX_HAS_CXX_ATOMIC)
  108. static sgx_thread_mutex_t mut_back_imp[__sp_mut_count] =
  109. {
  110. SGX_THREAD_MUTEX_INITIALIZER, SGX_THREAD_MUTEX_INITIALIZER, SGX_THREAD_MUTEX_INITIALIZER, SGX_THREAD_MUTEX_INITIALIZER,
  111. SGX_THREAD_MUTEX_INITIALIZER, SGX_THREAD_MUTEX_INITIALIZER, SGX_THREAD_MUTEX_INITIALIZER, SGX_THREAD_MUTEX_INITIALIZER,
  112. SGX_THREAD_MUTEX_INITIALIZER, SGX_THREAD_MUTEX_INITIALIZER, SGX_THREAD_MUTEX_INITIALIZER, SGX_THREAD_MUTEX_INITIALIZER,
  113. SGX_THREAD_MUTEX_INITIALIZER, SGX_THREAD_MUTEX_INITIALIZER, SGX_THREAD_MUTEX_INITIALIZER, SGX_THREAD_MUTEX_INITIALIZER
  114. };
  115. #else // !defined(_LIBCPP_SGX_HAS_CXX_ATOMIC)
  116. static __libcpp_mutex_t mut_back_imp[__sp_mut_count] =
  117. {
  118. _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER,
  119. _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER,
  120. _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER,
  121. _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER
  122. };
  123. #endif // defined(_LIBCPP_SGX_HAS_CXX_ATOMIC)
  124. static mutex* mut_back = reinterpret_cast<std::mutex*>(mut_back_imp);
  125. _LIBCPP_CONSTEXPR __sp_mut::__sp_mut(void* p) _NOEXCEPT
  126. : __lx(p)
  127. {
  128. }
  129. void
  130. __sp_mut::lock() _NOEXCEPT
  131. {
  132. mutex& m = *static_cast<mutex*>(__lx);
  133. unsigned count = 0;
  134. while (!m.try_lock())
  135. {
  136. if (++count > 16)
  137. {
  138. m.lock();
  139. break;
  140. }
  141. #if !defined(_LIBCPP_SGX_CONFIG)
  142. // We don't have yield() function;
  143. this_thread::yield();
  144. #endif // !defined(_LIBCPP_SGX_CONFIG)
  145. }
  146. }
  147. void
  148. __sp_mut::unlock() _NOEXCEPT
  149. {
  150. static_cast<mutex*>(__lx)->unlock();
  151. }
  152. __sp_mut&
  153. __get_sp_mut(const void* p)
  154. {
  155. static __sp_mut muts[__sp_mut_count]
  156. {
  157. &mut_back[ 0], &mut_back[ 1], &mut_back[ 2], &mut_back[ 3],
  158. &mut_back[ 4], &mut_back[ 5], &mut_back[ 6], &mut_back[ 7],
  159. &mut_back[ 8], &mut_back[ 9], &mut_back[10], &mut_back[11],
  160. &mut_back[12], &mut_back[13], &mut_back[14], &mut_back[15]
  161. };
  162. return muts[hash<const void*>()(p) & (__sp_mut_count-1)];
  163. }
  164. #endif // !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER) || defined(_LIBCPP_SGX_HAS_CXX_ATOMIC)
  165. void
  166. declare_reachable(void*)
  167. {
  168. }
  169. void
  170. declare_no_pointers(char*, size_t)
  171. {
  172. }
  173. void
  174. undeclare_no_pointers(char*, size_t)
  175. {
  176. }
  177. pointer_safety
  178. get_pointer_safety() _NOEXCEPT
  179. {
  180. return pointer_safety::relaxed;
  181. }
  182. void*
  183. __undeclare_reachable(void* p)
  184. {
  185. return p;
  186. }
  187. void*
  188. align(size_t alignment, size_t size, void*& ptr, size_t& space)
  189. {
  190. void* r = nullptr;
  191. if (size <= space)
  192. {
  193. char* p1 = static_cast<char*>(ptr);
  194. char* p2 = reinterpret_cast<char*>(reinterpret_cast<size_t>(p1 + (alignment - 1)) & -alignment);
  195. size_t d = static_cast<size_t>(p2 - p1);
  196. if (d <= space - size)
  197. {
  198. r = p2;
  199. ptr = r;
  200. space -= d;
  201. }
  202. }
  203. return r;
  204. }
  205. _LIBCPP_END_NAMESPACE_STD