1 //===------------------------- mutex.cpp ----------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #define _LIBCPP_BUILDING_MUTEX
13 #include "system_error"
14 #include "include/atomic_support.h"
16 _LIBCPP_BEGIN_NAMESPACE_STD
17 #ifndef _LIBCPP_HAS_NO_THREADS
19 const defer_lock_t defer_lock = {};
20 const try_to_lock_t try_to_lock = {};
21 const adopt_lock_t adopt_lock = {};
25 __libcpp_mutex_destroy(&__m_);
31 int ec = __libcpp_mutex_lock(&__m_);
33 __throw_system_error(ec, "mutex lock failed");
37 mutex::try_lock() _NOEXCEPT
39 return __libcpp_mutex_trylock(&__m_);
43 mutex::unlock() _NOEXCEPT
45 int ec = __libcpp_mutex_unlock(&__m_);
47 _LIBCPP_ASSERT(ec == 0, "call to mutex::unlock failed");
52 recursive_mutex::recursive_mutex()
54 int ec = __libcpp_recursive_mutex_init(&__m_);
56 __throw_system_error(ec, "recursive_mutex constructor failed");
59 recursive_mutex::~recursive_mutex()
61 int e = __libcpp_recursive_mutex_destroy(&__m_);
63 _LIBCPP_ASSERT(e == 0, "call to ~recursive_mutex() failed");
67 recursive_mutex::lock()
69 int ec = __libcpp_recursive_mutex_lock(&__m_);
71 __throw_system_error(ec, "recursive_mutex lock failed");
75 recursive_mutex::unlock() _NOEXCEPT
77 int e = __libcpp_recursive_mutex_unlock(&__m_);
79 _LIBCPP_ASSERT(e == 0, "call to recursive_mutex::unlock() failed");
83 recursive_mutex::try_lock() _NOEXCEPT
85 return __libcpp_recursive_mutex_trylock(&__m_);
90 timed_mutex::timed_mutex()
95 timed_mutex::~timed_mutex()
97 lock_guard<mutex> _(__m_);
103 unique_lock<mutex> lk(__m_);
110 timed_mutex::try_lock() _NOEXCEPT
112 unique_lock<mutex> lk(__m_, try_to_lock);
113 if (lk.owns_lock() && !__locked_)
122 timed_mutex::unlock() _NOEXCEPT
124 lock_guard<mutex> _(__m_);
129 // recursive_timed_mutex
131 recursive_timed_mutex::recursive_timed_mutex()
137 recursive_timed_mutex::~recursive_timed_mutex()
139 lock_guard<mutex> _(__m_);
143 recursive_timed_mutex::lock()
145 __libcpp_thread_id id = __libcpp_thread_get_current_id();
146 unique_lock<mutex> lk(__m_);
147 if (__libcpp_thread_id_equal(id, __id_))
149 if (__count_ == numeric_limits<size_t>::max())
150 __throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached");
154 while (__count_ != 0)
161 recursive_timed_mutex::try_lock() _NOEXCEPT
163 __libcpp_thread_id id = __libcpp_thread_get_current_id();
164 unique_lock<mutex> lk(__m_, try_to_lock);
165 if (lk.owns_lock() && (__count_ == 0 || __libcpp_thread_id_equal(id, __id_)))
167 if (__count_ == numeric_limits<size_t>::max())
177 recursive_timed_mutex::unlock() _NOEXCEPT
179 unique_lock<mutex> lk(__m_);
188 #endif // !_LIBCPP_HAS_NO_THREADS
190 // If dispatch_once_f ever handles C++ exceptions, and if one can get to it
191 // without illegal macros (unexpected macros not beginning with _UpperCase or
192 // __lowercase), and if it stops spinning waiting threads, then call_once should
193 // call into dispatch_once_f instead of here. Relevant radar this code needs to
194 // keep in sync with: 7741191.
196 #ifndef _LIBCPP_HAS_NO_THREADS
197 _LIBCPP_SAFE_STATIC static __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER;
198 _LIBCPP_SAFE_STATIC static __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER;
202 __call_once(volatile unsigned long& flag, void* arg, void(*func)(void*))
204 #if defined(_LIBCPP_HAS_NO_THREADS)
207 #ifndef _LIBCPP_NO_EXCEPTIONS
210 #endif // _LIBCPP_NO_EXCEPTIONS
214 #ifndef _LIBCPP_NO_EXCEPTIONS
221 #endif // _LIBCPP_NO_EXCEPTIONS
223 #else // !_LIBCPP_HAS_NO_THREADS
224 __libcpp_mutex_lock(&mut);
226 __libcpp_condvar_wait(&cv, &mut);
229 #ifndef _LIBCPP_NO_EXCEPTIONS
232 #endif // _LIBCPP_NO_EXCEPTIONS
233 __libcpp_relaxed_store(&flag, 1ul);
234 __libcpp_mutex_unlock(&mut);
236 __libcpp_mutex_lock(&mut);
237 __libcpp_atomic_store(&flag, ~0ul, _AO_Release);
238 __libcpp_mutex_unlock(&mut);
239 __libcpp_condvar_broadcast(&cv);
240 #ifndef _LIBCPP_NO_EXCEPTIONS
244 __libcpp_mutex_lock(&mut);
245 __libcpp_relaxed_store(&flag, 0ul);
246 __libcpp_mutex_unlock(&mut);
247 __libcpp_condvar_broadcast(&cv);
250 #endif // _LIBCPP_NO_EXCEPTIONS
253 __libcpp_mutex_unlock(&mut);
254 #endif // !_LIBCPP_HAS_NO_THREADS
258 _LIBCPP_END_NAMESPACE_STD