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