[NTOSKRNL]

- Keep APC delivery disabled while holding a Heap Lock, not just while acquiring/releasing it (Dedicated to Timo and Ged).
- Store the Heap Lock in non-paged pool, the only place where executive resources belong (Dedicated to patient people).
[RTL]
- Restructure/simplify/correct Heap and Heap Segment initialization (partially to cope with the changed Heap Lock interface).
- Restrict the location of Heap Segment headers to the base address of the Heap Segment (which frees up a whopping 60 bytes per Heap!).
- Cater for acquiring the Heap Lock exclusively or shared (the latter is only available in kernel-mode); only exclusive locking is used for now.
- Use a plain critical section to guard the Process Heap list, no reason to disguise it as a Heap Lock (saves us a handful more bytes).


svn path=/trunk/; revision=53761
This commit is contained in:
Roel Messiant 2011-09-19 16:52:37 +00:00
parent cf0a380afd
commit 2e6e9dd622
6 changed files with 214 additions and 227 deletions

View file

@ -112,32 +112,30 @@ RtlGetNtGlobalFlags(VOID)
NTSTATUS NTSTATUS
NTAPI NTAPI
RtlDeleteHeapLock( RtlDeleteHeapLock(IN OUT PHEAP_LOCK Lock)
PHEAP_LOCK Lock)
{ {
return RtlDeleteCriticalSection(&Lock->CriticalSection); return RtlDeleteCriticalSection(&Lock->CriticalSection);
} }
NTSTATUS NTSTATUS
NTAPI NTAPI
RtlEnterHeapLock( RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
PHEAP_LOCK Lock)
{ {
UNREFERENCED_PARAMETER(Exclusive);
return RtlEnterCriticalSection(&Lock->CriticalSection); return RtlEnterCriticalSection(&Lock->CriticalSection);
} }
NTSTATUS NTSTATUS
NTAPI NTAPI
RtlInitializeHeapLock( RtlInitializeHeapLock(IN OUT PHEAP_LOCK *Lock)
PHEAP_LOCK Lock)
{ {
return RtlInitializeCriticalSection(&Lock->CriticalSection); return RtlInitializeCriticalSection(&(*Lock)->CriticalSection);
} }
NTSTATUS NTSTATUS
NTAPI NTAPI
RtlLeaveHeapLock( RtlLeaveHeapLock(IN OUT PHEAP_LOCK Lock)
PHEAP_LOCK Lock)
{ {
return RtlLeaveCriticalSection(&Lock->CriticalSection); return RtlLeaveCriticalSection(&Lock->CriticalSection);
} }

View file

@ -23,7 +23,7 @@
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
HEAP_LOCK RtlpProcessHeapsListLock; RTL_CRITICAL_SECTION RtlpProcessHeapsListLock;
/* Bitmaps stuff */ /* Bitmaps stuff */
@ -82,44 +82,58 @@ UCHAR FillPattern[HEAP_ENTRY_SIZE] =
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
VOID NTAPI NTSTATUS NTAPI
RtlpInitializeHeap(PHEAP Heap, RtlpInitializeHeap(OUT PHEAP Heap,
PULONG HeaderSize, IN ULONG Flags,
ULONG Flags, IN PHEAP_LOCK Lock OPTIONAL,
BOOLEAN AllocateLock, IN PRTL_HEAP_PARAMETERS Parameters)
PVOID Lock)
{ {
PVOID NextHeapBase = Heap + 1;
PHEAP_UCR_DESCRIPTOR UcrDescriptor;
ULONG NumUCRs = 8; ULONG NumUCRs = 8;
ULONG i; ULONG Index;
SIZE_T HeaderSize;
NTSTATUS Status; NTSTATUS Status;
PHEAP_UCR_DESCRIPTOR UcrDescriptor;
/* Add UCRs size */ /* Preconditions */
*HeaderSize += NumUCRs * sizeof(*UcrDescriptor); ASSERT(Heap != NULL);
ASSERT(Parameters != NULL);
ASSERT(!(Flags & HEAP_LOCK_USER_ALLOCATED));
ASSERT(!(Flags & HEAP_NO_SERIALIZE) || (Lock == NULL)); /* HEAP_NO_SERIALIZE => no lock */
/* Prepare a list of UCRs */ /* Start out with the size of a plain Heap header */
InitializeListHead(&Heap->UCRList); HeaderSize = ROUND_UP(sizeof(HEAP), sizeof(HEAP_ENTRY));
InitializeListHead(&Heap->UCRSegments);
UcrDescriptor = NextHeapBase;
for (i=0; i<NumUCRs; i++, UcrDescriptor++) /* Check if space needs to be added for the Heap Lock */
if (!(Flags & HEAP_NO_SERIALIZE))
{ {
InsertTailList(&Heap->UCRList, &UcrDescriptor->ListEntry); if (Lock != NULL)
/* The user manages the Heap Lock */
Flags |= HEAP_LOCK_USER_ALLOCATED;
else
if (RtlpGetMode() == UserMode)
{
/* In user mode, the Heap Lock trails the Heap header */
Lock = (PHEAP_LOCK) ((ULONG_PTR) (Heap) + HeaderSize);
HeaderSize += ROUND_UP(sizeof(HEAP_LOCK), sizeof(HEAP_ENTRY));
}
} }
NextHeapBase = UcrDescriptor; /* Add space for the initial Heap UnCommitted Range Descriptor list */
// TODO: Add tagging UcrDescriptor = (PHEAP_UCR_DESCRIPTOR) ((ULONG_PTR) (Heap) + HeaderSize);
HeaderSize += ROUND_UP(NumUCRs * sizeof(HEAP_UCR_DESCRIPTOR), sizeof(HEAP_ENTRY));
/* Round up header size again */ /* Sanity check */
*HeaderSize = ROUND_UP(*HeaderSize, HEAP_ENTRY_SIZE); ASSERT(HeaderSize <= PAGE_SIZE);
ASSERT(*HeaderSize <= PAGE_SIZE); /* Initialise the Heap Entry header containing the Heap header */
Heap->Entry.Size = HeaderSize >> HEAP_ENTRY_SHIFT;
/* Initialize heap's header */
Heap->Entry.Size = (USHORT)((*HeaderSize) >> HEAP_ENTRY_SHIFT);
Heap->Entry.Flags = HEAP_ENTRY_BUSY; Heap->Entry.Flags = HEAP_ENTRY_BUSY;
Heap->Entry.SmallTagIndex = LOBYTE(Heap->Entry.Size) ^ HIBYTE(Heap->Entry.Size) ^ Heap->Entry.Flags;
Heap->Entry.PreviousSize = 0;
Heap->Entry.SegmentOffset = 0;
Heap->Entry.UnusedBytes = 0;
/* Initialise the Heap header */
Heap->Signature = HEAP_SIGNATURE; Heap->Signature = HEAP_SIGNATURE;
Heap->Flags = Flags; Heap->Flags = Flags;
Heap->ForceFlags = (Flags & (HEAP_NO_SERIALIZE | Heap->ForceFlags = (Flags & (HEAP_NO_SERIALIZE |
@ -131,32 +145,64 @@ RtlpInitializeHeap(PHEAP Heap,
HEAP_TAIL_CHECKING_ENABLED | HEAP_TAIL_CHECKING_ENABLED |
HEAP_CREATE_ALIGN_16 | HEAP_CREATE_ALIGN_16 |
HEAP_FREE_CHECKING_ENABLED)); HEAP_FREE_CHECKING_ENABLED));
Heap->HeaderValidateCopy = NULL;
Heap->HeaderValidateLength = ((PCHAR)NextHeapBase - (PCHAR)Heap);
/* Initialize free lists */ /* Initialise the Heap parameters */
for (i=0; i<HEAP_FREELISTS; i++) Heap->VirtualMemoryThreshold = ROUND_UP(Parameters->VirtualMemoryThreshold, sizeof(HEAP_ENTRY)) >> HEAP_ENTRY_SHIFT;
Heap->SegmentReserve = Parameters->SegmentReserve;
Heap->SegmentCommit = Parameters->SegmentCommit;
Heap->DeCommitFreeBlockThreshold = Parameters->DeCommitFreeBlockThreshold >> HEAP_ENTRY_SHIFT;
Heap->DeCommitTotalFreeThreshold = Parameters->DeCommitTotalFreeThreshold >> HEAP_ENTRY_SHIFT;
Heap->MaximumAllocationSize = Parameters->MaximumAllocationSize;
Heap->CommitRoutine = Parameters->CommitRoutine;
/* Initialise the Heap validation info */
Heap->HeaderValidateCopy = NULL;
Heap->HeaderValidateLength = HeaderSize;
/* Initialise the Heap Lock */
if (!(Flags & HEAP_NO_SERIALIZE) && !(Flags & HEAP_LOCK_USER_ALLOCATED))
{ {
InitializeListHead(&Heap->FreeLists[i]); Status = RtlInitializeHeapLock(&Lock);
if (!NT_SUCCESS(Status))
return Status;
}
Heap->LockVariable = Lock;
/* Initialise the Heap alignment info */
if (Flags & HEAP_CREATE_ALIGN_16)
{
Heap->AlignMask = (ULONG) ~15;
Heap->AlignRound = 15 + sizeof(HEAP_ENTRY);
}
else
{
Heap->AlignMask = (ULONG) ~(sizeof(HEAP_ENTRY) - 1);
Heap->AlignRound = 2 * sizeof(HEAP_ENTRY) - 1;
} }
/* Initialize "big" allocations list */ if (Flags & HEAP_TAIL_CHECKING_ENABLED)
Heap->AlignRound += sizeof(HEAP_ENTRY);
/* Initialise the Heap Segment list */
for (Index = 0; Index < HEAP_SEGMENTS; ++Index)
Heap->Segments[Index] = NULL;
/* Initialise the Heap Free Heap Entry lists */
for (Index = 0; Index < HEAP_FREELISTS; ++Index)
InitializeListHead(&Heap->FreeLists[Index]);
/* Initialise the Heap Virtual Allocated Blocks list */
InitializeListHead(&Heap->VirtualAllocdBlocks); InitializeListHead(&Heap->VirtualAllocdBlocks);
/* Initialize lock */ /* Initialise the Heap UnCommitted Region lists */
if (AllocateLock) InitializeListHead(&Heap->UCRSegments);
{ InitializeListHead(&Heap->UCRList);
Lock = NextHeapBase;
Status = RtlInitializeHeapLock((PHEAP_LOCK)Lock);
if (!NT_SUCCESS(Status))
{
DPRINT1("Initializing the lock failed!\n");
return /*NULL*/; // FIXME!
}
}
/* Set the lock variable */ /* Register the initial Heap UnCommitted Region Descriptors */
Heap->LockVariable = Lock; for (Index = 0; Index < NumUCRs; ++Index)
InsertTailList(&Heap->UCRList, &UcrDescriptor[Index].ListEntry);
return STATUS_SUCCESS;
} }
VOID FORCEINLINE VOID FORCEINLINE
@ -821,92 +867,76 @@ RtlpDeCommitFreeBlock(PHEAP Heap,
} }
BOOLEAN NTAPI BOOLEAN NTAPI
RtlpInitializeHeapSegment(PHEAP Heap, RtlpInitializeHeapSegment(IN OUT PHEAP Heap,
PHEAP_SEGMENT Segment, OUT PHEAP_SEGMENT Segment,
UCHAR SegmentIndex, IN UCHAR SegmentIndex,
ULONG Flags, IN ULONG SegmentFlags,
PVOID BaseAddress, IN SIZE_T SegmentReserve,
PVOID UncommittedBase, IN SIZE_T SegmentCommit)
PVOID LimitAddress)
{ {
ULONG Pages, CommitSize;
PHEAP_ENTRY HeapEntry; PHEAP_ENTRY HeapEntry;
USHORT PreviousSize = 0, NewSize;
NTSTATUS Status;
Pages = ((PCHAR)LimitAddress - (PCHAR)BaseAddress) / PAGE_SIZE; /* Preconditions */
ASSERT(Heap != NULL);
ASSERT(Segment != NULL);
ASSERT(SegmentCommit >= PAGE_SIZE);
ASSERT(ROUND_DOWN(SegmentCommit, PAGE_SIZE) == SegmentCommit);
ASSERT(SegmentReserve >= SegmentCommit);
ASSERT(ROUND_DOWN(SegmentReserve, PAGE_SIZE) == SegmentReserve);
HeapEntry = (PHEAP_ENTRY)ROUND_UP(Segment + 1, HEAP_ENTRY_SIZE); DPRINT("RtlpInitializeHeapSegment(%p %p %x %x %lx %lx)\n", Heap, Segment, SegmentIndex, SegmentFlags, SegmentReserve, SegmentCommit);
DPRINT("RtlpInitializeHeapSegment(%p %p %x %x %p %p %p)\n", Heap, Segment, SegmentIndex, Flags, BaseAddress, UncommittedBase, LimitAddress); /* Initialise the Heap Entry header if this is not the first Heap Segment */
DPRINT("Pages %x, HeapEntry %p, sizeof(HEAP_SEGMENT) %x\n", Pages, HeapEntry, sizeof(HEAP_SEGMENT)); if ((PHEAP_SEGMENT) (Heap) != Segment)
/* Check if it's the first segment and remember its size */
if (Heap == BaseAddress)
PreviousSize = Heap->Entry.Size;
NewSize = ((PCHAR)HeapEntry - (PCHAR)Segment) >> HEAP_ENTRY_SHIFT;
if ((PVOID)(HeapEntry + 1) >= UncommittedBase)
{ {
/* Check if it goes beyond the limit */ Segment->Entry.Size = ROUND_UP(sizeof(HEAP_SEGMENT), sizeof(HEAP_ENTRY)) >> HEAP_ENTRY_SHIFT;
if ((PVOID)(HeapEntry + 1) >= LimitAddress) Segment->Entry.Flags = HEAP_ENTRY_BUSY;
return FALSE; Segment->Entry.SmallTagIndex = LOBYTE(Segment->Entry.Size) ^ HIBYTE(Segment->Entry.Size) ^ Segment->Entry.Flags;
Segment->Entry.PreviousSize = 0;
/* Need to commit memory */ Segment->Entry.SegmentOffset = SegmentIndex;
CommitSize = (PCHAR)(HeapEntry + 1) - (PCHAR)UncommittedBase; Segment->Entry.UnusedBytes = 0;
Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
(PVOID)&UncommittedBase,
0,
&CommitSize,
MEM_COMMIT,
PAGE_READWRITE);
if (!NT_SUCCESS(Status))
{
DPRINT1("Committing page failed with status 0x%08X\n", Status);
return FALSE;
}
DPRINT("Committed %d bytes at base %p\n", CommitSize, UncommittedBase);
/* Calcule the new uncommitted base */
UncommittedBase = (PVOID)((PCHAR)UncommittedBase + CommitSize);
} }
/* Initialize the segment entry */ /* Sanity check */
Segment->Entry.PreviousSize = PreviousSize; ASSERT((Segment->Entry.Size << HEAP_ENTRY_SHIFT) <= PAGE_SIZE);
Segment->Entry.Size = NewSize;
Segment->Entry.Flags = HEAP_ENTRY_BUSY;
Segment->Entry.SegmentOffset = SegmentIndex;
/* Initialize the segment itself */ /* Initialise the Heap Segment header */
Segment->SegmentSignature = HEAP_SEGMENT_SIGNATURE; Segment->SegmentSignature = HEAP_SEGMENT_SIGNATURE;
Segment->SegmentFlags = SegmentFlags;
Segment->Heap = Heap; Segment->Heap = Heap;
Segment->BaseAddress = BaseAddress;
Segment->FirstEntry = HeapEntry;
Segment->LastValidEntry = (PHEAP_ENTRY)((PCHAR)BaseAddress + Pages * PAGE_SIZE);
Segment->NumberOfPages = Pages;
Segment->NumberOfUnCommittedPages = ((PCHAR)LimitAddress - (PCHAR)UncommittedBase) / PAGE_SIZE;
InitializeListHead(&Segment->UCRSegmentList);
/* Insert uncommitted pages into UCR (uncommitted ranges) list */
if (Segment->NumberOfUnCommittedPages)
{
RtlpInsertUnCommittedPages(Segment, (ULONG_PTR)UncommittedBase, Segment->NumberOfUnCommittedPages * PAGE_SIZE);
}
/* Set the segment index pointer */
Heap->Segments[SegmentIndex] = Segment; Heap->Segments[SegmentIndex] = Segment;
/* Prepare a free heap entry */ /* Initialise the Heap Segment location information */
HeapEntry->Flags = HEAP_ENTRY_LAST_ENTRY; Segment->BaseAddress = Segment;
HeapEntry->PreviousSize = Segment->Entry.Size; Segment->NumberOfPages = SegmentReserve >> PAGE_SHIFT;
HeapEntry->SegmentOffset = SegmentIndex;
/* Insert it */ /* Initialise the Heap Entries contained within the Heap Segment */
RtlpInsertFreeBlock(Heap, (PHEAP_FREE_ENTRY)HeapEntry, (PHEAP_ENTRY)UncommittedBase - HeapEntry); Segment->FirstEntry = &Segment->Entry + Segment->Entry.Size;
Segment->LastValidEntry = (PHEAP_ENTRY) ((ULONG_PTR) (Segment) + SegmentReserve);
return TRUE; if ((Segment->Entry.Size << HEAP_ENTRY_SHIFT) < SegmentCommit)
{
HeapEntry = Segment->FirstEntry;
/* Prepare a Free Heap Entry header */
HeapEntry->Flags = HEAP_ENTRY_LAST_ENTRY;
HeapEntry->PreviousSize = Segment->Entry.Size;
HeapEntry->SegmentOffset = SegmentIndex;
/* Register the Free Heap Entry */
RtlpInsertFreeBlock(Heap, (PHEAP_FREE_ENTRY) HeapEntry, (SegmentCommit >> HEAP_ENTRY_SHIFT) - Segment->Entry.Size);
}
/* Initialise the Heap Segment UnCommitted Range information */
Segment->NumberOfUnCommittedPages = (SegmentReserve - SegmentCommit) >> PAGE_SHIFT;
Segment->NumberOfUnCommittedRanges = 0;
InitializeListHead(&Segment->UCRSegmentList);
/* Register the UnCommitted Range of the Heap Segment */
if (Segment->NumberOfUnCommittedPages != 0)
RtlpInsertUnCommittedPages(Segment, (ULONG_PTR) (Segment) + SegmentCommit, SegmentReserve - SegmentCommit);
return STATUS_SUCCESS;
} }
VOID NTAPI VOID NTAPI
@ -944,7 +974,7 @@ RtlpAddHeapToProcessList(PHEAP Heap)
Peb = RtlGetCurrentPeb(); Peb = RtlGetCurrentPeb();
/* Acquire the lock */ /* Acquire the lock */
RtlEnterHeapLock(&RtlpProcessHeapsListLock); RtlEnterCriticalSection(&RtlpProcessHeapsListLock);
//_SEH2_TRY { //_SEH2_TRY {
/* Check if max number of heaps reached */ /* Check if max number of heaps reached */
@ -961,7 +991,7 @@ RtlpAddHeapToProcessList(PHEAP Heap)
// } _SEH2_FINALLY { // } _SEH2_FINALLY {
/* Release the lock */ /* Release the lock */
RtlLeaveHeapLock(&RtlpProcessHeapsListLock); RtlLeaveCriticalSection(&RtlpProcessHeapsListLock);
// } _SEH2_END // } _SEH2_END
} }
@ -978,7 +1008,7 @@ RtlpRemoveHeapFromProcessList(PHEAP Heap)
Peb = RtlGetCurrentPeb(); Peb = RtlGetCurrentPeb();
/* Acquire the lock */ /* Acquire the lock */
RtlEnterHeapLock(&RtlpProcessHeapsListLock); RtlEnterCriticalSection(&RtlpProcessHeapsListLock);
/* Check if we don't need anything to do */ /* Check if we don't need anything to do */
if ((Heap->ProcessHeapsListIndex == 0) || if ((Heap->ProcessHeapsListIndex == 0) ||
@ -986,7 +1016,7 @@ RtlpRemoveHeapFromProcessList(PHEAP Heap)
(Peb->NumberOfHeaps == 0)) (Peb->NumberOfHeaps == 0))
{ {
/* Release the lock */ /* Release the lock */
RtlLeaveHeapLock(&RtlpProcessHeapsListLock); RtlLeaveCriticalSection(&RtlpProcessHeapsListLock);
return; return;
} }
@ -1023,7 +1053,7 @@ RtlpRemoveHeapFromProcessList(PHEAP Heap)
Heap->ProcessHeapsListIndex = 0; Heap->ProcessHeapsListIndex = 0;
/* Release the lock */ /* Release the lock */
RtlLeaveHeapLock(&RtlpProcessHeapsListLock); RtlLeaveCriticalSection(&RtlpProcessHeapsListLock);
} }
PHEAP_FREE_ENTRY NTAPI PHEAP_FREE_ENTRY NTAPI
@ -1228,13 +1258,7 @@ RtlpExtendHeap(PHEAP Heap,
/* Initialize heap segment if commit was successful */ /* Initialize heap segment if commit was successful */
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ Status = RtlpInitializeHeapSegment(Heap, Segment, EmptyIndex, 0, ReserveSize, CommitSize);
if (!RtlpInitializeHeapSegment(Heap, Segment, EmptyIndex, 0, Segment,
(PCHAR)Segment + CommitSize, (PCHAR)Segment + ReserveSize))
{
Status = STATUS_NO_MEMORY;
}
}
/* If everything worked - cool */ /* If everything worked - cool */
if (NT_SUCCESS(Status)) return (PHEAP_FREE_ENTRY)Segment->FirstEntry; if (NT_SUCCESS(Status)) return (PHEAP_FREE_ENTRY)Segment->FirstEntry;
@ -1298,8 +1322,7 @@ RtlCreateHeap(ULONG Flags,
ULONG NtGlobalFlags = RtlGetNtGlobalFlags(); ULONG NtGlobalFlags = RtlGetNtGlobalFlags();
ULONG HeapSegmentFlags = 0; ULONG HeapSegmentFlags = 0;
NTSTATUS Status; NTSTATUS Status;
ULONG MaxBlockSize, HeaderSize; ULONG MaxBlockSize;
BOOLEAN AllocateLock = FALSE;
/* Check for a special heap */ /* Check for a special heap */
if (RtlpPageHeapEnabled && !Addr && !Lock) if (RtlpPageHeapEnabled && !Addr && !Lock)
@ -1422,25 +1445,9 @@ RtlCreateHeap(ULONG Flags,
if (RtlpHeapIsSpecial(Flags)) if (RtlpHeapIsSpecial(Flags))
return RtlDebugCreateHeap(Flags, Addr, TotalSize, CommitSize, Lock, Parameters); return RtlDebugCreateHeap(Flags, Addr, TotalSize, CommitSize, Lock, Parameters);
/* Calculate header size */ /* Without serialization, a lock makes no sense */
HeaderSize = sizeof(HEAP); if ((Flags & HEAP_NO_SERIALIZE) && (Lock != NULL))
if (!(Flags & HEAP_NO_SERIALIZE))
{
if (Lock)
{
Flags |= HEAP_LOCK_USER_ALLOCATED;
}
else
{
HeaderSize += sizeof(HEAP_LOCK);
AllocateLock = TRUE;
}
}
else if (Lock)
{
/* Invalid parameters */
return NULL; return NULL;
}
/* See if we are already provided with an address for the heap */ /* See if we are already provided with an address for the heap */
if (Addr) if (Addr)
@ -1583,48 +1590,23 @@ RtlCreateHeap(ULONG Flags,
UncommittedAddress = (PCHAR)UncommittedAddress + CommitSize; UncommittedAddress = (PCHAR)UncommittedAddress + CommitSize;
} }
DPRINT("Created heap %p, CommitSize %x, ReserveSize %x\n", Heap, CommitSize, TotalSize);
/* Initialize the heap */ /* Initialize the heap */
RtlpInitializeHeap(Heap, &HeaderSize, Flags, AllocateLock, Lock); Status = RtlpInitializeHeap(Heap, Flags, Lock, Parameters);
if (!NT_SUCCESS(Status))
/* Initialize heap's first segment */
if (!RtlpInitializeHeapSegment(Heap,
(PHEAP_SEGMENT)((PCHAR)Heap + HeaderSize),
0,
HeapSegmentFlags,
CommittedAddress,
UncommittedAddress,
(PCHAR)CommittedAddress + TotalSize))
{ {
DPRINT1("Failed to initialize heap segment\n"); DPRINT1("Failed to initialize heap (%x)\n", Status);
return NULL; return NULL;
} }
/* Set other data */ /* Initialize heap's first segment */
Heap->ProcessHeapsListIndex = 0; Status = RtlpInitializeHeapSegment(Heap, (PHEAP_SEGMENT) (Heap), 0, HeapSegmentFlags, TotalSize, CommitSize);
Heap->SegmentCommit = Parameters->SegmentCommit; if (!NT_SUCCESS(Status))
Heap->SegmentReserve = Parameters->SegmentReserve;
Heap->DeCommitFreeBlockThreshold = Parameters->DeCommitFreeBlockThreshold >> HEAP_ENTRY_SHIFT;
Heap->DeCommitTotalFreeThreshold = Parameters->DeCommitTotalFreeThreshold >> HEAP_ENTRY_SHIFT;
Heap->MaximumAllocationSize = Parameters->MaximumAllocationSize;
Heap->VirtualMemoryThreshold = ROUND_UP(Parameters->VirtualMemoryThreshold, HEAP_ENTRY_SIZE) >> HEAP_ENTRY_SHIFT;
Heap->CommitRoutine = Parameters->CommitRoutine;
/* Set alignment */
if (Flags & HEAP_CREATE_ALIGN_16)
{ {
Heap->AlignMask = (ULONG)~15; DPRINT1("Failed to initialize heap segment (%x)\n", Status);
Heap->AlignRound = 15 + sizeof(HEAP_ENTRY); return NULL;
}
else
{
Heap->AlignMask = (ULONG)~(HEAP_ENTRY_SIZE - 1);
Heap->AlignRound = HEAP_ENTRY_SIZE - 1 + sizeof(HEAP_ENTRY);
} }
if (Heap->Flags & HEAP_TAIL_CHECKING_ENABLED) DPRINT("Created heap %p, CommitSize %x, ReserveSize %x\n", Heap, CommitSize, TotalSize);
Heap->AlignRound += HEAP_ENTRY_SIZE;
/* Add heap to process list in case of usermode heap */ /* Add heap to process list in case of usermode heap */
if (RtlpGetMode() == UserMode) if (RtlpGetMode() == UserMode)
@ -1634,7 +1616,6 @@ RtlCreateHeap(ULONG Flags,
// FIXME: What about lookasides? // FIXME: What about lookasides?
} }
DPRINT("Heap %p, flags 0x%08x\n", Heap, Heap->Flags);
return Heap; return Heap;
} }
@ -2063,7 +2044,7 @@ RtlAllocateHeap(IN PVOID HeapPtr,
/* Acquire the lock if necessary */ /* Acquire the lock if necessary */
if (!(Flags & HEAP_NO_SERIALIZE)) if (!(Flags & HEAP_NO_SERIALIZE))
{ {
RtlEnterHeapLock(Heap->LockVariable); RtlEnterHeapLock(Heap->LockVariable, TRUE);
HeapLocked = TRUE; HeapLocked = TRUE;
} }
@ -2265,7 +2246,7 @@ BOOLEAN NTAPI RtlFreeHeap(
/* Lock if necessary */ /* Lock if necessary */
if (!(Flags & HEAP_NO_SERIALIZE)) if (!(Flags & HEAP_NO_SERIALIZE))
{ {
RtlEnterHeapLock(Heap->LockVariable); RtlEnterHeapLock(Heap->LockVariable, TRUE);
Locked = TRUE; Locked = TRUE;
} }
@ -2690,7 +2671,7 @@ RtlReAllocateHeap(HANDLE HeapPtr,
/* Acquire the lock if necessary */ /* Acquire the lock if necessary */
if (!(Flags & HEAP_NO_SERIALIZE)) if (!(Flags & HEAP_NO_SERIALIZE))
{ {
RtlEnterHeapLock(Heap->LockVariable); RtlEnterHeapLock(Heap->LockVariable, TRUE);
HeapLocked = TRUE; HeapLocked = TRUE;
Flags &= ~HEAP_NO_SERIALIZE; Flags &= ~HEAP_NO_SERIALIZE;
} }
@ -3071,7 +3052,7 @@ RtlLockHeap(IN HANDLE HeapPtr)
/* Lock if it's lockable */ /* Lock if it's lockable */
if (!(Heap->Flags & HEAP_NO_SERIALIZE)) if (!(Heap->Flags & HEAP_NO_SERIALIZE))
{ {
RtlEnterHeapLock(Heap->LockVariable); RtlEnterHeapLock(Heap->LockVariable, TRUE);
} }
return TRUE; return TRUE;
@ -3651,7 +3632,7 @@ BOOLEAN NTAPI RtlValidateHeap(
/* Acquire the lock if necessary */ /* Acquire the lock if necessary */
if (!(Flags & HEAP_NO_SERIALIZE)) if (!(Flags & HEAP_NO_SERIALIZE))
{ {
RtlEnterHeapLock(Heap->LockVariable); RtlEnterHeapLock(Heap->LockVariable, TRUE);
HeapLocked = TRUE; HeapLocked = TRUE;
} }
@ -3682,7 +3663,7 @@ RtlInitializeHeapManager(VOID)
Peb->NumberOfHeaps = 0; Peb->NumberOfHeaps = 0;
/* Initialize the process heaps list protecting lock */ /* Initialize the process heaps list protecting lock */
RtlInitializeHeapLock(&RtlpProcessHeapsListLock); RtlInitializeCriticalSection(&RtlpProcessHeapsListLock);
} }
@ -3759,7 +3740,7 @@ RtlSetUserValueHeap(IN PVOID HeapHandle,
/* Lock if it's lockable */ /* Lock if it's lockable */
if (!(Heap->Flags & HEAP_NO_SERIALIZE)) if (!(Heap->Flags & HEAP_NO_SERIALIZE))
{ {
RtlEnterHeapLock(Heap->LockVariable); RtlEnterHeapLock(Heap->LockVariable, TRUE);
HeapLocked = TRUE; HeapLocked = TRUE;
} }
@ -3818,7 +3799,7 @@ RtlSetUserFlagsHeap(IN PVOID HeapHandle,
/* Lock if it's lockable */ /* Lock if it's lockable */
if (!(Heap->Flags & HEAP_NO_SERIALIZE)) if (!(Heap->Flags & HEAP_NO_SERIALIZE))
{ {
RtlEnterHeapLock(Heap->LockVariable); RtlEnterHeapLock(Heap->LockVariable, TRUE);
HeapLocked = TRUE; HeapLocked = TRUE;
} }
@ -3874,7 +3855,7 @@ RtlGetUserInfoHeap(IN PVOID HeapHandle,
/* Lock if it's lockable */ /* Lock if it's lockable */
if (!(Heap->Flags & HEAP_NO_SERIALIZE)) if (!(Heap->Flags & HEAP_NO_SERIALIZE))
{ {
RtlEnterHeapLock(Heap->LockVariable); RtlEnterHeapLock(Heap->LockVariable, TRUE);
HeapLocked = TRUE; HeapLocked = TRUE;
} }

View file

@ -320,7 +320,7 @@ typedef struct _HEAP_VIRTUAL_ALLOC_ENTRY
} HEAP_VIRTUAL_ALLOC_ENTRY, *PHEAP_VIRTUAL_ALLOC_ENTRY; } HEAP_VIRTUAL_ALLOC_ENTRY, *PHEAP_VIRTUAL_ALLOC_ENTRY;
/* Global variables */ /* Global variables */
extern HEAP_LOCK RtlpProcessHeapsListLock; extern RTL_CRITICAL_SECTION RtlpProcessHeapsListLock;
extern BOOLEAN RtlpPageHeapEnabled; extern BOOLEAN RtlpPageHeapEnabled;
/* Functions declarations */ /* Functions declarations */

View file

@ -163,7 +163,7 @@ RtlDebugAllocateHeap(PVOID HeapPtr,
/* Lock the heap ourselves */ /* Lock the heap ourselves */
if (!(Flags & HEAP_NO_SERIALIZE)) if (!(Flags & HEAP_NO_SERIALIZE))
{ {
RtlEnterHeapLock(Heap->LockVariable); RtlEnterHeapLock(Heap->LockVariable, TRUE);
HeapLocked = TRUE; HeapLocked = TRUE;
/* Add no serialize flag so that the main routine won't try to acquire the lock again */ /* Add no serialize flag so that the main routine won't try to acquire the lock again */
@ -230,7 +230,7 @@ RtlDebugReAllocateHeap(HANDLE HeapPtr,
/* Lock the heap ourselves */ /* Lock the heap ourselves */
if (!(Flags & HEAP_NO_SERIALIZE)) if (!(Flags & HEAP_NO_SERIALIZE))
{ {
RtlEnterHeapLock(Heap->LockVariable); RtlEnterHeapLock(Heap->LockVariable, TRUE);
HeapLocked = TRUE; HeapLocked = TRUE;
/* Add no serialize flag so that the main routine won't try to acquire the lock again */ /* Add no serialize flag so that the main routine won't try to acquire the lock again */
@ -288,7 +288,7 @@ RtlDebugFreeHeap(HANDLE HeapPtr,
/* Lock the heap ourselves */ /* Lock the heap ourselves */
if (!(Flags & HEAP_NO_SERIALIZE)) if (!(Flags & HEAP_NO_SERIALIZE))
{ {
RtlEnterHeapLock(Heap->LockVariable); RtlEnterHeapLock(Heap->LockVariable, TRUE);
HeapLocked = TRUE; HeapLocked = TRUE;
/* Add no serialize flag so that the main routine won't try to acquire the lock again */ /* Add no serialize flag so that the main routine won't try to acquire the lock again */
@ -345,7 +345,7 @@ RtlDebugGetUserInfoHeap(PVOID HeapHandle,
/* Lock the heap ourselves */ /* Lock the heap ourselves */
if (!(Flags & HEAP_NO_SERIALIZE)) if (!(Flags & HEAP_NO_SERIALIZE))
{ {
RtlEnterHeapLock(Heap->LockVariable); RtlEnterHeapLock(Heap->LockVariable, TRUE);
HeapLocked = TRUE; HeapLocked = TRUE;
/* Add no serialize flag so that the main routine won't try to acquire the lock again */ /* Add no serialize flag so that the main routine won't try to acquire the lock again */
@ -397,7 +397,7 @@ RtlDebugSetUserValueHeap(PVOID HeapHandle,
/* Lock the heap ourselves */ /* Lock the heap ourselves */
if (!(Flags & HEAP_NO_SERIALIZE)) if (!(Flags & HEAP_NO_SERIALIZE))
{ {
RtlEnterHeapLock(Heap->LockVariable); RtlEnterHeapLock(Heap->LockVariable, TRUE);
HeapLocked = TRUE; HeapLocked = TRUE;
/* Add no serialize flag so that the main routine won't try to acquire the lock again */ /* Add no serialize flag so that the main routine won't try to acquire the lock again */
@ -461,7 +461,7 @@ RtlDebugSetUserFlagsHeap(PVOID HeapHandle,
/* Lock the heap ourselves */ /* Lock the heap ourselves */
if (!(Flags & HEAP_NO_SERIALIZE)) if (!(Flags & HEAP_NO_SERIALIZE))
{ {
RtlEnterHeapLock(Heap->LockVariable); RtlEnterHeapLock(Heap->LockVariable, TRUE);
HeapLocked = TRUE; HeapLocked = TRUE;
/* Add no serialize flag so that the main routine won't try to acquire the lock again */ /* Add no serialize flag so that the main routine won't try to acquire the lock again */
@ -516,7 +516,7 @@ RtlDebugSizeHeap(HANDLE HeapPtr,
/* Lock the heap ourselves */ /* Lock the heap ourselves */
if (!(Flags & HEAP_NO_SERIALIZE)) if (!(Flags & HEAP_NO_SERIALIZE))
{ {
RtlEnterHeapLock(Heap->LockVariable); RtlEnterHeapLock(Heap->LockVariable, TRUE);
HeapLocked = TRUE; HeapLocked = TRUE;
/* Add no serialize flag so that the main routine won't try to acquire the lock again */ /* Add no serialize flag so that the main routine won't try to acquire the lock again */

View file

@ -86,19 +86,19 @@ RtlpCaptureStackLimits(
NTSTATUS NTSTATUS
NTAPI NTAPI
RtlDeleteHeapLock(PHEAP_LOCK Lock); RtlDeleteHeapLock(IN OUT PHEAP_LOCK Lock);
NTSTATUS NTSTATUS
NTAPI NTAPI
RtlEnterHeapLock(PHEAP_LOCK Lock); RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive);
NTSTATUS NTSTATUS
NTAPI NTAPI
RtlInitializeHeapLock(PHEAP_LOCK Lock); RtlInitializeHeapLock(IN OUT PHEAP_LOCK *Lock);
NTSTATUS NTSTATUS
NTAPI NTAPI
RtlLeaveHeapLock(PHEAP_LOCK Lock); RtlLeaveHeapLock(IN OUT PHEAP_LOCK Lock);
BOOLEAN BOOLEAN
NTAPI NTAPI

View file

@ -156,41 +156,49 @@ RtlGetCurrentPeb(VOID)
NTSTATUS NTSTATUS
NTAPI NTAPI
RtlDeleteHeapLock( RtlDeleteHeapLock(IN OUT PHEAP_LOCK Lock)
PHEAP_LOCK Lock)
{ {
ExDeleteResource(&Lock->Resource); ExDeleteResourceLite(&Lock->Resource);
ExFreePool(Lock);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
NTSTATUS NTSTATUS
NTAPI NTAPI
RtlEnterHeapLock( RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive)
PHEAP_LOCK Lock)
{ {
KeEnterCriticalRegion(); KeEnterCriticalRegion();
ExAcquireResourceExclusive(&Lock->Resource, TRUE);
KeLeaveCriticalRegion(); if (Exclusive)
ExAcquireResourceExclusiveLite(&Lock->Resource, TRUE);
else
ExAcquireResourceSharedLite(&Lock->Resource, TRUE);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
NTSTATUS NTSTATUS
NTAPI NTAPI
RtlInitializeHeapLock( RtlInitializeHeapLock(IN OUT PHEAP_LOCK *Lock)
PHEAP_LOCK Lock)
{ {
ExInitializeResource(&Lock->Resource); PHEAP_LOCK HeapLock = ExAllocatePool(NonPagedPool, sizeof(HEAP_LOCK));
if (HeapLock == NULL)
return STATUS_NO_MEMORY;
ExInitializeResourceLite(&HeapLock->Resource);
*Lock = HeapLock;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
NTSTATUS NTSTATUS
NTAPI NTAPI
RtlLeaveHeapLock( RtlLeaveHeapLock(IN OUT PHEAP_LOCK Lock)
PHEAP_LOCK Lock)
{ {
KeEnterCriticalRegion(); ExReleaseResourceLite(&Lock->Resource);
ExReleaseResource(&Lock->Resource);
KeLeaveCriticalRegion(); KeLeaveCriticalRegion();
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }