14684ddb6SLionel Sambuc //===------------------------ memory.cpp ----------------------------------===//
24684ddb6SLionel Sambuc //
34684ddb6SLionel Sambuc // The LLVM Compiler Infrastructure
44684ddb6SLionel Sambuc //
54684ddb6SLionel Sambuc // This file is dual licensed under the MIT and the University of Illinois Open
64684ddb6SLionel Sambuc // Source Licenses. See LICENSE.TXT for details.
74684ddb6SLionel Sambuc //
84684ddb6SLionel Sambuc //===----------------------------------------------------------------------===//
94684ddb6SLionel Sambuc
104684ddb6SLionel Sambuc #define _LIBCPP_BUILDING_MEMORY
114684ddb6SLionel Sambuc #include "memory"
12*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_THREADS
134684ddb6SLionel Sambuc #include "mutex"
144684ddb6SLionel Sambuc #include "thread"
15*0a6a1f1dSLionel Sambuc #endif
16*0a6a1f1dSLionel Sambuc #include "include/atomic_support.h"
174684ddb6SLionel Sambuc
184684ddb6SLionel Sambuc _LIBCPP_BEGIN_NAMESPACE_STD
194684ddb6SLionel Sambuc
204684ddb6SLionel Sambuc namespace
214684ddb6SLionel Sambuc {
224684ddb6SLionel Sambuc
23*0a6a1f1dSLionel Sambuc // NOTE: Relaxed and acq/rel atomics (for increment and decrement respectively)
24*0a6a1f1dSLionel Sambuc // should be sufficient for thread safety.
25*0a6a1f1dSLionel Sambuc // See https://llvm.org/bugs/show_bug.cgi?id=22803
264684ddb6SLionel Sambuc template <class T>
274684ddb6SLionel Sambuc inline T
increment(T & t)284684ddb6SLionel Sambuc increment(T& t) _NOEXCEPT
294684ddb6SLionel Sambuc {
30*0a6a1f1dSLionel Sambuc return __libcpp_atomic_add(&t, 1, _AO_Relaxed);
314684ddb6SLionel Sambuc }
324684ddb6SLionel Sambuc
334684ddb6SLionel Sambuc template <class T>
344684ddb6SLionel Sambuc inline T
decrement(T & t)354684ddb6SLionel Sambuc decrement(T& t) _NOEXCEPT
364684ddb6SLionel Sambuc {
37*0a6a1f1dSLionel Sambuc return __libcpp_atomic_add(&t, -1, _AO_Acq_Rel);
384684ddb6SLionel Sambuc }
394684ddb6SLionel Sambuc
404684ddb6SLionel Sambuc } // namespace
414684ddb6SLionel Sambuc
424684ddb6SLionel Sambuc const allocator_arg_t allocator_arg = allocator_arg_t();
434684ddb6SLionel Sambuc
~bad_weak_ptr()444684ddb6SLionel Sambuc bad_weak_ptr::~bad_weak_ptr() _NOEXCEPT {}
454684ddb6SLionel Sambuc
464684ddb6SLionel Sambuc const char*
what() const474684ddb6SLionel Sambuc bad_weak_ptr::what() const _NOEXCEPT
484684ddb6SLionel Sambuc {
494684ddb6SLionel Sambuc return "bad_weak_ptr";
504684ddb6SLionel Sambuc }
514684ddb6SLionel Sambuc
~__shared_count()524684ddb6SLionel Sambuc __shared_count::~__shared_count()
534684ddb6SLionel Sambuc {
544684ddb6SLionel Sambuc }
554684ddb6SLionel Sambuc
564684ddb6SLionel Sambuc void
__add_shared()574684ddb6SLionel Sambuc __shared_count::__add_shared() _NOEXCEPT
584684ddb6SLionel Sambuc {
594684ddb6SLionel Sambuc increment(__shared_owners_);
604684ddb6SLionel Sambuc }
614684ddb6SLionel Sambuc
624684ddb6SLionel Sambuc bool
__release_shared()634684ddb6SLionel Sambuc __shared_count::__release_shared() _NOEXCEPT
644684ddb6SLionel Sambuc {
654684ddb6SLionel Sambuc if (decrement(__shared_owners_) == -1)
664684ddb6SLionel Sambuc {
674684ddb6SLionel Sambuc __on_zero_shared();
684684ddb6SLionel Sambuc return true;
694684ddb6SLionel Sambuc }
704684ddb6SLionel Sambuc return false;
714684ddb6SLionel Sambuc }
724684ddb6SLionel Sambuc
~__shared_weak_count()734684ddb6SLionel Sambuc __shared_weak_count::~__shared_weak_count()
744684ddb6SLionel Sambuc {
754684ddb6SLionel Sambuc }
764684ddb6SLionel Sambuc
774684ddb6SLionel Sambuc void
__add_shared()784684ddb6SLionel Sambuc __shared_weak_count::__add_shared() _NOEXCEPT
794684ddb6SLionel Sambuc {
804684ddb6SLionel Sambuc __shared_count::__add_shared();
814684ddb6SLionel Sambuc }
824684ddb6SLionel Sambuc
834684ddb6SLionel Sambuc void
__add_weak()844684ddb6SLionel Sambuc __shared_weak_count::__add_weak() _NOEXCEPT
854684ddb6SLionel Sambuc {
864684ddb6SLionel Sambuc increment(__shared_weak_owners_);
874684ddb6SLionel Sambuc }
884684ddb6SLionel Sambuc
894684ddb6SLionel Sambuc void
__release_shared()904684ddb6SLionel Sambuc __shared_weak_count::__release_shared() _NOEXCEPT
914684ddb6SLionel Sambuc {
924684ddb6SLionel Sambuc if (__shared_count::__release_shared())
934684ddb6SLionel Sambuc __release_weak();
944684ddb6SLionel Sambuc }
954684ddb6SLionel Sambuc
964684ddb6SLionel Sambuc void
__release_weak()974684ddb6SLionel Sambuc __shared_weak_count::__release_weak() _NOEXCEPT
984684ddb6SLionel Sambuc {
994684ddb6SLionel Sambuc if (decrement(__shared_weak_owners_) == -1)
1004684ddb6SLionel Sambuc __on_zero_shared_weak();
1014684ddb6SLionel Sambuc }
1024684ddb6SLionel Sambuc
1034684ddb6SLionel Sambuc __shared_weak_count*
lock()1044684ddb6SLionel Sambuc __shared_weak_count::lock() _NOEXCEPT
1054684ddb6SLionel Sambuc {
106*0a6a1f1dSLionel Sambuc long object_owners = __libcpp_atomic_load(&__shared_owners_);
1074684ddb6SLionel Sambuc while (object_owners != -1)
1084684ddb6SLionel Sambuc {
109*0a6a1f1dSLionel Sambuc if (__libcpp_atomic_compare_exchange(&__shared_owners_,
110*0a6a1f1dSLionel Sambuc &object_owners,
1114684ddb6SLionel Sambuc object_owners+1))
1124684ddb6SLionel Sambuc return this;
1134684ddb6SLionel Sambuc }
1144684ddb6SLionel Sambuc return 0;
1154684ddb6SLionel Sambuc }
1164684ddb6SLionel Sambuc
117*0a6a1f1dSLionel Sambuc #if !defined(_LIBCPP_NO_RTTI) || !defined(_LIBCPP_BUILD_STATIC)
1184684ddb6SLionel Sambuc
1194684ddb6SLionel Sambuc const void*
__get_deleter(const type_info &) const1204684ddb6SLionel Sambuc __shared_weak_count::__get_deleter(const type_info&) const _NOEXCEPT
1214684ddb6SLionel Sambuc {
1224684ddb6SLionel Sambuc return 0;
1234684ddb6SLionel Sambuc }
1244684ddb6SLionel Sambuc
1254684ddb6SLionel Sambuc #endif // _LIBCPP_NO_RTTI
1264684ddb6SLionel Sambuc
127*0a6a1f1dSLionel Sambuc #if defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_NO_THREADS)
1284684ddb6SLionel Sambuc
1294684ddb6SLionel Sambuc static const std::size_t __sp_mut_count = 16;
1304684ddb6SLionel Sambuc static pthread_mutex_t mut_back_imp[__sp_mut_count] =
1314684ddb6SLionel Sambuc {
1324684ddb6SLionel Sambuc PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
1334684ddb6SLionel Sambuc PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
1344684ddb6SLionel Sambuc PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
1354684ddb6SLionel Sambuc PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER
1364684ddb6SLionel Sambuc };
1374684ddb6SLionel Sambuc
1384684ddb6SLionel Sambuc static mutex* mut_back = reinterpret_cast<std::mutex*>(mut_back_imp);
1394684ddb6SLionel Sambuc
__sp_mut(void * p)1404684ddb6SLionel Sambuc _LIBCPP_CONSTEXPR __sp_mut::__sp_mut(void* p) _NOEXCEPT
1414684ddb6SLionel Sambuc : __lx(p)
1424684ddb6SLionel Sambuc {
1434684ddb6SLionel Sambuc }
1444684ddb6SLionel Sambuc
1454684ddb6SLionel Sambuc void
lock()1464684ddb6SLionel Sambuc __sp_mut::lock() _NOEXCEPT
1474684ddb6SLionel Sambuc {
1484684ddb6SLionel Sambuc mutex& m = *static_cast<mutex*>(__lx);
1494684ddb6SLionel Sambuc unsigned count = 0;
1504684ddb6SLionel Sambuc while (!m.try_lock())
1514684ddb6SLionel Sambuc {
1524684ddb6SLionel Sambuc if (++count > 16)
1534684ddb6SLionel Sambuc {
1544684ddb6SLionel Sambuc m.lock();
1554684ddb6SLionel Sambuc break;
1564684ddb6SLionel Sambuc }
1574684ddb6SLionel Sambuc this_thread::yield();
1584684ddb6SLionel Sambuc }
1594684ddb6SLionel Sambuc }
1604684ddb6SLionel Sambuc
1614684ddb6SLionel Sambuc void
unlock()1624684ddb6SLionel Sambuc __sp_mut::unlock() _NOEXCEPT
1634684ddb6SLionel Sambuc {
1644684ddb6SLionel Sambuc static_cast<mutex*>(__lx)->unlock();
1654684ddb6SLionel Sambuc }
1664684ddb6SLionel Sambuc
1674684ddb6SLionel Sambuc __sp_mut&
__get_sp_mut(const void * p)1684684ddb6SLionel Sambuc __get_sp_mut(const void* p)
1694684ddb6SLionel Sambuc {
1704684ddb6SLionel Sambuc static __sp_mut muts[__sp_mut_count]
1714684ddb6SLionel Sambuc {
1724684ddb6SLionel Sambuc &mut_back[ 0], &mut_back[ 1], &mut_back[ 2], &mut_back[ 3],
1734684ddb6SLionel Sambuc &mut_back[ 4], &mut_back[ 5], &mut_back[ 6], &mut_back[ 7],
1744684ddb6SLionel Sambuc &mut_back[ 8], &mut_back[ 9], &mut_back[10], &mut_back[11],
1754684ddb6SLionel Sambuc &mut_back[12], &mut_back[13], &mut_back[14], &mut_back[15]
1764684ddb6SLionel Sambuc };
1774684ddb6SLionel Sambuc return muts[hash<const void*>()(p) & (__sp_mut_count-1)];
1784684ddb6SLionel Sambuc }
1794684ddb6SLionel Sambuc
180*0a6a1f1dSLionel Sambuc #endif // defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_NO_THREADS)
1814684ddb6SLionel Sambuc
1824684ddb6SLionel Sambuc void
declare_reachable(void *)1834684ddb6SLionel Sambuc declare_reachable(void*)
1844684ddb6SLionel Sambuc {
1854684ddb6SLionel Sambuc }
1864684ddb6SLionel Sambuc
1874684ddb6SLionel Sambuc void
declare_no_pointers(char *,size_t)1884684ddb6SLionel Sambuc declare_no_pointers(char*, size_t)
1894684ddb6SLionel Sambuc {
1904684ddb6SLionel Sambuc }
1914684ddb6SLionel Sambuc
1924684ddb6SLionel Sambuc void
undeclare_no_pointers(char *,size_t)1934684ddb6SLionel Sambuc undeclare_no_pointers(char*, size_t)
1944684ddb6SLionel Sambuc {
1954684ddb6SLionel Sambuc }
1964684ddb6SLionel Sambuc
1974684ddb6SLionel Sambuc pointer_safety
get_pointer_safety()1984684ddb6SLionel Sambuc get_pointer_safety() _NOEXCEPT
1994684ddb6SLionel Sambuc {
2004684ddb6SLionel Sambuc return pointer_safety::relaxed;
2014684ddb6SLionel Sambuc }
2024684ddb6SLionel Sambuc
2034684ddb6SLionel Sambuc void*
__undeclare_reachable(void * p)2044684ddb6SLionel Sambuc __undeclare_reachable(void* p)
2054684ddb6SLionel Sambuc {
2064684ddb6SLionel Sambuc return p;
2074684ddb6SLionel Sambuc }
2084684ddb6SLionel Sambuc
2094684ddb6SLionel Sambuc void*
align(size_t alignment,size_t size,void * & ptr,size_t & space)2104684ddb6SLionel Sambuc align(size_t alignment, size_t size, void*& ptr, size_t& space)
2114684ddb6SLionel Sambuc {
2124684ddb6SLionel Sambuc void* r = nullptr;
2134684ddb6SLionel Sambuc if (size <= space)
2144684ddb6SLionel Sambuc {
2154684ddb6SLionel Sambuc char* p1 = static_cast<char*>(ptr);
216*0a6a1f1dSLionel Sambuc char* p2 = reinterpret_cast<char*>(reinterpret_cast<size_t>(p1 + (alignment - 1)) & -alignment);
2174684ddb6SLionel Sambuc size_t d = static_cast<size_t>(p2 - p1);
2184684ddb6SLionel Sambuc if (d <= space - size)
2194684ddb6SLionel Sambuc {
2204684ddb6SLionel Sambuc r = p2;
2214684ddb6SLionel Sambuc ptr = r;
2224684ddb6SLionel Sambuc space -= d;
2234684ddb6SLionel Sambuc }
2244684ddb6SLionel Sambuc }
2254684ddb6SLionel Sambuc return r;
2264684ddb6SLionel Sambuc }
2274684ddb6SLionel Sambuc
2284684ddb6SLionel Sambuc _LIBCPP_END_NAMESPACE_STD
229