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_backend/mutex_native.h" 24 25 namespace pw::sync { 26 27 // The Mutex is a synchronization primitive that can be used to protect 28 // shared data from being simultaneously accessed by multiple threads. 29 // It offers exclusive, non-recursive ownership semantics where priority 30 // inheritance is used to solve the classic priority-inversion problem. 31 // This is thread safe, but NOT IRQ safe. 32 // 33 // WARNING: In order to support global statically constructed Mutexes, the user 34 // and/or backend MUST ensure that any initialization required in your 35 // environment is done prior to the creation and/or initialization of the native 36 // synchronization primitives (e.g. kernel initialization). 37 class PW_LOCKABLE("pw::sync::Mutex") Mutex { 38 public: 39 using native_handle_type = backend::NativeMutexHandle; 40 41 Mutex(); 42 ~Mutex(); 43 Mutex(const Mutex&) = delete; 44 Mutex(Mutex&&) = delete; 45 Mutex& operator=(const Mutex&) = delete; 46 Mutex& operator=(Mutex&&) = delete; 47 48 // Locks the mutex, blocking indefinitely. Failures are fatal. 49 // 50 // PRECONDITION: 51 // The lock isn't already held by this thread. Recursive locking is 52 // undefined behavior. 53 void lock() PW_EXCLUSIVE_LOCK_FUNCTION(); 54 55 // Attempts to lock the mutex in a non-blocking manner. 56 // Returns true if the mutex was successfully acquired. 57 // 58 // PRECONDITION: 59 // The lock isn't already held by this thread. Recursive locking is 60 // undefined behavior. 61 bool try_lock() PW_EXCLUSIVE_TRYLOCK_FUNCTION(true); 62 63 // Unlocks the mutex. Failures are fatal. 64 // 65 // PRECONDITION: 66 // The mutex is held by this thread. 67 void unlock() PW_UNLOCK_FUNCTION(); 68 69 native_handle_type native_handle(); 70 71 private: 72 // This may be a wrapper around a native type with additional members. 73 backend::NativeMutex native_type_; 74 }; 75 76 } // namespace pw::sync 77 78 #include "pw_sync_backend/mutex_inline.h" 79 80 using pw_sync_Mutex = pw::sync::Mutex; 81 82 #else // !defined(__cplusplus) 83 84 typedef struct pw_sync_Mutex pw_sync_Mutex; 85 86 #endif // __cplusplus 87 88 PW_EXTERN_C_START 89 90 void pw_sync_Mutex_Lock(pw_sync_Mutex* mutex) PW_NO_LOCK_SAFETY_ANALYSIS; 91 bool pw_sync_Mutex_TryLock(pw_sync_Mutex* mutex) PW_NO_LOCK_SAFETY_ANALYSIS; 92 void pw_sync_Mutex_Unlock(pw_sync_Mutex* mutex) PW_NO_LOCK_SAFETY_ANALYSIS; 93 94 PW_EXTERN_C_END 95