Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenrundown.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Kernel 00004 * FILE: ntoskrnl/ex/rundown.c 00005 * PURPOSE: Rundown and Cache-Aware Rundown Protection 00006 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) 00007 * Thomas Weidenmueller 00008 */ 00009 00010 /* INCLUDES *****************************************************************/ 00011 00012 #include <ntoskrnl.h> 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 /* FUNCTIONS *****************************************************************/ 00017 00018 /*++ 00019 * @name ExfAcquireRundownProtection 00020 * @implemented NT5.1 00021 * 00022 * The ExfAcquireRundownProtection routine acquires rundown protection for 00023 * the specified descriptor. 00024 * 00025 * @param RunRef 00026 * Pointer to a rundown reference descriptor. 00027 * 00028 * @return TRUE if access to the protected structure was granted, FALSE otherwise. 00029 * 00030 * @remarks Callers of ExfAcquireRundownProtection can be running at any IRQL. 00031 * 00032 *--*/ 00033 BOOLEAN 00034 FASTCALL 00035 ExfAcquireRundownProtection(IN PEX_RUNDOWN_REF RunRef) 00036 { 00037 ULONG_PTR Value = RunRef->Count, NewValue; 00038 00039 /* Loop until successfully incremented the counter */ 00040 for (;;) 00041 { 00042 /* Make sure a rundown is not active */ 00043 if (Value & EX_RUNDOWN_ACTIVE) return FALSE; 00044 00045 /* Add a reference */ 00046 NewValue = Value + EX_RUNDOWN_COUNT_INC; 00047 00048 /* Change the value */ 00049 NewValue = ExpChangeRundown(RunRef, NewValue, Value); 00050 if (NewValue == Value) return TRUE; 00051 00052 /* Update it */ 00053 Value = NewValue; 00054 } 00055 } 00056 00057 /*++ 00058 * @name ExfAcquireRundownProtectionEx 00059 * @implemented NT5.2 00060 * 00061 * The ExfAcquireRundownProtectionEx routine acquires multiple rundown 00062 * protection references for the specified descriptor. 00063 * 00064 * @param RunRef 00065 * Pointer to a rundown reference descriptor. 00066 * 00067 * @param Count 00068 * Number of times to reference the descriptor. 00069 * 00070 * @return TRUE if access to the protected structure was granted, FALSE otherwise. 00071 * 00072 * @remarks Callers of ExfAcquireRundownProtectionEx can be running at any IRQL. 00073 * 00074 *--*/ 00075 BOOLEAN 00076 FASTCALL 00077 ExfAcquireRundownProtectionEx(IN PEX_RUNDOWN_REF RunRef, 00078 IN ULONG Count) 00079 { 00080 ULONG_PTR Value = RunRef->Count, NewValue; 00081 00082 /* Loop until successfully incremented the counter */ 00083 for (;;) 00084 { 00085 /* Make sure a rundown is not active */ 00086 if (Value & EX_RUNDOWN_ACTIVE) return FALSE; 00087 00088 /* Add references */ 00089 NewValue = Value + EX_RUNDOWN_COUNT_INC * Count; 00090 00091 /* Change the value */ 00092 NewValue = ExpChangeRundown(RunRef, NewValue, Value); 00093 if (NewValue == Value) return TRUE; 00094 00095 /* Update the value */ 00096 Value = NewValue; 00097 } 00098 } 00099 00100 /*++ 00101 * @name ExfInitializeRundownProtection 00102 * @implemented NT5.1 00103 * 00104 * The ExfInitializeRundownProtection routine initializes a rundown 00105 * protection descriptor. 00106 * 00107 * @param RunRef 00108 * Pointer to a rundown reference descriptor. 00109 * 00110 * @return None. 00111 * 00112 * @remarks Callers of ExfInitializeRundownProtection can be running at any IRQL. 00113 * 00114 *--*/ 00115 VOID 00116 FASTCALL 00117 ExfInitializeRundownProtection(IN PEX_RUNDOWN_REF RunRef) 00118 { 00119 /* Set the count to zero */ 00120 RunRef->Count = 0; 00121 } 00122 00123 /*++ 00124 * @name ExfReInitializeRundownProtection 00125 * @implemented NT5.1 00126 * 00127 * The ExfReInitializeRundownProtection routine re-initializes a rundown 00128 * protection descriptor. 00129 * 00130 * @param RunRef 00131 * Pointer to a rundown reference descriptor. 00132 * 00133 * @return None. 00134 * 00135 * @remarks Callers of ExfReInitializeRundownProtection can be running at any IRQL. 00136 * 00137 *--*/ 00138 VOID 00139 FASTCALL 00140 ExfReInitializeRundownProtection(IN PEX_RUNDOWN_REF RunRef) 00141 { 00142 PAGED_CODE(); 00143 00144 /* Sanity check */ 00145 ASSERT((RunRef->Count & EX_RUNDOWN_ACTIVE) != 0); 00146 00147 /* Reset the count */ 00148 ExpSetRundown(RunRef, 0); 00149 } 00150 00151 /*++ 00152 * @name ExfRundownCompleted 00153 * @implemented NT5.1 00154 * 00155 * The ExfRundownCompleted routine completes the rundown of the specified 00156 * descriptor by setting the active bit. 00157 * 00158 * @param RunRef 00159 * Pointer to a rundown reference descriptor. 00160 * 00161 * @return None. 00162 * 00163 * @remarks Callers of ExfRundownCompleted must be running at IRQL <= APC_LEVEL. 00164 * 00165 *--*/ 00166 VOID 00167 FASTCALL 00168 ExfRundownCompleted(IN PEX_RUNDOWN_REF RunRef) 00169 { 00170 PAGED_CODE(); 00171 00172 /* Sanity check */ 00173 ASSERT((RunRef->Count & EX_RUNDOWN_ACTIVE) != 0); 00174 00175 /* Mark the counter as active */ 00176 ExpSetRundown(RunRef, EX_RUNDOWN_ACTIVE); 00177 } 00178 00179 /*++ 00180 * @name ExfReleaseRundownProtection 00181 * @implemented NT5.1 00182 * 00183 * The ExfReleaseRundownProtection routine releases the rundown protection 00184 * reference for the specified descriptor. 00185 * 00186 * @param RunRef 00187 * Pointer to a rundown reference descriptor. 00188 * 00189 * @return None. 00190 * 00191 * @remarks Callers of ExfReleaseRundownProtection can be running at any IRQL. 00192 * 00193 *--*/ 00194 VOID 00195 FASTCALL 00196 ExfReleaseRundownProtection(IN PEX_RUNDOWN_REF RunRef) 00197 { 00198 ULONG_PTR Value = RunRef->Count, NewValue; 00199 PEX_RUNDOWN_WAIT_BLOCK WaitBlock; 00200 00201 /* Loop until successfully incremented the counter */ 00202 for (;;) 00203 { 00204 /* Check if rundown is not active */ 00205 if (!(Value & EX_RUNDOWN_ACTIVE)) 00206 { 00207 /* Sanity check */ 00208 ASSERT((Value >= EX_RUNDOWN_COUNT_INC) || (KeNumberProcessors > 1)); 00209 00210 /* Get the new value */ 00211 NewValue = Value - EX_RUNDOWN_COUNT_INC; 00212 00213 /* Change the value */ 00214 NewValue = ExpChangeRundown(RunRef, NewValue, Value); 00215 if (NewValue == Value) break; 00216 00217 /* Update value */ 00218 Value = NewValue; 00219 } 00220 else 00221 { 00222 /* Get the wait block */ 00223 WaitBlock = (PEX_RUNDOWN_WAIT_BLOCK)(Value & ~EX_RUNDOWN_ACTIVE); 00224 ASSERT((WaitBlock->Count > 0) || (KeNumberProcessors > 1)); 00225 00226 /* Remove the one count */ 00227 if (!InterlockedDecrementSizeT(&WaitBlock->Count)) 00228 { 00229 /* We're down to 0 now, so signal the event */ 00230 KeSetEvent(&WaitBlock->WakeEvent, IO_NO_INCREMENT, FALSE); 00231 } 00232 00233 /* We're all done */ 00234 break; 00235 } 00236 } 00237 } 00238 00239 /*++ 00240 * @name ExfReleaseRundownProtectionEx 00241 * @implemented NT5.2 00242 * 00243 * The ExfReleaseRundownProtectionEx routine releases multiple rundown 00244 * protection references for the specified descriptor. 00245 * 00246 * @param RunRef 00247 * Pointer to a rundown reference descriptor. 00248 * 00249 * @param Count 00250 * Number of times to dereference the descriptor. 00251 * 00252 * @return None. 00253 * 00254 * @remarks Callers of ExfAcquireRundownProtectionEx can be running at any IRQL. 00255 * 00256 *--*/ 00257 VOID 00258 FASTCALL 00259 ExfReleaseRundownProtectionEx(IN PEX_RUNDOWN_REF RunRef, 00260 IN ULONG Count) 00261 { 00262 ULONG_PTR Value = RunRef->Count, NewValue; 00263 PEX_RUNDOWN_WAIT_BLOCK WaitBlock; 00264 00265 /* Loop until successfully incremented the counter */ 00266 for (;;) 00267 { 00268 /* Check if rundown is not active */ 00269 if (!(Value & EX_RUNDOWN_ACTIVE)) 00270 { 00271 /* Sanity check */ 00272 ASSERT((Value >= EX_RUNDOWN_COUNT_INC * Count) || 00273 (KeNumberProcessors > 1)); 00274 00275 /* Get the new value */ 00276 NewValue = Value - EX_RUNDOWN_COUNT_INC * Count; 00277 00278 /* Change the value */ 00279 NewValue = ExpChangeRundown(RunRef, NewValue, Value); 00280 if (NewValue == Value) break; 00281 00282 /* Update value */ 00283 Value = NewValue; 00284 } 00285 else 00286 { 00287 /* Get the wait block */ 00288 WaitBlock = (PEX_RUNDOWN_WAIT_BLOCK)(Value & ~EX_RUNDOWN_ACTIVE); 00289 ASSERT((WaitBlock->Count >= Count) || (KeNumberProcessors > 1)); 00290 00291 /* Remove the counts */ 00292 if (InterlockedExchangeAddSizeT(&WaitBlock->Count, 00293 -(LONG)Count) == (LONG)Count) 00294 { 00295 /* We're down to 0 now, so signal the event */ 00296 KeSetEvent(&WaitBlock->WakeEvent, IO_NO_INCREMENT, FALSE); 00297 } 00298 00299 /* We're all done */ 00300 break; 00301 } 00302 } 00303 } 00304 00305 /*++ 00306 * @name ExfWaitForRundownProtectionRelease 00307 * @implemented NT5.1 00308 * 00309 * The ExfWaitForRundownProtectionRelease routine waits until the specified 00310 * rundown descriptor has been released. 00311 * 00312 * @param RunRef 00313 * Pointer to a rundown reference descriptor. 00314 * 00315 * @return None. 00316 * 00317 * @remarks Callers of ExfWaitForRundownProtectionRelease must be running 00318 * at IRQL <= APC_LEVEL. 00319 * 00320 *--*/ 00321 VOID 00322 FASTCALL 00323 ExfWaitForRundownProtectionRelease(IN PEX_RUNDOWN_REF RunRef) 00324 { 00325 ULONG_PTR Value, Count, NewValue; 00326 EX_RUNDOWN_WAIT_BLOCK WaitBlock; 00327 PEX_RUNDOWN_WAIT_BLOCK WaitBlockPointer; 00328 PKEVENT Event; 00329 PAGED_CODE(); 00330 00331 /* Set the active bit */ 00332 Value = ExpChangeRundown(RunRef, EX_RUNDOWN_ACTIVE, 0); 00333 if ((Value == 0) || (Value == EX_RUNDOWN_ACTIVE)) return; 00334 00335 /* No event for now */ 00336 Event = NULL; 00337 WaitBlockPointer = (PEX_RUNDOWN_WAIT_BLOCK)((ULONG_PTR)&WaitBlock | 00338 EX_RUNDOWN_ACTIVE); 00339 00340 /* Start waitblock set loop */ 00341 for (;;) 00342 { 00343 /* Save the count */ 00344 Count = Value >> EX_RUNDOWN_COUNT_SHIFT; 00345 00346 /* If the count is over one and we don't have en event yet, create it */ 00347 if ((Count) && !(Event)) 00348 { 00349 /* Initialize the event */ 00350 KeInitializeEvent(&WaitBlock.WakeEvent, 00351 SynchronizationEvent, 00352 FALSE); 00353 00354 /* Set the pointer */ 00355 Event = &WaitBlock.WakeEvent; 00356 } 00357 00358 /* Set the count */ 00359 WaitBlock.Count = Count; 00360 00361 /* Now set the pointer */ 00362 NewValue = ExpChangeRundown(RunRef, (ULONG_PTR)WaitBlockPointer, Value); 00363 if (NewValue == Value) break; 00364 00365 /* Loop again */ 00366 Value = NewValue; 00367 ASSERT((Value & EX_RUNDOWN_ACTIVE) == 0); 00368 } 00369 00370 /* If the count was 0, we're done */ 00371 if (!Count) return; 00372 00373 /* Wait for whoever needs to release to notify us */ 00374 KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL); 00375 ASSERT(WaitBlock.Count == 0); 00376 } 00377 00378 /* FIXME: STUBS **************************************************************/ 00379 00380 /* 00381 * @unimplemented NT5.2 00382 */ 00383 BOOLEAN 00384 FASTCALL 00385 ExfAcquireRundownProtectionCacheAware(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware) 00386 { 00387 DBG_UNREFERENCED_PARAMETER(RunRefCacheAware); 00388 UNIMPLEMENTED; 00389 return FALSE; 00390 } 00391 00392 /* 00393 * @unimplemented NT5.2 00394 */ 00395 BOOLEAN 00396 FASTCALL 00397 ExfAcquireRundownProtectionCacheAwareEx(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware, 00398 IN ULONG Count) 00399 { 00400 DBG_UNREFERENCED_PARAMETER(RunRefCacheAware); 00401 DBG_UNREFERENCED_PARAMETER(Count); 00402 UNIMPLEMENTED; 00403 return FALSE; 00404 } 00405 00406 /* 00407 * @unimplemented NT5.2 00408 */ 00409 VOID 00410 FASTCALL 00411 ExfReleaseRundownProtectionCacheAware(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware) 00412 { 00413 DBG_UNREFERENCED_PARAMETER(RunRefCacheAware); 00414 UNIMPLEMENTED; 00415 } 00416 00417 /* 00418 * @unimplemented NT5.2 00419 */ 00420 VOID 00421 FASTCALL 00422 ExfReleaseRundownProtectionCacheAwareEx(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware, 00423 IN ULONG Count) 00424 { 00425 DBG_UNREFERENCED_PARAMETER(RunRefCacheAware); 00426 DBG_UNREFERENCED_PARAMETER(Count); 00427 UNIMPLEMENTED; 00428 } 00429 00430 /* 00431 * @unimplemented NT5.2 00432 */ 00433 VOID 00434 FASTCALL 00435 ExfWaitForRundownProtectionReleaseCacheAware(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware) 00436 { 00437 DBG_UNREFERENCED_PARAMETER(RunRefCacheAware); 00438 UNIMPLEMENTED; 00439 } 00440 00441 /* 00442 * @unimplemented NT5.2 00443 */ 00444 VOID 00445 FASTCALL 00446 ExfRundownCompletedCacheAware(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware) 00447 { 00448 DBG_UNREFERENCED_PARAMETER(RunRefCacheAware); 00449 UNIMPLEMENTED; 00450 } 00451 00452 /* 00453 * @unimplemented NT5.2 00454 */ 00455 VOID 00456 FASTCALL 00457 ExfReInitializeRundownProtectionCacheAware(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware) 00458 { 00459 DBG_UNREFERENCED_PARAMETER(RunRefCacheAware); 00460 UNIMPLEMENTED; 00461 } 00462 00463 /* 00464 * @unimplemented NT5.2 00465 */ 00466 PEX_RUNDOWN_REF_CACHE_AWARE 00467 NTAPI 00468 ExAllocateCacheAwareRundownProtection(IN POOL_TYPE PoolType, 00469 IN ULONG Tag) 00470 { 00471 DBG_UNREFERENCED_PARAMETER(PoolType); 00472 DBG_UNREFERENCED_PARAMETER(Tag); 00473 UNIMPLEMENTED; 00474 return NULL; 00475 } 00476 00477 /* 00478 * @unimplemented NT5.2 00479 */ 00480 VOID 00481 NTAPI 00482 ExFreeCacheAwareRundownProtection(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware) 00483 { 00484 DBG_UNREFERENCED_PARAMETER(RunRefCacheAware); 00485 UNIMPLEMENTED; 00486 } 00487 00488 /* 00489 * @unimplemented NT5.2 00490 */ 00491 VOID 00492 NTAPI 00493 ExInitializeRundownProtectionCacheAware(IN PEX_RUNDOWN_REF_CACHE_AWARE RunRefCacheAware, 00494 IN SIZE_T Count) 00495 { 00496 DBG_UNREFERENCED_PARAMETER(RunRefCacheAware); 00497 DBG_UNREFERENCED_PARAMETER(Count); 00498 UNIMPLEMENTED; 00499 } 00500 00501 /* 00502 * @unimplemented NT5.2 00503 */ 00504 SIZE_T 00505 NTAPI 00506 ExSizeOfRundownProtectionCacheAware(VOID) 00507 { 00508 UNIMPLEMENTED; 00509 return 0; 00510 } 00511 Generated on Sat May 26 2012 04:36:03 for ReactOS by
1.7.6.1
|