From 2e6e9dd622e69cc490c5cb4e776f37a683aa6c68 Mon Sep 17 00:00:00 2001 From: Roel Messiant Date: Mon, 19 Sep 2011 16:52:37 +0000 Subject: [PATCH] [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 --- reactos/dll/ntdll/rtl/libsupp.c | 16 +- reactos/lib/rtl/heap.c | 365 +++++++++++++++----------------- reactos/lib/rtl/heap.h | 2 +- reactos/lib/rtl/heapdbg.c | 14 +- reactos/lib/rtl/rtlp.h | 8 +- reactos/ntoskrnl/rtl/libsupp.c | 36 ++-- 6 files changed, 214 insertions(+), 227 deletions(-) diff --git a/reactos/dll/ntdll/rtl/libsupp.c b/reactos/dll/ntdll/rtl/libsupp.c index f3e685c10af..5ca2f4899d2 100644 --- a/reactos/dll/ntdll/rtl/libsupp.c +++ b/reactos/dll/ntdll/rtl/libsupp.c @@ -112,32 +112,30 @@ RtlGetNtGlobalFlags(VOID) NTSTATUS NTAPI -RtlDeleteHeapLock( - PHEAP_LOCK Lock) +RtlDeleteHeapLock(IN OUT PHEAP_LOCK Lock) { return RtlDeleteCriticalSection(&Lock->CriticalSection); } NTSTATUS NTAPI -RtlEnterHeapLock( - PHEAP_LOCK Lock) +RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive) { + UNREFERENCED_PARAMETER(Exclusive); + return RtlEnterCriticalSection(&Lock->CriticalSection); } NTSTATUS NTAPI -RtlInitializeHeapLock( - PHEAP_LOCK Lock) +RtlInitializeHeapLock(IN OUT PHEAP_LOCK *Lock) { - return RtlInitializeCriticalSection(&Lock->CriticalSection); + return RtlInitializeCriticalSection(&(*Lock)->CriticalSection); } NTSTATUS NTAPI -RtlLeaveHeapLock( - PHEAP_LOCK Lock) +RtlLeaveHeapLock(IN OUT PHEAP_LOCK Lock) { return RtlLeaveCriticalSection(&Lock->CriticalSection); } diff --git a/reactos/lib/rtl/heap.c b/reactos/lib/rtl/heap.c index 00f63ec3c64..56b815e3bc9 100644 --- a/reactos/lib/rtl/heap.c +++ b/reactos/lib/rtl/heap.c @@ -23,7 +23,7 @@ #define NDEBUG #include -HEAP_LOCK RtlpProcessHeapsListLock; +RTL_CRITICAL_SECTION RtlpProcessHeapsListLock; /* Bitmaps stuff */ @@ -82,44 +82,58 @@ UCHAR FillPattern[HEAP_ENTRY_SIZE] = /* FUNCTIONS *****************************************************************/ -VOID NTAPI -RtlpInitializeHeap(PHEAP Heap, - PULONG HeaderSize, - ULONG Flags, - BOOLEAN AllocateLock, - PVOID Lock) +NTSTATUS NTAPI +RtlpInitializeHeap(OUT PHEAP Heap, + IN ULONG Flags, + IN PHEAP_LOCK Lock OPTIONAL, + IN PRTL_HEAP_PARAMETERS Parameters) { - PVOID NextHeapBase = Heap + 1; - PHEAP_UCR_DESCRIPTOR UcrDescriptor; ULONG NumUCRs = 8; - ULONG i; + ULONG Index; + SIZE_T HeaderSize; NTSTATUS Status; + PHEAP_UCR_DESCRIPTOR UcrDescriptor; - /* Add UCRs size */ - *HeaderSize += NumUCRs * sizeof(*UcrDescriptor); + /* Preconditions */ + 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 */ - InitializeListHead(&Heap->UCRList); - InitializeListHead(&Heap->UCRSegments); - UcrDescriptor = NextHeapBase; + /* Start out with the size of a plain Heap header */ + HeaderSize = ROUND_UP(sizeof(HEAP), sizeof(HEAP_ENTRY)); - for (i=0; iUCRList, &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; - // TODO: Add tagging + /* Add space for the initial Heap UnCommitted Range Descriptor list */ + UcrDescriptor = (PHEAP_UCR_DESCRIPTOR) ((ULONG_PTR) (Heap) + HeaderSize); + HeaderSize += ROUND_UP(NumUCRs * sizeof(HEAP_UCR_DESCRIPTOR), sizeof(HEAP_ENTRY)); - /* Round up header size again */ - *HeaderSize = ROUND_UP(*HeaderSize, HEAP_ENTRY_SIZE); + /* Sanity check */ + ASSERT(HeaderSize <= PAGE_SIZE); - ASSERT(*HeaderSize <= PAGE_SIZE); - - /* Initialize heap's header */ - Heap->Entry.Size = (USHORT)((*HeaderSize) >> HEAP_ENTRY_SHIFT); + /* Initialise the Heap Entry header containing the Heap header */ + Heap->Entry.Size = HeaderSize >> HEAP_ENTRY_SHIFT; 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->Flags = Flags; Heap->ForceFlags = (Flags & (HEAP_NO_SERIALIZE | @@ -131,32 +145,64 @@ RtlpInitializeHeap(PHEAP Heap, HEAP_TAIL_CHECKING_ENABLED | HEAP_CREATE_ALIGN_16 | HEAP_FREE_CHECKING_ENABLED)); - Heap->HeaderValidateCopy = NULL; - Heap->HeaderValidateLength = ((PCHAR)NextHeapBase - (PCHAR)Heap); - /* Initialize free lists */ - for (i=0; iVirtualMemoryThreshold = 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); - /* Initialize lock */ - if (AllocateLock) - { - Lock = NextHeapBase; - Status = RtlInitializeHeapLock((PHEAP_LOCK)Lock); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Initializing the lock failed!\n"); - return /*NULL*/; // FIXME! - } - } + /* Initialise the Heap UnCommitted Region lists */ + InitializeListHead(&Heap->UCRSegments); + InitializeListHead(&Heap->UCRList); - /* Set the lock variable */ - Heap->LockVariable = Lock; + /* Register the initial Heap UnCommitted Region Descriptors */ + for (Index = 0; Index < NumUCRs; ++Index) + InsertTailList(&Heap->UCRList, &UcrDescriptor[Index].ListEntry); + + return STATUS_SUCCESS; } VOID FORCEINLINE @@ -821,92 +867,76 @@ RtlpDeCommitFreeBlock(PHEAP Heap, } BOOLEAN NTAPI -RtlpInitializeHeapSegment(PHEAP Heap, - PHEAP_SEGMENT Segment, - UCHAR SegmentIndex, - ULONG Flags, - PVOID BaseAddress, - PVOID UncommittedBase, - PVOID LimitAddress) +RtlpInitializeHeapSegment(IN OUT PHEAP Heap, + OUT PHEAP_SEGMENT Segment, + IN UCHAR SegmentIndex, + IN ULONG SegmentFlags, + IN SIZE_T SegmentReserve, + IN SIZE_T SegmentCommit) { - ULONG Pages, CommitSize; 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); - DPRINT("Pages %x, HeapEntry %p, sizeof(HEAP_SEGMENT) %x\n", Pages, HeapEntry, sizeof(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) + /* Initialise the Heap Entry header if this is not the first Heap Segment */ + if ((PHEAP_SEGMENT) (Heap) != Segment) { - /* Check if it goes beyond the limit */ - if ((PVOID)(HeapEntry + 1) >= LimitAddress) - return FALSE; - - /* Need to commit memory */ - CommitSize = (PCHAR)(HeapEntry + 1) - (PCHAR)UncommittedBase; - 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); + Segment->Entry.Size = ROUND_UP(sizeof(HEAP_SEGMENT), sizeof(HEAP_ENTRY)) >> HEAP_ENTRY_SHIFT; + Segment->Entry.Flags = HEAP_ENTRY_BUSY; + Segment->Entry.SmallTagIndex = LOBYTE(Segment->Entry.Size) ^ HIBYTE(Segment->Entry.Size) ^ Segment->Entry.Flags; + Segment->Entry.PreviousSize = 0; + Segment->Entry.SegmentOffset = SegmentIndex; + Segment->Entry.UnusedBytes = 0; } - /* Initialize the segment entry */ - Segment->Entry.PreviousSize = PreviousSize; - Segment->Entry.Size = NewSize; - Segment->Entry.Flags = HEAP_ENTRY_BUSY; - Segment->Entry.SegmentOffset = SegmentIndex; + /* Sanity check */ + ASSERT((Segment->Entry.Size << HEAP_ENTRY_SHIFT) <= PAGE_SIZE); - /* Initialize the segment itself */ + /* Initialise the Heap Segment header */ Segment->SegmentSignature = HEAP_SEGMENT_SIGNATURE; + Segment->SegmentFlags = SegmentFlags; 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; - /* Prepare a free heap entry */ - HeapEntry->Flags = HEAP_ENTRY_LAST_ENTRY; - HeapEntry->PreviousSize = Segment->Entry.Size; - HeapEntry->SegmentOffset = SegmentIndex; + /* Initialise the Heap Segment location information */ + Segment->BaseAddress = Segment; + Segment->NumberOfPages = SegmentReserve >> PAGE_SHIFT; - /* Insert it */ - RtlpInsertFreeBlock(Heap, (PHEAP_FREE_ENTRY)HeapEntry, (PHEAP_ENTRY)UncommittedBase - HeapEntry); + /* Initialise the Heap Entries contained within the Heap Segment */ + 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 @@ -944,7 +974,7 @@ RtlpAddHeapToProcessList(PHEAP Heap) Peb = RtlGetCurrentPeb(); /* Acquire the lock */ - RtlEnterHeapLock(&RtlpProcessHeapsListLock); + RtlEnterCriticalSection(&RtlpProcessHeapsListLock); //_SEH2_TRY { /* Check if max number of heaps reached */ @@ -961,7 +991,7 @@ RtlpAddHeapToProcessList(PHEAP Heap) // } _SEH2_FINALLY { /* Release the lock */ - RtlLeaveHeapLock(&RtlpProcessHeapsListLock); + RtlLeaveCriticalSection(&RtlpProcessHeapsListLock); // } _SEH2_END } @@ -978,7 +1008,7 @@ RtlpRemoveHeapFromProcessList(PHEAP Heap) Peb = RtlGetCurrentPeb(); /* Acquire the lock */ - RtlEnterHeapLock(&RtlpProcessHeapsListLock); + RtlEnterCriticalSection(&RtlpProcessHeapsListLock); /* Check if we don't need anything to do */ if ((Heap->ProcessHeapsListIndex == 0) || @@ -986,7 +1016,7 @@ RtlpRemoveHeapFromProcessList(PHEAP Heap) (Peb->NumberOfHeaps == 0)) { /* Release the lock */ - RtlLeaveHeapLock(&RtlpProcessHeapsListLock); + RtlLeaveCriticalSection(&RtlpProcessHeapsListLock); return; } @@ -1023,7 +1053,7 @@ RtlpRemoveHeapFromProcessList(PHEAP Heap) Heap->ProcessHeapsListIndex = 0; /* Release the lock */ - RtlLeaveHeapLock(&RtlpProcessHeapsListLock); + RtlLeaveCriticalSection(&RtlpProcessHeapsListLock); } PHEAP_FREE_ENTRY NTAPI @@ -1228,13 +1258,7 @@ RtlpExtendHeap(PHEAP Heap, /* Initialize heap segment if commit was successful */ if (NT_SUCCESS(Status)) - { - if (!RtlpInitializeHeapSegment(Heap, Segment, EmptyIndex, 0, Segment, - (PCHAR)Segment + CommitSize, (PCHAR)Segment + ReserveSize)) - { - Status = STATUS_NO_MEMORY; - } - } + Status = RtlpInitializeHeapSegment(Heap, Segment, EmptyIndex, 0, ReserveSize, CommitSize); /* If everything worked - cool */ if (NT_SUCCESS(Status)) return (PHEAP_FREE_ENTRY)Segment->FirstEntry; @@ -1298,8 +1322,7 @@ RtlCreateHeap(ULONG Flags, ULONG NtGlobalFlags = RtlGetNtGlobalFlags(); ULONG HeapSegmentFlags = 0; NTSTATUS Status; - ULONG MaxBlockSize, HeaderSize; - BOOLEAN AllocateLock = FALSE; + ULONG MaxBlockSize; /* Check for a special heap */ if (RtlpPageHeapEnabled && !Addr && !Lock) @@ -1422,25 +1445,9 @@ RtlCreateHeap(ULONG Flags, if (RtlpHeapIsSpecial(Flags)) return RtlDebugCreateHeap(Flags, Addr, TotalSize, CommitSize, Lock, Parameters); - /* Calculate header size */ - HeaderSize = sizeof(HEAP); - if (!(Flags & HEAP_NO_SERIALIZE)) - { - if (Lock) - { - Flags |= HEAP_LOCK_USER_ALLOCATED; - } - else - { - HeaderSize += sizeof(HEAP_LOCK); - AllocateLock = TRUE; - } - } - else if (Lock) - { - /* Invalid parameters */ + /* Without serialization, a lock makes no sense */ + if ((Flags & HEAP_NO_SERIALIZE) && (Lock != NULL)) return NULL; - } /* See if we are already provided with an address for the heap */ if (Addr) @@ -1583,48 +1590,23 @@ RtlCreateHeap(ULONG Flags, UncommittedAddress = (PCHAR)UncommittedAddress + CommitSize; } - DPRINT("Created heap %p, CommitSize %x, ReserveSize %x\n", Heap, CommitSize, TotalSize); - /* Initialize the heap */ - RtlpInitializeHeap(Heap, &HeaderSize, Flags, AllocateLock, Lock); - - /* Initialize heap's first segment */ - if (!RtlpInitializeHeapSegment(Heap, - (PHEAP_SEGMENT)((PCHAR)Heap + HeaderSize), - 0, - HeapSegmentFlags, - CommittedAddress, - UncommittedAddress, - (PCHAR)CommittedAddress + TotalSize)) + Status = RtlpInitializeHeap(Heap, Flags, Lock, Parameters); + if (!NT_SUCCESS(Status)) { - DPRINT1("Failed to initialize heap segment\n"); + DPRINT1("Failed to initialize heap (%x)\n", Status); return NULL; } - /* Set other data */ - Heap->ProcessHeapsListIndex = 0; - Heap->SegmentCommit = Parameters->SegmentCommit; - 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) + /* Initialize heap's first segment */ + Status = RtlpInitializeHeapSegment(Heap, (PHEAP_SEGMENT) (Heap), 0, HeapSegmentFlags, TotalSize, CommitSize); + if (!NT_SUCCESS(Status)) { - Heap->AlignMask = (ULONG)~15; - Heap->AlignRound = 15 + sizeof(HEAP_ENTRY); - } - else - { - Heap->AlignMask = (ULONG)~(HEAP_ENTRY_SIZE - 1); - Heap->AlignRound = HEAP_ENTRY_SIZE - 1 + sizeof(HEAP_ENTRY); + DPRINT1("Failed to initialize heap segment (%x)\n", Status); + return NULL; } - if (Heap->Flags & HEAP_TAIL_CHECKING_ENABLED) - Heap->AlignRound += HEAP_ENTRY_SIZE; + DPRINT("Created heap %p, CommitSize %x, ReserveSize %x\n", Heap, CommitSize, TotalSize); /* Add heap to process list in case of usermode heap */ if (RtlpGetMode() == UserMode) @@ -1634,7 +1616,6 @@ RtlCreateHeap(ULONG Flags, // FIXME: What about lookasides? } - DPRINT("Heap %p, flags 0x%08x\n", Heap, Heap->Flags); return Heap; } @@ -2063,7 +2044,7 @@ RtlAllocateHeap(IN PVOID HeapPtr, /* Acquire the lock if necessary */ if (!(Flags & HEAP_NO_SERIALIZE)) { - RtlEnterHeapLock(Heap->LockVariable); + RtlEnterHeapLock(Heap->LockVariable, TRUE); HeapLocked = TRUE; } @@ -2265,7 +2246,7 @@ BOOLEAN NTAPI RtlFreeHeap( /* Lock if necessary */ if (!(Flags & HEAP_NO_SERIALIZE)) { - RtlEnterHeapLock(Heap->LockVariable); + RtlEnterHeapLock(Heap->LockVariable, TRUE); Locked = TRUE; } @@ -2690,7 +2671,7 @@ RtlReAllocateHeap(HANDLE HeapPtr, /* Acquire the lock if necessary */ if (!(Flags & HEAP_NO_SERIALIZE)) { - RtlEnterHeapLock(Heap->LockVariable); + RtlEnterHeapLock(Heap->LockVariable, TRUE); HeapLocked = TRUE; Flags &= ~HEAP_NO_SERIALIZE; } @@ -3071,7 +3052,7 @@ RtlLockHeap(IN HANDLE HeapPtr) /* Lock if it's lockable */ if (!(Heap->Flags & HEAP_NO_SERIALIZE)) { - RtlEnterHeapLock(Heap->LockVariable); + RtlEnterHeapLock(Heap->LockVariable, TRUE); } return TRUE; @@ -3651,7 +3632,7 @@ BOOLEAN NTAPI RtlValidateHeap( /* Acquire the lock if necessary */ if (!(Flags & HEAP_NO_SERIALIZE)) { - RtlEnterHeapLock(Heap->LockVariable); + RtlEnterHeapLock(Heap->LockVariable, TRUE); HeapLocked = TRUE; } @@ -3682,7 +3663,7 @@ RtlInitializeHeapManager(VOID) Peb->NumberOfHeaps = 0; /* Initialize the process heaps list protecting lock */ - RtlInitializeHeapLock(&RtlpProcessHeapsListLock); + RtlInitializeCriticalSection(&RtlpProcessHeapsListLock); } @@ -3759,7 +3740,7 @@ RtlSetUserValueHeap(IN PVOID HeapHandle, /* Lock if it's lockable */ if (!(Heap->Flags & HEAP_NO_SERIALIZE)) { - RtlEnterHeapLock(Heap->LockVariable); + RtlEnterHeapLock(Heap->LockVariable, TRUE); HeapLocked = TRUE; } @@ -3818,7 +3799,7 @@ RtlSetUserFlagsHeap(IN PVOID HeapHandle, /* Lock if it's lockable */ if (!(Heap->Flags & HEAP_NO_SERIALIZE)) { - RtlEnterHeapLock(Heap->LockVariable); + RtlEnterHeapLock(Heap->LockVariable, TRUE); HeapLocked = TRUE; } @@ -3874,7 +3855,7 @@ RtlGetUserInfoHeap(IN PVOID HeapHandle, /* Lock if it's lockable */ if (!(Heap->Flags & HEAP_NO_SERIALIZE)) { - RtlEnterHeapLock(Heap->LockVariable); + RtlEnterHeapLock(Heap->LockVariable, TRUE); HeapLocked = TRUE; } diff --git a/reactos/lib/rtl/heap.h b/reactos/lib/rtl/heap.h index ac130eade7d..7c3a58ed2ed 100644 --- a/reactos/lib/rtl/heap.h +++ b/reactos/lib/rtl/heap.h @@ -320,7 +320,7 @@ typedef struct _HEAP_VIRTUAL_ALLOC_ENTRY } HEAP_VIRTUAL_ALLOC_ENTRY, *PHEAP_VIRTUAL_ALLOC_ENTRY; /* Global variables */ -extern HEAP_LOCK RtlpProcessHeapsListLock; +extern RTL_CRITICAL_SECTION RtlpProcessHeapsListLock; extern BOOLEAN RtlpPageHeapEnabled; /* Functions declarations */ diff --git a/reactos/lib/rtl/heapdbg.c b/reactos/lib/rtl/heapdbg.c index 89865227fcc..90672ab98bb 100644 --- a/reactos/lib/rtl/heapdbg.c +++ b/reactos/lib/rtl/heapdbg.c @@ -163,7 +163,7 @@ RtlDebugAllocateHeap(PVOID HeapPtr, /* Lock the heap ourselves */ if (!(Flags & HEAP_NO_SERIALIZE)) { - RtlEnterHeapLock(Heap->LockVariable); + RtlEnterHeapLock(Heap->LockVariable, TRUE); HeapLocked = TRUE; /* 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 */ if (!(Flags & HEAP_NO_SERIALIZE)) { - RtlEnterHeapLock(Heap->LockVariable); + RtlEnterHeapLock(Heap->LockVariable, TRUE); HeapLocked = TRUE; /* 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 */ if (!(Flags & HEAP_NO_SERIALIZE)) { - RtlEnterHeapLock(Heap->LockVariable); + RtlEnterHeapLock(Heap->LockVariable, TRUE); HeapLocked = TRUE; /* 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 */ if (!(Flags & HEAP_NO_SERIALIZE)) { - RtlEnterHeapLock(Heap->LockVariable); + RtlEnterHeapLock(Heap->LockVariable, TRUE); HeapLocked = TRUE; /* 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 */ if (!(Flags & HEAP_NO_SERIALIZE)) { - RtlEnterHeapLock(Heap->LockVariable); + RtlEnterHeapLock(Heap->LockVariable, TRUE); HeapLocked = TRUE; /* 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 */ if (!(Flags & HEAP_NO_SERIALIZE)) { - RtlEnterHeapLock(Heap->LockVariable); + RtlEnterHeapLock(Heap->LockVariable, TRUE); HeapLocked = TRUE; /* 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 */ if (!(Flags & HEAP_NO_SERIALIZE)) { - RtlEnterHeapLock(Heap->LockVariable); + RtlEnterHeapLock(Heap->LockVariable, TRUE); HeapLocked = TRUE; /* Add no serialize flag so that the main routine won't try to acquire the lock again */ diff --git a/reactos/lib/rtl/rtlp.h b/reactos/lib/rtl/rtlp.h index b0cdcd521c1..2953c45dc01 100644 --- a/reactos/lib/rtl/rtlp.h +++ b/reactos/lib/rtl/rtlp.h @@ -86,19 +86,19 @@ RtlpCaptureStackLimits( NTSTATUS NTAPI -RtlDeleteHeapLock(PHEAP_LOCK Lock); +RtlDeleteHeapLock(IN OUT PHEAP_LOCK Lock); NTSTATUS NTAPI -RtlEnterHeapLock(PHEAP_LOCK Lock); +RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive); NTSTATUS NTAPI -RtlInitializeHeapLock(PHEAP_LOCK Lock); +RtlInitializeHeapLock(IN OUT PHEAP_LOCK *Lock); NTSTATUS NTAPI -RtlLeaveHeapLock(PHEAP_LOCK Lock); +RtlLeaveHeapLock(IN OUT PHEAP_LOCK Lock); BOOLEAN NTAPI diff --git a/reactos/ntoskrnl/rtl/libsupp.c b/reactos/ntoskrnl/rtl/libsupp.c index 7171284d61a..e1218047017 100644 --- a/reactos/ntoskrnl/rtl/libsupp.c +++ b/reactos/ntoskrnl/rtl/libsupp.c @@ -156,41 +156,49 @@ RtlGetCurrentPeb(VOID) NTSTATUS NTAPI -RtlDeleteHeapLock( - PHEAP_LOCK Lock) +RtlDeleteHeapLock(IN OUT PHEAP_LOCK Lock) { - ExDeleteResource(&Lock->Resource); + ExDeleteResourceLite(&Lock->Resource); + ExFreePool(Lock); + return STATUS_SUCCESS; } NTSTATUS NTAPI -RtlEnterHeapLock( - PHEAP_LOCK Lock) +RtlEnterHeapLock(IN OUT PHEAP_LOCK Lock, IN BOOLEAN Exclusive) { KeEnterCriticalRegion(); - ExAcquireResourceExclusive(&Lock->Resource, TRUE); - KeLeaveCriticalRegion(); + + if (Exclusive) + ExAcquireResourceExclusiveLite(&Lock->Resource, TRUE); + else + ExAcquireResourceSharedLite(&Lock->Resource, TRUE); + return STATUS_SUCCESS; } NTSTATUS NTAPI -RtlInitializeHeapLock( - PHEAP_LOCK Lock) +RtlInitializeHeapLock(IN OUT 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; } NTSTATUS NTAPI -RtlLeaveHeapLock( - PHEAP_LOCK Lock) +RtlLeaveHeapLock(IN OUT PHEAP_LOCK Lock) { - KeEnterCriticalRegion(); - ExReleaseResource(&Lock->Resource); + ExReleaseResourceLite(&Lock->Resource); KeLeaveCriticalRegion(); + return STATUS_SUCCESS; }