//===-- Shared pthread condition variable helpers ---------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_LIBC_SRC_PTHREAD_PTHREAD_COND_UTILS_H #define LLVM_LIBC_SRC_PTHREAD_PTHREAD_COND_UTILS_H #include "hdr/errno_macros.h" // EINVAL, ETIMEDOUT #include "hdr/time_macros.h" // CLOCK_MONOTONIC, CLOCK_REALTIME #include "include/llvm-libc-types/clockid_t.h" #include "include/llvm-libc-types/pthread_cond_t.h" #include "include/llvm-libc-types/pthread_mutex_t.h" #include "include/llvm-libc-types/struct_timespec.h" #include "src/__support/CPP/optional.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" #include "src/__support/macros/null_check.h" #include "src/__support/macros/optimization.h" #include "src/__support/threads/CndVar.h" #include "src/__support/threads/mutex.h" #include "src/__support/time/abs_timeout.h" namespace LIBC_NAMESPACE_DECL { namespace pthread_cond_utils { static_assert( sizeof(CndVar) == sizeof(pthread_cond_t) && alignof(CndVar) == alignof(pthread_cond_t), "The public pthread_cond_t type must be of the same size and alignment " "as the internal condition variable type."); LIBC_INLINE CndVar *to_cndvar(pthread_cond_t *cond) { LIBC_CRASH_ON_NULLPTR(cond); // TODO: use cpp:start_lifetime_as once // https://github.com/llvm/llvm-project/pull/193326 is merged return reinterpret_cast(cond); } LIBC_INLINE Mutex *to_mutex(pthread_mutex_t *mutex) { LIBC_CRASH_ON_NULLPTR(mutex); // TODO: use cpp:start_lifetime_as once // https://github.com/llvm/llvm-project/pull/193326 is merged Mutex *m = reinterpret_cast(mutex); LIBC_ASSERT(!m->is_robust() && "Robust mutex not supported yet"); return m; } LIBC_INLINE bool is_supported_clock(clockid_t clock_id) { return clock_id == CLOCK_MONOTONIC || clock_id == CLOCK_REALTIME; } LIBC_INLINE bool is_realtime_clock(clockid_t clock_id) { return clock_id == CLOCK_REALTIME; } LIBC_INLINE int wait(CndVar *cond, Mutex *mutex, cpp::optional timeout) { switch (cond->wait(mutex, timeout)) { case CndVarResult::Success: return 0; case CndVarResult::Timeout: return ETIMEDOUT; case CndVarResult::MutexError: return EINVAL; } __builtin_unreachable(); } LIBC_INLINE int timed_wait(CndVar *cond, Mutex *mutex, const struct timespec *abstime, bool is_realtime) { LIBC_CRASH_ON_NULLPTR(abstime); auto timeout = internal::AbsTimeout::from_timespec(*abstime, /*realtime=*/is_realtime); if (LIBC_LIKELY(timeout.has_value())) return wait(cond, mutex, timeout.value()); switch (timeout.error()) { case internal::AbsTimeout::Error::Invalid: return EINVAL; case internal::AbsTimeout::Error::BeforeEpoch: return ETIMEDOUT; } __builtin_unreachable(); } } // namespace pthread_cond_utils } // namespace LIBC_NAMESPACE_DECL #endif // LLVM_LIBC_SRC_PTHREAD_PTHREAD_COND_UTILS_H