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 10 #define _LIBCPP_BUILDING_MEMORY 11 #include "memory" 12 #ifndef _LIBCPP_HAS_NO_THREADS 13 #include "mutex" 14 #include "thread" 15 #endif 16 17 _LIBCPP_BEGIN_NAMESPACE_STD 18 19 namespace 20 { 21 22 template <class T> 23 inline T 24 increment(T& t) _NOEXCEPT 25 { 26 return __sync_add_and_fetch(&t, 1); 27 } 28 29 template <class T> 30 inline T 31 decrement(T& t) _NOEXCEPT 32 { 33 return __sync_add_and_fetch(&t, -1); 34 } 35 36 } // namespace 37 38 const allocator_arg_t allocator_arg = allocator_arg_t(); 39 40 bad_weak_ptr::~bad_weak_ptr() _NOEXCEPT {} 41 42 const char* 43 bad_weak_ptr::what() const _NOEXCEPT 44 { 45 return "bad_weak_ptr"; 46 } 47 48 __shared_count::~__shared_count() 49 { 50 } 51 52 void 53 __shared_count::__add_shared() _NOEXCEPT 54 { 55 increment(__shared_owners_); 56 } 57 58 bool 59 __shared_count::__release_shared() _NOEXCEPT 60 { 61 if (decrement(__shared_owners_) == -1) 62 { 63 __on_zero_shared(); 64 return true; 65 } 66 return false; 67 } 68 69 __shared_weak_count::~__shared_weak_count() 70 { 71 } 72 73 void 74 __shared_weak_count::__add_shared() _NOEXCEPT 75 { 76 __shared_count::__add_shared(); 77 } 78 79 void 80 __shared_weak_count::__add_weak() _NOEXCEPT 81 { 82 increment(__shared_weak_owners_); 83 } 84 85 void 86 __shared_weak_count::__release_shared() _NOEXCEPT 87 { 88 if (__shared_count::__release_shared()) 89 __release_weak(); 90 } 91 92 void 93 __shared_weak_count::__release_weak() _NOEXCEPT 94 { 95 if (decrement(__shared_weak_owners_) == -1) 96 __on_zero_shared_weak(); 97 } 98 99 __shared_weak_count* 100 __shared_weak_count::lock() _NOEXCEPT 101 { 102 long object_owners = __shared_owners_; 103 while (object_owners != -1) 104 { 105 if (__sync_bool_compare_and_swap(&__shared_owners_, 106 object_owners, 107 object_owners+1)) 108 return this; 109 object_owners = __shared_owners_; 110 } 111 return 0; 112 } 113 114 #if !defined(_LIBCPP_NO_RTTI) || !defined(_LIBCPP_BUILD_STATIC) 115 116 const void* 117 __shared_weak_count::__get_deleter(const type_info&) const _NOEXCEPT 118 { 119 return 0; 120 } 121 122 #endif // _LIBCPP_NO_RTTI 123 124 #if __has_feature(cxx_atomic) && !defined(_LIBCPP_HAS_NO_THREADS) 125 126 static const std::size_t __sp_mut_count = 16; 127 static pthread_mutex_t mut_back_imp[__sp_mut_count] = 128 { 129 PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 130 PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 131 PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 132 PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER 133 }; 134 135 static mutex* mut_back = reinterpret_cast<std::mutex*>(mut_back_imp); 136 137 _LIBCPP_CONSTEXPR __sp_mut::__sp_mut(void* p) _NOEXCEPT 138 : __lx(p) 139 { 140 } 141 142 void 143 __sp_mut::lock() _NOEXCEPT 144 { 145 mutex& m = *static_cast<mutex*>(__lx); 146 unsigned count = 0; 147 while (!m.try_lock()) 148 { 149 if (++count > 16) 150 { 151 m.lock(); 152 break; 153 } 154 this_thread::yield(); 155 } 156 } 157 158 void 159 __sp_mut::unlock() _NOEXCEPT 160 { 161 static_cast<mutex*>(__lx)->unlock(); 162 } 163 164 __sp_mut& 165 __get_sp_mut(const void* p) 166 { 167 static __sp_mut muts[__sp_mut_count] 168 { 169 &mut_back[ 0], &mut_back[ 1], &mut_back[ 2], &mut_back[ 3], 170 &mut_back[ 4], &mut_back[ 5], &mut_back[ 6], &mut_back[ 7], 171 &mut_back[ 8], &mut_back[ 9], &mut_back[10], &mut_back[11], 172 &mut_back[12], &mut_back[13], &mut_back[14], &mut_back[15] 173 }; 174 return muts[hash<const void*>()(p) & (__sp_mut_count-1)]; 175 } 176 177 #endif // __has_feature(cxx_atomic) && !_LIBCPP_HAS_NO_THREADS 178 179 void 180 declare_reachable(void*) 181 { 182 } 183 184 void 185 declare_no_pointers(char*, size_t) 186 { 187 } 188 189 void 190 undeclare_no_pointers(char*, size_t) 191 { 192 } 193 194 pointer_safety 195 get_pointer_safety() _NOEXCEPT 196 { 197 return pointer_safety::relaxed; 198 } 199 200 void* 201 __undeclare_reachable(void* p) 202 { 203 return p; 204 } 205 206 void* 207 align(size_t alignment, size_t size, void*& ptr, size_t& space) 208 { 209 void* r = nullptr; 210 if (size <= space) 211 { 212 char* p1 = static_cast<char*>(ptr); 213 char* p2 = reinterpret_cast<char*>(reinterpret_cast<size_t>(p1 + (alignment - 1)) & -alignment); 214 size_t d = static_cast<size_t>(p2 - p1); 215 if (d <= space - size) 216 { 217 r = p2; 218 ptr = r; 219 space -= d; 220 } 221 } 222 return r; 223 } 224 225 _LIBCPP_END_NAMESPACE_STD 226