blob: b3b84c4dc430dc75de5ce7fcab9cf90f5e225ac4 [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
Louis Dionnef87aa192022-02-14 18:41:099#include <__assert>
Louis Dionne053d9e52023-07-04 20:10:4510#include <__thread/id.h>
Arthur O'Dwyerbbb0f2c2022-02-11 18:00:3911#include <limits>
12#include <mutex>
Arthur O'Dwyerbbb0f2c2022-02-11 18:00:3913
Eric Fiseliere8fd1642015-08-18 21:08:5414#include "include/atomic_support.h"
Howard Hinnant3e519522010-05-11 19:42:1615
Petr Hosek996e62e2019-05-30 01:34:4116#ifndef _LIBCPP_HAS_NO_THREADS
Arthur O'Dwyerbbb0f2c2022-02-11 18:00:3917# if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
18# pragma comment(lib, "pthread")
19# endif
Petr Hosek996e62e2019-05-30 01:34:4120#endif
21
Arthur O'Dwyerbbb0f2c2022-02-11 18:00:3922_LIBCPP_PUSH_MACROS
23#include <__undef_macros>
24
Howard Hinnant3e519522010-05-11 19:42:1625_LIBCPP_BEGIN_NAMESPACE_STD
Arthur O'Dwyerbbb0f2c2022-02-11 18:00:3926
Jonathan Roelofsb3fcc672014-09-05 19:45:0527#ifndef _LIBCPP_HAS_NO_THREADS
Howard Hinnant3e519522010-05-11 19:42:1628
Eric Fiselier8baf8382019-07-07 01:20:5429// ~mutex is defined elsewhere
Howard Hinnant3e519522010-05-11 19:42:1630
31void
32mutex::lock()
33{
Asiri Rathnayakec7e42392016-05-06 14:06:2934 int ec = __libcpp_mutex_lock(&__m_);
Howard Hinnant3e519522010-05-11 19:42:1635 if (ec)
36 __throw_system_error(ec, "mutex lock failed");
37}
38
39bool
Louis Dionne56013052021-03-01 17:09:4540mutex::try_lock() noexcept
Howard Hinnant3e519522010-05-11 19:42:1641{
Eric Fiselier08e14772017-01-14 10:27:1242 return __libcpp_mutex_trylock(&__m_);
Howard Hinnant3e519522010-05-11 19:42:1643}
44
45void
Louis Dionne56013052021-03-01 17:09:4546mutex::unlock() noexcept
Howard Hinnant3e519522010-05-11 19:42:1647{
Asiri Rathnayakec7e42392016-05-06 14:06:2948 int ec = __libcpp_mutex_unlock(&__m_);
Howard Hinnant12bfc4f2013-09-21 21:26:3749 (void)ec;
varconstcd0ad422023-06-27 23:40:3950 _LIBCPP_ASSERT_UNCATEGORIZED(ec == 0, "call to mutex::unlock failed");
Howard Hinnant3e519522010-05-11 19:42:1651}
52
53// recursive_mutex
54
55recursive_mutex::recursive_mutex()
56{
Asiri Rathnayakec7e42392016-05-06 14:06:2957 int ec = __libcpp_recursive_mutex_init(&__m_);
Howard Hinnant3e519522010-05-11 19:42:1658 if (ec)
Asiri Rathnayakec7e42392016-05-06 14:06:2959 __throw_system_error(ec, "recursive_mutex constructor failed");
Howard Hinnant3e519522010-05-11 19:42:1660}
61
62recursive_mutex::~recursive_mutex()
63{
Saleem Abdulrasool58a0dce2017-01-05 17:54:4564 int e = __libcpp_recursive_mutex_destroy(&__m_);
Howard Hinnant12bfc4f2013-09-21 21:26:3765 (void)e;
varconstcd0ad422023-06-27 23:40:3966 _LIBCPP_ASSERT_UNCATEGORIZED(e == 0, "call to ~recursive_mutex() failed");
Howard Hinnant3e519522010-05-11 19:42:1667}
68
69void
70recursive_mutex::lock()
71{
Saleem Abdulrasool58a0dce2017-01-05 17:54:4572 int ec = __libcpp_recursive_mutex_lock(&__m_);
Howard Hinnant3e519522010-05-11 19:42:1673 if (ec)
74 __throw_system_error(ec, "recursive_mutex lock failed");
75}
76
77void
Louis Dionne56013052021-03-01 17:09:4578recursive_mutex::unlock() noexcept
Howard Hinnant3e519522010-05-11 19:42:1679{
Saleem Abdulrasool58a0dce2017-01-05 17:54:4580 int e = __libcpp_recursive_mutex_unlock(&__m_);
Howard Hinnant12bfc4f2013-09-21 21:26:3781 (void)e;
varconstcd0ad422023-06-27 23:40:3982 _LIBCPP_ASSERT_UNCATEGORIZED(e == 0, "call to recursive_mutex::unlock() failed");
Howard Hinnant3e519522010-05-11 19:42:1683}
84
85bool
Louis Dionne56013052021-03-01 17:09:4586recursive_mutex::try_lock() noexcept
Howard Hinnant3e519522010-05-11 19:42:1687{
Eric Fiselier08e14772017-01-14 10:27:1288 return __libcpp_recursive_mutex_trylock(&__m_);
Howard Hinnant3e519522010-05-11 19:42:1689}
90
91// timed_mutex
92
93timed_mutex::timed_mutex()
94 : __locked_(false)
95{
96}
97
98timed_mutex::~timed_mutex()
99{
100 lock_guard<mutex> _(__m_);
101}
102
103void
104timed_mutex::lock()
105{
106 unique_lock<mutex> lk(__m_);
107 while (__locked_)
108 __cv_.wait(lk);
109 __locked_ = true;
110}
111
112bool
Louis Dionne56013052021-03-01 17:09:45113timed_mutex::try_lock() noexcept
Howard Hinnant3e519522010-05-11 19:42:16114{
115 unique_lock<mutex> lk(__m_, try_to_lock);
116 if (lk.owns_lock() && !__locked_)
117 {
118 __locked_ = true;
119 return true;
120 }
121 return false;
122}
123
124void
Louis Dionne56013052021-03-01 17:09:45125timed_mutex::unlock() noexcept
Howard Hinnant3e519522010-05-11 19:42:16126{
127 lock_guard<mutex> _(__m_);
128 __locked_ = false;
129 __cv_.notify_one();
130}
131
132// recursive_timed_mutex
133
134recursive_timed_mutex::recursive_timed_mutex()
135 : __count_(0),
Marshall Clow2b1d4252019-08-14 16:21:27136 __id_{}
Howard Hinnant3e519522010-05-11 19:42:16137{
138}
139
140recursive_timed_mutex::~recursive_timed_mutex()
141{
142 lock_guard<mutex> _(__m_);
143}
144
145void
146recursive_timed_mutex::lock()
147{
Marshall Clow2b1d4252019-08-14 16:21:27148 __thread_id id = this_thread::get_id();
Howard Hinnant3e519522010-05-11 19:42:16149 unique_lock<mutex> lk(__m_);
Marshall Clow2b1d4252019-08-14 16:21:27150 if (id ==__id_)
Howard Hinnant3e519522010-05-11 19:42:16151 {
152 if (__count_ == numeric_limits<size_t>::max())
153 __throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached");
154 ++__count_;
155 return;
156 }
157 while (__count_ != 0)
158 __cv_.wait(lk);
159 __count_ = 1;
160 __id_ = id;
161}
162
163bool
Louis Dionne56013052021-03-01 17:09:45164recursive_timed_mutex::try_lock() noexcept
Howard Hinnant3e519522010-05-11 19:42:16165{
Marshall Clow2b1d4252019-08-14 16:21:27166 __thread_id id = this_thread::get_id();
Howard Hinnant3e519522010-05-11 19:42:16167 unique_lock<mutex> lk(__m_, try_to_lock);
Marshall Clow2b1d4252019-08-14 16:21:27168 if (lk.owns_lock() && (__count_ == 0 || id == __id_))
Howard Hinnant3e519522010-05-11 19:42:16169 {
170 if (__count_ == numeric_limits<size_t>::max())
171 return false;
172 ++__count_;
173 __id_ = id;
174 return true;
175 }
176 return false;
177}
178
179void
Louis Dionne56013052021-03-01 17:09:45180recursive_timed_mutex::unlock() noexcept
Howard Hinnant3e519522010-05-11 19:42:16181{
182 unique_lock<mutex> lk(__m_);
183 if (--__count_ == 0)
184 {
Marshall Clow2e80d012019-08-14 20:54:56185 __id_.__reset();
Howard Hinnant3e519522010-05-11 19:42:16186 lk.unlock();
187 __cv_.notify_one();
188 }
189}
190
Jonathan Roelofsb3fcc672014-09-05 19:45:05191#endif // !_LIBCPP_HAS_NO_THREADS
192
Howard Hinnant3e519522010-05-11 19:42:16193// If dispatch_once_f ever handles C++ exceptions, and if one can get to it
194// without illegal macros (unexpected macros not beginning with _UpperCase or
195// __lowercase), and if it stops spinning waiting threads, then call_once should
196// call into dispatch_once_f instead of here. Relevant radar this code needs to
197// keep in sync with: 7741191.
198
Jonathan Roelofsb3fcc672014-09-05 19:45:05199#ifndef _LIBCPP_HAS_NO_THREADS
Arthur O'Dwyer05337a72022-02-08 18:08:59200static constinit __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER;
201static constinit __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER;
Jonathan Roelofsb3fcc672014-09-05 19:45:05202#endif
Howard Hinnant3e519522010-05-11 19:42:16203
Nico Weber0fd00a52019-03-20 22:55:03204void __call_once(volatile once_flag::_State_type& flag, void* arg,
205 void (*func)(void*))
Howard Hinnant3e519522010-05-11 19:42:16206{
Jonathan Roelofsb3fcc672014-09-05 19:45:05207#if defined(_LIBCPP_HAS_NO_THREADS)
208 if (flag == 0)
209 {
Nikolas Klauserb22aa3d2023-02-02 10:47:01210#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
Jonathan Roelofsb3fcc672014-09-05 19:45:05211 try
212 {
Nikolas Klauserb22aa3d2023-02-02 10:47:01213#endif // _LIBCPP_HAS_NO_EXCEPTIONS
Jonathan Roelofsb3fcc672014-09-05 19:45:05214 flag = 1;
215 func(arg);
Nico Weber0fd00a52019-03-20 22:55:03216 flag = ~once_flag::_State_type(0);
Nikolas Klauserb22aa3d2023-02-02 10:47:01217#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
Jonathan Roelofsb3fcc672014-09-05 19:45:05218 }
219 catch (...)
220 {
Nico Weber0fd00a52019-03-20 22:55:03221 flag = 0;
Jonathan Roelofsb3fcc672014-09-05 19:45:05222 throw;
223 }
Nikolas Klauserb22aa3d2023-02-02 10:47:01224#endif // _LIBCPP_HAS_NO_EXCEPTIONS
Jonathan Roelofsb3fcc672014-09-05 19:45:05225 }
226#else // !_LIBCPP_HAS_NO_THREADS
Asiri Rathnayakec7e42392016-05-06 14:06:29227 __libcpp_mutex_lock(&mut);
Howard Hinnant3e519522010-05-11 19:42:16228 while (flag == 1)
Asiri Rathnayakec7e42392016-05-06 14:06:29229 __libcpp_condvar_wait(&cv, &mut);
Howard Hinnant3e519522010-05-11 19:42:16230 if (flag == 0)
231 {
Nikolas Klauserb22aa3d2023-02-02 10:47:01232#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
Howard Hinnant3e519522010-05-11 19:42:16233 try
234 {
Nikolas Klauserb22aa3d2023-02-02 10:47:01235#endif // _LIBCPP_HAS_NO_EXCEPTIONS
Nico Weber0fd00a52019-03-20 22:55:03236 __libcpp_relaxed_store(&flag, once_flag::_State_type(1));
Asiri Rathnayakec7e42392016-05-06 14:06:29237 __libcpp_mutex_unlock(&mut);
Howard Hinnant3e519522010-05-11 19:42:16238 func(arg);
Asiri Rathnayakec7e42392016-05-06 14:06:29239 __libcpp_mutex_lock(&mut);
Nico Weber0fd00a52019-03-20 22:55:03240 __libcpp_atomic_store(&flag, ~once_flag::_State_type(0),
241 _AO_Release);
Asiri Rathnayakec7e42392016-05-06 14:06:29242 __libcpp_mutex_unlock(&mut);
243 __libcpp_condvar_broadcast(&cv);
Nikolas Klauserb22aa3d2023-02-02 10:47:01244#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
Howard Hinnant3e519522010-05-11 19:42:16245 }
246 catch (...)
247 {
Asiri Rathnayakec7e42392016-05-06 14:06:29248 __libcpp_mutex_lock(&mut);
Nico Weber0fd00a52019-03-20 22:55:03249 __libcpp_relaxed_store(&flag, once_flag::_State_type(0));
Asiri Rathnayakec7e42392016-05-06 14:06:29250 __libcpp_mutex_unlock(&mut);
251 __libcpp_condvar_broadcast(&cv);
Howard Hinnant3e519522010-05-11 19:42:16252 throw;
253 }
Nikolas Klauserb22aa3d2023-02-02 10:47:01254#endif // _LIBCPP_HAS_NO_EXCEPTIONS
Howard Hinnant3e519522010-05-11 19:42:16255 }
256 else
Asiri Rathnayakec7e42392016-05-06 14:06:29257 __libcpp_mutex_unlock(&mut);
Jonathan Roelofsb3fcc672014-09-05 19:45:05258#endif // !_LIBCPP_HAS_NO_THREADS
Howard Hinnant3e519522010-05-11 19:42:16259}
260
261_LIBCPP_END_NAMESPACE_STD
Arthur O'Dwyerbbb0f2c2022-02-11 18:00:39262
263_LIBCPP_POP_MACROS