mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[RTL][NTDLL] Implement and export RtlInitializeCriticalSectionEx
This commit is contained in:
parent
1d59cf43af
commit
8f6aaa8af6
2 changed files with 143 additions and 71 deletions
|
@ -940,7 +940,7 @@
|
|||
@ stdcall RtlInitializeContext(ptr ptr ptr ptr ptr)
|
||||
@ stdcall RtlInitializeCriticalSection(ptr)
|
||||
@ stdcall RtlInitializeCriticalSectionAndSpinCount(ptr long)
|
||||
@ stub -version=0x600+ RtlInitializeCriticalSectionEx
|
||||
@ stdcall -version=0x600+ RtlInitializeCriticalSectionEx(ptr long long)
|
||||
@ stub -version=0x600+ -arch=i386 RtlInitializeExceptionChain
|
||||
@ stdcall RtlInitializeGenericTable(ptr ptr ptr ptr ptr)
|
||||
@ stdcall RtlInitializeGenericTableAvl(ptr ptr ptr ptr ptr)
|
||||
|
|
|
@ -28,6 +28,10 @@ extern HANDLE LdrpShutdownThreadId;
|
|||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
#define CRITSECT_HAS_DEBUG_INFO(CriticalSection) \
|
||||
(((CriticalSection)->DebugInfo != NULL) && \
|
||||
((CriticalSection)->DebugInfo != LongToPtr(-1)))
|
||||
|
||||
/*++
|
||||
* RtlpCreateCriticalSectionSem
|
||||
*
|
||||
|
@ -119,7 +123,7 @@ RtlpWaitForCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)
|
|||
CriticalSection,
|
||||
CriticalSection->LockSemaphore);
|
||||
|
||||
if (CriticalSection->DebugInfo)
|
||||
if (CRITSECT_HAS_DEBUG_INFO(CriticalSection))
|
||||
CriticalSection->DebugInfo->EntryCount++;
|
||||
|
||||
/*
|
||||
|
@ -142,7 +146,7 @@ RtlpWaitForCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)
|
|||
for (;;)
|
||||
{
|
||||
/* Increase the number of times we've had contention */
|
||||
if (CriticalSection->DebugInfo)
|
||||
if (CRITSECT_HAS_DEBUG_INFO(CriticalSection))
|
||||
CriticalSection->DebugInfo->ContentionCount++;
|
||||
|
||||
/* Check if allocating the event failed */
|
||||
|
@ -404,7 +408,7 @@ RtlDeleteCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)
|
|||
/* Protect List */
|
||||
RtlEnterCriticalSection(&RtlCriticalSectionLock);
|
||||
|
||||
if (CriticalSection->DebugInfo)
|
||||
if (CRITSECT_HAS_DEBUG_INFO(CriticalSection))
|
||||
{
|
||||
/* Remove it from the list */
|
||||
RemoveEntryList(&CriticalSection->DebugInfo->ProcessLocksList);
|
||||
|
@ -417,7 +421,7 @@ RtlDeleteCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)
|
|||
/* Unprotect */
|
||||
RtlLeaveCriticalSection(&RtlCriticalSectionLock);
|
||||
|
||||
if (CriticalSection->DebugInfo)
|
||||
if (CRITSECT_HAS_DEBUG_INFO(CriticalSection))
|
||||
{
|
||||
/* Free it */
|
||||
RtlpFreeDebugInfo(CriticalSection->DebugInfo);
|
||||
|
@ -542,6 +546,135 @@ RtlInitializeCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)
|
|||
return RtlInitializeCriticalSectionAndSpinCount(CriticalSection, 0);
|
||||
}
|
||||
|
||||
/*++
|
||||
* RtlInitializeCriticalSectionEx
|
||||
* @implemented NT6.0
|
||||
*
|
||||
* Initialises a new critical section.
|
||||
*
|
||||
* Params:
|
||||
* CriticalSection - Critical section to initialise
|
||||
*
|
||||
* SpinCount - Spin count for the critical section.
|
||||
*
|
||||
* Flags - Flags for initialization.
|
||||
*
|
||||
* Returns:
|
||||
* STATUS_SUCCESS.
|
||||
*
|
||||
* Remarks:
|
||||
* SpinCount is ignored on single-processor systems.
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RtlInitializeCriticalSectionEx(
|
||||
_Out_ PRTL_CRITICAL_SECTION CriticalSection,
|
||||
_In_ ULONG SpinCount,
|
||||
_In_ ULONG Flags)
|
||||
{
|
||||
PRTL_CRITICAL_SECTION_DEBUG CritcalSectionDebugData;
|
||||
ULONG AllowedFlags;
|
||||
ULONG OsVersion;
|
||||
|
||||
/* Remove lower bits from flags */
|
||||
Flags &= RTL_CRITICAL_SECTION_ALL_FLAG_BITS;
|
||||
|
||||
/* These flags generally allowed */
|
||||
AllowedFlags = RTL_CRITICAL_SECTION_FLAG_NO_DEBUG_INFO |
|
||||
RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN |
|
||||
RTL_CRITICAL_SECTION_FLAG_STATIC_INIT;
|
||||
|
||||
/* Flags for Windows 7+ (CHECKME) */
|
||||
OsVersion = NtCurrentPeb()->OSMajorVersion << 8 |
|
||||
NtCurrentPeb()->OSMinorVersion;
|
||||
if (OsVersion >= _WIN32_WINNT_WIN7)
|
||||
{
|
||||
AllowedFlags |= RTL_CRITICAL_SECTION_FLAG_RESOURCE_TYPE |
|
||||
RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO;
|
||||
}
|
||||
|
||||
if (Flags & ~AllowedFlags)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER_3;
|
||||
}
|
||||
|
||||
if (SpinCount & RTL_CRITICAL_SECTION_ALL_FLAG_BITS)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER_2;
|
||||
}
|
||||
|
||||
/* First things first, set up the Object */
|
||||
DPRINT("Initializing Critical Section: %p\n", CriticalSection);
|
||||
CriticalSection->LockCount = -1;
|
||||
CriticalSection->RecursionCount = 0;
|
||||
CriticalSection->OwningThread = 0;
|
||||
CriticalSection->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? SpinCount : 0;
|
||||
CriticalSection->LockSemaphore = 0;
|
||||
|
||||
if (Flags & RTL_CRITICAL_SECTION_FLAG_NO_DEBUG_INFO)
|
||||
{
|
||||
CriticalSection->DebugInfo = LongToPtr(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate the Debug Data */
|
||||
CritcalSectionDebugData = RtlpAllocateDebugInfo();
|
||||
DPRINT("Allocated Debug Data: %p inside Process: %p\n",
|
||||
CritcalSectionDebugData,
|
||||
NtCurrentTeb()->ClientId.UniqueProcess);
|
||||
|
||||
if (!CritcalSectionDebugData)
|
||||
{
|
||||
/* This is bad! */
|
||||
DPRINT1("Couldn't allocate Debug Data for: %p\n", CriticalSection);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Set it up */
|
||||
CritcalSectionDebugData->Type = RTL_CRITSECT_TYPE;
|
||||
CritcalSectionDebugData->ContentionCount = 0;
|
||||
CritcalSectionDebugData->EntryCount = 0;
|
||||
CritcalSectionDebugData->CriticalSection = CriticalSection;
|
||||
CritcalSectionDebugData->Flags = 0;
|
||||
CriticalSection->DebugInfo = CritcalSectionDebugData;
|
||||
|
||||
/*
|
||||
* Add it to the List of Critical Sections owned by the process.
|
||||
* If we've initialized the Lock, then use it. If not, then probably
|
||||
* this is the lock initialization itself, so insert it directly.
|
||||
*/
|
||||
if ((CriticalSection != &RtlCriticalSectionLock) && (RtlpCritSectInitialized))
|
||||
{
|
||||
DPRINT("Securely Inserting into ProcessLocks: %p, %p, %p\n",
|
||||
&CritcalSectionDebugData->ProcessLocksList,
|
||||
CriticalSection,
|
||||
&RtlCriticalSectionList);
|
||||
|
||||
/* Protect List */
|
||||
RtlEnterCriticalSection(&RtlCriticalSectionLock);
|
||||
|
||||
/* Add this one */
|
||||
InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList);
|
||||
|
||||
/* Unprotect */
|
||||
RtlLeaveCriticalSection(&RtlCriticalSectionLock);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("Inserting into ProcessLocks: %p, %p, %p\n",
|
||||
&CritcalSectionDebugData->ProcessLocksList,
|
||||
CriticalSection,
|
||||
&RtlCriticalSectionList);
|
||||
|
||||
/* Add it directly */
|
||||
InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList);
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*++
|
||||
* RtlInitializeCriticalSectionAndSpinCount
|
||||
* @implemented NT4
|
||||
|
@ -562,73 +695,12 @@ RtlInitializeCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)
|
|||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RtlInitializeCriticalSectionAndSpinCount(PRTL_CRITICAL_SECTION CriticalSection,
|
||||
ULONG SpinCount)
|
||||
RtlInitializeCriticalSectionAndSpinCount(
|
||||
_Out_ PRTL_CRITICAL_SECTION CriticalSection,
|
||||
_In_ ULONG SpinCount)
|
||||
{
|
||||
PRTL_CRITICAL_SECTION_DEBUG CritcalSectionDebugData;
|
||||
|
||||
/* First things first, set up the Object */
|
||||
DPRINT("Initializing Critical Section: %p\n", CriticalSection);
|
||||
CriticalSection->LockCount = -1;
|
||||
CriticalSection->RecursionCount = 0;
|
||||
CriticalSection->OwningThread = 0;
|
||||
CriticalSection->SpinCount = (NtCurrentPeb()->NumberOfProcessors > 1) ? SpinCount : 0;
|
||||
CriticalSection->LockSemaphore = 0;
|
||||
|
||||
/* Allocate the Debug Data */
|
||||
CritcalSectionDebugData = RtlpAllocateDebugInfo();
|
||||
DPRINT("Allocated Debug Data: %p inside Process: %p\n",
|
||||
CritcalSectionDebugData,
|
||||
NtCurrentTeb()->ClientId.UniqueProcess);
|
||||
|
||||
if (!CritcalSectionDebugData)
|
||||
{
|
||||
/* This is bad! */
|
||||
DPRINT1("Couldn't allocate Debug Data for: %p\n", CriticalSection);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Set it up */
|
||||
CritcalSectionDebugData->Type = RTL_CRITSECT_TYPE;
|
||||
CritcalSectionDebugData->ContentionCount = 0;
|
||||
CritcalSectionDebugData->EntryCount = 0;
|
||||
CritcalSectionDebugData->CriticalSection = CriticalSection;
|
||||
CritcalSectionDebugData->Flags = 0;
|
||||
CriticalSection->DebugInfo = CritcalSectionDebugData;
|
||||
|
||||
/*
|
||||
* Add it to the List of Critical Sections owned by the process.
|
||||
* If we've initialized the Lock, then use it. If not, then probably
|
||||
* this is the lock initialization itself, so insert it directly.
|
||||
*/
|
||||
if ((CriticalSection != &RtlCriticalSectionLock) && (RtlpCritSectInitialized))
|
||||
{
|
||||
DPRINT("Securely Inserting into ProcessLocks: %p, %p, %p\n",
|
||||
&CritcalSectionDebugData->ProcessLocksList,
|
||||
CriticalSection,
|
||||
&RtlCriticalSectionList);
|
||||
|
||||
/* Protect List */
|
||||
RtlEnterCriticalSection(&RtlCriticalSectionLock);
|
||||
|
||||
/* Add this one */
|
||||
InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList);
|
||||
|
||||
/* Unprotect */
|
||||
RtlLeaveCriticalSection(&RtlCriticalSectionLock);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("Inserting into ProcessLocks: %p, %p, %p\n",
|
||||
&CritcalSectionDebugData->ProcessLocksList,
|
||||
CriticalSection,
|
||||
&RtlCriticalSectionList);
|
||||
|
||||
/* Add it directly */
|
||||
InsertTailList(&RtlCriticalSectionList, &CritcalSectionDebugData->ProcessLocksList);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
SpinCount &= ~RTL_CRITICAL_SECTION_ALL_FLAG_BITS;
|
||||
return RtlInitializeCriticalSectionEx(CriticalSection, SpinCount, 0);
|
||||
}
|
||||
|
||||
/*++
|
||||
|
|
Loading…
Reference in a new issue