1*58b9f456SAndroid Build Coastguard Worker //===------------------------- mutex.cpp ----------------------------------===//
2*58b9f456SAndroid Build Coastguard Worker //
3*58b9f456SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*58b9f456SAndroid Build Coastguard Worker //
5*58b9f456SAndroid Build Coastguard Worker // This file is dual licensed under the MIT and the University of Illinois Open
6*58b9f456SAndroid Build Coastguard Worker // Source Licenses. See LICENSE.TXT for details.
7*58b9f456SAndroid Build Coastguard Worker //
8*58b9f456SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*58b9f456SAndroid Build Coastguard Worker
10*58b9f456SAndroid Build Coastguard Worker #include "mutex"
11*58b9f456SAndroid Build Coastguard Worker #include "limits"
12*58b9f456SAndroid Build Coastguard Worker #include "system_error"
13*58b9f456SAndroid Build Coastguard Worker #include "include/atomic_support.h"
14*58b9f456SAndroid Build Coastguard Worker #include "__undef_macros"
15*58b9f456SAndroid Build Coastguard Worker
16*58b9f456SAndroid Build Coastguard Worker _LIBCPP_BEGIN_NAMESPACE_STD
17*58b9f456SAndroid Build Coastguard Worker #ifndef _LIBCPP_HAS_NO_THREADS
18*58b9f456SAndroid Build Coastguard Worker
19*58b9f456SAndroid Build Coastguard Worker const defer_lock_t defer_lock = {};
20*58b9f456SAndroid Build Coastguard Worker const try_to_lock_t try_to_lock = {};
21*58b9f456SAndroid Build Coastguard Worker const adopt_lock_t adopt_lock = {};
22*58b9f456SAndroid Build Coastguard Worker
~mutex()23*58b9f456SAndroid Build Coastguard Worker mutex::~mutex()
24*58b9f456SAndroid Build Coastguard Worker {
25*58b9f456SAndroid Build Coastguard Worker __libcpp_mutex_destroy(&__m_);
26*58b9f456SAndroid Build Coastguard Worker }
27*58b9f456SAndroid Build Coastguard Worker
28*58b9f456SAndroid Build Coastguard Worker void
lock()29*58b9f456SAndroid Build Coastguard Worker mutex::lock()
30*58b9f456SAndroid Build Coastguard Worker {
31*58b9f456SAndroid Build Coastguard Worker int ec = __libcpp_mutex_lock(&__m_);
32*58b9f456SAndroid Build Coastguard Worker if (ec)
33*58b9f456SAndroid Build Coastguard Worker __throw_system_error(ec, "mutex lock failed");
34*58b9f456SAndroid Build Coastguard Worker }
35*58b9f456SAndroid Build Coastguard Worker
36*58b9f456SAndroid Build Coastguard Worker bool
try_lock()37*58b9f456SAndroid Build Coastguard Worker mutex::try_lock() _NOEXCEPT
38*58b9f456SAndroid Build Coastguard Worker {
39*58b9f456SAndroid Build Coastguard Worker return __libcpp_mutex_trylock(&__m_);
40*58b9f456SAndroid Build Coastguard Worker }
41*58b9f456SAndroid Build Coastguard Worker
42*58b9f456SAndroid Build Coastguard Worker void
unlock()43*58b9f456SAndroid Build Coastguard Worker mutex::unlock() _NOEXCEPT
44*58b9f456SAndroid Build Coastguard Worker {
45*58b9f456SAndroid Build Coastguard Worker int ec = __libcpp_mutex_unlock(&__m_);
46*58b9f456SAndroid Build Coastguard Worker (void)ec;
47*58b9f456SAndroid Build Coastguard Worker _LIBCPP_ASSERT(ec == 0, "call to mutex::unlock failed");
48*58b9f456SAndroid Build Coastguard Worker }
49*58b9f456SAndroid Build Coastguard Worker
50*58b9f456SAndroid Build Coastguard Worker // recursive_mutex
51*58b9f456SAndroid Build Coastguard Worker
recursive_mutex()52*58b9f456SAndroid Build Coastguard Worker recursive_mutex::recursive_mutex()
53*58b9f456SAndroid Build Coastguard Worker {
54*58b9f456SAndroid Build Coastguard Worker int ec = __libcpp_recursive_mutex_init(&__m_);
55*58b9f456SAndroid Build Coastguard Worker if (ec)
56*58b9f456SAndroid Build Coastguard Worker __throw_system_error(ec, "recursive_mutex constructor failed");
57*58b9f456SAndroid Build Coastguard Worker }
58*58b9f456SAndroid Build Coastguard Worker
~recursive_mutex()59*58b9f456SAndroid Build Coastguard Worker recursive_mutex::~recursive_mutex()
60*58b9f456SAndroid Build Coastguard Worker {
61*58b9f456SAndroid Build Coastguard Worker int e = __libcpp_recursive_mutex_destroy(&__m_);
62*58b9f456SAndroid Build Coastguard Worker (void)e;
63*58b9f456SAndroid Build Coastguard Worker _LIBCPP_ASSERT(e == 0, "call to ~recursive_mutex() failed");
64*58b9f456SAndroid Build Coastguard Worker }
65*58b9f456SAndroid Build Coastguard Worker
66*58b9f456SAndroid Build Coastguard Worker void
lock()67*58b9f456SAndroid Build Coastguard Worker recursive_mutex::lock()
68*58b9f456SAndroid Build Coastguard Worker {
69*58b9f456SAndroid Build Coastguard Worker int ec = __libcpp_recursive_mutex_lock(&__m_);
70*58b9f456SAndroid Build Coastguard Worker if (ec)
71*58b9f456SAndroid Build Coastguard Worker __throw_system_error(ec, "recursive_mutex lock failed");
72*58b9f456SAndroid Build Coastguard Worker }
73*58b9f456SAndroid Build Coastguard Worker
74*58b9f456SAndroid Build Coastguard Worker void
unlock()75*58b9f456SAndroid Build Coastguard Worker recursive_mutex::unlock() _NOEXCEPT
76*58b9f456SAndroid Build Coastguard Worker {
77*58b9f456SAndroid Build Coastguard Worker int e = __libcpp_recursive_mutex_unlock(&__m_);
78*58b9f456SAndroid Build Coastguard Worker (void)e;
79*58b9f456SAndroid Build Coastguard Worker _LIBCPP_ASSERT(e == 0, "call to recursive_mutex::unlock() failed");
80*58b9f456SAndroid Build Coastguard Worker }
81*58b9f456SAndroid Build Coastguard Worker
82*58b9f456SAndroid Build Coastguard Worker bool
try_lock()83*58b9f456SAndroid Build Coastguard Worker recursive_mutex::try_lock() _NOEXCEPT
84*58b9f456SAndroid Build Coastguard Worker {
85*58b9f456SAndroid Build Coastguard Worker return __libcpp_recursive_mutex_trylock(&__m_);
86*58b9f456SAndroid Build Coastguard Worker }
87*58b9f456SAndroid Build Coastguard Worker
88*58b9f456SAndroid Build Coastguard Worker // timed_mutex
89*58b9f456SAndroid Build Coastguard Worker
timed_mutex()90*58b9f456SAndroid Build Coastguard Worker timed_mutex::timed_mutex()
91*58b9f456SAndroid Build Coastguard Worker : __locked_(false)
92*58b9f456SAndroid Build Coastguard Worker {
93*58b9f456SAndroid Build Coastguard Worker }
94*58b9f456SAndroid Build Coastguard Worker
~timed_mutex()95*58b9f456SAndroid Build Coastguard Worker timed_mutex::~timed_mutex()
96*58b9f456SAndroid Build Coastguard Worker {
97*58b9f456SAndroid Build Coastguard Worker lock_guard<mutex> _(__m_);
98*58b9f456SAndroid Build Coastguard Worker }
99*58b9f456SAndroid Build Coastguard Worker
100*58b9f456SAndroid Build Coastguard Worker void
lock()101*58b9f456SAndroid Build Coastguard Worker timed_mutex::lock()
102*58b9f456SAndroid Build Coastguard Worker {
103*58b9f456SAndroid Build Coastguard Worker unique_lock<mutex> lk(__m_);
104*58b9f456SAndroid Build Coastguard Worker while (__locked_)
105*58b9f456SAndroid Build Coastguard Worker __cv_.wait(lk);
106*58b9f456SAndroid Build Coastguard Worker __locked_ = true;
107*58b9f456SAndroid Build Coastguard Worker }
108*58b9f456SAndroid Build Coastguard Worker
109*58b9f456SAndroid Build Coastguard Worker bool
try_lock()110*58b9f456SAndroid Build Coastguard Worker timed_mutex::try_lock() _NOEXCEPT
111*58b9f456SAndroid Build Coastguard Worker {
112*58b9f456SAndroid Build Coastguard Worker unique_lock<mutex> lk(__m_, try_to_lock);
113*58b9f456SAndroid Build Coastguard Worker if (lk.owns_lock() && !__locked_)
114*58b9f456SAndroid Build Coastguard Worker {
115*58b9f456SAndroid Build Coastguard Worker __locked_ = true;
116*58b9f456SAndroid Build Coastguard Worker return true;
117*58b9f456SAndroid Build Coastguard Worker }
118*58b9f456SAndroid Build Coastguard Worker return false;
119*58b9f456SAndroid Build Coastguard Worker }
120*58b9f456SAndroid Build Coastguard Worker
121*58b9f456SAndroid Build Coastguard Worker void
unlock()122*58b9f456SAndroid Build Coastguard Worker timed_mutex::unlock() _NOEXCEPT
123*58b9f456SAndroid Build Coastguard Worker {
124*58b9f456SAndroid Build Coastguard Worker lock_guard<mutex> _(__m_);
125*58b9f456SAndroid Build Coastguard Worker __locked_ = false;
126*58b9f456SAndroid Build Coastguard Worker __cv_.notify_one();
127*58b9f456SAndroid Build Coastguard Worker }
128*58b9f456SAndroid Build Coastguard Worker
129*58b9f456SAndroid Build Coastguard Worker // recursive_timed_mutex
130*58b9f456SAndroid Build Coastguard Worker
recursive_timed_mutex()131*58b9f456SAndroid Build Coastguard Worker recursive_timed_mutex::recursive_timed_mutex()
132*58b9f456SAndroid Build Coastguard Worker : __count_(0),
133*58b9f456SAndroid Build Coastguard Worker __id_(0)
134*58b9f456SAndroid Build Coastguard Worker {
135*58b9f456SAndroid Build Coastguard Worker }
136*58b9f456SAndroid Build Coastguard Worker
~recursive_timed_mutex()137*58b9f456SAndroid Build Coastguard Worker recursive_timed_mutex::~recursive_timed_mutex()
138*58b9f456SAndroid Build Coastguard Worker {
139*58b9f456SAndroid Build Coastguard Worker lock_guard<mutex> _(__m_);
140*58b9f456SAndroid Build Coastguard Worker }
141*58b9f456SAndroid Build Coastguard Worker
142*58b9f456SAndroid Build Coastguard Worker void
lock()143*58b9f456SAndroid Build Coastguard Worker recursive_timed_mutex::lock()
144*58b9f456SAndroid Build Coastguard Worker {
145*58b9f456SAndroid Build Coastguard Worker __libcpp_thread_id id = __libcpp_thread_get_current_id();
146*58b9f456SAndroid Build Coastguard Worker unique_lock<mutex> lk(__m_);
147*58b9f456SAndroid Build Coastguard Worker if (__libcpp_thread_id_equal(id, __id_))
148*58b9f456SAndroid Build Coastguard Worker {
149*58b9f456SAndroid Build Coastguard Worker if (__count_ == numeric_limits<size_t>::max())
150*58b9f456SAndroid Build Coastguard Worker __throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached");
151*58b9f456SAndroid Build Coastguard Worker ++__count_;
152*58b9f456SAndroid Build Coastguard Worker return;
153*58b9f456SAndroid Build Coastguard Worker }
154*58b9f456SAndroid Build Coastguard Worker while (__count_ != 0)
155*58b9f456SAndroid Build Coastguard Worker __cv_.wait(lk);
156*58b9f456SAndroid Build Coastguard Worker __count_ = 1;
157*58b9f456SAndroid Build Coastguard Worker __id_ = id;
158*58b9f456SAndroid Build Coastguard Worker }
159*58b9f456SAndroid Build Coastguard Worker
160*58b9f456SAndroid Build Coastguard Worker bool
try_lock()161*58b9f456SAndroid Build Coastguard Worker recursive_timed_mutex::try_lock() _NOEXCEPT
162*58b9f456SAndroid Build Coastguard Worker {
163*58b9f456SAndroid Build Coastguard Worker __libcpp_thread_id id = __libcpp_thread_get_current_id();
164*58b9f456SAndroid Build Coastguard Worker unique_lock<mutex> lk(__m_, try_to_lock);
165*58b9f456SAndroid Build Coastguard Worker if (lk.owns_lock() && (__count_ == 0 || __libcpp_thread_id_equal(id, __id_)))
166*58b9f456SAndroid Build Coastguard Worker {
167*58b9f456SAndroid Build Coastguard Worker if (__count_ == numeric_limits<size_t>::max())
168*58b9f456SAndroid Build Coastguard Worker return false;
169*58b9f456SAndroid Build Coastguard Worker ++__count_;
170*58b9f456SAndroid Build Coastguard Worker __id_ = id;
171*58b9f456SAndroid Build Coastguard Worker return true;
172*58b9f456SAndroid Build Coastguard Worker }
173*58b9f456SAndroid Build Coastguard Worker return false;
174*58b9f456SAndroid Build Coastguard Worker }
175*58b9f456SAndroid Build Coastguard Worker
176*58b9f456SAndroid Build Coastguard Worker void
unlock()177*58b9f456SAndroid Build Coastguard Worker recursive_timed_mutex::unlock() _NOEXCEPT
178*58b9f456SAndroid Build Coastguard Worker {
179*58b9f456SAndroid Build Coastguard Worker unique_lock<mutex> lk(__m_);
180*58b9f456SAndroid Build Coastguard Worker if (--__count_ == 0)
181*58b9f456SAndroid Build Coastguard Worker {
182*58b9f456SAndroid Build Coastguard Worker __id_ = 0;
183*58b9f456SAndroid Build Coastguard Worker lk.unlock();
184*58b9f456SAndroid Build Coastguard Worker __cv_.notify_one();
185*58b9f456SAndroid Build Coastguard Worker }
186*58b9f456SAndroid Build Coastguard Worker }
187*58b9f456SAndroid Build Coastguard Worker
188*58b9f456SAndroid Build Coastguard Worker #endif // !_LIBCPP_HAS_NO_THREADS
189*58b9f456SAndroid Build Coastguard Worker
190*58b9f456SAndroid Build Coastguard Worker // If dispatch_once_f ever handles C++ exceptions, and if one can get to it
191*58b9f456SAndroid Build Coastguard Worker // without illegal macros (unexpected macros not beginning with _UpperCase or
192*58b9f456SAndroid Build Coastguard Worker // __lowercase), and if it stops spinning waiting threads, then call_once should
193*58b9f456SAndroid Build Coastguard Worker // call into dispatch_once_f instead of here. Relevant radar this code needs to
194*58b9f456SAndroid Build Coastguard Worker // keep in sync with: 7741191.
195*58b9f456SAndroid Build Coastguard Worker
196*58b9f456SAndroid Build Coastguard Worker #ifndef _LIBCPP_HAS_NO_THREADS
197*58b9f456SAndroid Build Coastguard Worker _LIBCPP_SAFE_STATIC static __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER;
198*58b9f456SAndroid Build Coastguard Worker _LIBCPP_SAFE_STATIC static __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER;
199*58b9f456SAndroid Build Coastguard Worker #endif
200*58b9f456SAndroid Build Coastguard Worker
201*58b9f456SAndroid Build Coastguard Worker void
__call_once(volatile unsigned long & flag,void * arg,void (* func)(void *))202*58b9f456SAndroid Build Coastguard Worker __call_once(volatile unsigned long& flag, void* arg, void(*func)(void*))
203*58b9f456SAndroid Build Coastguard Worker {
204*58b9f456SAndroid Build Coastguard Worker #if defined(_LIBCPP_HAS_NO_THREADS)
205*58b9f456SAndroid Build Coastguard Worker if (flag == 0)
206*58b9f456SAndroid Build Coastguard Worker {
207*58b9f456SAndroid Build Coastguard Worker #ifndef _LIBCPP_NO_EXCEPTIONS
208*58b9f456SAndroid Build Coastguard Worker try
209*58b9f456SAndroid Build Coastguard Worker {
210*58b9f456SAndroid Build Coastguard Worker #endif // _LIBCPP_NO_EXCEPTIONS
211*58b9f456SAndroid Build Coastguard Worker flag = 1;
212*58b9f456SAndroid Build Coastguard Worker func(arg);
213*58b9f456SAndroid Build Coastguard Worker flag = ~0ul;
214*58b9f456SAndroid Build Coastguard Worker #ifndef _LIBCPP_NO_EXCEPTIONS
215*58b9f456SAndroid Build Coastguard Worker }
216*58b9f456SAndroid Build Coastguard Worker catch (...)
217*58b9f456SAndroid Build Coastguard Worker {
218*58b9f456SAndroid Build Coastguard Worker flag = 0ul;
219*58b9f456SAndroid Build Coastguard Worker throw;
220*58b9f456SAndroid Build Coastguard Worker }
221*58b9f456SAndroid Build Coastguard Worker #endif // _LIBCPP_NO_EXCEPTIONS
222*58b9f456SAndroid Build Coastguard Worker }
223*58b9f456SAndroid Build Coastguard Worker #else // !_LIBCPP_HAS_NO_THREADS
224*58b9f456SAndroid Build Coastguard Worker __libcpp_mutex_lock(&mut);
225*58b9f456SAndroid Build Coastguard Worker while (flag == 1)
226*58b9f456SAndroid Build Coastguard Worker __libcpp_condvar_wait(&cv, &mut);
227*58b9f456SAndroid Build Coastguard Worker if (flag == 0)
228*58b9f456SAndroid Build Coastguard Worker {
229*58b9f456SAndroid Build Coastguard Worker #ifndef _LIBCPP_NO_EXCEPTIONS
230*58b9f456SAndroid Build Coastguard Worker try
231*58b9f456SAndroid Build Coastguard Worker {
232*58b9f456SAndroid Build Coastguard Worker #endif // _LIBCPP_NO_EXCEPTIONS
233*58b9f456SAndroid Build Coastguard Worker __libcpp_relaxed_store(&flag, 1ul);
234*58b9f456SAndroid Build Coastguard Worker __libcpp_mutex_unlock(&mut);
235*58b9f456SAndroid Build Coastguard Worker func(arg);
236*58b9f456SAndroid Build Coastguard Worker __libcpp_mutex_lock(&mut);
237*58b9f456SAndroid Build Coastguard Worker __libcpp_atomic_store(&flag, ~0ul, _AO_Release);
238*58b9f456SAndroid Build Coastguard Worker __libcpp_mutex_unlock(&mut);
239*58b9f456SAndroid Build Coastguard Worker __libcpp_condvar_broadcast(&cv);
240*58b9f456SAndroid Build Coastguard Worker #ifndef _LIBCPP_NO_EXCEPTIONS
241*58b9f456SAndroid Build Coastguard Worker }
242*58b9f456SAndroid Build Coastguard Worker catch (...)
243*58b9f456SAndroid Build Coastguard Worker {
244*58b9f456SAndroid Build Coastguard Worker __libcpp_mutex_lock(&mut);
245*58b9f456SAndroid Build Coastguard Worker __libcpp_relaxed_store(&flag, 0ul);
246*58b9f456SAndroid Build Coastguard Worker __libcpp_mutex_unlock(&mut);
247*58b9f456SAndroid Build Coastguard Worker __libcpp_condvar_broadcast(&cv);
248*58b9f456SAndroid Build Coastguard Worker throw;
249*58b9f456SAndroid Build Coastguard Worker }
250*58b9f456SAndroid Build Coastguard Worker #endif // _LIBCPP_NO_EXCEPTIONS
251*58b9f456SAndroid Build Coastguard Worker }
252*58b9f456SAndroid Build Coastguard Worker else
253*58b9f456SAndroid Build Coastguard Worker __libcpp_mutex_unlock(&mut);
254*58b9f456SAndroid Build Coastguard Worker #endif // !_LIBCPP_HAS_NO_THREADS
255*58b9f456SAndroid Build Coastguard Worker
256*58b9f456SAndroid Build Coastguard Worker }
257*58b9f456SAndroid Build Coastguard Worker
258*58b9f456SAndroid Build Coastguard Worker _LIBCPP_END_NAMESPACE_STD
259