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)
10 // Returns the hashkey corresponding to a convkey
12 #define GET_HASH_KEY(ConvKey) \
13 ((CMP_HASH_IRRATIONAL * (ConvKey)) % CMP_HASH_PRIME)
16 // Returns the index into the hash table, or the entry itself
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))
26 // Returns whether or not the cell is cached
28 #define CMP_IS_CELL_CACHED(c) \
29 (((c) & HCELL_CACHED) && ((c) != HCELL_NIL))
32 // Return data from a cached cell
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))
44 // Makes sure that the registry is locked
46 #define CMP_ASSERT_REGISTRY_LOCK() \
47 ASSERT((CmpSpecialBootCondition == TRUE) || \
48 (CmpTestRegistryLock() == TRUE))
51 // Makes sure that the registry is locked or loading
53 #define CMP_ASSERT_REGISTRY_LOCK_OR_LOADING(h) \
54 ASSERT((CmpSpecialBootCondition == TRUE) || \
55 (((PCMHIVE)h)->HiveIsLoading == TRUE) || \
56 (CmpTestRegistryLock() == TRUE))
59 // Makes sure that the registry is exclusively locked
61 #define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK() \
62 ASSERT((CmpSpecialBootCondition == TRUE) || \
63 (CmpTestRegistryLockExclusive() == TRUE))
66 // Makes sure that the registry is exclusively locked or loading
68 #define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK_OR_LOADING(h) \
69 ASSERT((CmpSpecialBootCondition == TRUE) || \
70 (((PCMHIVE)h)->HiveIsLoading == TRUE) || \
71 (CmpTestRegistryLockExclusive() == TRUE))
74 // Makes sure this is a valid KCB
76 #define ASSERT_KCB_VALID(k) \
77 ASSERT((k)->Signature == CM_KCB_SIGNATURE)
80 // Checks if a KCB is exclusively locked
82 #define CmpIsKcbLockedExclusive(k) \
83 (GET_HASH_ENTRY(CmpCacheTable, \
84 (k)->ConvKey)->Owner == KeGetCurrentThread())
87 // Exclusively acquires a KCB by index
91 CmpAcquireKcbLockExclusiveByIndex(ULONG Index
)
93 ExAcquirePushLockExclusive(&CmpCacheTable
[Index
].Lock
);
94 CmpCacheTable
[Index
].Owner
= KeGetCurrentThread();
98 // Exclusively acquires a KCB
102 CmpAcquireKcbLockExclusive(PCM_KEY_CONTROL_BLOCK Kcb
)
104 CmpAcquireKcbLockExclusiveByIndex(GET_HASH_INDEX(Kcb
->ConvKey
));
108 // Exclusively acquires a KCB by key
112 CmpAcquireKcbLockExclusiveByKey(IN ULONG ConvKey
)
114 CmpAcquireKcbLockExclusiveByIndex(GET_HASH_INDEX(ConvKey
));
119 // Shared acquires a KCB
121 #define CmpAcquireKcbLockShared(k) \
123 ExAcquirePushLockShared(&GET_HASH_ENTRY(CmpCacheTable, \
124 (k)->ConvKey)->Lock); \
128 // Shared acquires a KCB by index
130 #define CmpAcquireKcbLockSharedByIndex(i) \
132 ExAcquirePushLockShared(&CmpCacheTable[(i)].Lock); \
136 // Tries to convert a KCB lock
140 CmpTryToConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k
)
142 ASSERT(CmpIsKcbLockedExclusive(k
) == FALSE
);
143 if (ExConvertPushLockSharedToExclusive(
144 &GET_HASH_ENTRY(CmpCacheTable
, k
->ConvKey
)->Lock
))
146 GET_HASH_ENTRY(CmpCacheTable
,
147 k
->ConvKey
)->Owner
= KeGetCurrentThread();
154 // Releases an exlusively or shared acquired KCB by index
158 CmpReleaseKcbLockByIndex(ULONG Index
)
160 CmpCacheTable
[Index
].Owner
= NULL
;
161 ExReleasePushLock(&CmpCacheTable
[Index
].Lock
);
165 // Releases an exlusively or shared acquired KCB
169 CmpReleaseKcbLock(PCM_KEY_CONTROL_BLOCK Kcb
)
171 CmpReleaseKcbLockByIndex(GET_HASH_INDEX(Kcb
->ConvKey
));
175 // Releases an exlusively or shared acquired KCB by key
179 CmpReleaseKcbLockByKey(ULONG ConvKey
)
181 CmpReleaseKcbLockByIndex(GET_HASH_INDEX(ConvKey
));
185 // Converts a KCB lock
189 CmpConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k
)
191 ASSERT(CmpIsKcbLockedExclusive(k
) == FALSE
);
192 CmpReleaseKcbLock(k
);
193 CmpAcquireKcbLockExclusive(k
);
197 // Exclusively acquires an NCB
199 #define CmpAcquireNcbLockExclusive(n) \
201 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
202 (n)->ConvKey)->Lock); \
206 // Exclusively acquires an NCB by key
208 #define CmpAcquireNcbLockExclusiveByKey(k) \
210 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
215 // Releases an exlusively or shared acquired NCB
217 #define CmpReleaseNcbLock(k) \
219 ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
220 (k)->ConvKey)->Lock); \
224 // Releases an exlusively or shared acquired NCB by key
226 #define CmpReleaseNcbLockByKey(k) \
228 ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
233 // Asserts that either the registry or the KCB is locked
235 #define CMP_ASSERT_HASH_ENTRY_LOCK(k) \
237 ASSERT(((GET_HASH_ENTRY(CmpCacheTable, k)->Owner == \
238 KeGetCurrentThread())) || \
239 (CmpTestRegistryLockExclusive() == TRUE)); \
243 // Asserts that either the registry or the KCB is locked
245 #define CMP_ASSERT_KCB_LOCK(k) \
247 ASSERT((CmpIsKcbLockedExclusive(k) == TRUE) || \
248 (CmpTestRegistryLockExclusive() == TRUE)); \
252 // Gets the page attached to the KCB
254 #define CmpGetAllocPageFromKcb(k) \
255 (PCM_ALLOC_PAGE)(((ULONG_PTR)(k)) & ~(PAGE_SIZE - 1))
258 // Gets the page attached to the delayed allocation
260 #define CmpGetAllocPageFromDelayAlloc(a) \
261 (PCM_ALLOC_PAGE)(((ULONG_PTR)(a)) & ~(PAGE_SIZE - 1))
264 // Makes sure that the registry is locked for flushes
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));