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