ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

rundown.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.