xref: /aosp_15_r20/external/pigweed/pw_sync/public/pw_sync/mutex.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 #pragma once
15 
16 #include <stdbool.h>
17 
18 #include "pw_preprocessor/util.h"
19 #include "pw_sync/lock_annotations.h"
20 
21 #ifdef __cplusplus
22 
23 #include "pw_sync/virtual_basic_lockable.h"
24 #include "pw_sync_backend/mutex_native.h"
25 
26 namespace pw::sync {
27 
28 /// The `Mutex` is a synchronization primitive that can be used to protect
29 /// shared data from being simultaneously accessed by multiple threads.  It
30 /// offers exclusive, non-recursive ownership semantics where priority
31 /// inheritance is used to solve the classic priority-inversion problem.  This
32 /// is thread safe, but NOT IRQ safe.
33 ///
34 /// @rst
35 /// .. warning::
36 ///
37 ///    In order to support global statically constructed Mutexes, the user
38 ///    and/or backend MUST ensure that any initialization required in your
39 ///    environment is done prior to the creation and/or initialization of the
40 ///    native synchronization primitives (e.g. kernel initialization).
41 /// @endrst
42 class PW_LOCKABLE("pw::sync::Mutex") Mutex {
43  public:
44   using native_handle_type = backend::NativeMutexHandle;
45 
46   Mutex();
47   ~Mutex();
48   Mutex(const Mutex&) = delete;
49   Mutex(Mutex&&) = delete;
50   Mutex& operator=(const Mutex&) = delete;
51   Mutex& operator=(Mutex&&) = delete;
52 
53   /// Locks the mutex, blocking indefinitely. Failures are fatal.
54   ///
55   /// @b PRECONDITION:
56   ///   The lock isn't already held by this thread. Recursive locking is
57   ///   undefined behavior.
58   void lock() PW_EXCLUSIVE_LOCK_FUNCTION();
59 
60   /// Attempts to lock the mutex in a non-blocking manner.
61   /// Returns true if the mutex was successfully acquired.
62   ///
63   /// @b PRECONDITION:
64   ///   The lock isn't already held by this thread. Recursive locking is
65   ///   undefined behavior.
66   [[nodiscard]] bool try_lock() PW_EXCLUSIVE_TRYLOCK_FUNCTION(true);
67 
68   /// Unlocks the mutex. Failures are fatal.
69   ///
70   /// @b PRECONDITION:
71   ///   The mutex is held by this thread.
72   void unlock() PW_UNLOCK_FUNCTION();
73 
74   [[nodiscard]] native_handle_type native_handle();
75 
76  protected:
77   /// Expose the NativeMutex directly to derived classes (TimedMutex) in case
78   /// implementations use different types for backend::NativeMutex and
79   /// native_handle().
native_type()80   backend::NativeMutex& native_type() { return native_type_; }
native_type()81   const backend::NativeMutex& native_type() const { return native_type_; }
82 
83  private:
84   /// This may be a wrapper around a native type with additional members.
85   backend::NativeMutex native_type_;
86 };
87 
88 class PW_LOCKABLE("pw::sync::VirtualMutex") VirtualMutex final
89     : public GenericBasicLockable<Mutex> {
90  public:
mutex()91   Mutex& mutex() { return impl(); }
92 };
93 
94 }  // namespace pw::sync
95 
96 #include "pw_sync_backend/mutex_inline.h"
97 
98 using pw_sync_Mutex = pw::sync::Mutex;
99 
100 #else  // !defined(__cplusplus)
101 
102 typedef struct pw_sync_Mutex pw_sync_Mutex;
103 
104 #endif  // __cplusplus
105 
106 PW_EXTERN_C_START
107 
108 /// Invokes the `Mutex::lock` member function on the given `mutex`.
109 void pw_sync_Mutex_Lock(pw_sync_Mutex* mutex) PW_NO_LOCK_SAFETY_ANALYSIS;
110 
111 /// Invokes the `Mutex::try_lock` member function on the given `mutex`.
112 bool pw_sync_Mutex_TryLock(pw_sync_Mutex* mutex) PW_NO_LOCK_SAFETY_ANALYSIS;
113 
114 /// Invokes the `Mutex::unlock` member function on the given `mutex`.
115 void pw_sync_Mutex_Unlock(pw_sync_Mutex* mutex) PW_NO_LOCK_SAFETY_ANALYSIS;
116 
117 PW_EXTERN_C_END
118