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_chrono/system_clock.h" 19 #include "pw_preprocessor/util.h" 20 #include "pw_sync/lock_annotations.h" 21 #include "pw_sync/mutex.h" 22 23 #ifdef __cplusplus 24 25 namespace pw::sync { 26 27 // The TimedMutex is a synchronization primitive that can be used to protect 28 // shared data from being simultaneously accessed by multiple threads with 29 // timeouts and deadlines, extending the Mutex. 30 // It offers exclusive, non-recursive ownership semantics where priority 31 // inheritance is used to solve the classic priority-inversion problem. 32 // This is thread safe, but NOT IRQ safe. 33 // 34 // WARNING: In order to support global statically constructed TimedMutexes, the 35 // user and/or backend MUST ensure that any initialization required in your 36 // environment is done prior to the creation and/or initialization of the native 37 // synchronization primitives (e.g. kernel initialization). 38 class TimedMutex : public Mutex { 39 public: 40 TimedMutex() = default; 41 ~TimedMutex() = default; 42 TimedMutex(const TimedMutex&) = delete; 43 TimedMutex(TimedMutex&&) = delete; 44 TimedMutex& operator=(const TimedMutex&) = delete; 45 TimedMutex& operator=(TimedMutex&&) = delete; 46 47 // Attempts to lock the mutex where, if needed, blocking for at least the 48 // specified duration. 49 // Returns true if the mutex was successfully acquired. 50 // 51 // PRECONDITION: 52 // The lock isn't already held by this thread. Recursive locking is 53 // undefined behavior. 54 bool try_lock_for(chrono::SystemClock::duration for_at_least) 55 PW_EXCLUSIVE_TRYLOCK_FUNCTION(true); 56 57 // Attempts to lock the mutex where, if needed, blocking until at least the 58 // specified time_point. 59 // Returns true if the mutex was successfully acquired. 60 // 61 // PRECONDITION: 62 // The lock isn't already held by this thread. Recursive locking is 63 // undefined behavior. 64 bool try_lock_until(chrono::SystemClock::time_point until_at_least) 65 PW_EXCLUSIVE_TRYLOCK_FUNCTION(true); 66 }; 67 68 } // namespace pw::sync 69 70 #include "pw_sync_backend/timed_mutex_inline.h" 71 72 using pw_sync_TimedMutex = pw::sync::TimedMutex; 73 74 #else // !defined(__cplusplus) 75 76 typedef struct pw_sync_TimedMutex pw_sync_TimedMutex; 77 78 #endif // __cplusplus 79 80 PW_EXTERN_C_START 81 82 void pw_sync_TimedMutex_Lock(pw_sync_TimedMutex* mutex) 83 PW_NO_LOCK_SAFETY_ANALYSIS; 84 bool pw_sync_TimedMutex_TryLock(pw_sync_TimedMutex* mutex) 85 PW_NO_LOCK_SAFETY_ANALYSIS; 86 bool pw_sync_TimedMutex_TryLockFor(pw_sync_TimedMutex* mutex, 87 pw_chrono_SystemClock_Duration for_at_least) 88 PW_NO_LOCK_SAFETY_ANALYSIS; 89 bool pw_sync_TimedMutex_TryLockUntil( 90 pw_sync_TimedMutex* mutex, 91 pw_chrono_SystemClock_TimePoint until_at_least) PW_NO_LOCK_SAFETY_ANALYSIS; 92 void pw_sync_TimedMutex_Unlock(pw_sync_TimedMutex* mutex) 93 PW_NO_LOCK_SAFETY_ANALYSIS; 94 95 PW_EXTERN_C_END 96