1349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 981ad6265SDimitry Andric #include <__assert> 1006c3fb27SDimitry Andric #include <__thread/id.h> 115f757f3fSDimitry Andric #include <__utility/exception_guard.h> 1281ad6265SDimitry Andric #include <limits> 1381ad6265SDimitry Andric #include <mutex> 1481ad6265SDimitry Andric 150b57cec5SDimitry Andric #include "include/atomic_support.h" 160b57cec5SDimitry Andric 17480093f4SDimitry Andric #if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) 180b57cec5SDimitry Andric # pragma comment(lib, "pthread") 190b57cec5SDimitry Andric #endif 200b57cec5SDimitry Andric 2181ad6265SDimitry Andric _LIBCPP_PUSH_MACROS 2281ad6265SDimitry Andric #include <__undef_macros> 2381ad6265SDimitry Andric 240b57cec5SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 2581ad6265SDimitry Andric 260b57cec5SDimitry Andric // ~mutex is defined elsewhere 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric void 290b57cec5SDimitry Andric mutex::lock() 300b57cec5SDimitry Andric { 310b57cec5SDimitry Andric int ec = __libcpp_mutex_lock(&__m_); 320b57cec5SDimitry Andric if (ec) 330b57cec5SDimitry Andric __throw_system_error(ec, "mutex lock failed"); 340b57cec5SDimitry Andric } 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric bool 37fe6060f1SDimitry Andric mutex::try_lock() noexcept 380b57cec5SDimitry Andric { 390b57cec5SDimitry Andric return __libcpp_mutex_trylock(&__m_); 400b57cec5SDimitry Andric } 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric void 43fe6060f1SDimitry Andric mutex::unlock() noexcept 440b57cec5SDimitry Andric { 450b57cec5SDimitry Andric int ec = __libcpp_mutex_unlock(&__m_); 460b57cec5SDimitry Andric (void)ec; 4706c3fb27SDimitry Andric _LIBCPP_ASSERT_UNCATEGORIZED(ec == 0, "call to mutex::unlock failed"); 480b57cec5SDimitry Andric } 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric // recursive_mutex 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric recursive_mutex::recursive_mutex() 530b57cec5SDimitry Andric { 540b57cec5SDimitry Andric int ec = __libcpp_recursive_mutex_init(&__m_); 550b57cec5SDimitry Andric if (ec) 560b57cec5SDimitry Andric __throw_system_error(ec, "recursive_mutex constructor failed"); 570b57cec5SDimitry Andric } 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric recursive_mutex::~recursive_mutex() 600b57cec5SDimitry Andric { 610b57cec5SDimitry Andric int e = __libcpp_recursive_mutex_destroy(&__m_); 620b57cec5SDimitry Andric (void)e; 6306c3fb27SDimitry Andric _LIBCPP_ASSERT_UNCATEGORIZED(e == 0, "call to ~recursive_mutex() failed"); 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric void 670b57cec5SDimitry Andric recursive_mutex::lock() 680b57cec5SDimitry Andric { 690b57cec5SDimitry Andric int ec = __libcpp_recursive_mutex_lock(&__m_); 700b57cec5SDimitry Andric if (ec) 710b57cec5SDimitry Andric __throw_system_error(ec, "recursive_mutex lock failed"); 720b57cec5SDimitry Andric } 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric void 75fe6060f1SDimitry Andric recursive_mutex::unlock() noexcept 760b57cec5SDimitry Andric { 770b57cec5SDimitry Andric int e = __libcpp_recursive_mutex_unlock(&__m_); 780b57cec5SDimitry Andric (void)e; 7906c3fb27SDimitry Andric _LIBCPP_ASSERT_UNCATEGORIZED(e == 0, "call to recursive_mutex::unlock() failed"); 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric bool 83fe6060f1SDimitry Andric recursive_mutex::try_lock() noexcept 840b57cec5SDimitry Andric { 850b57cec5SDimitry Andric return __libcpp_recursive_mutex_trylock(&__m_); 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric // timed_mutex 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric timed_mutex::timed_mutex() 910b57cec5SDimitry Andric : __locked_(false) 920b57cec5SDimitry Andric { 930b57cec5SDimitry Andric } 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric timed_mutex::~timed_mutex() 960b57cec5SDimitry Andric { 970b57cec5SDimitry Andric lock_guard<mutex> _(__m_); 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric void 1010b57cec5SDimitry Andric timed_mutex::lock() 1020b57cec5SDimitry Andric { 1030b57cec5SDimitry Andric unique_lock<mutex> lk(__m_); 1040b57cec5SDimitry Andric while (__locked_) 1050b57cec5SDimitry Andric __cv_.wait(lk); 1060b57cec5SDimitry Andric __locked_ = true; 1070b57cec5SDimitry Andric } 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric bool 110fe6060f1SDimitry Andric timed_mutex::try_lock() noexcept 1110b57cec5SDimitry Andric { 1120b57cec5SDimitry Andric unique_lock<mutex> lk(__m_, try_to_lock); 1130b57cec5SDimitry Andric if (lk.owns_lock() && !__locked_) 1140b57cec5SDimitry Andric { 1150b57cec5SDimitry Andric __locked_ = true; 1160b57cec5SDimitry Andric return true; 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric return false; 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric void 122fe6060f1SDimitry Andric timed_mutex::unlock() noexcept 1230b57cec5SDimitry Andric { 1240b57cec5SDimitry Andric lock_guard<mutex> _(__m_); 1250b57cec5SDimitry Andric __locked_ = false; 1260b57cec5SDimitry Andric __cv_.notify_one(); 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric // recursive_timed_mutex 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric recursive_timed_mutex::recursive_timed_mutex() 1320b57cec5SDimitry Andric : __count_(0), 1330b57cec5SDimitry Andric __id_{} 1340b57cec5SDimitry Andric { 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric recursive_timed_mutex::~recursive_timed_mutex() 1380b57cec5SDimitry Andric { 1390b57cec5SDimitry Andric lock_guard<mutex> _(__m_); 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric void 1430b57cec5SDimitry Andric recursive_timed_mutex::lock() 1440b57cec5SDimitry Andric { 1450b57cec5SDimitry Andric __thread_id id = this_thread::get_id(); 1460b57cec5SDimitry Andric unique_lock<mutex> lk(__m_); 1470b57cec5SDimitry Andric if (id ==__id_) 1480b57cec5SDimitry Andric { 1490b57cec5SDimitry Andric if (__count_ == numeric_limits<size_t>::max()) 1500b57cec5SDimitry Andric __throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached"); 1510b57cec5SDimitry Andric ++__count_; 1520b57cec5SDimitry Andric return; 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric while (__count_ != 0) 1550b57cec5SDimitry Andric __cv_.wait(lk); 1560b57cec5SDimitry Andric __count_ = 1; 1570b57cec5SDimitry Andric __id_ = id; 1580b57cec5SDimitry Andric } 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric bool 161fe6060f1SDimitry Andric recursive_timed_mutex::try_lock() noexcept 1620b57cec5SDimitry Andric { 1630b57cec5SDimitry Andric __thread_id id = this_thread::get_id(); 1640b57cec5SDimitry Andric unique_lock<mutex> lk(__m_, try_to_lock); 1650b57cec5SDimitry Andric if (lk.owns_lock() && (__count_ == 0 || id == __id_)) 1660b57cec5SDimitry Andric { 1670b57cec5SDimitry Andric if (__count_ == numeric_limits<size_t>::max()) 1680b57cec5SDimitry Andric return false; 1690b57cec5SDimitry Andric ++__count_; 1700b57cec5SDimitry Andric __id_ = id; 1710b57cec5SDimitry Andric return true; 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric return false; 1740b57cec5SDimitry Andric } 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric void 177fe6060f1SDimitry Andric recursive_timed_mutex::unlock() noexcept 1780b57cec5SDimitry Andric { 1790b57cec5SDimitry Andric unique_lock<mutex> lk(__m_); 1800b57cec5SDimitry Andric if (--__count_ == 0) 1810b57cec5SDimitry Andric { 1820b57cec5SDimitry Andric __id_.__reset(); 1830b57cec5SDimitry Andric lk.unlock(); 1840b57cec5SDimitry Andric __cv_.notify_one(); 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric } 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric _LIBCPP_END_NAMESPACE_STD 18981ad6265SDimitry Andric 19081ad6265SDimitry Andric _LIBCPP_POP_MACROS 191