xref: /aosp_15_r20/external/llvm-libc/src/__support/threads/linux/mutex.h (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
1 //===--- Implementation of a Linux mutex class ------------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_MUTEX_H
10 #define LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_MUTEX_H
11 
12 #include "hdr/types/pid_t.h"
13 #include "src/__support/CPP/optional.h"
14 #include "src/__support/libc_assert.h"
15 #include "src/__support/macros/config.h"
16 #include "src/__support/threads/linux/futex_utils.h"
17 #include "src/__support/threads/linux/raw_mutex.h"
18 #include "src/__support/threads/mutex_common.h"
19 
20 namespace LIBC_NAMESPACE_DECL {
21 
22 // TODO: support shared/recursive/robust mutexes.
23 class Mutex final : private RawMutex {
24   // reserved timed, may be useful when combined with other flags.
25   unsigned char timed;
26   unsigned char recursive;
27   unsigned char robust;
28   unsigned char pshared;
29 
30   // TLS address may not work across forked processes. Use thread id instead.
31   pid_t owner;
32   unsigned long long lock_count;
33 
34 public:
Mutex(bool is_timed,bool is_recursive,bool is_robust,bool is_pshared)35   LIBC_INLINE constexpr Mutex(bool is_timed, bool is_recursive, bool is_robust,
36                               bool is_pshared)
37       : RawMutex(), timed(is_timed), recursive(is_recursive), robust(is_robust),
38         pshared(is_pshared), owner(0), lock_count(0) {}
39 
init(Mutex * mutex,bool is_timed,bool isrecur,bool isrobust,bool is_pshared)40   LIBC_INLINE static MutexError init(Mutex *mutex, bool is_timed, bool isrecur,
41                                      bool isrobust, bool is_pshared) {
42     RawMutex::init(mutex);
43     mutex->timed = is_timed;
44     mutex->recursive = isrecur;
45     mutex->robust = isrobust;
46     mutex->pshared = is_pshared;
47     mutex->owner = 0;
48     mutex->lock_count = 0;
49     return MutexError::NONE;
50   }
51 
destroy(Mutex * lock)52   LIBC_INLINE static MutexError destroy(Mutex *lock) {
53     LIBC_ASSERT(lock->owner == 0 && lock->lock_count == 0 &&
54                 "Mutex destroyed while being locked.");
55     RawMutex::destroy(lock);
56     return MutexError::NONE;
57   }
58 
59   // TODO: record owner and lock count.
lock()60   LIBC_INLINE MutexError lock() {
61     // Since timeout is not specified, we do not need to check the return value.
62     this->RawMutex::lock(
63         /* timeout=*/cpp::nullopt, this->pshared);
64     return MutexError::NONE;
65   }
66 
67   // TODO: record owner and lock count.
timed_lock(internal::AbsTimeout abs_time)68   LIBC_INLINE MutexError timed_lock(internal::AbsTimeout abs_time) {
69     if (this->RawMutex::lock(abs_time, this->pshared))
70       return MutexError::NONE;
71     return MutexError::TIMEOUT;
72   }
73 
unlock()74   LIBC_INLINE MutexError unlock() {
75     if (this->RawMutex::unlock(this->pshared))
76       return MutexError::NONE;
77     return MutexError::UNLOCK_WITHOUT_LOCK;
78   }
79 
80   // TODO: record owner and lock count.
try_lock()81   LIBC_INLINE MutexError try_lock() {
82     if (this->RawMutex::try_lock())
83       return MutexError::NONE;
84     return MutexError::BUSY;
85   }
86 };
87 
88 } // namespace LIBC_NAMESPACE_DECL
89 
90 #endif // LLVM_LIBC_SRC___SUPPORT_THREADS_LINUX_MUTEX_H
91