- Fix several problems with the System PTE implementation, including the lack of locks.

- I also didn't fully like the idea of sticking "-1" into a 5-bit wide bitfield -- instead just stuff it as 0xFFFFF with a typecast. 
    - This seems to be NT's MM_EMPTY_LIST that shows up in a couple of ASSERTs on the checked build.
- This fixes several random crashes seen on my test boxes when mapping MDLs and using NP expansion VA.
- Dedicated to Brüno.

svn path=/trunk/; revision=41934
This commit is contained in:
ReactOS Portable Systems Group 2009-07-12 13:06:41 +00:00
parent 1279c44e6c
commit 0067e2c1a5

View file

@ -33,6 +33,7 @@ MiReserveAlignedSystemPtes(IN ULONG NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType,
IN ULONG Alignment) IN ULONG Alignment)
{ {
KIRQL OldIrql;
PMMPTE PointerPte, NextPte, PreviousPte; PMMPTE PointerPte, NextPte, PreviousPte;
ULONG_PTR ClusterSize; ULONG_PTR ClusterSize;
@ -41,11 +42,23 @@ MiReserveAlignedSystemPtes(IN ULONG NumberOfPtes,
// //
ASSERT(Alignment <= PAGE_SIZE); ASSERT(Alignment <= PAGE_SIZE);
//
// Lock the system PTE space
//
OldIrql = KeAcquireQueuedSpinLock(LockQueueSystemSpaceLock);
// //
// Get the first free cluster and make sure we have PTEs available // Get the first free cluster and make sure we have PTEs available
// //
PointerPte = &MmFirstFreeSystemPte[SystemPtePoolType]; PointerPte = &MmFirstFreeSystemPte[SystemPtePoolType];
if (PointerPte->u.List.NextEntry == -1) return NULL; if (PointerPte->u.List.NextEntry == ((ULONG)0xFFFFF))
{
//
// Fail
//
KeReleaseQueuedSpinLock(LockQueueSystemSpaceLock, OldIrql);
return NULL;
}
// //
// Now move to the first free system PTE cluster // Now move to the first free system PTE cluster
@ -96,6 +109,7 @@ MiReserveAlignedSystemPtes(IN ULONG NumberOfPtes,
// Decrement the free count and move to the next starting PTE // Decrement the free count and move to the next starting PTE
// //
MmTotalFreeSystemPtes[SystemPtePoolType] -= NumberOfPtes; MmTotalFreeSystemPtes[SystemPtePoolType] -= NumberOfPtes;
KeReleaseQueuedSpinLock(LockQueueSystemSpaceLock, OldIrql);
PointerPte += (ClusterSize - NumberOfPtes); PointerPte += (ClusterSize - NumberOfPtes);
break; break;
} }
@ -126,7 +140,14 @@ MiReserveAlignedSystemPtes(IN ULONG NumberOfPtes,
// //
// We couldn't find what you wanted -- is this the last cluster? // We couldn't find what you wanted -- is this the last cluster?
// //
if (PointerPte->u.List.NextEntry == -1) return NULL; if (PointerPte->u.List.NextEntry == ((ULONG)0xFFFFF))
{
//
// Fail
//
KeReleaseQueuedSpinLock(LockQueueSystemSpaceLock, OldIrql);
return NULL;
}
// //
// Go to the next cluster // Go to the next cluster
@ -164,20 +185,27 @@ MiReleaseSystemPtes(IN PMMPTE StartingPte,
IN ULONG NumberOfPtes, IN ULONG NumberOfPtes,
IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType) IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
{ {
KIRQL OldIrql;
ULONG_PTR ClusterSize, CurrentSize; ULONG_PTR ClusterSize, CurrentSize;
PMMPTE CurrentPte, NextPte, PointerPte; PMMPTE CurrentPte, NextPte, PointerPte;
// //
// Check to make sure the PTE address is within bounds. // Check to make sure the PTE address is within bounds
// //
ASSERT(NumberOfPtes != 0); ASSERT(NumberOfPtes != 0);
ASSERT(StartingPte >= MmSystemPtesStart[SystemPtePoolType]); ASSERT(StartingPte >= MmSystemPtesStart[SystemPtePoolType]);
ASSERT(StartingPte <= MmSystemPtesEnd[SystemPtePoolType]); ASSERT(StartingPte <= MmSystemPtesEnd[SystemPtePoolType]);
// //
// Zero PTEs. // Zero PTEs
// //
RtlZeroMemory(StartingPte, NumberOfPtes * sizeof (MMPTE)); RtlZeroMemory(StartingPte, NumberOfPtes * sizeof(MMPTE));
CurrentSize = (ULONG_PTR)(StartingPte - MmSystemPteBase);
//
// Acquire the system PTE lock
//
OldIrql = KeAcquireQueuedSpinLock(LockQueueSystemSpaceLock);
// //
// Increase availability // Increase availability
@ -187,7 +215,6 @@ MiReleaseSystemPtes(IN PMMPTE StartingPte,
// //
// Get the free cluster and start going through them // Get the free cluster and start going through them
// //
CurrentSize = (ULONG_PTR)(StartingPte - MmSystemPteBase);
CurrentPte = &MmFirstFreeSystemPte[SystemPtePoolType]; CurrentPte = &MmFirstFreeSystemPte[SystemPtePoolType];
while (TRUE) while (TRUE)
{ {
@ -201,7 +228,7 @@ MiReleaseSystemPtes(IN PMMPTE StartingPte,
// Sanity check // Sanity check
// //
ASSERT(((StartingPte + NumberOfPtes) <= PointerPte) || ASSERT(((StartingPte + NumberOfPtes) <= PointerPte) ||
(CurrentPte->u.List.NextEntry == -1)); (CurrentPte->u.List.NextEntry == ((ULONG)0xFFFFF)));
// //
// Get the next cluster in case it's the one // Get the next cluster in case it's the one
@ -312,6 +339,7 @@ MiReleaseSystemPtes(IN PMMPTE StartingPte,
// //
// We released the PTEs into their cluster (and optimized the list) // We released the PTEs into their cluster (and optimized the list)
// //
KeReleaseQueuedSpinLock(LockQueueSystemSpaceLock, OldIrql);
break; break;
} }
@ -350,7 +378,7 @@ MiInitializeSystemPtes(IN PMMPTE StartingPte,
// //
// Make the first entry free and link it // Make the first entry free and link it
// //
StartingPte->u.List.NextEntry = -1; StartingPte->u.List.NextEntry = ((ULONG)0xFFFFF);
MmFirstFreeSystemPte[PoolType].u.Long = 0; MmFirstFreeSystemPte[PoolType].u.Long = 0;
MmFirstFreeSystemPte[PoolType].u.List.NextEntry = StartingPte - MmFirstFreeSystemPte[PoolType].u.List.NextEntry = StartingPte -
MmSystemPteBase; MmSystemPteBase;