Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_sync / public / pw_sync / spin_lock.h
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
20 #ifdef __cplusplus
21
22 #include "pw_sync_backend/spin_lock_native.h"
23
24 namespace pw::sync {
25
26 // The SpinLock is a synchronization primitive that can be used to protect
27 // shared data from being simultaneously accessed by multiple threads and/or
28 // IRQs as a targeted global lock (except for NMIs).
29 // It offers exclusive, non-recursive ownership semantics where IRQs up to a
30 // backend defined level of "NMIs" will be masked to solve priority-inversion.
31 //
32 // NOTE: This SpinLock relies on built-in local interrupt masking to make it IRQ
33 // safe without requiring the caller to mask interrupts manually when using this
34 // primitive.
35 //
36 // Unlike global interrupt locks, this also works safely and efficiently on SMP
37 // systems. This entire API is IRQ safe.
38 //
39 // WARNING: Code that holds a specific SpinLock must not try to re-acquire it
40 // or it will deadlock. However, it is okay to nest distinct spinlocks.
41 //
42 // WARNING: In order to support global statically constructed SpinLocks, the
43 // backend MUST ensure that any initialization required in your environment
44 // prior to the creation and/or initialization of the native semaphore
45 // (e.g. kernel initialization), is done before or during the invocation of the
46 // global static C++ constructors.
47 class SpinLock {
48  public:
49   using native_handle_type = backend::NativeSpinLockHandle;
50
51   SpinLock();
52   ~SpinLock() = default;
53   SpinLock(const SpinLock&) = delete;
54   SpinLock(SpinLock&&) = delete;
55   SpinLock& operator=(const SpinLock&) = delete;
56   SpinLock& operator=(SpinLock&&) = delete;
57
58   // Locks the spinlock, blocking indefinitely. Failures are fatal.
59   void lock();
60
61   // Attempts to lock the spinlock in a non-blocking manner.
62   // Returns true if the spinlock was successfully acquired.
63   bool try_lock();
64
65   // Unlocks the spinlock. Failures are fatal.
66   void unlock();
67
68   native_handle_type native_handle();
69
70  private:
71   // This may be a wrapper around a native type with additional members.
72   backend::NativeSpinLock native_type_;
73 };
74
75 }  // namespace pw::sync
76
77 #include "pw_sync_backend/spin_lock_inline.h"
78
79 using pw_sync_SpinLock = pw::sync::SpinLock;
80
81 #else  // !defined(__cplusplus)
82
83 typedef struct pw_sync_SpinLock pw_sync_SpinLock;
84
85 #endif  // __cplusplus
86
87 PW_EXTERN_C_START
88
89 void pw_sync_SpinLock_Lock(pw_sync_SpinLock* spin_lock);
90 bool pw_sync_SpinLock_TryLock(pw_sync_SpinLock* spin_lock);
91 void pw_sync_SpinLock_Unlock(pw_sync_SpinLock* spin_lock);
92
93 PW_EXTERN_C_END