xref: /reactos/ntoskrnl/include/internal/cm_x.h (revision 40462c92)
1 /*
2 * PROJECT:         ReactOS Kernel
3 * LICENSE:         GPL - See COPYING in the top level directory
4 * FILE:            ntoskrnl/include/internal/cm_x.h
5 * PURPOSE:         Inlined Functions for the Configuration Manager
6 * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
7 */
8 
9 //
10 // Returns the hashkey corresponding to a convkey
11 //
12 #define GET_HASH_KEY(ConvKey)                                       \
13     ((CMP_HASH_IRRATIONAL * (ConvKey)) % CMP_HASH_PRIME)
14 
15 //
16 // Returns the index into the hash table, or the entry itself
17 //
18 #define GET_HASH_INDEX(ConvKey)                                     \
19     GET_HASH_KEY(ConvKey) % CmpHashTableSize
20 #define GET_HASH_ENTRY(Table, ConvKey)                              \
21     (&Table[GET_HASH_INDEX(ConvKey)])
22 #define ASSERT_VALID_HASH(h)                                        \
23     ASSERT_KCB_VALID(CONTAINING_RECORD((h), CM_KEY_CONTROL_BLOCK, KeyHash))
24 
25 //
26 // Returns whether or not the cell is cached
27 //
28 #define CMP_IS_CELL_CACHED(c)                                       \
29     (((c) & HCELL_CACHED) && ((c) != HCELL_NIL))
30 
31 //
32 // Return data from a cached cell
33 //
34 #define CMP_GET_CACHED_CELL(c)                                      \
35     (ULONG_PTR)((c) & ~HCELL_CACHED)
36 #define CMP_GET_CACHED_DATA(c)                                      \
37     (&(((PCM_CACHED_VALUE_INDEX)(CMP_GET_CACHED_CELL(c)))->Data.CellData))
38 #define CMP_GET_CACHED_INDEX(c)                                     \
39     (&(((PCM_CACHED_ENTRY)(CMP_GET_CACHED_CELL(c)))->CellIndex))
40 #define CMP_GET_CACHED_VALUE(c)                                     \
41     (&(((PCM_CACHED_VALUE)(CMP_GET_CACHED_CELL(c)))->KeyValue))
42 
43 //
44 // Makes sure that the registry is locked
45 //
46 #define CMP_ASSERT_REGISTRY_LOCK()                                  \
47     ASSERT((CmpSpecialBootCondition == TRUE) ||                     \
48            (CmpTestRegistryLock() == TRUE))
49 
50 //
51 // Makes sure that the registry is locked or loading
52 //
53 #define CMP_ASSERT_REGISTRY_LOCK_OR_LOADING(h)                      \
54     ASSERT((CmpSpecialBootCondition == TRUE) ||                     \
55            (((PCMHIVE)h)->HiveIsLoading == TRUE) ||                 \
56            (CmpTestRegistryLock() == TRUE))
57 
58 //
59 // Makes sure that the registry is exclusively locked
60 //
61 #define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK()                        \
62     ASSERT((CmpSpecialBootCondition == TRUE) ||                     \
63            (CmpTestRegistryLockExclusive() == TRUE))
64 
65 //
66 // Makes sure that the registry is exclusively locked or loading
67 //
68 #define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK_OR_LOADING(h)            \
69     ASSERT((CmpSpecialBootCondition == TRUE) ||                     \
70            (((PCMHIVE)h)->HiveIsLoading == TRUE) ||                 \
71            (CmpTestRegistryLockExclusive() == TRUE))
72 
73 //
74 // Makes sure this is a valid KCB
75 //
76 #define ASSERT_KCB_VALID(k)                                         \
77     ASSERT((k)->Signature == CM_KCB_SIGNATURE)
78 
79 //
80 // Checks if a KCB is exclusively locked
81 //
82 #define CmpIsKcbLockedExclusive(k)                                  \
83     (GET_HASH_ENTRY(CmpCacheTable,                                  \
84                     (k)->ConvKey)->Owner == KeGetCurrentThread())
85 
86 //
87 // Exclusively acquires a KCB by index
88 //
89 FORCEINLINE
90 VOID
91 CmpAcquireKcbLockExclusiveByIndex(ULONG Index)
92 {
93     ExAcquirePushLockExclusive(&CmpCacheTable[Index].Lock);
94     CmpCacheTable[Index].Owner = KeGetCurrentThread();
95 }
96 
97 //
98 // Exclusively acquires a KCB
99 //
100 FORCEINLINE
101 VOID
102 CmpAcquireKcbLockExclusive(PCM_KEY_CONTROL_BLOCK Kcb)
103 {
104     CmpAcquireKcbLockExclusiveByIndex(GET_HASH_INDEX(Kcb->ConvKey));
105 }
106 
107 //
108 // Exclusively acquires a KCB by key
109 //
110 FORCEINLINE
111 VOID
112 CmpAcquireKcbLockExclusiveByKey(IN ULONG ConvKey)
113 {
114     CmpAcquireKcbLockExclusiveByIndex(GET_HASH_INDEX(ConvKey));
115 }
116 
117 
118 //
119 // Shared acquires a KCB
120 //
121 #define CmpAcquireKcbLockShared(k)                                  \
122 {                                                                   \
123     ExAcquirePushLockShared(&GET_HASH_ENTRY(CmpCacheTable,          \
124                                             (k)->ConvKey)->Lock);    \
125 }
126 
127 //
128 // Shared acquires a KCB by index
129 //
130 #define CmpAcquireKcbLockSharedByIndex(i)                           \
131 {                                                                   \
132     ExAcquirePushLockShared(&CmpCacheTable[(i)].Lock);              \
133 }
134 
135 //
136 // Tries to convert a KCB lock
137 //
138 FORCEINLINE
139 BOOLEAN
140 CmpTryToConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
141 {
142     ASSERT(CmpIsKcbLockedExclusive(k) == FALSE);
143     if (ExConvertPushLockSharedToExclusive(
144             &GET_HASH_ENTRY(CmpCacheTable, k->ConvKey)->Lock))
145     {
146         GET_HASH_ENTRY(CmpCacheTable,
147                        k->ConvKey)->Owner = KeGetCurrentThread();
148         return TRUE;
149     }
150     return FALSE;
151 }
152 
153 //
154 // Releases an exlusively or shared acquired KCB by index
155 //
156 FORCEINLINE
157 VOID
158 CmpReleaseKcbLockByIndex(ULONG Index)
159 {
160     CmpCacheTable[Index].Owner = NULL;
161     ExReleasePushLock(&CmpCacheTable[Index].Lock);
162 }
163 
164 //
165 // Releases an exlusively or shared acquired KCB
166 //
167 FORCEINLINE
168 VOID
169 CmpReleaseKcbLock(PCM_KEY_CONTROL_BLOCK Kcb)
170 {
171     CmpReleaseKcbLockByIndex(GET_HASH_INDEX(Kcb->ConvKey));
172 }
173 
174 //
175 // Releases an exlusively or shared acquired KCB by key
176 //
177 FORCEINLINE
178 VOID
179 CmpReleaseKcbLockByKey(ULONG ConvKey)
180 {
181     CmpReleaseKcbLockByIndex(GET_HASH_INDEX(ConvKey));
182 }
183 
184 //
185 // Converts a KCB lock
186 //
187 FORCEINLINE
188 VOID
189 CmpConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
190 {
191     ASSERT(CmpIsKcbLockedExclusive(k) == FALSE);
192     CmpReleaseKcbLock(k);
193     CmpAcquireKcbLockExclusive(k);
194 }
195 
196 //
197 // Exclusively acquires an NCB
198 //
199 #define CmpAcquireNcbLockExclusive(n)                               \
200 {                                                                   \
201     ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable,   \
202                                               (n)->ConvKey)->Lock);  \
203 }
204 
205 //
206 // Exclusively acquires an NCB by key
207 //
208 #define CmpAcquireNcbLockExclusiveByKey(k)                          \
209 {                                                                   \
210     ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable,   \
211                                                (k))->Lock);          \
212 }
213 
214 //
215 // Releases an exlusively or shared acquired NCB
216 //
217 #define CmpReleaseNcbLock(k)                                        \
218 {                                                                   \
219     ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable,            \
220                                      (k)->ConvKey)->Lock);           \
221 }
222 
223 //
224 // Releases an exlusively or shared acquired NCB by key
225 //
226 #define CmpReleaseNcbLockByKey(k)                                   \
227 {                                                                   \
228     ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable,            \
229                                       (k))->Lock);                   \
230 }
231 
232 //
233 // Asserts that either the registry or the KCB is locked
234 //
235 #define CMP_ASSERT_HASH_ENTRY_LOCK(k)                               \
236 {                                                                   \
237     ASSERT(((GET_HASH_ENTRY(CmpCacheTable, k)->Owner ==              \
238             KeGetCurrentThread())) ||                               \
239            (CmpTestRegistryLockExclusive() == TRUE));               \
240 }
241 
242 //
243 // Asserts that either the registry or the KCB is locked
244 //
245 #define CMP_ASSERT_KCB_LOCK(k)                                      \
246 {                                                                   \
247     ASSERT((CmpIsKcbLockedExclusive(k) == TRUE) ||                  \
248            (CmpTestRegistryLockExclusive() == TRUE));               \
249 }
250 
251 //
252 // Gets the page attached to the KCB
253 //
254 #define CmpGetAllocPageFromKcb(k)                                   \
255     (PCM_ALLOC_PAGE)(((ULONG_PTR)(k)) & ~(PAGE_SIZE - 1))
256 
257 //
258 // Gets the page attached to the delayed allocation
259 //
260 #define CmpGetAllocPageFromDelayAlloc(a)                            \
261     (PCM_ALLOC_PAGE)(((ULONG_PTR)(a)) & ~(PAGE_SIZE - 1))
262 
263 //
264 // Makes sure that the registry is locked for flushes
265 //
266 #define CMP_ASSERT_FLUSH_LOCK(h)                                    \
267     ASSERT((CmpSpecialBootCondition == TRUE) ||                     \
268            (((PCMHIVE)h)->HiveIsLoading == TRUE) ||                 \
269            (CmpTestHiveFlusherLockShared((PCMHIVE)h) == TRUE) ||    \
270            (CmpTestHiveFlusherLockExclusive((PCMHIVE)h) == TRUE) || \
271            (CmpTestRegistryLockExclusive() == TRUE));
272