Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

resource.c File Reference

#include <ntos.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <heap.h>
#include "ldrp.h"

Go to the source code of this file.

Defines

#define DESIRED_EVENT_ACCESS   (EVENT_QUERY_STATE | EVENT_MODIFY_STATE | SYNCHRONIZE)
#define DESIRED_SEMAPHORE_ACCESS   (SEMAPHORE_QUERY_STATE | SEMAPHORE_MODIFY_STATE | SYNCHRONIZE)
#define MAX_SPIN_COUNT   0x00ffffff
#define PREALLOCATE_EVENT_MASK   0x80000000

Functions

VOID RtlDumpResource (IN PRTL_RESOURCE Resource)
VOID RtlpInitDeferedCriticalSection (VOID)
PRTL_CRITICAL_SECTION_DEBUG RtlpChainDebugInfo (IN PVOID BaseAddress, IN ULONG Size)
PVOID RtlpAllocateDebugInfo (VOID)
VOID RtlpFreeDebugInfo (IN PVOID DebugInfo)
VOID RtlpCreateCriticalSectionSem (IN PRTL_CRITICAL_SECTION CriticalSection)
BOOLEAN NtdllOkayToLockRoutine (IN PVOID Lock)
VOID RtlInitializeResource (IN PRTL_RESOURCE Resource)
BOOLEAN RtlAcquireResourceShared (IN PRTL_RESOURCE Resource, IN BOOLEAN Wait)
BOOLEAN RtlAcquireResourceExclusive (IN PRTL_RESOURCE Resource, IN BOOLEAN Wait)
VOID RtlReleaseResource (IN PRTL_RESOURCE Resource)
VOID RtlConvertSharedToExclusive (IN PRTL_RESOURCE Resource)
VOID RtlConvertExclusiveToShared (IN PRTL_RESOURCE Resource)
VOID RtlDeleteResource (IN PRTL_RESOURCE Resource)
NTSTATUS RtlInitializeCriticalSection (IN PRTL_CRITICAL_SECTION CriticalSection)
VOID RtlEnableEarlyCriticalSectionEventCreation (VOID)
NTSTATUS RtlInitializeCriticalSectionAndSpinCount (IN PRTL_CRITICAL_SECTION CriticalSection, ULONG SpinCount)
ULONG RtlSetCriticalSectionSpinCount (IN PRTL_CRITICAL_SECTION CriticalSection, ULONG SpinCount)
VOID RtlpCheckDeferedCriticalSection (IN PRTL_CRITICAL_SECTION CriticalSection)
NTSTATUS RtlDeleteCriticalSection (IN PRTL_CRITICAL_SECTION CriticalSection)
void RtlpWaitForCriticalSection (IN PRTL_CRITICAL_SECTION CriticalSection)
void RtlpUnWaitCriticalSection (IN PRTL_CRITICAL_SECTION CriticalSection)
void RtlpNotOwnerCriticalSection (IN PRTL_CRITICAL_SECTION CriticalSection)
void RtlCheckForOrphanedCriticalSections (IN HANDLE hThread)

Variables

BOOLEAN LdrpShutdownInProgress
HANDLE LdrpShutdownThreadId
RTL_CRITICAL_SECTION DeferedCriticalSection
RTL_CRITICAL_SECTION_DEBUG RtlpStaticDebugInfo [64]
PRTL_CRITICAL_SECTION_DEBUG RtlpDebugInfoFreeList
BOOLEAN RtlpCritSectInitialized


Define Documentation

#define DESIRED_EVENT_ACCESS   (EVENT_QUERY_STATE | EVENT_MODIFY_STATE | SYNCHRONIZE)
 

Definition at line 38 of file dll/resource.c.

Referenced by RtlInitializeCriticalSectionAndSpinCount(), and RtlpCreateCriticalSectionSem().

#define DESIRED_SEMAPHORE_ACCESS   (SEMAPHORE_QUERY_STATE | SEMAPHORE_MODIFY_STATE | SYNCHRONIZE)
 

Definition at line 41 of file dll/resource.c.

Referenced by RtlInitializeResource().

#define MAX_SPIN_COUNT   0x00ffffff
 

Definition at line 1236 of file dll/resource.c.

Referenced by RtlInitializeCriticalSectionAndSpinCount().

#define PREALLOCATE_EVENT_MASK   0x80000000
 

Definition at line 1237 of file dll/resource.c.

Referenced by RtlInitializeCriticalSectionAndSpinCount().


Function Documentation

BOOLEAN NtdllOkayToLockRoutine IN PVOID  Lock  ) 
 

Definition at line 236 of file dll/resource.c.

00239 { 00240 return TRUE; 00241 }

BOOLEAN RtlAcquireResourceExclusive IN PRTL_RESOURCE  Resource,
IN BOOLEAN  Wait
 

Definition at line 515 of file dll/resource.c.

References _ERESOURCE::ContentionCount, DbgPrint, FALSE, NT_SUCCESS, NTSTATUS(), NtWaitForSingleObject(), NULL, Resource, RtlImageNtHeader(), RtlpTimeout, RtlRaiseException(), RtlRaiseStatus(), Status, and TRUE.

00522 : 00523 00524 The routine acquires the resource for exclusive access. Upon return from 00525 the procedure the resource is acquired for exclusive access. 00526 00527 Arguments: 00528 00529 Resource - Supplies the resource to acquire 00530 00531 Wait - Indicates if the call is allowed to wait for the resource 00532 to become available for must return immediately 00533 00534 Return Value: 00535 00536 BOOLEAN - TRUE if the resource is acquired and FALSE otherwise 00537 00538 --*/ 00539 00540 { 00541 NTSTATUS Status; 00542 ULONG TimeoutCount = 0; 00543 PLARGE_INTEGER TimeoutTime = &RtlpTimeout; 00544 00545 // 00546 // Loop until the resource is ours or exit if we cannot wait. 00547 // 00548 00549 while (TRUE) { 00550 00551 // 00552 // Enter the critical section 00553 // 00554 00555 RtlEnterCriticalSection(&Resource->CriticalSection); 00556 00557 // 00558 // If there are no shared users and it is not currently acquired for 00559 // exclusive use then we can acquire the resource for exclusive 00560 // access. We also can acquire it if the resource indicates exclusive 00561 // access but there isn't currently an owner. 00562 // 00563 00564 if ((Resource->NumberOfActive == 0) 00565 00566 || 00567 00568 ((Resource->NumberOfActive == -1) && 00569 (Resource->ExclusiveOwnerThread == NULL))) { 00570 00571 // 00572 // The resource is ours, so indicate that we have it and 00573 // exit the critical section 00574 // 00575 00576 Resource->NumberOfActive = -1; 00577 00578 Resource->ExclusiveOwnerThread = NtCurrentTeb()->ClientId.UniqueThread; 00579 00580 RtlLeaveCriticalSection(&Resource->CriticalSection); 00581 00582 return TRUE; 00583 00584 } 00585 00586 // 00587 // Otherwise check to see if we already have exclusive access to the 00588 // resource and can simply recusively acquire it again. 00589 // 00590 00591 if (Resource->ExclusiveOwnerThread == NtCurrentTeb()->ClientId.UniqueThread) { 00592 00593 // 00594 // The resource is ours (recusively) so indicate that we have it 00595 // and exit the critial section 00596 // 00597 00598 Resource->NumberOfActive -= 1; 00599 00600 RtlLeaveCriticalSection(&Resource->CriticalSection); 00601 00602 return TRUE; 00603 00604 } 00605 00606 // 00607 // Check if we are allowed to wait or must return immedately, and 00608 // indicate that we didn't acquire the resource 00609 // 00610 00611 if (!Wait) { 00612 00613 RtlLeaveCriticalSection(&Resource->CriticalSection); 00614 00615 return FALSE; 00616 00617 } 00618 00619 // 00620 // Otherwise we need to wait to acquire the resource. 00621 // To wait we will increment the number of waiting exclusive, 00622 // release the lock, and wait on the exclusive semaphore 00623 // 00624 00625 Resource->NumberOfWaitingExclusive += 1; 00626 Resource->DebugInfo->ContentionCount++; 00627 00628 RtlLeaveCriticalSection(&Resource->CriticalSection); 00629 00630 rewait: 00631 if ( Resource->Flags & RTL_RESOURCE_FLAG_LONG_TERM ) { 00632 TimeoutTime = NULL; 00633 } 00634 Status = NtWaitForSingleObject( 00635 Resource->ExclusiveSemaphore, 00636 FALSE, 00637 TimeoutTime 00638 ); 00639 if ( Status == STATUS_TIMEOUT ) { 00640 DbgPrint("RTL: Acquire Exclusive Sem Timeout %d (2 minutes)\n",TimeoutCount); 00641 DbgPrint("RTL: Resource at %p\n",Resource); 00642 TimeoutCount++; 00643 if ( TimeoutCount > 2 ) { 00644 PIMAGE_NT_HEADERS NtHeaders; 00645 00646 // 00647 // If the image is a Win32 image, then raise an exception and try to get to the 00648 // uae popup 00649 // 00650 00651 NtHeaders = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress); 00652 00653 if (NtHeaders->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI || 00654 NtHeaders->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) { 00655 EXCEPTION_RECORD ExceptionRecord; 00656 00657 ExceptionRecord.ExceptionCode = STATUS_POSSIBLE_DEADLOCK; 00658 ExceptionRecord.ExceptionFlags = 0; 00659 ExceptionRecord.ExceptionRecord = NULL; 00660 ExceptionRecord.ExceptionAddress = (PVOID)RtlRaiseException; 00661 ExceptionRecord.NumberParameters = 1; 00662 ExceptionRecord.ExceptionInformation[0] = (ULONG_PTR)Resource; 00663 RtlRaiseException(&ExceptionRecord); 00664 } 00665 else { 00666 DbgBreakPoint(); 00667 } 00668 } 00669 DbgPrint("RTL: Re-Waiting\n"); 00670 goto rewait; 00671 } 00672 if ( !NT_SUCCESS(Status) ) { 00673 RtlRaiseStatus(Status); 00674 } 00675 } 00676 }

BOOLEAN RtlAcquireResourceShared IN PRTL_RESOURCE  Resource,
IN BOOLEAN  Wait
 

Definition at line 350 of file dll/resource.c.

References _ERESOURCE::ContentionCount, DbgPrint, FALSE, NT_SUCCESS, NTSTATUS(), NtWaitForSingleObject(), NULL, Resource, RtlImageNtHeader(), RtlpTimeout, RtlRaiseException(), RtlRaiseStatus(), Status, and TRUE.

00357 : 00358 00359 The routine acquires the resource for shared access. Upon return from 00360 the procedure the resource is acquired for shared access. 00361 00362 Arguments: 00363 00364 Resource - Supplies the resource to acquire 00365 00366 Wait - Indicates if the call is allowed to wait for the resource 00367 to become available for must return immediately 00368 00369 Return Value: 00370 00371 BOOLEAN - TRUE if the resource is acquired and FALSE otherwise 00372 00373 --*/ 00374 00375 { 00376 NTSTATUS Status; 00377 ULONG TimeoutCount = 0; 00378 PLARGE_INTEGER TimeoutTime = &RtlpTimeout; 00379 // 00380 // Enter the critical section 00381 // 00382 00383 RtlEnterCriticalSection(&Resource->CriticalSection); 00384 00385 // 00386 // If it is not currently acquired for exclusive use then we can acquire 00387 // the resource for shared access. Note that this can potentially 00388 // starve an exclusive waiter however, this is necessary given the 00389 // ability to recursively acquire the resource shared. Otherwise we 00390 // might/will reach a deadlock situation where a thread tries to acquire 00391 // the resource recusively shared but is blocked by an exclusive waiter. 00392 // 00393 // The test to reanable not starving an exclusive waiter is: 00394 // 00395 // if ((Resource->NumberOfWaitingExclusive == 0) && 00396 // (Resource->NumberOfActive >= 0)) { 00397 // 00398 00399 if (Resource->NumberOfActive >= 0) { 00400 00401 // 00402 // The resource is ours, so indicate that we have it and 00403 // exit the critical section 00404 // 00405 00406 Resource->NumberOfActive += 1; 00407 00408 RtlLeaveCriticalSection(&Resource->CriticalSection); 00409 00410 // 00411 // Otherwise check to see if this thread is the one currently holding 00412 // exclusive access to the resource. And if it is then we change 00413 // this shared request to an exclusive recusive request and grant 00414 // access to the resource. 00415 // 00416 00417 } else if (Resource->ExclusiveOwnerThread == NtCurrentTeb()->ClientId.UniqueThread) { 00418 00419 // 00420 // The resource is ours (recusively) so indicate that we have it 00421 // and exit the critial section 00422 // 00423 00424 Resource->NumberOfActive -= 1; 00425 00426 RtlLeaveCriticalSection(&Resource->CriticalSection); 00427 00428 // 00429 // Otherwise we'll have to wait for access. 00430 // 00431 00432 } else { 00433 00434 // 00435 // Check if we are allowed to wait or must return immedately, and 00436 // indicate that we didn't acquire the resource 00437 // 00438 00439 if (!Wait) { 00440 00441 RtlLeaveCriticalSection(&Resource->CriticalSection); 00442 00443 return FALSE; 00444 00445 } 00446 00447 // 00448 // Otherwise we need to wait to acquire the resource. 00449 // To wait we will increment the number of waiting shared, 00450 // release the lock, and wait on the shared semaphore 00451 // 00452 00453 Resource->NumberOfWaitingShared += 1; 00454 Resource->DebugInfo->ContentionCount++; 00455 00456 RtlLeaveCriticalSection(&Resource->CriticalSection); 00457 00458 rewait: 00459 if ( Resource->Flags & RTL_RESOURCE_FLAG_LONG_TERM ) { 00460 TimeoutTime = NULL; 00461 } 00462 Status = NtWaitForSingleObject( 00463 Resource->SharedSemaphore, 00464 FALSE, 00465 TimeoutTime 00466 ); 00467 if ( Status == STATUS_TIMEOUT ) { 00468 DbgPrint("RTL: Acquire Shared Sem Timeout %d(2 minutes)\n",TimeoutCount); 00469 DbgPrint("RTL: Resource at %p\n",Resource); 00470 TimeoutCount++; 00471 if ( TimeoutCount > 2 ) { 00472 PIMAGE_NT_HEADERS NtHeaders; 00473 00474 // 00475 // If the image is a Win32 image, then raise an exception and try to get to the 00476 // uae popup 00477 // 00478 00479 NtHeaders = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress); 00480 00481 if (NtHeaders->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI || 00482 NtHeaders->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) { 00483 EXCEPTION_RECORD ExceptionRecord; 00484 00485 ExceptionRecord.ExceptionCode = STATUS_POSSIBLE_DEADLOCK; 00486 ExceptionRecord.ExceptionFlags = 0; 00487 ExceptionRecord.ExceptionRecord = NULL; 00488 ExceptionRecord.ExceptionAddress = (PVOID)RtlRaiseException; 00489 ExceptionRecord.NumberParameters = 1; 00490 ExceptionRecord.ExceptionInformation[0] = (ULONG_PTR)Resource; 00491 RtlRaiseException(&ExceptionRecord); 00492 } 00493 else { 00494 DbgBreakPoint(); 00495 } 00496 } 00497 DbgPrint("RTL: Re-Waiting\n"); 00498 goto rewait; 00499 } 00500 if ( !NT_SUCCESS(Status) ) { 00501 RtlRaiseStatus(Status); 00502 } 00503 } 00504 00505 // 00506 // Now the resource is ours, for shared access 00507 // 00508 00509 return TRUE; 00510 00511 }

void RtlCheckForOrphanedCriticalSections IN HANDLE  hThread  ) 
 

Definition at line 1788 of file dll/resource.c.

References DbgPrint, FALSE, LdrpShutdownInProgress, NT_SUCCESS, NtQueryInformationThread(), NtReadVirtualMemory(), NTSTATUS(), NULL, RtlCriticalSectionList, RtlCriticalSectionLock, Status, and TRUE.

01793 : 01794 01795 This routine is called from kernel32's ExitThread and TerminateThread 01796 in an effort to track calls that kill threads while they own 01797 critical sections. 01798 01799 Arguments: 01800 01801 hThread -- thread to be killed 01802 01803 Return Value: 01804 01805 None. 01806 01807 --*/ 01808 { 01809 // 01810 // This whole routine should be called only on checked builds. 01811 // It is a stub in the free build, so that a checked kernel32.dll 01812 // can bind against a free ntdll.dll 01813 // 01814 #if DBG 01815 NTSTATUS Status; 01816 THREAD_BASIC_INFORMATION ThreadInfo; 01817 PLIST_ENTRY Entry; 01818 PRTL_CRITICAL_SECTION_DEBUG DebugInfo; 01819 PRTL_CRITICAL_SECTION CriticalSection; 01820 BOOLEAN OrphanAboutToHappen; 01821 RTL_CRITICAL_SECTION CritSectCopy; 01822 01823 if (LdrpShutdownInProgress) { 01824 // 01825 // In the middle of shutting down the process 01826 // 01827 return; 01828 } 01829 01830 Status = NtQueryInformationThread( 01831 hThread, 01832 ThreadBasicInformation, 01833 &ThreadInfo, 01834 sizeof(ThreadInfo), 01835 NULL 01836 ); 01837 if (!NT_SUCCESS(Status)) { 01838 return; 01839 } 01840 01841 OrphanAboutToHappen = FALSE; 01842 01843 RtlEnterCriticalSection( &RtlCriticalSectionLock ); 01844 01845 for (Entry = RtlCriticalSectionList.Flink; 01846 Entry != &RtlCriticalSectionList; 01847 Entry = Entry->Flink) { 01848 01849 DebugInfo = CONTAINING_RECORD(Entry, 01850 RTL_CRITICAL_SECTION_DEBUG, 01851 ProcessLocksList); 01852 01853 CriticalSection = DebugInfo->CriticalSection; 01854 01855 if (CriticalSection == &RtlCriticalSectionLock || 01856 CriticalSection == NtCurrentPeb()->LoaderLock) { 01857 // 01858 // Skip these critsects. 01859 // 01860 continue; 01861 } 01862 01863 // 01864 // Call NtReadVirtualMemory() and make a copy of the critsect. 01865 // This won't AV and break to the debugger if the critsect's 01866 // memory has been freed without an RtlDeleteCriticalSection call. 01867 // 01868 Status = NtReadVirtualMemory(NtCurrentProcess(), 01869 CriticalSection, 01870 &CritSectCopy, 01871 sizeof(CritSectCopy), 01872 NULL); 01873 if (!NT_SUCCESS(Status) || CritSectCopy.DebugInfo != DebugInfo) { 01874 // 01875 // Error reading the contents of the critsect. The critsect 01876 // has probably been decommitted without a call to 01877 // RtlDeleteCriticalSection. Ignore it. 01878 // 01879 // You might think the entry could be deleted from the list, 01880 // but it can't... there may be another RTL_CRITICAL_SECTION 01881 // out there that is truly allocated, and who DebugInfo pointer 01882 // points at this DebugInfo. In that case, when that critsect 01883 // is deleted, the RtlCriticalSectionList is corrupted. 01884 // 01885 } else if (CritSectCopy.OwningThread == ThreadInfo.ClientId.UniqueThread 01886 && CritSectCopy.LockCount != -1) { 01887 // 01888 // The thread is about to die with a critical section locked. 01889 // 01890 DbgPrint("NTDLL: Pid.Tid %x.%x Critsec %p about to be orphaned when owning thread is terminated.\n", 01891 NtCurrentTeb()->ClientId.UniqueProcess, 01892 NtCurrentTeb()->ClientId.UniqueThread, 01893 CriticalSection); 01894 OrphanAboutToHappen = TRUE; 01895 } 01896 } 01897 01898 if (OrphanAboutToHappen) { 01899 #if i386 01900 _asm { int 3 } 01901 #else 01902 DbgBreakPoint(); 01903 #endif 01904 } 01905 01906 RtlLeaveCriticalSection( &RtlCriticalSectionLock ); 01907 #endif 01908 } }

VOID RtlConvertExclusiveToShared IN PRTL_RESOURCE  Resource  ) 
 

Definition at line 1061 of file dll/resource.c.

References DbgPrint, NT_SUCCESS, NtReleaseSemaphore(), NTSTATUS(), NULL, Resource, RtlRaiseStatus(), and Status.

01067 : 01068 01069 This routine converts a resource acquired for exclusive access into 01070 one acquired for shared access. Upon return from the procedure 01071 the resource is acquired for shared access 01072 01073 Arguments: 01074 01075 Resource - Supplies the resource to acquire for shared access, it 01076 must already be acquired for exclusive access 01077 01078 Return Value: 01079 01080 None 01081 01082 --*/ 01083 01084 { 01085 LONG PreviousCount; 01086 NTSTATUS Status; 01087 01088 // 01089 // Enter the critical section 01090 // 01091 01092 RtlEnterCriticalSection(&Resource->CriticalSection); 01093 01094 // 01095 // If there is only one shared user (it's us) and we can acquire the 01096 // resource for exclusive access. 01097 // 01098 01099 if (Resource->NumberOfActive == -1) { 01100 01101 Resource->ExclusiveOwnerThread = NULL; 01102 01103 // 01104 // Check to see if there are waiting shared, who should now get the 01105 // resource along with us 01106 // 01107 01108 if (Resource->NumberOfWaitingShared > 0) { 01109 01110 // 01111 // Set the new state to indicate that all of the shared requesters 01112 // have access including us, and there are no more waiting shared 01113 // requesters, and then release all of the shared requsters 01114 // 01115 01116 Resource->NumberOfActive = Resource->NumberOfWaitingShared + 1; 01117 01118 Resource->NumberOfWaitingShared = 0; 01119 01120 Status = NtReleaseSemaphore( 01121 Resource->SharedSemaphore, 01122 Resource->NumberOfActive - 1, 01123 &PreviousCount 01124 ); 01125 if ( !NT_SUCCESS(Status) ) { 01126 RtlRaiseStatus(Status); 01127 } 01128 01129 } else { 01130 01131 // 01132 // There is no one waiting for shared access so it's only ours 01133 // 01134 01135 Resource->NumberOfActive = 1; 01136 01137 } 01138 01139 RtlLeaveCriticalSection(&Resource->CriticalSection); 01140 01141 return; 01142 01143 } 01144 01145 // 01146 // The resource is not currently acquired for exclusive, or we've 01147 // recursively acquired it, so this must be a spurious call 01148 // 01149 01150 #if DBG 01151 DbgPrint("NTDLL: Failed error - SHARED_RESOURCE_CONV_ERROR\n"); 01152 DbgBreakPoint(); 01153 #endif 01154 }

VOID RtlConvertSharedToExclusive IN PRTL_RESOURCE  Resource  ) 
 

Definition at line 851 of file dll/resource.c.

References _ERESOURCE::ContentionCount, DbgPrint, FALSE, NT_SUCCESS, NTSTATUS(), NtWaitForSingleObject(), NULL, Resource, RtlImageNtHeader(), RtlpTimeout, RtlRaiseException(), RtlRaiseStatus(), Status, and TRUE.

00857 : 00858 00859 This routine converts a resource acquired for shared access into 00860 one acquired for exclusive access. Upon return from the procedure 00861 the resource is acquired for exclusive access 00862 00863 Arguments: 00864 00865 Resource - Supplies the resource to acquire for shared access, it 00866 must already be acquired for shared access 00867 00868 Return Value: 00869 00870 None 00871 00872 --*/ 00873 00874 { 00875 NTSTATUS Status; 00876 ULONG TimeoutCount = 0; 00877 00878 // 00879 // Enter the critical section 00880 // 00881 00882 RtlEnterCriticalSection(&Resource->CriticalSection); 00883 00884 // 00885 // If there is only one shared user (it's us) and we can acquire the 00886 // resource for exclusive access. 00887 // 00888 00889 if (Resource->NumberOfActive == 1) { 00890 00891 // 00892 // The resource is ours, so indicate that we have it and 00893 // exit the critical section, and return 00894 // 00895 00896 Resource->NumberOfActive = -1; 00897 00898 Resource->ExclusiveOwnerThread = NtCurrentTeb()->ClientId.UniqueThread; 00899 00900 RtlLeaveCriticalSection(&Resource->CriticalSection); 00901 00902 return; 00903 } 00904 00905 // 00906 // If the resource is currently acquired exclusive and it's us then 00907 // we already have exclusive access 00908 // 00909 00910 if ((Resource->NumberOfActive < 0) && 00911 (Resource->ExclusiveOwnerThread == NtCurrentTeb()->ClientId.UniqueThread)) { 00912 00913 // 00914 // We already have exclusive access to the resource so we'll just 00915 // exit the critical section and return 00916 // 00917 00918 RtlLeaveCriticalSection(&Resource->CriticalSection); 00919 00920 return; 00921 } 00922 00923 // 00924 // If the resource is acquired by more than one shared then we need 00925 // to wait to get exclusive access to the resource 00926 // 00927 00928 if (Resource->NumberOfActive > 1) { 00929 00930 // 00931 // To wait we will decrement the fact that we have the resource for 00932 // shared, and then loop waiting on the exclusive lock, and then 00933 // testing to see if we can get exclusive access to the resource 00934 // 00935 00936 Resource->NumberOfActive -= 1; 00937 00938 while (TRUE) { 00939 00940 // 00941 // Increment the number of waiting exclusive, exit and critical 00942 // section and wait on the exclusive semaphore 00943 // 00944 00945 Resource->NumberOfWaitingExclusive += 1; 00946 Resource->DebugInfo->ContentionCount++; 00947 00948 RtlLeaveCriticalSection(&Resource->CriticalSection); 00949 rewait: 00950 Status = NtWaitForSingleObject( 00951 Resource->ExclusiveSemaphore, 00952 FALSE, 00953 &RtlpTimeout 00954 ); 00955 if ( Status == STATUS_TIMEOUT ) { 00956 DbgPrint("RTL: Convert Exclusive Sem Timeout %d (2 minutes)\n",TimeoutCount); 00957 DbgPrint("RTL: Resource at %p\n",Resource); 00958 TimeoutCount++; 00959 if ( TimeoutCount > 2 ) { 00960 PIMAGE_NT_HEADERS NtHeaders; 00961 00962 // 00963 // If the image is a Win32 image, then raise an exception and try to get to the 00964 // uae popup 00965 // 00966 00967 NtHeaders = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress); 00968 00969 if (NtHeaders->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI || 00970 NtHeaders->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) { 00971 EXCEPTION_RECORD ExceptionRecord; 00972 00973 ExceptionRecord.ExceptionCode = STATUS_POSSIBLE_DEADLOCK; 00974 ExceptionRecord.ExceptionFlags = 0; 00975 ExceptionRecord.ExceptionRecord = NULL; 00976 ExceptionRecord.ExceptionAddress = (PVOID)RtlRaiseException; 00977 ExceptionRecord.NumberParameters = 1; 00978 ExceptionRecord.ExceptionInformation[0] = (ULONG_PTR)Resource; 00979 RtlRaiseException(&ExceptionRecord); 00980 } 00981 else { 00982 DbgBreakPoint(); 00983 } 00984 } 00985 DbgPrint("RTL: Re-Waiting\n"); 00986 goto rewait; 00987 } 00988 if ( !NT_SUCCESS(Status) ) { 00989 RtlRaiseStatus(Status); 00990 } 00991 00992 // 00993 // Enter the critical section 00994 // 00995 00996 RtlEnterCriticalSection(&Resource->CriticalSection); 00997 00998 // 00999 // If there are no shared users and it is not currently acquired 01000 // for exclusive use then we can acquire the resource for 01001 // exclusive access. We can also acquire it if the resource 01002 // indicates exclusive access but there isn't currently an owner 01003 // 01004 01005 if ((Resource->NumberOfActive == 0) 01006 01007 || 01008 01009 ((Resource->NumberOfActive == -1) && 01010 (Resource->ExclusiveOwnerThread == NULL))) { 01011 01012 // 01013 // The resource is ours, so indicate that we have it and 01014 // exit the critical section and return. 01015 // 01016 01017 Resource->NumberOfActive = -1; 01018 01019 Resource->ExclusiveOwnerThread = NtCurrentTeb()->ClientId.UniqueThread; 01020 01021 RtlLeaveCriticalSection(&Resource->CriticalSection); 01022 01023 return; 01024 } 01025 01026 // 01027 // Otherwise check to see if we already have exclusive access to 01028 // the resource and can simply recusively acquire it again. 01029 // 01030 01031 if (Resource->ExclusiveOwnerThread == NtCurrentTeb()->ClientId.UniqueThread) { 01032 01033 // 01034 // The resource is ours (recusively) so indicate that we have 01035 // it and exit the critical section and return. 01036 // 01037 01038 Resource->NumberOfActive -= 1; 01039 01040 RtlLeaveCriticalSection(&Resource->CriticalSection); 01041 01042 return; 01043 } 01044 } 01045 01046 } 01047 01048 // 01049 // The resource is not currently acquired for shared so this is a 01050 // spurious call 01051 // 01052 01053 #if DBG 01054 DbgPrint("NTDLL: Failed error - SHARED_RESOURCE_CONV_ERROR\n"); 01055 DbgBreakPoint(); 01056 #endif 01057 }

NTSTATUS RtlDeleteCriticalSection IN PRTL_CRITICAL_SECTION  CriticalSection  ) 
 

Definition at line 1474 of file dll/resource.c.

References NtClose(), NTSTATUS(), NULL, RtlCriticalSectionLock, RtlpFreeDebugInfo(), Status, and UnProtectHandle().

Referenced by AllocateConsole(), DestroyConsole(), FreeInputHandle(), ImmDllInitialize(), RtlCreateLpcServer(), RtlDeleteResource(), RtlpDebugPageHeapDestroy(), RtlpDestroyLockAtomTable(), and UserClientDllInitialize().

01480 : 01481 01482 This routine deletes (i.e., uninitializes) the input critical 01483 section variable 01484 01485 01486 Arguments: 01487 01488 CriticalSection - Supplies the resource variable being deleted 01489 01490 Return Value: 01491 01492 TBD - Status of semaphore close. 01493 01494 --*/ 01495 01496 { 01497 NTSTATUS Status; 01498 PRTL_CRITICAL_SECTION_DEBUG DebugInfo; 01499 01500 if ( CriticalSection->LockSemaphore ) { 01501 #if DBG 01502 UnProtectHandle( CriticalSection->LockSemaphore ); 01503 #endif // DBG 01504 Status = NtClose( CriticalSection->LockSemaphore ); 01505 } 01506 else { 01507 Status = STATUS_SUCCESS; 01508 } 01509 01510 // 01511 // Remove critical section from the list 01512 // 01513 01514 RtlEnterCriticalSection( &RtlCriticalSectionLock ); 01515 try { 01516 DebugInfo = CriticalSection->DebugInfo; 01517 if (DebugInfo != NULL) { 01518 RemoveEntryList( &DebugInfo->ProcessLocksList ); 01519 RtlZeroMemory( DebugInfo, sizeof( *DebugInfo ) ); 01520 } 01521 } 01522 finally { 01523 RtlLeaveCriticalSection( &RtlCriticalSectionLock ); 01524 } 01525 if (DebugInfo != NULL) { 01526 RtlpFreeDebugInfo( DebugInfo ); 01527 } 01528 RtlZeroMemory( CriticalSection, 01529 FIELD_OFFSET(RTL_CRITICAL_SECTION, SpinCount) + sizeof(ULONG) ); 01530 01531 return Status; 01532 }

VOID RtlDeleteResource IN PRTL_RESOURCE  Resource  ) 
 

Definition at line 1158 of file dll/resource.c.

References NtClose(), Resource, RtlDeleteCriticalSection(), and RtlpFreeDebugInfo().

01164 : 01165 01166 This routine deletes (i.e., uninitializes) the input resource variable 01167 01168 01169 Arguments: 01170 01171 Resource - Supplies the resource variable being deleted 01172 01173 Return Value: 01174 01175 None 01176 01177 --*/ 01178 01179 { 01180 RtlDeleteCriticalSection( &Resource->CriticalSection ); 01181 NtClose(Resource->SharedSemaphore); 01182 NtClose(Resource->ExclusiveSemaphore); 01183 01184 RtlpFreeDebugInfo( Resource->DebugInfo ); 01185 RtlZeroMemory( Resource, sizeof( *Resource ) ); 01186 01187 return; 01188 }

VOID RtlDumpResource IN PRTL_RESOURCE  Resource  ) 
 

Definition at line 1193 of file dll/resource.c.

References DbgPrint, and Resource.

01197 { 01198 DbgPrint("Resource @ %lx\n", Resource); 01199 01200 DbgPrint(" NumberOfWaitingShared = %lx\n", Resource->NumberOfWaitingShared); 01201 DbgPrint(" NumberOfWaitingExclusive = %lx\n", Resource->NumberOfWaitingExclusive); 01202 01203 DbgPrint(" NumberOfActive = %lx\n", Resource->NumberOfActive); 01204 01205 return; 01206 }

VOID RtlEnableEarlyCriticalSectionEventCreation VOID   ) 
 

Definition at line 1240 of file dll/resource.c.

01245 : 01246 01247 This routine marks the PEB of the calling process so critical section events 01248 are created at critical section creation time rather than at contetion time. 01249 This allows critical processes not to have to worry about error paths later 01250 on at the expense of extra pool consumed. 01251 01252 Arguments: 01253 01254 None 01255 01256 Return Value: 01257 01258 None 01259 01260 --*/ 01261 { 01262 NtCurrentPeb ()->NtGlobalFlag |= FLG_CRITSEC_EVENT_CREATION; 01263 }

NTSTATUS RtlInitializeCriticalSection IN PRTL_CRITICAL_SECTION  CriticalSection  ) 
 

Definition at line 1210 of file dll/resource.c.

References RtlInitializeCriticalSectionAndSpinCount().

Referenced by AllocateConsole(), ConDllInitialize(), ImmInitializeGlobals(), InheritIoHandleTable(), InitConsoleIME(), InitExeName(), InitializeInputHandle(), LdrpForkProcess(), LdrpInitializeProcess(), RtlpDebugPageHeapCreate(), RtlpDebugPageHeapGetProcessHeaps(), RtlpDphInitializeDelayedFreeQueue(), RtlpDphTargetDllsLogicInitialize(), RtlpInitializeEventCache(), RtlpInitializeLockAtomTable(), RtlpInitializeTimerThreadPool(), RtlpInitializeWaitThreadPool(), RtlpInitializeWorkerThreadPool(), UserClientDllInitialize(), and UserServerDllInitialization().

01216 : 01217 01218 This routine initializes the input critial section variable 01219 01220 Arguments: 01221 01222 CriticalSection - Supplies the resource variable being initialized 01223 01224 Return Value: 01225 01226 TBD - Status of semaphore creation. 01227 01228 --*/ 01229 01230 { 01231 return RtlInitializeCriticalSectionAndSpinCount(CriticalSection,0); 01232 }

NTSTATUS RtlInitializeCriticalSectionAndSpinCount IN PRTL_CRITICAL_SECTION  CriticalSection,
ULONG  SpinCount
 

Definition at line 1266 of file dll/resource.c.

References DESIRED_EVENT_ACCESS, FALSE, MAX_SPIN_COUNT, NT_SUCCESS, NtClose(), NtCreateEvent(), NTSTATUS(), NULL, PREALLOCATE_EVENT_MASK, ProtectHandle(), RtlCriticalSectionList, RtlCriticalSectionLock, RtlpAllocateDebugInfo(), RtlpCritSectInitialized, Status, UnProtectHandle(), and USHORT.

Referenced by ConServerDllInitialization(), InitializeConsoleHandleTable(), InitializeScrollBuffer(), RtlCreateLpcServer(), RtlInitializeCriticalSection(), RtlInitializeResource(), and RtlpInitDeferedCriticalSection().

01273 : 01274 01275 This routine initializes the input critial section variable 01276 01277 Arguments: 01278 01279 CriticalSection - Supplies the resource variable being initialized 01280 01281 Return Value: 01282 01283 TBD - Status of semaphore creation. 01284 01285 --*/ 01286 01287 { 01288 PRTL_CRITICAL_SECTION_DEBUG DebugInfo; 01289 NTSTATUS Status; 01290 01291 // 01292 // Initialize the lock fields, the count indicates how many are waiting 01293 // to enter or are in the critical section, LockSemaphore is the object 01294 // to wait on when entering the critical section. SpinLock is used 01295 // for the add interlock instruction. Recursion count is the number of 01296 // times the critical section has been recursively entered. 01297 // 01298 01299 CriticalSection->LockCount = -1; 01300 CriticalSection->RecursionCount = 0; 01301 CriticalSection->OwningThread = 0; 01302 CriticalSection->LockSemaphore = 0; 01303 if ( NtCurrentPeb()->NumberOfProcessors > 1 ) { 01304 CriticalSection->SpinCount = SpinCount & MAX_SPIN_COUNT; 01305 } 01306 else { 01307 CriticalSection->SpinCount = 0; 01308 } 01309 01310 if ( ( SpinCount & PREALLOCATE_EVENT_MASK ) || 01311 ( NtCurrentPeb ()->NtGlobalFlag & FLG_CRITSEC_EVENT_CREATION ) ) { 01312 Status = NtCreateEvent( 01313 &CriticalSection->LockSemaphore, 01314 DESIRED_EVENT_ACCESS, 01315 NULL, 01316 SynchronizationEvent, 01317 FALSE 01318 ); 01319 if ( !NT_SUCCESS(Status) ) { 01320 return Status; 01321 } 01322 #if DBG 01323 ProtectHandle(CriticalSection->LockSemaphore); 01324 #endif // DBG 01325 } 01326 01327 // 01328 // Initialize debugging information. 01329 // 01330 01331 DebugInfo = (PRTL_CRITICAL_SECTION_DEBUG)RtlpAllocateDebugInfo(); 01332 if (DebugInfo == NULL) { 01333 if (CriticalSection->LockSemaphore) { 01334 #if DBG 01335 UnProtectHandle( CriticalSection->LockSemaphore ); 01336 #endif // DBG 01337 NtClose( CriticalSection->LockSemaphore ); 01338 CriticalSection->LockSemaphore = 0; 01339 } 01340 return STATUS_NO_MEMORY; 01341 } 01342 01343 DebugInfo->Type = RTL_CRITSECT_TYPE; 01344 DebugInfo->ContentionCount = 0; 01345 DebugInfo->EntryCount = 0; 01346 01347 // 01348 // If the critical section lock itself is not being initialized, then 01349 // synchronize the insert of the critical section in the process locks 01350 // list. Otherwise, insert the critical section with no synchronization. 01351 // 01352 01353 if ((CriticalSection != &RtlCriticalSectionLock) && 01354 (RtlpCritSectInitialized != FALSE)) { 01355 RtlEnterCriticalSection(&RtlCriticalSectionLock); 01356 InsertTailList(&RtlCriticalSectionList, &DebugInfo->ProcessLocksList); 01357 RtlLeaveCriticalSection(&RtlCriticalSectionLock ); 01358 01359 } else { 01360 InsertTailList(&RtlCriticalSectionList, &DebugInfo->ProcessLocksList); 01361 } 01362 01363 DebugInfo->CriticalSection = CriticalSection; 01364 CriticalSection->DebugInfo = DebugInfo; 01365 #if i386 01366 DebugInfo->CreatorBackTraceIndex = (USHORT)RtlLogStackBackTrace(); 01367 #endif // i386 01368 01369 return STATUS_SUCCESS; 01370 }

VOID RtlInitializeResource IN PRTL_RESOURCE  Resource  ) 
 

Definition at line 247 of file dll/resource.c.

References DESIRED_SEMAPHORE_ACCESS, NT_SUCCESS, NtCreateSemaphore(), NTSTATUS(), NULL, Resource, RtlInitializeCriticalSectionAndSpinCount(), RtlpAllocateDebugInfo(), RtlRaiseStatus(), and Status.

00253 : 00254 00255 This routine initializes the input resource variable 00256 00257 Arguments: 00258 00259 Resource - Supplies the resource variable being initialized 00260 00261 Return Value: 00262 00263 None 00264 00265 --*/ 00266 00267 { 00268 NTSTATUS Status; 00269 PRTL_RESOURCE_DEBUG ResourceDebugInfo; 00270 00271 // 00272 // Initialize the lock fields, the count indicates how many are waiting 00273 // to enter or are in the critical section, LockSemaphore is the object 00274 // to wait on when entering the critical section. SpinLock is used 00275 // for the add interlock instruction. 00276 // 00277 00278 Status = RtlInitializeCriticalSectionAndSpinCount( &Resource->CriticalSection, 1000 ); 00279 if ( !NT_SUCCESS(Status) ){ 00280 RtlRaiseStatus(Status); 00281 } 00282 00283 Resource->CriticalSection.DebugInfo->Type = RTL_RESOURCE_TYPE; 00284 ResourceDebugInfo = (PRTL_RESOURCE_DEBUG) 00285 RtlpAllocateDebugInfo(); 00286 00287 if (ResourceDebugInfo == NULL) { 00288 RtlRaiseStatus(STATUS_NO_MEMORY); 00289 } 00290 00291 ResourceDebugInfo->ContentionCount = 0; 00292 Resource->DebugInfo = ResourceDebugInfo; 00293 00294 // 00295 // Initialize flags so there is a default value. 00296 // (Some apps may set RTL_RESOURCE_FLAGS_LONG_TERM to affect timeouts.) 00297 // 00298 00299 Resource->Flags = 0; 00300 00301 00302 // 00303 // Initialize the shared and exclusive waiting counters and semaphore. 00304 // The counters indicate how many are waiting for access to the resource 00305 // and the semaphores are used to wait on the resource. Note that 00306 // the semaphores can also indicate the number waiting for a resource 00307 // however there is a race condition in the alogrithm on the acquire 00308 // side if count if not updated before the critical section is exited. 00309 // 00310 00311 Status = NtCreateSemaphore( 00312 &Resource->SharedSemaphore, 00313 DESIRED_SEMAPHORE_ACCESS, 00314 NULL, 00315 0, 00316 MAXLONG 00317 ); 00318 if ( !NT_SUCCESS(Status) ){ 00319 RtlRaiseStatus(Status); 00320 } 00321 00322 Resource->NumberOfWaitingShared = 0; 00323 00324 Status = NtCreateSemaphore( 00325 &Resource->ExclusiveSemaphore, 00326 DESIRED_SEMAPHORE_ACCESS, 00327 NULL, 00328 0, 00329 MAXLONG 00330 ); 00331 if ( !NT_SUCCESS(Status) ){ 00332 RtlRaiseStatus(Status); 00333 } 00334 00335 Resource->NumberOfWaitingExclusive = 0; 00336 00337 // 00338 // Initialize the current state of the resource 00339 // 00340 00341 Resource->NumberOfActive = 0; 00342 00343 Resource->ExclusiveOwnerThread = NULL; 00344 00345 return; 00346 }

PVOID RtlpAllocateDebugInfo VOID   ) 
 

Definition at line 151 of file dll/resource.c.

References DeferedCriticalSection, HEAP_GRANULARITY, NULL, PAGE_SIZE, RtlAllocateHeap, RtlpChainDebugInfo(), RtlpCritSectInitialized, and RtlpDebugInfoFreeList.

Referenced by RtlInitializeCriticalSectionAndSpinCount(), and RtlInitializeResource().

00152 { 00153 PRTL_CRITICAL_SECTION_DEBUG p; 00154 PPEB Peb; 00155 00156 00157 if (RtlpCritSectInitialized) { 00158 RtlEnterCriticalSection(&DeferedCriticalSection); 00159 } 00160 try { 00161 p = RtlpDebugInfoFreeList; 00162 if (p == NULL) { 00163 Peb = NtCurrentPeb(); 00164 p = RtlAllocateHeap(Peb->ProcessHeap,0,PAGE_SIZE-HEAP_GRANULARITY); 00165 if ( !p ) { 00166 KdPrint(( "NTDLL: Unable to allocate debug information from heap\n")); 00167 } 00168 else { 00169 p = RtlpChainDebugInfo( p, PAGE_SIZE-HEAP_GRANULARITY ); 00170 } 00171 } 00172 00173 if (p != NULL) { 00174 RtlpDebugInfoFreeList = *(PRTL_CRITICAL_SECTION_DEBUG *)p; 00175 } 00176 } 00177 finally { 00178 if (RtlpCritSectInitialized) { 00179 RtlLeaveCriticalSection(&DeferedCriticalSection); 00180 } 00181 } 00182 00183 return p; 00184 }

PRTL_CRITICAL_SECTION_DEBUG RtlpChainDebugInfo IN PVOID  BaseAddress,
IN ULONG  Size
 

Definition at line 121 of file dll/resource.c.

References NULL, and Size.

Referenced by RtlpAllocateDebugInfo(), and RtlpInitDeferedCriticalSection().

00125 { 00126 PRTL_CRITICAL_SECTION_DEBUG p, p1; 00127 00128 if (Size = Size / sizeof( RTL_CRITICAL_SECTION_DEBUG )) { 00129 p = (PRTL_CRITICAL_SECTION_DEBUG)BaseAddress + Size - 1; 00130 *(PRTL_CRITICAL_SECTION_DEBUG *)p = NULL; 00131 while (--Size) { 00132 p1 = p - 1; 00133 *(PRTL_CRITICAL_SECTION_DEBUG *)p1 = p; 00134 p = p1; 00135 } 00136 } 00137 00138 return p; 00139 }

VOID RtlpCheckDeferedCriticalSection IN PRTL_CRITICAL_SECTION  CriticalSection  ) 
 

Definition at line 1456 of file dll/resource.c.

References DeferedCriticalSection, and RtlpCreateCriticalSectionSem().

Referenced by RtlpUnWaitCriticalSection(), and RtlpWaitForCriticalSection().

01459 { 01460 RtlEnterCriticalSection(&DeferedCriticalSection); 01461 try { 01462 if ( !CriticalSection->LockSemaphore ) { 01463 RtlpCreateCriticalSectionSem(CriticalSection); 01464 } 01465 } 01466 finally { 01467 RtlLeaveCriticalSection(&DeferedCriticalSection); 01468 } 01469 return; 01470 }

VOID RtlpCreateCriticalSectionSem IN PRTL_CRITICAL_SECTION  CriticalSection  ) 
 

Definition at line 1412 of file dll/resource.c.

References DESIRED_EVENT_ACCESS, FALSE, NT_SUCCESS, NtCreateEvent(), NtDelayExecution(), NTSTATUS(), NULL, ProtectHandle(), RtlRaiseStatus(), and Status.

Referenced by RtlpCheckDeferedCriticalSection(), and RtlpInitDeferedCriticalSection().

01415 { 01416 NTSTATUS Status; 01417 LARGE_INTEGER tmo = {(ULONG) -100000, -1}; // Start at 1/100th of a second 01418 LONGLONG max_tmo = (LONGLONG) -10000000 * 60 * 3; // Wait for a max of 3 minutes 01419 01420 // 01421 // Loop trying to create the event on failure. 01422 // 01423 while (1) { 01424 Status = NtCreateEvent( 01425 &CriticalSection->LockSemaphore, 01426 DESIRED_EVENT_ACCESS, 01427 NULL, 01428 SynchronizationEvent, 01429 FALSE 01430 ); 01431 01432 if ( NT_SUCCESS(Status) ) { 01433 break; 01434 } else { 01435 if ( tmo.QuadPart < max_tmo ) { 01436 KdPrint(( "NTDLL: Warning. Unable to allocate lock semaphore for Cs %p. Status %x raising\n", CriticalSection,Status )); 01437 InterlockedDecrement(&CriticalSection->LockCount); 01438 RtlRaiseStatus(Status); 01439 } 01440 KdPrint(( "NTDLL: Warning. Unable to allocate lock semaphore for Cs %p. Status %x retrying\n", CriticalSection,Status )); 01441 01442 Status = NtDelayExecution (FALSE, &tmo); 01443 if ( !NT_SUCCESS(Status) ) { 01444 InterlockedDecrement(&CriticalSection->LockCount); 01445 RtlRaiseStatus(Status); 01446 } 01447 tmo.QuadPart *= 2; 01448 } 01449 } 01450 #if DBG 01451 ProtectHandle(CriticalSection->LockSemaphore); 01452 #endif // DBG 01453 }

VOID RtlpFreeDebugInfo IN PVOID  DebugInfo  ) 
 

Definition at line 188 of file dll/resource.c.

References DeferedCriticalSection, and RtlpDebugInfoFreeList.

Referenced by RtlDeleteCriticalSection(), and RtlDeleteResource().

00191 { 00192 RtlEnterCriticalSection(&DeferedCriticalSection); 00193 try { 00194 RtlZeroMemory( DebugInfo, sizeof( RTL_CRITICAL_SECTION_DEBUG ) ); 00195 *(PRTL_CRITICAL_SECTION_DEBUG *)DebugInfo = RtlpDebugInfoFreeList; 00196 RtlpDebugInfoFreeList = (PRTL_CRITICAL_SECTION_DEBUG)DebugInfo; 00197 } 00198 finally { 00199 RtlLeaveCriticalSection(&DeferedCriticalSection); 00200 } 00201 00202 return; 00203 }

VOID RtlpInitDeferedCriticalSection VOID   ) 
 

Referenced by LdrpForkProcess(), and LdrpInitializeProcess().

void RtlpNotOwnerCriticalSection IN PRTL_CRITICAL_SECTION  CriticalSection  ) 
 

Definition at line 1717 of file dll/resource.c.

References DbgPrint, LdrpShutdownInProgress, LdrpShutdownThreadId, and RtlRaiseStatus().

01720 { 01721 BOOLEAN CsIsLoaderLock; 01722 01723 // 01724 // critical sections are disabled during exit process so that 01725 // apps that are not carefull during shutdown don't hang 01726 // 01727 01728 CsIsLoaderLock = (CriticalSection == NtCurrentPeb()->LoaderLock); 01729 01730 if ( LdrpShutdownInProgress && 01731 ((!CsIsLoaderLock) || 01732 (CsIsLoaderLock && LdrpShutdownThreadId == NtCurrentTeb()->ClientId.UniqueThread) ) ) { 01733 return; 01734 } 01735 01736 if (NtCurrentPeb()->BeingDebugged) { 01737 DbgPrint( "NTDLL: Calling thread (%X) not owner of CritSect: %p Owner ThreadId: %X\n", 01738 NtCurrentTeb()->ClientId.UniqueThread, 01739 CriticalSection, 01740 CriticalSection->OwningThread 01741 ); 01742 #if i386 01743 _asm { int 3 } 01744 #else 01745 DbgBreakPoint(); 01746 #endif 01747 } 01748 RtlRaiseStatus( STATUS_RESOURCE_NOT_OWNED ); 01749 }

void RtlpUnWaitCriticalSection IN PRTL_CRITICAL_SECTION  CriticalSection  ) 
 

Definition at line 1675 of file dll/resource.c.

References DbgPrint, NT_SUCCESS, NtSetEvent(), NTSTATUS(), NULL, RtlpCheckDeferedCriticalSection(), and RtlRaiseStatus().

01678 { 01679 NTSTATUS st; 01680 01681 #if 0 01682 DbgPrint( "NTDLL: Releasing CritSect: %p ThreadId: %X\n", 01683 CriticalSection, CriticalSection->OwningThread 01684 ); 01685 #endif 01686 01687 if ( !CriticalSection->LockSemaphore ) { 01688 RtlpCheckDeferedCriticalSection(CriticalSection); 01689 } 01690 01691 #if DBG 01692 // 01693 // Sneaky trick here to catch sleazy apps (csrss) that erroneously call 01694 // NtSetEvent on an event that happens to be somebody else's 01695 // critical section. Only allow setting a protected handle if the low 01696 // bit of PreviousState is set. 01697 // 01698 st = NtSetEvent( CriticalSection->LockSemaphore, 01699 (PLONG)1 01700 ); 01701 #else 01702 st = NtSetEvent( CriticalSection->LockSemaphore, 01703 NULL 01704 ); 01705 #endif 01706 01707 if ( NT_SUCCESS(st) ) { 01708 return; 01709 } 01710 else { 01711 RtlRaiseStatus(st); 01712 } 01713 }

void RtlpWaitForCriticalSection IN PRTL_CRITICAL_SECTION  CriticalSection  ) 
 

Definition at line 1544 of file dll/resource.c.

References ASSERT, DbgPrint, FALSE, LdrpShutdownInProgress, LdrpShutdownThreadId, NT_SUCCESS, NTSTATUS(), NtWaitForSingleObject(), NULL, RtlImageNtHeader(), RtlpCheckDeferedCriticalSection(), RtlpTimeout, RtlpTimoutDisable, RtlRaiseException(), RtlRaiseStatus(), and TRUE.

01547 { 01548 NTSTATUS st; 01549 ULONG TimeoutCount = 0; 01550 PLARGE_INTEGER TimeoutTime; 01551 BOOLEAN CsIsLoaderLock; 01552 01553 // 01554 // critical sections are disabled during exit process so that 01555 // apps that are not carefull during shutdown don't hang 01556 // 01557 01558 CsIsLoaderLock = (CriticalSection == NtCurrentPeb()->LoaderLock); 01559 NtCurrentTeb()->WaitingOnLoaderLock = (ULONG)CsIsLoaderLock; 01560 01561 if ( LdrpShutdownInProgress && 01562 ((!CsIsLoaderLock) || 01563 (CsIsLoaderLock && LdrpShutdownThreadId == NtCurrentTeb()->ClientId.UniqueThread) ) ) { 01564 01565 // 01566 // slimey reinitialization of the critical section with the count biased by one 01567 // this is how the critical section would normally look to the thread coming out 01568 // of this function. Note that the semaphore handle is leaked, but since the 01569 // app is exiting, it's ok 01570 // 01571 01572 CriticalSection->LockCount = 0; 01573 CriticalSection->RecursionCount = 0; 01574 CriticalSection->OwningThread = 0; 01575 CriticalSection->LockSemaphore = 0; 01576 01577 NtCurrentTeb()->WaitingOnLoaderLock = 0; 01578 01579 return; 01580 01581 } 01582 01583 if (RtlpTimoutDisable) { 01584 TimeoutTime = NULL; 01585 } 01586 else { 01587 TimeoutTime = &RtlpTimeout; 01588 } 01589 01590 if ( !CriticalSection->LockSemaphore ) { 01591 RtlpCheckDeferedCriticalSection(CriticalSection); 01592 } 01593 01594 CriticalSection->DebugInfo->EntryCount++; 01595 while( TRUE ) { 01596 01597 CriticalSection->DebugInfo->ContentionCount++; 01598 01599 #if 0 01600 DbgPrint( "NTDLL: Waiting for CritSect: %p owned by ThreadId: %X Count: %u Level: %u\n", 01601 CriticalSection, 01602 CriticalSection->OwningThread, 01603 CriticalSection->LockCount, 01604 CriticalSection->RecursionCount 01605 ); 01606 #endif 01607 01608 st = NtWaitForSingleObject( CriticalSection->LockSemaphore, 01609 FALSE, 01610 TimeoutTime 01611 ); 01612 if ( st == STATUS_TIMEOUT ) { 01613 DbgPrint( "RTL: Enter Critical Section Timeout (2 minutes) %d\n", 01614 TimeoutCount 01615 ); 01616 DbgPrint( "RTL: Pid.Tid %x.%x, owner tid %x Critical Section %p - ContentionCount == %lu\n", 01617 NtCurrentTeb()->ClientId.UniqueProcess, 01618 NtCurrentTeb()->ClientId.UniqueThread, 01619 CriticalSection->OwningThread, 01620 CriticalSection, CriticalSection->DebugInfo->ContentionCount 01621 ); 01622 TimeoutCount++; 01623 if ( TimeoutCount > 2 && CriticalSection != NtCurrentPeb()->LoaderLock ) { 01624 PIMAGE_NT_HEADERS NtHeaders; 01625 01626 // 01627 // If the image is a Win32 image, then raise an exception and try to get to the 01628 // uae popup 01629 // 01630 01631 NtHeaders = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress); 01632 01633 if (NtHeaders->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI || 01634 NtHeaders->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) { 01635 EXCEPTION_RECORD ExceptionRecord; 01636 01637 ExceptionRecord.ExceptionCode = STATUS_POSSIBLE_DEADLOCK; 01638 ExceptionRecord.ExceptionFlags = 0; 01639 ExceptionRecord.ExceptionRecord = NULL; 01640 ExceptionRecord.ExceptionAddress = (PVOID)RtlRaiseException; 01641 ExceptionRecord.NumberParameters = 1; 01642 ExceptionRecord.ExceptionInformation[0] = (ULONG_PTR)CriticalSection; 01643 RtlRaiseException(&ExceptionRecord); 01644 } 01645 else { 01646 DbgBreakPoint(); 01647 } 01648 } 01649 DbgPrint("RTL: Re-Waiting\n"); 01650 } 01651 else { 01652 if ( NT_SUCCESS(st) ) { 01653 // 01654 // If some errant thread calls SetEvent on a bogus handle 01655 // which happens to match the handle we are using in the critical 01656 // section, everything gets really messed up since two threads 01657 // now own the lock at the same time. ASSERT that no other thread 01658 // owns the lock if we have been granted ownership. 01659 // 01660 ASSERT(CriticalSection->OwningThread == 0); 01661 if ( CsIsLoaderLock ) { 01662 CriticalSection->OwningThread = NtCurrentTeb()->ClientId.UniqueThread; 01663 NtCurrentTeb()->WaitingOnLoaderLock = 0; 01664 } 01665 return; 01666 } 01667 else { 01668 RtlRaiseStatus(st); 01669 } 01670 } 01671 } 01672 }

VOID RtlReleaseResource IN PRTL_RESOURCE  Resource  ) 
 

Definition at line 680 of file dll/resource.c.

References DbgPrint, NT_SUCCESS, NtReleaseSemaphore(), NTSTATUS(), NULL, Resource, RtlRaiseStatus(), and Status.

00686 : 00687 00688 This routine release the input resource. The resource can have been 00689 acquired for either shared or exclusive access. 00690 00691 Arguments: 00692 00693 Resource - Supplies the resource to release 00694 00695 Return Value: 00696 00697 None. 00698 00699 --*/ 00700 00701 { 00702 NTSTATUS Status; 00703 LONG PreviousCount; 00704 00705 // 00706 // Enter the critical section 00707 // 00708 00709 RtlEnterCriticalSection(&Resource->CriticalSection); 00710 00711 // 00712 // Test if the resource is acquired for shared or exclusive access 00713 // 00714 00715 if (Resource->NumberOfActive > 0) { 00716 00717 // 00718 // Releasing shared access to the resource, so decrement 00719 // the number of shared users 00720 // 00721 00722 Resource->NumberOfActive -= 1; 00723 00724 // 00725 // If the resource is now available and there is a waiting 00726 // exclusive user then give the resource to the waiting thread 00727 // 00728 00729 if ((Resource->NumberOfActive == 0) && 00730 (Resource->NumberOfWaitingExclusive > 0)) { 00731 00732 // 00733 // Set the resource state to exclusive (but not owned), 00734 // decrement the number of waiting exclusive, and release 00735 // one exclusive waiter 00736 // 00737 00738 Resource->NumberOfActive = -1; 00739 Resource->ExclusiveOwnerThread = NULL; 00740 00741 Resource->NumberOfWaitingExclusive -= 1; 00742 00743 Status = NtReleaseSemaphore( 00744 Resource->ExclusiveSemaphore, 00745 1, 00746 &PreviousCount 00747 ); 00748 if ( !NT_SUCCESS(Status) ) { 00749 RtlRaiseStatus(Status); 00750 } 00751 } 00752 00753 } else if (Resource->NumberOfActive < 0) { 00754 00755 // 00756 // Releasing exclusive access to the resource, so increment the 00757 // number of active by one. And continue testing only 00758 // if the resource is now available. 00759 // 00760 00761 Resource->NumberOfActive += 1; 00762 00763 if (Resource->NumberOfActive == 0) { 00764 00765 // 00766 // The resource is now available. Remove ourselves as the 00767 // owner thread 00768 // 00769 00770 Resource->ExclusiveOwnerThread = NULL; 00771 00772 // 00773 // If there is another waiting exclusive then give the resource 00774 // to it. 00775 // 00776 00777 if (Resource->NumberOfWaitingExclusive > 0) { 00778 00779 // 00780 // Set the resource to exclusive, and its owner undefined. 00781 // Decrement the number of waiting exclusive and release one 00782 // exclusive waiter 00783 // 00784 00785 Resource->NumberOfActive = -1; 00786 Resource->NumberOfWaitingExclusive -= 1; 00787 00788 Status = NtReleaseSemaphore( 00789 Resource->ExclusiveSemaphore, 00790 1, 00791 &PreviousCount 00792 ); 00793 if ( !NT_SUCCESS(Status) ) { 00794 RtlRaiseStatus(Status); 00795 } 00796 00797 // 00798 // Check to see if there are waiting shared, who should now get 00799 // the resource 00800 // 00801 00802 } else if (Resource->NumberOfWaitingShared > 0) { 00803 00804 // 00805 // Set the new state to indicate that all of the shared 00806 // requesters have access and there are no more waiting 00807 // shared requesters, and then release all of the shared 00808 // requsters 00809 // 00810 00811 Resource->NumberOfActive = Resource->NumberOfWaitingShared; 00812 00813 Resource->NumberOfWaitingShared = 0; 00814 00815 Status = NtReleaseSemaphore( 00816 Resource->SharedSemaphore, 00817 Resource->NumberOfActive, 00818 &PreviousCount 00819 ); 00820 if ( !NT_SUCCESS(Status) ) { 00821 RtlRaiseStatus(Status); 00822 } 00823 } 00824 } 00825 00826 #if DBG 00827 } else { 00828 00829 // 00830 // The resource isn't current acquired, there is nothing to release 00831 // so tell the user the mistake 00832 // 00833 00834 00835 DbgPrint("NTDLL - Resource released too many times %lx\n", Resource); 00836 DbgBreakPoint(); 00837 #endif 00838 } 00839 00840 // 00841 // Exit the critical section, and return to the caller 00842 // 00843 00844 RtlLeaveCriticalSection(&Resource->CriticalSection); 00845 00846 return; 00847 }

ULONG RtlSetCriticalSectionSpinCount IN PRTL_CRITICAL_SECTION  CriticalSection,
ULONG  SpinCount
 

Definition at line 1374 of file dll/resource.c.

01381 : 01382 01383 This routine initializes the input critial section variable 01384 01385 Arguments: 01386 01387 CriticalSection - Supplies the resource variable being initialized 01388 01389 Return Value: 01390 01391 Returns the previous critical section spin count 01392 01393 --*/ 01394 01395 { 01396 ULONG OldSpinCount; 01397 01398 OldSpinCount = (ULONG)CriticalSection->SpinCount; 01399 01400 if ( NtCurrentPeb()->NumberOfProcessors > 1 ) { 01401 CriticalSection->SpinCount = SpinCount; 01402 } 01403 else { 01404 CriticalSection->SpinCount = 0; 01405 } 01406 01407 return OldSpinCount; 01408 }


Variable Documentation

RTL_CRITICAL_SECTION DeferedCriticalSection
 

Definition at line 51 of file dll/resource.c.

Referenced by RtlpAllocateDebugInfo(), RtlpCheckDeferedCriticalSection(), RtlpFreeDebugInfo(), and RtlpInitDeferedCriticalSection().

BOOLEAN LdrpShutdownInProgress
 

Definition at line 46 of file dll/resource.c.

HANDLE LdrpShutdownThreadId
 

Definition at line 47 of file dll/resource.c.

Referenced by LdrShutdownProcess(), RtlpNotOwnerCriticalSection(), and RtlpWaitForCriticalSection().

BOOLEAN RtlpCritSectInitialized
 

Definition at line 118 of file dll/resource.c.

Referenced by RtlInitializeCriticalSectionAndSpinCount(), RtlpAllocateDebugInfo(), and RtlpInitDeferedCriticalSection().

PRTL_CRITICAL_SECTION_DEBUG RtlpDebugInfoFreeList
 

Definition at line 117 of file dll/resource.c.

Referenced by RtlpAllocateDebugInfo(), RtlpFreeDebugInfo(), and RtlpInitDeferedCriticalSection().

RTL_CRITICAL_SECTION_DEBUG RtlpStaticDebugInfo[64]
 

Definition at line 116 of file dll/resource.c.

Referenced by RtlpInitDeferedCriticalSection().


Generated on Sat May 15 19:45:29 2004 for test by doxygen 1.3.7