xref: /aosp_15_r20/external/pigweed/pw_sync_threadx/public/pw_sync_threadx/mutex_inline.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 "pw_assert/assert.h"
17 #include "pw_interrupt/context.h"
18 #include "pw_sync/mutex.h"
19 #include "tx_api.h"
20 
21 namespace pw::sync {
22 namespace backend {
23 
24 inline constexpr char kMutexName[] = "pw::Mutex";
25 
26 // Precondition: The mutex must be held when calling this!
NotRecursivelyHeld(TX_MUTEX & mutex)27 inline bool NotRecursivelyHeld(TX_MUTEX& mutex) {
28   // Don't use tx_mutex_info_get which goes into a critical section to read
29   // this count. Given that this is only called while the mutex is held, nothing
30   // can mutate this count and ergo we access the control block directly.
31   return mutex.tx_mutex_ownership_count == 1;
32 }
33 
34 }  // namespace backend
35 
Mutex()36 inline Mutex::Mutex() : native_type_() {
37   PW_ASSERT(tx_mutex_create(&native_type_,
38                             const_cast<char*>(backend::kMutexName),
39                             TX_INHERIT) == TX_SUCCESS);
40 }
41 
~Mutex()42 inline Mutex::~Mutex() {
43   PW_ASSERT(tx_mutex_delete(&native_type_) == TX_SUCCESS);
44 }
45 
lock()46 inline void Mutex::lock() {
47   // Enforce the pw::sync::Mutex IRQ contract.
48   PW_DASSERT(!interrupt::InInterruptContext());
49   PW_ASSERT(tx_mutex_get(&native_type_, TX_WAIT_FOREVER) == TX_SUCCESS);
50 
51   // Recursive locking is not supported.
52   PW_DASSERT(backend::NotRecursivelyHeld(native_type_));
53 }
54 
try_lock()55 inline bool Mutex::try_lock() {
56   // Enforce the pw::sync::Mutex IRQ contract.
57   PW_DASSERT(!interrupt::InInterruptContext());
58   const UINT result = tx_mutex_get(&native_type_, TX_NO_WAIT);
59   if (result == TX_NOT_AVAILABLE) {
60     return false;
61   }
62   PW_ASSERT(result == TX_SUCCESS);
63   // Recursive locking is not supported.
64   PW_DASSERT(backend::NotRecursivelyHeld(native_type_));
65   return true;
66 }
67 
unlock()68 inline void Mutex::unlock() {
69   // Enforce the pw::sync::Mutex IRQ contract.
70   PW_DASSERT(!interrupt::InInterruptContext());
71   PW_ASSERT(tx_mutex_put(&native_type_) == TX_SUCCESS);
72 }
73 
native_handle()74 inline Mutex::native_handle_type Mutex::native_handle() { return native_type_; }
75 
76 }  // namespace pw::sync
77