1 // Copyright 2018 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #pragma once 6 7 #include <stddef.h> 8 #include <stdint.h> 9 10 namespace lockdep { 11 12 // Forward declaration. 13 template <typename Class, typename LockType, size_t Index> 14 class LockDep; 15 16 // Flags to specify which rules to apply to a lock class during validation. 17 enum LockFlags : uint8_t { 18 // Apply only common rules that apply to all locks. 19 LockFlagsNone = 0, 20 21 // Apply the irq-safety rules in addition to the common rules for all locks. 22 LockFlagsIrqSafe = (1 << 0), 23 24 // Apply the nestable rules in addition to the common rules for all locks. 25 LockFlagsNestable = (1 << 1), 26 27 // Do not report validation errors. This flag prevents recursive validation 28 // of locks that are acquired by reporting routines. 29 LockFlagsReportingDisabled = (1 << 2), 30 31 // There is only one member of this locks class. 32 LockFlagsSingletonLock = (1 << 3), 33 34 // Abort the program with an error if a lock is improperly acquired more 35 // than once in the same context. 36 LockFlagsReAcquireFatal = (1 << 4), 37 38 // Do not add this acquisition to the active list. This may be required for 39 // locks that are used to protect context switching logic. 40 LockFlagsActiveListDisabled = (1 << 5), 41 42 // Do not track this lock. 43 LockFlagsTrackingDisabled = (1 << 6), 44 }; 45 46 // Prevent implicit conversion to int of bitwise-or expressions involving 47 // LockFlags. 48 constexpr inline LockFlags operator|(LockFlags a, LockFlags b) { 49 return static_cast<LockFlags>( 50 static_cast<uint8_t>(a) | static_cast<uint8_t>(b)); 51 } 52 53 // Prevent implicit conversion to int of bitwise-and expressions involving 54 // LockFlags. 55 constexpr inline LockFlags operator&(LockFlags a, LockFlags b) { 56 return static_cast<LockFlags>( 57 static_cast<uint8_t>(a) & static_cast<uint8_t>(b)); 58 } 59 60 namespace internal { 61 62 // Receives the optional lock flags in the macros below and injects the 63 // singleton lock flag. 64 constexpr inline LockFlags SingletonLockFlags( 65 LockFlags flags = LockFlagsNone) { 66 return flags | LockFlagsSingletonLock; 67 } 68 69 } // namespace internal 70 71 // 72 // The following macros are used to instrument locks and lock types for runtime 73 // tracking and validation. 74 // 75 76 // Instruments a lock with dependency tracking features. Instrumentation is 77 // enabled and disabled by the LOCK_DEP_ENABLE_VALIDATION define. 78 // 79 // Arguments: 80 // containing_type: The name of the type that contains the lock. 81 // lock_type: The type of the lock to use under the hood. 82 // 83 // Example usage: 84 // 85 // struct MyType { 86 // LOCK_DEP_INSTRUMENT(MyType, Mutex) mutex; 87 // // ... 88 // }; 89 #define LOCK_DEP_INSTRUMENT(containing_type, lock_type) \ 90 ::lockdep::LockDep<containing_type, lock_type, __LINE__> 91 92 // Defines a singleton lock with the given name and type. The singleton 93 // instance may be retrieved using the static Get() method provided by the base 94 // class. This instance is appropriate to pass to Guard<lock_type, [option]>. 95 // 96 // Arguments: 97 // name: The name of the singleton to define. 98 // lock_type: The type of the lock to use under the hood. 99 // __VA_ARGS__: LockFlags expression specifying lock flags to honor in addition 100 // to the flags specified for the lock type using the 101 // LOCK_DEP_TRAITS macro below. 102 // 103 // Example usage: 104 // 105 // LOCK_DEP_SINGLETON_LOCK(FooLock, fbl::Mutex [, LockFlags]); 106 // 107 // struct Foo { ... }; // Data type of global data. 108 // 109 // Foo g_foo{}; // Global data. 110 // 111 // void MutateFoo() { 112 // Guard<fbl::Mutex> guard{FooLock::Get()}; 113 // // Mutate g_foo ... 114 // } 115 #define LOCK_DEP_SINGLETON_LOCK(name, lock_type, ...) \ 116 struct name : ::lockdep::SingletonLockDep< \ 117 name, lock_type, \ 118 ::lockdep::internal::SingletonLockFlags(__VA_ARGS__)> {} 119 120 // Defines a singleton lock with the given name that wraps a raw global lock. 121 // The singleton behaves similarly to the version above, except the raw global 122 // lock is used as the underlying lock instead of an internally-defined lock. 123 // This is useful to instrument an existing global lock that may be shared with 124 // C code or for other reasons cannot be completely replaced with the above 125 // global lock type. 126 // 127 // Arguments: 128 // name: The name of the singleton to define. 129 // global_lock: The global lock to wrap with this lock type. This must be an 130 // lvalue reference expression to a lock with static storage 131 // duration, with either external or internal linkage. 132 // __VA_ARGS__: LockFlags expression specifying lock flags to honor in addition 133 // to the flags specified for the lock type using the 134 // LOCK_DEP_TRAITS macro below. 135 // 136 // Example usage: 137 // 138 // extern spin_lock_t thread_lock; 139 // LOCK_DEP_SINGLETON_LOCK_WRAPPER(ThreadLock, thread_lock [, LockFlags]); 140 // 141 // void DoThreadStuff() { 142 // Guard<spin_lock_t, IrqSave> guard{ThreadLock::Get()}; 143 // // ... 144 // } 145 #define LOCK_DEP_SINGLETON_LOCK_WRAPPER(name, global_lock, ...) \ 146 struct name : public ::lockdep::SingletonLockDep< \ 147 name, ::lockdep::GlobalReference<decltype(global_lock), global_lock>, \ 148 ::lockdep::internal::SingletonLockFlags(__VA_ARGS__)> { \ 149 auto& capability() __TA_RETURN_CAPABILITY(global_lock) { \ 150 return global_lock; \ 151 } \ 152 } 153 154 // Tags the given lock type with the given lock state flags value. This informs 155 // the validator about the properties of the lock to enforce during validation. 156 // Untagged lock types default to flags lockdep::LockFlagsNone. 157 // 158 // This macro must be called once in the same namespace as lock_type is defined 159 // in and visible to each invocation of LOCK_DEP_INSTRUMENT() for the same lock 160 // type. If possible, it is a good idea to call the macro close to the 161 // definition of the lock type. 162 // 163 // Arguments: 164 // lock_type: The lock type to specify the lock traits for. 165 // lock_flags: A combination of lockdep::LockFlags values that specifies the 166 // properties to enforce for the lock type. 167 // 168 // Example usage: 169 // 170 // namespace MyNamespace { 171 // 172 // class MySpinLock { 173 // // ... 174 // }; 175 // LOCK_DEP_TRAITS(MySpinLock, lockdep::LockFlagsIrqSafe [ | other bits...]); 176 // 177 // } // MyNamespace 178 // 179 #define LOCK_DEP_TRAITS(lock_type, lock_flags) \ 180 template <typename> \ 181 struct LOCK_DEP_TRAITS; \ 182 template <> \ 183 struct LOCK_DEP_TRAITS<lock_type> { \ 184 static constexpr ::lockdep::LockFlags Flags = (lock_flags); \ 185 }; \ 186 LOCK_DEP_TRAITS<lock_type> LOCK_DEP_GetLockTraits(lock_type*) 187 188 } // namespace lockdep 189