blob: 9e780aaff64e85dadf2695dc8a6f5f3fb0f82522 [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 <limits>
10#include <mutex>
11#include <system_error>
12
Eric Fiseliere8fd1642015-08-18 21:08:5413#include "include/atomic_support.h"
Howard Hinnant3e519522010-05-11 19:42:1614
Petr Hosek996e62e2019-05-30 01:34:4115#ifndef _LIBCPP_HAS_NO_THREADS
Arthur O'Dwyerbbb0f2c2022-02-11 18:00:3916# if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
17# pragma comment(lib, "pthread")
18# endif
Petr Hosek996e62e2019-05-30 01:34:4119#endif
20
Arthur O'Dwyerbbb0f2c2022-02-11 18:00:3921_LIBCPP_PUSH_MACROS
22#include <__undef_macros>
23
Howard Hinnant3e519522010-05-11 19:42:1624_LIBCPP_BEGIN_NAMESPACE_STD
Arthur O'Dwyerbbb0f2c2022-02-11 18:00:3925
Jonathan Roelofsb3fcc672014-09-05 19:45:0526#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant3e519522010-05-11 19:42:1627
Louis Dionnee16f2cb2019-09-26 14:51:1028const defer_lock_t defer_lock{};
29const try_to_lock_t try_to_lock{};
30const adopt_lock_t adopt_lock{};
Howard Hinnant3e519522010-05-11 19:42:1631
Eric Fiselier8baf8382019-07-07 01:20:5432// ~mutex is defined elsewhere
Howard Hinnant3e519522010-05-11 19:42:1633
34void
35mutex::lock()
36{
Asiri Rathnayakec7e42392016-05-06 14:06:2937 int ec = __libcpp_mutex_lock(&__m_);
Howard Hinnant3e519522010-05-11 19:42:1638 if (ec)
39 __throw_system_error(ec, "mutex lock failed");
40}
41
42bool
Louis Dionne56013052021-03-01 17:09:4543mutex::try_lock() noexcept
Howard Hinnant3e519522010-05-11 19:42:1644{
Eric Fiselier08e14772017-01-14 10:27:1245 return __libcpp_mutex_trylock(&__m_);
Howard Hinnant3e519522010-05-11 19:42:1646}
47
48void
Louis Dionne56013052021-03-01 17:09:4549mutex::unlock() noexcept
Howard Hinnant3e519522010-05-11 19:42:1650{
Asiri Rathnayakec7e42392016-05-06 14:06:2951 int ec = __libcpp_mutex_unlock(&__m_);
Howard Hinnant12bfc4f2013-09-21 21:26:3752 (void)ec;
Eric Fiseliere49cdfb2017-02-04 23:22:2853 _LIBCPP_ASSERT(ec == 0, "call to mutex::unlock failed");
Howard Hinnant3e519522010-05-11 19:42:1654}
55
56// recursive_mutex
57
58recursive_mutex::recursive_mutex()
59{
Asiri Rathnayakec7e42392016-05-06 14:06:2960 int ec = __libcpp_recursive_mutex_init(&__m_);
Howard Hinnant3e519522010-05-11 19:42:1661 if (ec)
Asiri Rathnayakec7e42392016-05-06 14:06:2962 __throw_system_error(ec, "recursive_mutex constructor failed");
Howard Hinnant3e519522010-05-11 19:42:1663}
64
65recursive_mutex::~recursive_mutex()
66{
Saleem Abdulrasool58a0dce2017-01-05 17:54:4567 int e = __libcpp_recursive_mutex_destroy(&__m_);
Howard Hinnant12bfc4f2013-09-21 21:26:3768 (void)e;
Eric Fiseliere49cdfb2017-02-04 23:22:2869 _LIBCPP_ASSERT(e == 0, "call to ~recursive_mutex() failed");
Howard Hinnant3e519522010-05-11 19:42:1670}
71
72void
73recursive_mutex::lock()
74{
Saleem Abdulrasool58a0dce2017-01-05 17:54:4575 int ec = __libcpp_recursive_mutex_lock(&__m_);
Howard Hinnant3e519522010-05-11 19:42:1676 if (ec)
77 __throw_system_error(ec, "recursive_mutex lock failed");
78}
79
80void
Louis Dionne56013052021-03-01 17:09:4581recursive_mutex::unlock() noexcept
Howard Hinnant3e519522010-05-11 19:42:1682{
Saleem Abdulrasool58a0dce2017-01-05 17:54:4583 int e = __libcpp_recursive_mutex_unlock(&__m_);
Howard Hinnant12bfc4f2013-09-21 21:26:3784 (void)e;
Eric Fiseliere49cdfb2017-02-04 23:22:2885 _LIBCPP_ASSERT(e == 0, "call to recursive_mutex::unlock() failed");
Howard Hinnant3e519522010-05-11 19:42:1686}
87
88bool
Louis Dionne56013052021-03-01 17:09:4589recursive_mutex::try_lock() noexcept
Howard Hinnant3e519522010-05-11 19:42:1690{
Eric Fiselier08e14772017-01-14 10:27:1291 return __libcpp_recursive_mutex_trylock(&__m_);
Howard Hinnant3e519522010-05-11 19:42:1692}
93
94// timed_mutex
95
96timed_mutex::timed_mutex()
97 : __locked_(false)
98{
99}
100
101timed_mutex::~timed_mutex()
102{
103 lock_guard<mutex> _(__m_);
104}
105
106void
107timed_mutex::lock()
108{
109 unique_lock<mutex> lk(__m_);
110 while (__locked_)
111 __cv_.wait(lk);
112 __locked_ = true;
113}
114
115bool
Louis Dionne56013052021-03-01 17:09:45116timed_mutex::try_lock() noexcept
Howard Hinnant3e519522010-05-11 19:42:16117{
118 unique_lock<mutex> lk(__m_, try_to_lock);
119 if (lk.owns_lock() && !__locked_)
120 {
121 __locked_ = true;
122 return true;
123 }
124 return false;
125}
126
127void
Louis Dionne56013052021-03-01 17:09:45128timed_mutex::unlock() noexcept
Howard Hinnant3e519522010-05-11 19:42:16129{
130 lock_guard<mutex> _(__m_);
131 __locked_ = false;
132 __cv_.notify_one();
133}
134
135// recursive_timed_mutex
136
137recursive_timed_mutex::recursive_timed_mutex()
138 : __count_(0),
Marshall Clow2b1d4252019-08-14 16:21:27139 __id_{}
Howard Hinnant3e519522010-05-11 19:42:16140{
141}
142
143recursive_timed_mutex::~recursive_timed_mutex()
144{
145 lock_guard<mutex> _(__m_);
146}
147
148void
149recursive_timed_mutex::lock()
150{
Marshall Clow2b1d4252019-08-14 16:21:27151 __thread_id id = this_thread::get_id();
Howard Hinnant3e519522010-05-11 19:42:16152 unique_lock<mutex> lk(__m_);
Marshall Clow2b1d4252019-08-14 16:21:27153 if (id ==__id_)
Howard Hinnant3e519522010-05-11 19:42:16154 {
155 if (__count_ == numeric_limits<size_t>::max())
156 __throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached");
157 ++__count_;
158 return;
159 }
160 while (__count_ != 0)
161 __cv_.wait(lk);
162 __count_ = 1;
163 __id_ = id;
164}
165
166bool
Louis Dionne56013052021-03-01 17:09:45167recursive_timed_mutex::try_lock() noexcept
Howard Hinnant3e519522010-05-11 19:42:16168{
Marshall Clow2b1d4252019-08-14 16:21:27169 __thread_id id = this_thread::get_id();
Howard Hinnant3e519522010-05-11 19:42:16170 unique_lock<mutex> lk(__m_, try_to_lock);
Marshall Clow2b1d4252019-08-14 16:21:27171 if (lk.owns_lock() && (__count_ == 0 || id == __id_))
Howard Hinnant3e519522010-05-11 19:42:16172 {
173 if (__count_ == numeric_limits<size_t>::max())
174 return false;
175 ++__count_;
176 __id_ = id;
177 return true;
178 }
179 return false;
180}
181
182void
Louis Dionne56013052021-03-01 17:09:45183recursive_timed_mutex::unlock() noexcept
Howard Hinnant3e519522010-05-11 19:42:16184{
185 unique_lock<mutex> lk(__m_);
186 if (--__count_ == 0)
187 {
Marshall Clow2e80d012019-08-14 20:54:56188 __id_.__reset();
Howard Hinnant3e519522010-05-11 19:42:16189 lk.unlock();
190 __cv_.notify_one();
191 }
192}
193
Jonathan Roelofsb3fcc672014-09-05 19:45:05194#endif // !_LIBCPP_HAS_NO_THREADS
195
Howard Hinnant3e519522010-05-11 19:42:16196// If dispatch_once_f ever handles C++ exceptions, and if one can get to it
197// without illegal macros (unexpected macros not beginning with _UpperCase or
198// __lowercase), and if it stops spinning waiting threads, then call_once should
199// call into dispatch_once_f instead of here. Relevant radar this code needs to
200// keep in sync with: 7741191.
201
Jonathan Roelofsb3fcc672014-09-05 19:45:05202#ifndef _LIBCPP_HAS_NO_THREADS
Arthur O'Dwyer05337a72022-02-08 18:08:59203static constinit __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER;
204static constinit __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER;
Jonathan Roelofsb3fcc672014-09-05 19:45:05205#endif
Howard Hinnant3e519522010-05-11 19:42:16206
Nico Weber0fd00a52019-03-20 22:55:03207void __call_once(volatile once_flag::_State_type& flag, void* arg,
208 void (*func)(void*))
Howard Hinnant3e519522010-05-11 19:42:16209{
Jonathan Roelofsb3fcc672014-09-05 19:45:05210#if defined(_LIBCPP_HAS_NO_THREADS)
211 if (flag == 0)
212 {
213#ifndef _LIBCPP_NO_EXCEPTIONS
214 try
215 {
Louis Dionne4cd6ca12021-04-20 16:03:32216#endif // _LIBCPP_NO_EXCEPTIONS
Jonathan Roelofsb3fcc672014-09-05 19:45:05217 flag = 1;
218 func(arg);
Nico Weber0fd00a52019-03-20 22:55:03219 flag = ~once_flag::_State_type(0);
Jonathan Roelofsb3fcc672014-09-05 19:45:05220#ifndef _LIBCPP_NO_EXCEPTIONS
221 }
222 catch (...)
223 {
Nico Weber0fd00a52019-03-20 22:55:03224 flag = 0;
Jonathan Roelofsb3fcc672014-09-05 19:45:05225 throw;
226 }
Louis Dionne4cd6ca12021-04-20 16:03:32227#endif // _LIBCPP_NO_EXCEPTIONS
Jonathan Roelofsb3fcc672014-09-05 19:45:05228 }
229#else // !_LIBCPP_HAS_NO_THREADS
Asiri Rathnayakec7e42392016-05-06 14:06:29230 __libcpp_mutex_lock(&mut);
Howard Hinnant3e519522010-05-11 19:42:16231 while (flag == 1)
Asiri Rathnayakec7e42392016-05-06 14:06:29232 __libcpp_condvar_wait(&cv, &mut);
Howard Hinnant3e519522010-05-11 19:42:16233 if (flag == 0)
234 {
Howard Hinnant54b409f2010-08-11 17:04:31235#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3e519522010-05-11 19:42:16236 try
237 {
Louis Dionne4cd6ca12021-04-20 16:03:32238#endif // _LIBCPP_NO_EXCEPTIONS
Nico Weber0fd00a52019-03-20 22:55:03239 __libcpp_relaxed_store(&flag, once_flag::_State_type(1));
Asiri Rathnayakec7e42392016-05-06 14:06:29240 __libcpp_mutex_unlock(&mut);
Howard Hinnant3e519522010-05-11 19:42:16241 func(arg);
Asiri Rathnayakec7e42392016-05-06 14:06:29242 __libcpp_mutex_lock(&mut);
Nico Weber0fd00a52019-03-20 22:55:03243 __libcpp_atomic_store(&flag, ~once_flag::_State_type(0),
244 _AO_Release);
Asiri Rathnayakec7e42392016-05-06 14:06:29245 __libcpp_mutex_unlock(&mut);
246 __libcpp_condvar_broadcast(&cv);
Howard Hinnant54b409f2010-08-11 17:04:31247#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3e519522010-05-11 19:42:16248 }
249 catch (...)
250 {
Asiri Rathnayakec7e42392016-05-06 14:06:29251 __libcpp_mutex_lock(&mut);
Nico Weber0fd00a52019-03-20 22:55:03252 __libcpp_relaxed_store(&flag, once_flag::_State_type(0));
Asiri Rathnayakec7e42392016-05-06 14:06:29253 __libcpp_mutex_unlock(&mut);
254 __libcpp_condvar_broadcast(&cv);
Howard Hinnant3e519522010-05-11 19:42:16255 throw;
256 }
Louis Dionne4cd6ca12021-04-20 16:03:32257#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3e519522010-05-11 19:42:16258 }
259 else
Asiri Rathnayakec7e42392016-05-06 14:06:29260 __libcpp_mutex_unlock(&mut);
Jonathan Roelofsb3fcc672014-09-05 19:45:05261#endif // !_LIBCPP_HAS_NO_THREADS
Howard Hinnant3e519522010-05-11 19:42:16262}
263
264_LIBCPP_END_NAMESPACE_STD
Arthur O'Dwyerbbb0f2c2022-02-11 18:00:39265
266_LIBCPP_POP_MACROS