From ab67c61e6d6a8e964279196b9c5c048098f74cd9 Mon Sep 17 00:00:00 2001 From: ergo720 Date: Sat, 28 Apr 2018 01:02:30 +0200 Subject: [PATCH] DeallocatePool --- import/OpenXDK/include/xboxkrnl/xboxkrnl.h | 2 + src/CxbxKrnl/PoolManager.cpp | 113 +++++++++++++++++++-- src/CxbxKrnl/PoolManager.h | 7 +- 3 files changed, 112 insertions(+), 10 deletions(-) diff --git a/import/OpenXDK/include/xboxkrnl/xboxkrnl.h b/import/OpenXDK/include/xboxkrnl/xboxkrnl.h index 00a16b531..10f445931 100644 --- a/import/OpenXDK/include/xboxkrnl/xboxkrnl.h +++ b/import/OpenXDK/include/xboxkrnl/xboxkrnl.h @@ -416,6 +416,8 @@ typedef union _SLIST_HEADER { }; } SLIST_HEADER, *PSLIST_HEADER; +#define QUERY_DEPTH_SLIST(_listhead_) (USHORT)(_listhead_)->Depth + /* * Disabled as Cxbx-Reloaded does not support Win64 compilation * Win64 is not possible while using direct code execution, unless we add diff --git a/src/CxbxKrnl/PoolManager.cpp b/src/CxbxKrnl/PoolManager.cpp index 173f7e5a8..42d8f76e8 100644 --- a/src/CxbxKrnl/PoolManager.cpp +++ b/src/CxbxKrnl/PoolManager.cpp @@ -37,12 +37,7 @@ #include "PoolManager.h" #include -#define LOG_PREFIX "PMEM" - - -#define MARK_POOL_HEADER_ALLOCATED(POOLHEADER) {(POOLHEADER)->PoolIndex = 0x80;} -#define MARK_POOL_HEADER_FREED(POOLHEADER) {(POOLHEADER)->PoolIndex = 0;} -#define IS_POOL_HEADER_MARKED_ALLOCATED(POOLHEADER) ((POOLHEADER)->PoolIndex == 0x80) +#define LOG_PREFIX "POOLMEM" PoolManager g_PoolManager; @@ -106,7 +101,7 @@ void* PoolManager::AllocatePool(size_t Size, uint32_t Tag) Unlock(); } else { - EmuWarning("AllocatePool returns nullptr"); + EmuWarning(LOG_PREFIX " AllocatePool returns nullptr"); Unlock(); } @@ -198,7 +193,7 @@ void* PoolManager::AllocatePool(size_t Size, uint32_t Tag) Entry = reinterpret_cast(g_VMManager.AllocateSystemMemory(PoolType, XBOX_PAGE_READWRITE, PAGE_SIZE, false)); if (Entry == nullptr) { - EmuWarning("AllocatePool returns nullptr"); + EmuWarning(LOG_PREFIX " AllocatePool returns nullptr"); Unlock(); return Entry; @@ -222,6 +217,108 @@ void* PoolManager::AllocatePool(size_t Size, uint32_t Tag) } while (true); } +void PoolManager::DeallocatePool(void* addr) +{ + PPOOL_HEADER Entry; + ULONG Index; + PPOOL_LOOKASIDE_LIST LookasideList; + PPOOL_HEADER NextEntry; + PPOOL_DESCRIPTOR PoolDesc = &m_NonPagedPoolDescriptor; + bool Combined; + ULONG BigPages; + ULONG Tag; + + if (CHECK_ALIGNMENT(reinterpret_cast(addr), PAGE_SIZE)) { + Lock(); + + PoolDesc->RunningDeAllocs += 1; + + BigPages = g_VMManager.DeallocateSystemMemory(PoolType, reinterpret_cast(addr), 0); + + PoolDesc->TotalBigPages -= BigPages; + + Unlock(); + + return; + } + + Entry = reinterpret_cast(static_cast(addr) - POOL_OVERHEAD); + + assert((Entry->PoolType & POOL_TYPE_MASK) != 0); + + if (!IS_POOL_HEADER_MARKED_ALLOCATED(Entry)) { + CxbxKrnlCleanup("Pool at address 0x%X is already free!", addr); + } + + MARK_POOL_HEADER_FREED(Entry); + + assert(Entry->PoolType); + + Index = Entry->BlockSize; + + if (Index <= POOL_SMALL_LISTS) { + LookasideList = &m_ExpSmallNPagedPoolLookasideLists[Index - 1]; + + if (QUERY_DEPTH_SLIST(&LookasideList->ListHead) < LookasideList->Depth) { + Entry += 1; + xboxkrnl::KRNL(InterlockedPushEntrySList)(&LookasideList->ListHead, reinterpret_cast(Entry)); + + return; + } + } + + Lock(); + + PoolDesc->RunningDeAllocs += 1; + + Combined = false; + NextEntry = reinterpret_cast(reinterpret_cast(Entry) + Entry->BlockSize); + if (PAGE_END(NextEntry) == false) { + if (NextEntry->PoolType == 0) { + Combined = true; + LIST_ENTRY_REMOVE((reinterpret_cast(reinterpret_cast(NextEntry) + POOL_OVERHEAD))); + Entry->BlockSize += NextEntry->BlockSize; + } + } + + if (Entry->PreviousSize != 0) { + NextEntry = reinterpret_cast(reinterpret_cast(Entry) - Entry->PreviousSize); + if (NextEntry->PoolType == 0) { + Combined = true; + LIST_ENTRY_REMOVE((reinterpret_cast(reinterpret_cast(NextEntry) + POOL_OVERHEAD))); + NextEntry->BlockSize += Entry->BlockSize; + Entry = NextEntry; + } + } + + if (CHECK_ALIGNMENT(reinterpret_cast(Entry), PAGE_SIZE) && + (PAGE_END(reinterpret_cast(Entry) + Entry->BlockSize) != false)) { + + g_VMManager.DeallocateSystemMemory(PoolType, reinterpret_cast(Entry), 0); + + PoolDesc->TotalPages -= 1; + } + else { + Entry->PoolType = 0; + Index = Entry->BlockSize; + + if (Combined != false) { + NextEntry = reinterpret_cast(reinterpret_cast(Entry) + Entry->BlockSize); + if (PAGE_END(NextEntry) == false) { + NextEntry->PreviousSize = Entry->BlockSize; + } + LIST_ENTRY_INSERT_TAIL(&PoolDesc->ListHeads[Index - 1], (reinterpret_cast( + reinterpret_cast(Entry) + POOL_OVERHEAD))); + } + else { + LIST_ENTRY_INSERT_HEAD(&PoolDesc->ListHeads[Index - 1], (reinterpret_cast( + reinterpret_cast(Entry) + POOL_OVERHEAD))); + } + } + + Unlock(); +} + void PoolManager::Lock() { EnterCriticalSection(&m_CriticalSection); diff --git a/src/CxbxKrnl/PoolManager.h b/src/CxbxKrnl/PoolManager.h index dadf62398..f8566caf8 100644 --- a/src/CxbxKrnl/PoolManager.h +++ b/src/CxbxKrnl/PoolManager.h @@ -43,6 +43,7 @@ #define POOL_BLOCK_SHIFT 5 #define POOL_LIST_HEADS (PAGE_SIZE / (1 << POOL_BLOCK_SHIFT)) // 0x80 #define POOL_SMALL_LISTS 8 +#define POOL_TYPE_MASK 3 typedef struct _POOL_DESCRIPTOR { @@ -84,8 +85,10 @@ typedef struct _POOL_BLOCK { #define POOL_OVERHEAD ((LONG)sizeof(POOL_HEADER)) #define POOL_SMALLEST_BLOCK (sizeof(POOL_BLOCK)) -#define POOL_BUDDY_MAX \ - (PAGE_SIZE - (POOL_OVERHEAD + POOL_SMALLEST_BLOCK )) +#define POOL_BUDDY_MAX (PAGE_SIZE - (POOL_OVERHEAD + POOL_SMALLEST_BLOCK )) +#define MARK_POOL_HEADER_ALLOCATED(POOLHEADER) {(POOLHEADER)->PoolIndex = 0x80;} +#define IS_POOL_HEADER_MARKED_ALLOCATED(POOLHEADER) ((POOLHEADER)->PoolIndex == 0x80) +#define MARK_POOL_HEADER_FREED(POOLHEADER) {(POOLHEADER)->PoolIndex = 0;} /* PoolManager class */