[NTOS] Make the GET_HASH_ENTRY() macro return a pointer to the entry instead of the...
[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 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));