ReactOS Fundraising Campaign 2012
 
€ 3,303 / € 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

critical.c

Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS system libraries
00004  * FILE:            lib/rtl/critical.c
00005  * PURPOSE:         Critical sections
00006  * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
00007  *                  Gunnar Dalsnes
00008  */
00009 
00010 /* INCLUDES *****************************************************************/
00011 
00012 #include <rtl.h>
00013 
00014 #define NDEBUG
00015 #include <debug.h>
00016 
00017 #define MAX_STATIC_CS_DEBUG_OBJECTS 64
00018 
00019 static RTL_CRITICAL_SECTION RtlCriticalSectionLock;
00020 static LIST_ENTRY RtlCriticalSectionList;
00021 static BOOLEAN RtlpCritSectInitialized = FALSE;
00022 static RTL_CRITICAL_SECTION_DEBUG RtlpStaticDebugInfo[MAX_STATIC_CS_DEBUG_OBJECTS];
00023 static BOOLEAN RtlpDebugInfoFreeList[MAX_STATIC_CS_DEBUG_OBJECTS];
00024 
00025 /* FUNCTIONS *****************************************************************/
00026 
00027 /*++
00028  * RtlpCreateCriticalSectionSem
00029  *
00030  *     Checks if an Event has been created for the critical section.
00031  *
00032  * Params:
00033  *     None
00034  *
00035  * Returns:
00036  *     None. Raises an exception if the system call failed.
00037  *
00038  * Remarks:
00039  *     None
00040  *
00041  *--*/
00042 VOID
00043 NTAPI
00044 RtlpCreateCriticalSectionSem(PRTL_CRITICAL_SECTION CriticalSection)
00045 {
00046     HANDLE hEvent = CriticalSection->LockSemaphore;
00047     HANDLE hNewEvent;
00048     NTSTATUS Status;
00049 
00050     /* Chevk if we have an event */
00051     if (!hEvent) {
00052 
00053         /* No, so create it */
00054         if (!NT_SUCCESS(Status = NtCreateEvent(&hNewEvent,
00055                                                EVENT_ALL_ACCESS,
00056                                                NULL,
00057                                                SynchronizationEvent,
00058                                                FALSE))) {
00059 
00060                 /* We failed, this is bad... */
00061                 DPRINT1("Failed to Create Event!\n");
00062                 InterlockedDecrement(&CriticalSection->LockCount);
00063                 RtlRaiseStatus(Status);
00064                 return;
00065         }
00066         DPRINT("Created Event: %p \n", hNewEvent);
00067 
00068         if (InterlockedCompareExchangePointer((PVOID*)&CriticalSection->LockSemaphore,
00069                                               (PVOID)hNewEvent,
00070                                                0)) {
00071 
00072             /* Some just created an event */
00073             DPRINT("Closing already created event: %p\n", hNewEvent);
00074             NtClose(hNewEvent);
00075         }
00076     }
00077 
00078     return;
00079 }
00080 
00081 /*++
00082  * RtlpWaitForCriticalSection
00083  *
00084  *     Slow path of RtlEnterCriticalSection. Waits on an Event Object.
00085  *
00086  * Params:
00087  *     CriticalSection - Critical section to acquire.
00088  *
00089  * Returns:
00090  *     STATUS_SUCCESS, or raises an exception if a deadlock is occuring.
00091  *
00092  * Remarks:
00093  *     None
00094  *
00095  *--*/
00096 NTSTATUS
00097 NTAPI
00098 RtlpWaitForCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)
00099 {
00100     NTSTATUS Status;
00101     EXCEPTION_RECORD ExceptionRecord;
00102     BOOLEAN LastChance = FALSE;
00103     LARGE_INTEGER Timeout;
00104 
00105     /* Wait 2.5 minutes */
00106     Timeout.QuadPart = 150000L * (ULONGLONG)10000;
00107     Timeout.QuadPart = -Timeout.QuadPart;
00108     /* ^^ HACK HACK HACK. Good way:
00109     Timeout = &NtCurrentPeb()->CriticalSectionTimeout   */
00110 
00111     /* Do we have an Event yet? */
00112     if (!CriticalSection->LockSemaphore) {
00113         RtlpCreateCriticalSectionSem(CriticalSection);
00114     }
00115 
00116     /* Increase the Debug Entry count */
00117     DPRINT("Waiting on Critical Section Event: %p %p\n",
00118             CriticalSection,
00119             CriticalSection->LockSemaphore);
00120 
00121     if (CriticalSection->DebugInfo)
00122         CriticalSection->DebugInfo->EntryCount++;
00123 
00124     for (;;) {
00125 
00126         /* Increase the number of times we've had contention */
00127         if (CriticalSection->DebugInfo)
00128             CriticalSection->DebugInfo->ContentionCount++;
00129 
00130         /* Wait on the Event */
00131         Status = NtWaitForSingleObject(CriticalSection->LockSemaphore,
00132                                        FALSE,
00133                                        &Timeout);
00134 
00135         /* We have Timed out */
00136         if (Status == STATUS_TIMEOUT) {
00137 
00138             /* Is this the 2nd time we've timed out? */
00139             if (LastChance) {
00140 
00141                 DPRINT1("Deadlock: %p\n", CriticalSection);
00142 
00143                 /* Yes it is, we are raising an exception */
00144                 ExceptionRecord.ExceptionCode    = STATUS_POSSIBLE_DEADLOCK;
00145                 ExceptionRecord.ExceptionFlags   = 0;
00146                 ExceptionRecord.ExceptionRecord  = NULL;
00147                 ExceptionRecord.ExceptionAddress = RtlRaiseException;
00148                 ExceptionRecord.NumberParameters = 1;
00149                 ExceptionRecord.ExceptionInformation[0] = (ULONG_PTR)CriticalSection;
00150                 RtlRaiseException(&ExceptionRecord);
00151 
00152             }
00153 
00154             /* One more try */
00155             LastChance = TRUE;
00156 
00157         } else {
00158 
00159             /* If we are here, everything went fine */
00160             return STATUS_SUCCESS;
00161         }
00162     }
00163 }
00164 
00165 /*++
00166  * RtlpUnWaitCriticalSection
00167  *
00168  *     Slow path of RtlLeaveCriticalSection. Fires an Event Object.
00169  *
00170  * Params:
00171  *     CriticalSection - Critical section to release.
00172  *
00173  * Returns:
00174  *     None. Raises an exception if the system call failed.
00175  *
00176  * Remarks:
00177  *     None
00178  *
00179  *--*/
00180 VOID
00181 NTAPI
00182 RtlpUnWaitCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)
00183 {
00184     NTSTATUS Status;
00185 
00186     /* Do we have an Event yet? */
00187     if (!CriticalSection->LockSemaphore) {
00188         RtlpCreateCriticalSectionSem(CriticalSection);
00189     }
00190 
00191     /* Signal the Event */
00192     DPRINT("Signaling Critical Section Event: %p, %p\n",
00193             CriticalSection,
00194             CriticalSection->LockSemaphore);
00195     Status = NtSetEvent(CriticalSection->LockSemaphore, NULL);
00196 
00197     if (!NT_SUCCESS(Status)) {
00198 
00199         /* We've failed */
00200         DPRINT1("Signaling Failed for: %p, %p, 0x%08lx\n",
00201                 CriticalSection,
00202                 CriticalSection->LockSemaphore,
00203                 Status);
00204         RtlRaiseStatus(Status);
00205     }
00206 }
00207 
00208 /*++
00209  * RtlpInitDeferedCriticalSection
00210  *
00211  *     Initializes the Critical Section implementation.
00212  *
00213  * Params:
00214  *     None
00215  *
00216  * Returns:
00217  *     None.
00218  *
00219  * Remarks:
00220  *     After this call, the Process Critical Section list is protected.
00221  *
00222  *--*/
00223 VOID
00224 NTAPI
00225 RtlpInitDeferedCriticalSection(VOID)
00226 {
00227 
00228     /* Initialize the Process Critical Section List */
00229     InitializeListHead(&RtlCriticalSectionList);
00230 
00231     /* Initialize the CS Protecting the List */
00232     RtlInitializeCriticalSection(&RtlCriticalSectionLock);
00233 
00234     /* It's now safe to enter it */
00235     RtlpCritSectInitialized = TRUE;
00236 }
00237 
00238 /*++
00239  * RtlpAllocateDebugInfo
00240  *
00241  *     Finds or allocates memory for a Critical Section Debug Object
00242  *
00243  * Params:
00244  *     None
00245  *
00246  * Returns:
00247  *     A pointer to an empty Critical Section Debug Object.
00248  *
00249  * Remarks:
00250  *     For optimization purposes, the first 64 entries can be cached. From
00251  *     then on, future Critical Sections will allocate memory from the heap.
00252  *
00253  *--*/
00254 PRTL_CRITICAL_SECTION_DEBUG
00255 NTAPI
00256 RtlpAllocateDebugInfo(VOID)
00257 {
00258     ULONG i;
00259 
00260     /* Try to allocate from our buffer first */
00261     for (i = 0; i < MAX_STATIC_CS_DEBUG_OBJECTS; i++) {
00262 
00263         /* Check if Entry is free */
00264         if (!RtlpDebugInfoFreeList[i]) {
00265 
00266             /* Mark entry in use */
00267             DPRINT("Using entry: %lu. Buffer: %p\n", i, &RtlpStaticDebugInfo[i]);
00268             RtlpDebugInfoFreeList[i] = TRUE;
00269 
00270             /* Use free entry found */
00271             return &RtlpStaticDebugInfo[i];
00272         }
00273 
00274     }
00275 
00276     /* We are out of static buffer, allocate dynamic */
00277     return RtlAllocateHeap(NtCurrentPeb()->ProcessHeap,
00278                            0,
00279                            sizeof(RTL_CRITICAL_SECTION_DEBUG));
00280 }
00281 
00282 /*++
00283  * RtlpFreeDebugInfo
00284  *
00285  *     Frees the memory for a Critical Section Debug Object
00286  *
00287  * Params:
00288  *     DebugInfo - Pointer to Critical Section Debug Object to free.
00289  *
00290  * Returns:
00291  *     None.
00292  *
00293  * Remarks:
00294  *     If the pointer is part of the static buffer, then the entry is made
00295  *     free again. If not, the object is de-allocated from the heap.
00296  *
00297  *--*/
00298 VOID
00299 NTAPI
00300 RtlpFreeDebugInfo(PRTL_CRITICAL_SECTION_DEBUG DebugInfo)
00301 {
00302     SIZE_T EntryId;
00303 
00304     /* Is it part of our cached entries? */
00305     if ((DebugInfo >= RtlpStaticDebugInfo) &&
00306         (DebugInfo <= &RtlpStaticDebugInfo[MAX_STATIC_CS_DEBUG_OBJECTS-1])) {
00307 
00308         /* Yes. zero it out */
00309         RtlZeroMemory(DebugInfo, sizeof(RTL_CRITICAL_SECTION_DEBUG));
00310 
00311         /* Mark as free */
00312         EntryId = (DebugInfo - RtlpStaticDebugInfo);
00313         DPRINT("Freeing from Buffer: %p. Entry: %Iu inside Process: %p\n",
00314                DebugInfo,
00315                EntryId,
00316                NtCurrentTeb()->ClientId.UniqueProcess);
00317         RtlpDebugInfoFreeList[EntryId] = FALSE;
00318 
00319     } else if (!DebugInfo->Flags) {
00320 
00321         /* It's a dynamic one, so free from the heap */
00322         DPRINT("Freeing from Heap: %p inside Process: %p\n",
00323                DebugInfo,
00324                NtCurrentTeb()->ClientId.UniqueProcess);
00325         RtlFreeHeap(NtCurrentPeb()->ProcessHeap, 0, DebugInfo);
00326 
00327     } else {
00328 
00329         /* Wine stores a section name pointer in the Flags member */
00330         DPRINT("Assuming static: %p inside Process: %p\n",
00331                DebugInfo,
00332                NtCurrentTeb()->ClientId.UniqueProcess);
00333 
00334     }
00335 }
00336 
00337 /*++
00338  * RtlDeleteCriticalSection
00339  * @implemented NT4
00340  *
00341  *     Deletes a Critical Section
00342  *
00343  * Params:
00344  *     CriticalSection - Critical section to delete.
00345  *
00346  * Returns:
00347  *     STATUS_SUCCESS, or error value returned by NtClose.
00348  *
00349  * Remarks:
00350  *     The critical section members should not be read after this call.
00351  *
00352  *--*/
00353 NTSTATUS
00354 NTAPI
00355 RtlDeleteCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)
00356 {
00357     NTSTATUS Status = STATUS_SUCCESS;
00358 
00359     DPRINT("Deleting Critical Section: %p\n", CriticalSection);
00360     /* Close the Event Object Handle if it exists */
00361     if (CriticalSection->LockSemaphore) {
00362 
00363         /* In case NtClose fails, return the status */
00364         Status = NtClose(CriticalSection->LockSemaphore);
00365 
00366     }
00367 
00368     /* Protect List */
00369     RtlEnterCriticalSection(&RtlCriticalSectionLock);
00370 
00371     if (CriticalSection->DebugInfo)
00372     {
00373         /* Remove it from the list */
00374         RemoveEntryList(&CriticalSection->DebugInfo->ProcessLocksList);
00375 #if 0 /* We need to preserve Flags for RtlpFreeDebugInfo */
00376         RtlZeroMemory(CriticalSection->DebugInfo, sizeof(RTL_CRITICAL_SECTION_DEBUG));
00377 #endif
00378     }
00379 
00380     /* Unprotect */
00381     RtlLeaveCriticalSection(&RtlCriticalSectionLock);
00382 
00383     if (CriticalSection->DebugInfo)
00384     {
00385         /* Free it */
00386         RtlpFreeDebugInfo(CriticalSection->DebugInfo);
00387     }
00388 
00389     /* Wipe it out */
00390     RtlZeroMemory(CriticalSection, sizeof(RTL_CRITICAL_SECTION));
00391 
00392     /* Return */
00393     return Status;
00394 }
00395 
00396 /*++
00397  * RtlSetCriticalSectionSpinCount
00398  * @implemented NT4
00399  *
00400  *     Sets the spin count for a critical section.
00401  *
00402  * Params:
00403  *     CriticalSection - Critical section to set the spin count for.
00404  *
00405  *     SpinCount - Spin count for the critical section.
00406  *
00407  * Returns:
00408  *     STATUS_SUCCESS.
00409  *
00410  * Remarks:
00411  *     SpinCount is ignored on single-processor systems.
00412  *
00413  *--*/
00414 DWORD
00415 NTAPI
00416 RtlSetCriticalSectionSpinCount(PRTL_CRITICAL_SECTION CriticalSection,
00417                                ULONG SpinCount)
00418 {
00419     ULONG OldCount = (ULONG)CriticalSection->SpinCount;
00420 
00421     /* Set to parameter if MP, or to 0 if this is Uniprocessor */
00422     CriticalSection->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? SpinCount : 0;
00423     return OldCount;
00424 }
00425 
00426 /*++
00427  * RtlEnterCriticalSection
00428  * @implemented NT4
00429  *
00430  *     Waits to gain ownership of the critical section.
00431  *
00432  * Params:
00433  *     CriticalSection - Critical section to wait for.
00434  *
00435  * Returns:
00436  *     STATUS_SUCCESS.
00437  *
00438  * Remarks:
00439  *     Uses a fast-path unless contention happens.
00440  *
00441  *--*/
00442 NTSTATUS
00443 NTAPI
00444 RtlEnterCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)
00445 {
00446     HANDLE Thread = (HANDLE)NtCurrentTeb()->ClientId.UniqueThread;
00447 
00448     /* Try to Lock it */
00449     if (InterlockedIncrement(&CriticalSection->LockCount) != 0) {
00450 
00451         /*
00452          * We've failed to lock it! Does this thread
00453          * actually own it?
00454          */
00455         if (Thread == CriticalSection->OwningThread) {
00456 
00457             /* You own it, so you'll get it when you're done with it! No need to
00458                use the interlocked functions as only the thread who already owns
00459                the lock can modify this data. */
00460             CriticalSection->RecursionCount++;
00461             return STATUS_SUCCESS;
00462         }
00463 
00464         /* NOTE - CriticalSection->OwningThread can be NULL here because changing
00465                   this information is not serialized. This happens when thread a
00466                   acquires the lock (LockCount == 0) and thread b tries to
00467                   acquire it as well (LockCount == 1) but thread a hasn't had a
00468                   chance to set the OwningThread! So it's not an error when
00469                   OwningThread is NULL here! */
00470 
00471         /* We don't own it, so we must wait for it */
00472         RtlpWaitForCriticalSection(CriticalSection);
00473     }
00474 
00475     /* Lock successful. Changing this information has not to be serialized because
00476        only one thread at a time can actually change it (the one who acquired
00477        the lock)! */
00478     CriticalSection->OwningThread = Thread;
00479     CriticalSection->RecursionCount = 1;
00480     return STATUS_SUCCESS;
00481 }
00482 
00483 /*++
00484  * RtlInitializeCriticalSection
00485  * @implemented NT4
00486  *
00487  *     Initialises a new critical section.
00488  *
00489  * Params:
00490  *     CriticalSection - Critical section to initialise
00491  *
00492  * Returns:
00493  *     STATUS_SUCCESS.
00494  *
00495  * Remarks:
00496  *     Simply calls RtlInitializeCriticalSectionAndSpinCount
00497  *
00498  *--*/
00499 NTSTATUS
00500 NTAPI
00501 RtlInitializeCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)
00502 {
00503     /* Call the Main Function */
00504     return RtlInitializeCriticalSectionAndSpinCount(CriticalSection, 0);
00505 }
00506 
00507 /*++
00508  * RtlInitializeCriticalSectionAndSpinCount
00509  * @implemented NT4
00510  *
00511  *     Initialises a new critical section.
00512  *
00513  * Params:
00514  *     CriticalSection - Critical section to initialise
00515  *
00516  *     SpinCount - Spin count for the critical section.
00517  *
00518  * Returns:
00519  *     STATUS_SUCCESS.
00520  *
00521  * Remarks:
00522  *     SpinCount is ignored on single-processor systems.
00523  *
00524  *--*/
00525 NTSTATUS
00526 NTAPI
00527 RtlInitializeCriticalSectionAndSpinCount(PRTL_CRITICAL_SECTION CriticalSection,
00528                                          ULONG SpinCount)
00529 {
00530     PRTL_CRITICAL_SECTION_DEBUG CritcalSectionDebugData;
00531 
00532     /* First things first, set up the Object */
00533     DPRINT("Initializing Critical Section: %p\n", CriticalSection);
00534     CriticalSection->LockCount = -1;
00535     CriticalSection->RecursionCount = 0;
00536     CriticalSection->OwningThread = 0;
00537     CriticalSection->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? SpinCount : 0;
00538     CriticalSection->LockSemaphore = 0;
00539 
00540     /* Allocate the Debug Data */
00541     CritcalSectionDebugData = RtlpAllocateDebugInfo();
00542     DPRINT("Allocated Debug Data: %p inside Process: %p\n",
00543            CritcalSectionDebugData,
00544            NtCurrentTeb()->ClientId.UniqueProcess);
00545 
00546     if (!CritcalSectionDebugData) {
00547 
00548         /* This is bad! */
00549         DPRINT1("Couldn't allocate Debug Data for: %p\n", CriticalSection);
00550         return STATUS_NO_MEMORY;
00551     }
00552 
00553     /* Set it up */
00554     CritcalSectionDebugData->Type = RTL_CRITSECT_TYPE;
00555     CritcalSectionDebugData->ContentionCount = 0;
00556     CritcalSectionDebugData->EntryCount = 0;
00557     CritcalSectionDebugData->CriticalSection = CriticalSection;
00558     CritcalSectionDebugData->Flags = 0;
00559     CriticalSection->DebugInfo = CritcalSectionDebugData;
00560 
00561     /*
00562     * Add it to the List of Critical Sections owned by the process.
00563     * If we've initialized the Lock, then use it. If not, then probably
00564     * this is the lock initialization itself, so insert it directly.
00565     */
00566     if ((CriticalSection != &RtlCriticalSectionLock) && (RtlpCritSectInitialized)) {
00567 
00568         DPRINT("Securely Inserting into ProcessLocks: %p, %p, %p\n",
00569                &CritcalSectionDebugData->ProcessLocksList,
00570                CriticalSection,
00571                &RtlCriticalSectionList);
00572 
00573         /* Protect List */
00574         RtlEnterCriticalSection(&RtlCriticalSectionLock);
00575 
00576         /* Add this one */
00577         InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList);
00578 
00579         /* Unprotect */
00580         RtlLeaveCriticalSection(&RtlCriticalSectionLock);
00581 
00582     } else {
00583 
00584         DPRINT("Inserting into ProcessLocks: %p, %p, %p\n",
00585                &CritcalSectionDebugData->ProcessLocksList,
00586                CriticalSection,
00587                &RtlCriticalSectionList);
00588 
00589         /* Add it directly */
00590         InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList);
00591     }
00592 
00593     return STATUS_SUCCESS;
00594 }
00595 
00596 /*++
00597  * RtlLeaveCriticalSection
00598  * @implemented NT4
00599  *
00600  *     Releases a critical section and makes if available for new owners.
00601  *
00602  * Params:
00603  *     CriticalSection - Critical section to release.
00604  *
00605  * Returns:
00606  *     STATUS_SUCCESS.
00607  *
00608  * Remarks:
00609  *     If another thread was waiting, the slow path is entered.
00610  *
00611  *--*/
00612 NTSTATUS
00613 NTAPI
00614 RtlLeaveCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)
00615 {
00616 #ifndef NDEBUG
00617     HANDLE Thread = (HANDLE)NtCurrentTeb()->ClientId.UniqueThread;
00618 
00619     /* In win this case isn't checked. However it's a valid check so it should only
00620        be performed in debug builds! */
00621     if (Thread != CriticalSection->OwningThread)
00622     {
00623        DPRINT1("Releasing critical section not owned!\n");
00624        return STATUS_INVALID_PARAMETER;
00625     }
00626 #endif
00627 
00628     /* Decrease the Recursion Count. No need to do this atomically because only
00629        the thread who holds the lock can call this function (unless the program
00630        is totally screwed... */
00631     if (--CriticalSection->RecursionCount) {
00632 
00633         /* Someone still owns us, but we are free. This needs to be done atomically. */
00634         InterlockedDecrement(&CriticalSection->LockCount);
00635 
00636     } else {
00637 
00638          /* Nobody owns us anymore. No need to do this atomically. See comment
00639             above. */
00640         CriticalSection->OwningThread = 0;
00641 
00642         /* Was someone wanting us? This needs to be done atomically. */
00643         if (-1 != InterlockedDecrement(&CriticalSection->LockCount)) {
00644 
00645             /* Let him have us */
00646             RtlpUnWaitCriticalSection(CriticalSection);
00647         }
00648     }
00649 
00650     /* Sucessful! */
00651     return STATUS_SUCCESS;
00652 }
00653 
00654 /*++
00655  * RtlTryEnterCriticalSection
00656  * @implemented NT4
00657  *
00658  *     Attemps to gain ownership of the critical section without waiting.
00659  *
00660  * Params:
00661  *     CriticalSection - Critical section to attempt acquiring.
00662  *
00663  * Returns:
00664  *     TRUE if the critical section has been acquired, FALSE otherwise.
00665  *
00666  * Remarks:
00667  *     None
00668  *
00669  *--*/
00670 BOOLEAN
00671 NTAPI
00672 RtlTryEnterCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)
00673 {
00674     /* Try to take control */
00675     if (InterlockedCompareExchange(&CriticalSection->LockCount,
00676                                     0,
00677                                     -1) == -1) {
00678 
00679         /* It's ours */
00680         CriticalSection->OwningThread =  NtCurrentTeb()->ClientId.UniqueThread;
00681         CriticalSection->RecursionCount = 1;
00682         return TRUE;
00683 
00684    } else if (CriticalSection->OwningThread == NtCurrentTeb()->ClientId.UniqueThread) {
00685 
00686         /* It's already ours */
00687         InterlockedIncrement(&CriticalSection->LockCount);
00688         CriticalSection->RecursionCount++;
00689         return TRUE;
00690     }
00691 
00692     /* It's not ours */
00693     return FALSE;
00694 }
00695 
00696 /* EOF */

Generated on Tue May 15 05:00:36 2012 for ReactOS by doxygen 1.6.3

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