a6b27428f300f62e7748ce0bf78bd590d7a919e3
[reactos.git] / reactos / ntoskrnl / include / internal / cm_x.h
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
88 //
89 #define CmpAcquireKcbLockExclusive(k) \
90 { \
91 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpCacheTable, \
92 (k)->ConvKey).Lock); \
93 GET_HASH_ENTRY(CmpCacheTable, \
94 (k)->ConvKey).Owner = KeGetCurrentThread(); \
95 }
96
97 //
98 // Exclusively acquires a KCB by index
99 //
100 #define CmpAcquireKcbLockExclusiveByIndex(i) \
101 { \
102 ExAcquirePushLockExclusive(&CmpCacheTable[(i)].Lock); \
103 CmpCacheTable[(i)].Owner = KeGetCurrentThread(); \
104 }
105
106 //
107 // Exclusively acquires a KCB by key
108 //
109 #define CmpAcquireKcbLockExclusiveByKey(k) \
110 { \
111 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpCacheTable, \
112 (k)).Lock); \
113 GET_HASH_ENTRY(CmpCacheTable, \
114 (k)).Owner = KeGetCurrentThread(); \
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
155 //
156 #define CmpReleaseKcbLock(k) \
157 { \
158 GET_HASH_ENTRY(CmpCacheTable, (k)->ConvKey).Owner = NULL; \
159 ExReleasePushLock(&GET_HASH_ENTRY(CmpCacheTable, \
160 (k)->ConvKey).Lock); \
161 }
162
163 //
164 // Releases an exlusively or shared acquired KCB by index
165 //
166 #define CmpReleaseKcbLockByIndex(i) \
167 { \
168 CmpCacheTable[(i)].Owner = NULL; \
169 ExReleasePushLock(&CmpCacheTable[(i)].Lock); \
170 }
171
172 //
173 // Releases an exlusively or shared acquired KCB by key
174 //
175 #define CmpReleaseKcbLockByKey(k) \
176 { \
177 GET_HASH_ENTRY(CmpCacheTable, (k)).Owner = NULL; \
178 ExReleasePushLock(&GET_HASH_ENTRY(CmpCacheTable, \
179 (k)).Lock); \
180 }
181
182 //
183 // Converts a KCB lock
184 //
185 FORCEINLINE
186 VOID
187 CmpConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
188 {
189 ASSERT(CmpIsKcbLockedExclusive(k) == FALSE);
190 CmpReleaseKcbLock(k);
191 CmpAcquireKcbLockExclusive(k);
192 }
193
194 //
195 // Exclusively acquires an NCB
196 //
197 #define CmpAcquireNcbLockExclusive(n) \
198 { \
199 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
200 (n)->ConvKey).Lock); \
201 }
202
203 //
204 // Exclusively acquires an NCB by key
205 //
206 #define CmpAcquireNcbLockExclusiveByKey(k) \
207 { \
208 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
209 (k)).Lock); \
210 }
211
212 //
213 // Releases an exlusively or shared acquired NCB
214 //
215 #define CmpReleaseNcbLock(k) \
216 { \
217 ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
218 (k)->ConvKey).Lock); \
219 }
220
221 //
222 // Releases an exlusively or shared acquired NCB by key
223 //
224 #define CmpReleaseNcbLockByKey(k) \
225 { \
226 ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
227 (k)).Lock); \
228 }
229
230 //
231 // Asserts that either the registry or the hash entry is locked
232 //
233 #define CMP_ASSERT_HASH_ENTRY_LOCK(k) \
234 { \
235 ASSERT(((GET_HASH_ENTRY(CmpCacheTable, k).Owner == \
236 KeGetCurrentThread())) || \
237 (CmpTestRegistryLockExclusive() == TRUE)); \
238 }
239
240 //
241 // Asserts that either the registry or the KCB is locked
242 //
243 #define CMP_ASSERT_KCB_LOCK(k) \
244 { \
245 ASSERT((CmpIsKcbLockedExclusive(k) == TRUE) || \
246 (CmpTestRegistryLockExclusive() == TRUE)); \
247 }
248
249 //
250 // Gets the page attached to the KCB
251 //
252 #define CmpGetAllocPageFromKcb(k) \
253 (PCM_ALLOC_PAGE)(((ULONG_PTR)(k)) & ~(PAGE_SIZE - 1))
254
255 //
256 // Gets the page attached to the delayed allocation
257 //
258 #define CmpGetAllocPageFromDelayAlloc(a) \
259 (PCM_ALLOC_PAGE)(((ULONG_PTR)(a)) & ~(PAGE_SIZE - 1))
260
261 //
262 // Makes sure that the registry is locked for flushes
263 //
264 #define CMP_ASSERT_FLUSH_LOCK(h) \
265 ASSERT((CmpSpecialBootCondition == TRUE) || \
266 (((PCMHIVE)h)->HiveIsLoading == TRUE) || \
267 (CmpTestHiveFlusherLockShared((PCMHIVE)h) == TRUE) || \
268 (CmpTestHiveFlusherLockExclusive((PCMHIVE)h) == TRUE) || \
269 (CmpTestRegistryLockExclusive() == TRUE));