blob: 77ebe837c73c014ef9fd14dfa1d3668d73e30f4d [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001//===------------------------ memory.cpp ----------------------------------===//
2//
Howard Hinnantf5256e12010-05-11 21:36:01 +00003// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004//
Howard Hinnantb64f8b02010-11-16 22:09:02 +00005// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00007//
8//===----------------------------------------------------------------------===//
9
10#include "memory"
Jonathan Roelofs8d86b2e2014-09-05 19:45:05 +000011#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant5fec82d2012-07-30 01:40:57 +000012#include "mutex"
Howard Hinnant65f059b2012-07-30 17:13:21 +000013#include "thread"
Jonathan Roelofs8d86b2e2014-09-05 19:45:05 +000014#endif
Eric Fiselier3b1fb532015-08-18 21:08:54 +000015#include "include/atomic_support.h"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000016
17_LIBCPP_BEGIN_NAMESPACE_STD
18
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000019const allocator_arg_t allocator_arg = allocator_arg_t();
20
Howard Hinnant1694d232011-05-28 14:41:13 +000021bad_weak_ptr::~bad_weak_ptr() _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000022
23const char*
Howard Hinnant1694d232011-05-28 14:41:13 +000024bad_weak_ptr::what() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000025{
26 return "bad_weak_ptr";
27}
28
29__shared_count::~__shared_count()
30{
31}
32
Kevin Hu89937592017-01-17 02:46:33 +000033__shared_weak_count::~__shared_weak_count()
34{
35}
36
Eric Fiseliera7ae3032017-01-17 03:16:26 +000037#if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000038void
Howard Hinnant1694d232011-05-28 14:41:13 +000039__shared_count::__add_shared() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000040{
Kevin Hu89937592017-01-17 02:46:33 +000041 __libcpp_atomic_refcount_increment(__shared_owners_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000042}
43
Howard Hinnant28dbbe02010-11-16 21:33:17 +000044bool
Howard Hinnant1694d232011-05-28 14:41:13 +000045__shared_count::__release_shared() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000046{
Kevin Hu89937592017-01-17 02:46:33 +000047 if (__libcpp_atomic_refcount_decrement(__shared_owners_) == -1)
Howard Hinnant28dbbe02010-11-16 21:33:17 +000048 {
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000049 __on_zero_shared();
Howard Hinnant28dbbe02010-11-16 21:33:17 +000050 return true;
51 }
52 return false;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000053}
54
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000055void
Howard Hinnant1694d232011-05-28 14:41:13 +000056__shared_weak_count::__add_shared() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000057{
58 __shared_count::__add_shared();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000059}
60
61void
Howard Hinnant1694d232011-05-28 14:41:13 +000062__shared_weak_count::__add_weak() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000063{
Kevin Hu89937592017-01-17 02:46:33 +000064 __libcpp_atomic_refcount_increment(__shared_weak_owners_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000065}
66
67void
Howard Hinnant1694d232011-05-28 14:41:13 +000068__shared_weak_count::__release_shared() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000069{
Howard Hinnant28dbbe02010-11-16 21:33:17 +000070 if (__shared_count::__release_shared())
71 __release_weak();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000072}
73
Eric Fiseliera7ae3032017-01-17 03:16:26 +000074#endif // _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS
75
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000076void
Howard Hinnant1694d232011-05-28 14:41:13 +000077__shared_weak_count::__release_weak() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000078{
Ben Craig16d768b2016-08-01 17:51:26 +000079 // NOTE: The acquire load here is an optimization of the very
80 // common case where a shared pointer is being destructed while
81 // having no other contended references.
82 //
83 // BENEFIT: We avoid expensive atomic stores like XADD and STREX
84 // in a common case. Those instructions are slow and do nasty
85 // things to caches.
86 //
87 // IS THIS SAFE? Yes. During weak destruction, if we see that we
88 // are the last reference, we know that no-one else is accessing
89 // us. If someone were accessing us, then they would be doing so
90 // while the last shared / weak_ptr was being destructed, and
91 // that's undefined anyway.
92 //
93 // If we see anything other than a 0, then we have possible
94 // contention, and need to use an atomicrmw primitive.
95 // The same arguments don't apply for increment, where it is legal
96 // (though inadvisable) to share shared_ptr references between
97 // threads, and have them all get copied at once. The argument
98 // also doesn't apply for __release_shared, because an outstanding
99 // weak_ptr::lock() could read / modify the shared count.
Ben Craigdb870e62016-08-02 13:43:48 +0000100 if (__libcpp_atomic_load(&__shared_weak_owners_, _AO_Acquire) == 0)
Ben Craig16d768b2016-08-01 17:51:26 +0000101 {
102 // no need to do this store, because we are about
103 // to destroy everything.
104 //__libcpp_atomic_store(&__shared_weak_owners_, -1, _AO_Release);
105 __on_zero_shared_weak();
106 }
Kevin Hu89937592017-01-17 02:46:33 +0000107 else if (__libcpp_atomic_refcount_decrement(__shared_weak_owners_) == -1)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000108 __on_zero_shared_weak();
109}
110
111__shared_weak_count*
Howard Hinnant1694d232011-05-28 14:41:13 +0000112__shared_weak_count::lock() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000113{
Eric Fiselierc6e46692015-07-07 00:27:16 +0000114 long object_owners = __libcpp_atomic_load(&__shared_owners_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000115 while (object_owners != -1)
116 {
Eric Fiselierc6e46692015-07-07 00:27:16 +0000117 if (__libcpp_atomic_compare_exchange(&__shared_owners_,
118 &object_owners,
119 object_owners+1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000120 return this;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000121 }
Eric Fiselier83e040f2017-05-04 01:06:56 +0000122 return nullptr;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000123}
124
Eric Fiselier01f6a142014-12-12 02:36:23 +0000125#if !defined(_LIBCPP_NO_RTTI) || !defined(_LIBCPP_BUILD_STATIC)
Howard Hinnantd4444702010-08-11 17:04:31 +0000126
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000127const void*
Howard Hinnant1694d232011-05-28 14:41:13 +0000128__shared_weak_count::__get_deleter(const type_info&) const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000129{
Eric Fiselier83e040f2017-05-04 01:06:56 +0000130 return nullptr;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000131}
132
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000133#endif // _LIBCPP_NO_RTTI
Howard Hinnantd4444702010-08-11 17:04:31 +0000134
Eric Fiselierba9dccd2016-06-18 02:12:53 +0000135#if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER)
Howard Hinnant96c60b42012-08-19 15:13:16 +0000136
Eric Fiselierff4f2982016-09-28 22:08:13 +0000137_LIBCPP_SAFE_STATIC static const std::size_t __sp_mut_count = 16;
138_LIBCPP_SAFE_STATIC static __libcpp_mutex_t mut_back[__sp_mut_count] =
Howard Hinnante33c2d12013-03-16 00:17:53 +0000139{
Asiri Rathnayake35ff03b2016-05-06 14:06:29 +0000140 _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER,
141 _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER,
142 _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER,
143 _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER
Howard Hinnante33c2d12013-03-16 00:17:53 +0000144};
145
Howard Hinnant5fec82d2012-07-30 01:40:57 +0000146_LIBCPP_CONSTEXPR __sp_mut::__sp_mut(void* p) _NOEXCEPT
Howard Hinnant9c0df142012-10-30 19:06:59 +0000147 : __lx(p)
Howard Hinnant5fec82d2012-07-30 01:40:57 +0000148{
149}
150
151void
152__sp_mut::lock() _NOEXCEPT
153{
Eric Fiselierff4f2982016-09-28 22:08:13 +0000154 auto m = static_cast<__libcpp_mutex_t*>(__lx);
Howard Hinnant65f059b2012-07-30 17:13:21 +0000155 unsigned count = 0;
Eric Fiselier474dfc32017-05-04 07:45:09 +0000156 while (!__libcpp_mutex_trylock(m))
Howard Hinnant65f059b2012-07-30 17:13:21 +0000157 {
158 if (++count > 16)
159 {
Eric Fiselierff4f2982016-09-28 22:08:13 +0000160 __libcpp_mutex_lock(m);
Howard Hinnant65f059b2012-07-30 17:13:21 +0000161 break;
162 }
163 this_thread::yield();
164 }
Howard Hinnant5fec82d2012-07-30 01:40:57 +0000165}
166
167void
168__sp_mut::unlock() _NOEXCEPT
169{
Eric Fiselierff4f2982016-09-28 22:08:13 +0000170 __libcpp_mutex_unlock(static_cast<__libcpp_mutex_t*>(__lx));
Howard Hinnant5fec82d2012-07-30 01:40:57 +0000171}
172
173__sp_mut&
174__get_sp_mut(const void* p)
175{
Eric Fiselierff4f2982016-09-28 22:08:13 +0000176 static __sp_mut muts[__sp_mut_count]
Howard Hinnant5fec82d2012-07-30 01:40:57 +0000177 {
178 &mut_back[ 0], &mut_back[ 1], &mut_back[ 2], &mut_back[ 3],
179 &mut_back[ 4], &mut_back[ 5], &mut_back[ 6], &mut_back[ 7],
180 &mut_back[ 8], &mut_back[ 9], &mut_back[10], &mut_back[11],
181 &mut_back[12], &mut_back[13], &mut_back[14], &mut_back[15]
182 };
183 return muts[hash<const void*>()(p) & (__sp_mut_count-1)];
184}
185
Eric Fiselierba9dccd2016-06-18 02:12:53 +0000186#endif // !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER)
Howard Hinnant5fec82d2012-07-30 01:40:57 +0000187
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000188void
189declare_reachable(void*)
190{
191}
192
193void
194declare_no_pointers(char*, size_t)
195{
196}
197
198void
199undeclare_no_pointers(char*, size_t)
200{
201}
202
Eric Fiselier46a0c2e2017-01-05 01:15:42 +0000203#if !defined(_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE)
204pointer_safety get_pointer_safety() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000205{
206 return pointer_safety::relaxed;
207}
Eric Fiselier46a0c2e2017-01-05 01:15:42 +0000208#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000209
210void*
211__undeclare_reachable(void* p)
212{
213 return p;
214}
215
216void*
217align(size_t alignment, size_t size, void*& ptr, size_t& space)
218{
219 void* r = nullptr;
220 if (size <= space)
221 {
222 char* p1 = static_cast<char*>(ptr);
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +0000223 char* p2 = reinterpret_cast<char*>(reinterpret_cast<size_t>(p1 + (alignment - 1)) & -alignment);
Howard Hinnantec3773c2011-12-01 20:21:04 +0000224 size_t d = static_cast<size_t>(p2 - p1);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000225 if (d <= space - size)
226 {
227 r = p2;
228 ptr = r;
229 space -= d;
230 }
231 }
232 return r;
233}
234
235_LIBCPP_END_NAMESPACE_STD