blob: 1b8c6b7e80fc3383f90b2046a2418d2fa0f33dcd [file] [log] [blame]
Louis Dionneeb8650a2021-11-17 21:25:011//===----------------------------------------------------------------------===//
Howard Hinnant3e519522010-05-11 19:42:162//
Chandler Carruth57b08b02019-01-19 10:56:403// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Howard Hinnant3e519522010-05-11 19:42:166//
7//===----------------------------------------------------------------------===//
8
Arthur O'Dwyerbbb0f2c2022-02-11 18:00:399#include <memory>
10
Jonathan Roelofsb3fcc672014-09-05 19:45:0511#ifndef _LIBCPP_HAS_NO_THREADS
Arthur O'Dwyerbbb0f2c2022-02-11 18:00:3912# include <mutex>
13# include <thread>
14# if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
15# pragma comment(lib, "pthread")
16# endif
Jonathan Roelofsb3fcc672014-09-05 19:45:0517#endif
Arthur O'Dwyerbbb0f2c2022-02-11 18:00:3918
Eric Fiseliere8fd1642015-08-18 21:08:5419#include "include/atomic_support.h"
Howard Hinnant3e519522010-05-11 19:42:1620
21_LIBCPP_BEGIN_NAMESPACE_STD
22
Howard Hinnant3e519522010-05-11 19:42:1623const allocator_arg_t allocator_arg = allocator_arg_t();
24
Louis Dionne56013052021-03-01 17:09:4525bad_weak_ptr::~bad_weak_ptr() noexcept {}
Howard Hinnant3e519522010-05-11 19:42:1626
27const char*
Louis Dionne56013052021-03-01 17:09:4528bad_weak_ptr::what() const noexcept
Howard Hinnant3e519522010-05-11 19:42:1629{
30 return "bad_weak_ptr";
31}
32
33__shared_count::~__shared_count()
34{
35}
36
Kevin Huf08de522017-01-17 02:46:3337__shared_weak_count::~__shared_weak_count()
38{
39}
40
Eric Fiselier11f60452017-01-17 03:16:2641#if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS)
Howard Hinnant3e519522010-05-11 19:42:1642void
Louis Dionne56013052021-03-01 17:09:4543__shared_count::__add_shared() noexcept
Howard Hinnant3e519522010-05-11 19:42:1644{
Kevin Huf08de522017-01-17 02:46:3345 __libcpp_atomic_refcount_increment(__shared_owners_);
Howard Hinnant3e519522010-05-11 19:42:1646}
47
Howard Hinnant9b35c822010-11-16 21:33:1748bool
Louis Dionne56013052021-03-01 17:09:4549__shared_count::__release_shared() noexcept
Howard Hinnant3e519522010-05-11 19:42:1650{
Kevin Huf08de522017-01-17 02:46:3351 if (__libcpp_atomic_refcount_decrement(__shared_owners_) == -1)
Howard Hinnant9b35c822010-11-16 21:33:1752 {
Howard Hinnant3e519522010-05-11 19:42:1653 __on_zero_shared();
Howard Hinnant9b35c822010-11-16 21:33:1754 return true;
55 }
56 return false;
Howard Hinnant3e519522010-05-11 19:42:1657}
58
Howard Hinnant3e519522010-05-11 19:42:1659void
Louis Dionne56013052021-03-01 17:09:4560__shared_weak_count::__add_shared() noexcept
Howard Hinnant3e519522010-05-11 19:42:1661{
62 __shared_count::__add_shared();
Howard Hinnant3e519522010-05-11 19:42:1663}
64
65void
Louis Dionne56013052021-03-01 17:09:4566__shared_weak_count::__add_weak() noexcept
Howard Hinnant3e519522010-05-11 19:42:1667{
Kevin Huf08de522017-01-17 02:46:3368 __libcpp_atomic_refcount_increment(__shared_weak_owners_);
Howard Hinnant3e519522010-05-11 19:42:1669}
70
71void
Louis Dionne56013052021-03-01 17:09:4572__shared_weak_count::__release_shared() noexcept
Howard Hinnant3e519522010-05-11 19:42:1673{
Howard Hinnant9b35c822010-11-16 21:33:1774 if (__shared_count::__release_shared())
75 __release_weak();
Howard Hinnant3e519522010-05-11 19:42:1676}
77
Eric Fiselier11f60452017-01-17 03:16:2678#endif // _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS
79
Howard Hinnant3e519522010-05-11 19:42:1680void
Louis Dionne56013052021-03-01 17:09:4581__shared_weak_count::__release_weak() noexcept
Howard Hinnant3e519522010-05-11 19:42:1682{
Ben Craigac9eec82016-08-01 17:51:2683 // NOTE: The acquire load here is an optimization of the very
84 // common case where a shared pointer is being destructed while
85 // having no other contended references.
86 //
87 // BENEFIT: We avoid expensive atomic stores like XADD and STREX
88 // in a common case. Those instructions are slow and do nasty
89 // things to caches.
90 //
91 // IS THIS SAFE? Yes. During weak destruction, if we see that we
92 // are the last reference, we know that no-one else is accessing
93 // us. If someone were accessing us, then they would be doing so
94 // while the last shared / weak_ptr was being destructed, and
95 // that's undefined anyway.
96 //
97 // If we see anything other than a 0, then we have possible
98 // contention, and need to use an atomicrmw primitive.
99 // The same arguments don't apply for increment, where it is legal
100 // (though inadvisable) to share shared_ptr references between
101 // threads, and have them all get copied at once. The argument
102 // also doesn't apply for __release_shared, because an outstanding
103 // weak_ptr::lock() could read / modify the shared count.
Ben Craig8ddd3ef2016-08-02 13:43:48104 if (__libcpp_atomic_load(&__shared_weak_owners_, _AO_Acquire) == 0)
Ben Craigac9eec82016-08-01 17:51:26105 {
106 // no need to do this store, because we are about
107 // to destroy everything.
108 //__libcpp_atomic_store(&__shared_weak_owners_, -1, _AO_Release);
109 __on_zero_shared_weak();
110 }
Kevin Huf08de522017-01-17 02:46:33111 else if (__libcpp_atomic_refcount_decrement(__shared_weak_owners_) == -1)
Howard Hinnant3e519522010-05-11 19:42:16112 __on_zero_shared_weak();
113}
114
115__shared_weak_count*
Louis Dionne56013052021-03-01 17:09:45116__shared_weak_count::lock() noexcept
Howard Hinnant3e519522010-05-11 19:42:16117{
Eric Fiselier1faf2892015-07-07 00:27:16118 long object_owners = __libcpp_atomic_load(&__shared_owners_);
Howard Hinnant3e519522010-05-11 19:42:16119 while (object_owners != -1)
120 {
Eric Fiselier1faf2892015-07-07 00:27:16121 if (__libcpp_atomic_compare_exchange(&__shared_owners_,
122 &object_owners,
123 object_owners+1))
Howard Hinnant3e519522010-05-11 19:42:16124 return this;
Howard Hinnant3e519522010-05-11 19:42:16125 }
Eric Fiselier9c973b92017-05-04 01:06:56126 return nullptr;
Howard Hinnant3e519522010-05-11 19:42:16127}
128
129const void*
Louis Dionne56013052021-03-01 17:09:45130__shared_weak_count::__get_deleter(const type_info&) const noexcept
Howard Hinnant3e519522010-05-11 19:42:16131{
Eric Fiselier9c973b92017-05-04 01:06:56132 return nullptr;
Howard Hinnant3e519522010-05-11 19:42:16133}
134
Louis Dionne92832e42021-11-17 15:59:31135#if !defined(_LIBCPP_HAS_NO_THREADS)
Howard Hinnante4b2a742012-08-19 15:13:16136
Arthur O'Dwyer05337a72022-02-08 18:08:59137static constexpr std::size_t __sp_mut_count = 16;
138static constinit __libcpp_mutex_t mut_back[__sp_mut_count] =
Howard Hinnant5efca642013-03-16 00:17:53139{
Asiri Rathnayakec7e42392016-05-06 14:06:29140 _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 Hinnant5efca642013-03-16 00:17:53144};
145
Louis Dionne56013052021-03-01 17:09:45146_LIBCPP_CONSTEXPR __sp_mut::__sp_mut(void* p) noexcept
Howard Hinnant54d333a2012-10-30 19:06:59147 : __lx(p)
Howard Hinnantd77851e2012-07-30 01:40:57148{
149}
150
151void
Louis Dionne56013052021-03-01 17:09:45152__sp_mut::lock() noexcept
Howard Hinnantd77851e2012-07-30 01:40:57153{
Eric Fiselierea117bf2016-09-28 22:08:13154 auto m = static_cast<__libcpp_mutex_t*>(__lx);
Howard Hinnant088e37c2012-07-30 17:13:21155 unsigned count = 0;
Eric Fiselier61a241e2017-05-04 07:45:09156 while (!__libcpp_mutex_trylock(m))
Howard Hinnant088e37c2012-07-30 17:13:21157 {
158 if (++count > 16)
159 {
Eric Fiselierea117bf2016-09-28 22:08:13160 __libcpp_mutex_lock(m);
Howard Hinnant088e37c2012-07-30 17:13:21161 break;
162 }
163 this_thread::yield();
164 }
Howard Hinnantd77851e2012-07-30 01:40:57165}
166
167void
Louis Dionne56013052021-03-01 17:09:45168__sp_mut::unlock() noexcept
Howard Hinnantd77851e2012-07-30 01:40:57169{
Eric Fiselierea117bf2016-09-28 22:08:13170 __libcpp_mutex_unlock(static_cast<__libcpp_mutex_t*>(__lx));
Howard Hinnantd77851e2012-07-30 01:40:57171}
172
173__sp_mut&
174__get_sp_mut(const void* p)
175{
Arthur O'Dwyer05337a72022-02-08 18:08:59176 static constinit __sp_mut muts[__sp_mut_count] = {
Howard Hinnantd77851e2012-07-30 01:40:57177 &mut_back[ 0], &mut_back[ 1], &mut_back[ 2], &mut_back[ 3],
178 &mut_back[ 4], &mut_back[ 5], &mut_back[ 6], &mut_back[ 7],
179 &mut_back[ 8], &mut_back[ 9], &mut_back[10], &mut_back[11],
180 &mut_back[12], &mut_back[13], &mut_back[14], &mut_back[15]
181 };
182 return muts[hash<const void*>()(p) & (__sp_mut_count-1)];
183}
184
Louis Dionne92832e42021-11-17 15:59:31185#endif // !defined(_LIBCPP_HAS_NO_THREADS)
Howard Hinnantd77851e2012-07-30 01:40:57186
Howard Hinnant3e519522010-05-11 19:42:16187void*
188align(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);
Joerg Sonnenberger634b9dd2014-01-04 17:43:00194 char* p2 = reinterpret_cast<char*>(reinterpret_cast<size_t>(p1 + (alignment - 1)) & -alignment);
Howard Hinnantc2063662011-12-01 20:21:04195 size_t d = static_cast<size_t>(p2 - p1);
Howard Hinnant3e519522010-05-11 19:42:16196 if (d <= space - size)
197 {
198 r = p2;
199 ptr = r;
200 space -= d;
201 }
202 }
203 return r;
204}
205
206_LIBCPP_END_NAMESPACE_STD