1 //===----------------------------------------------------------------------===//
3 // 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
7 //===----------------------------------------------------------------------===//
10 #include <__thread/id.h>
11 #include <__utility/exception_guard.h>
15 #include "include/atomic_support.h"
17 #if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
18 # pragma comment(lib, "pthread")
22 #include <__undef_macros>
24 _LIBCPP_BEGIN_NAMESPACE_STD
26 // ~mutex is defined elsewhere
29 int ec
= __libcpp_mutex_lock(&__m_
);
31 __throw_system_error(ec
, "mutex lock failed");
34 bool mutex::try_lock() noexcept
{ return __libcpp_mutex_trylock(&__m_
); }
36 void mutex::unlock() noexcept
{
37 int ec
= __libcpp_mutex_unlock(&__m_
);
39 _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(
40 ec
== 0, "call to mutex::unlock failed. A possible reason is that the mutex wasn't locked");
45 recursive_mutex::recursive_mutex() {
46 int ec
= __libcpp_recursive_mutex_init(&__m_
);
48 __throw_system_error(ec
, "recursive_mutex constructor failed");
51 recursive_mutex::~recursive_mutex() {
52 int e
= __libcpp_recursive_mutex_destroy(&__m_
);
54 _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(e
== 0, "call to ~recursive_mutex() failed");
57 void recursive_mutex::lock() {
58 int ec
= __libcpp_recursive_mutex_lock(&__m_
);
60 __throw_system_error(ec
, "recursive_mutex lock failed");
63 void recursive_mutex::unlock() noexcept
{
64 int e
= __libcpp_recursive_mutex_unlock(&__m_
);
66 _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(
67 e
== 0, "call to recursive_mutex::unlock() failed. A possible reason is that the mutex wasn't locked");
70 bool recursive_mutex::try_lock() noexcept
{ return __libcpp_recursive_mutex_trylock(&__m_
); }
74 timed_mutex::timed_mutex() : __locked_(false) {}
76 timed_mutex::~timed_mutex() { lock_guard
<mutex
> _(__m_
); }
78 void timed_mutex::lock() {
79 unique_lock
<mutex
> lk(__m_
);
85 bool timed_mutex::try_lock() noexcept
{
86 unique_lock
<mutex
> lk(__m_
, try_to_lock
);
87 if (lk
.owns_lock() && !__locked_
) {
94 void timed_mutex::unlock() noexcept
{
95 lock_guard
<mutex
> _(__m_
);
100 // recursive_timed_mutex
102 recursive_timed_mutex::recursive_timed_mutex() : __count_(0), __id_
{} {}
104 recursive_timed_mutex::~recursive_timed_mutex() { lock_guard
<mutex
> _(__m_
); }
106 void recursive_timed_mutex::lock() {
107 __thread_id id
= this_thread::get_id();
108 unique_lock
<mutex
> lk(__m_
);
110 if (__count_
== numeric_limits
<size_t>::max())
111 __throw_system_error(EAGAIN
, "recursive_timed_mutex lock limit reached");
115 while (__count_
!= 0)
121 bool recursive_timed_mutex::try_lock() noexcept
{
122 __thread_id id
= this_thread::get_id();
123 unique_lock
<mutex
> lk(__m_
, try_to_lock
);
124 if (lk
.owns_lock() && (__count_
== 0 || id
== __id_
)) {
125 if (__count_
== numeric_limits
<size_t>::max())
134 void recursive_timed_mutex::unlock() noexcept
{
135 unique_lock
<mutex
> lk(__m_
);
136 if (--__count_
== 0) {
143 _LIBCPP_END_NAMESPACE_STD