DeallocatePool

This commit is contained in:
ergo720 2018-04-28 01:02:30 +02:00
parent e14b775b7e
commit ab67c61e6d
3 changed files with 112 additions and 10 deletions

View File

@ -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

View File

@ -37,12 +37,7 @@
#include "PoolManager.h"
#include <assert.h>
#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<PPOOL_HEADER>(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<VAddr>(addr), PAGE_SIZE)) {
Lock();
PoolDesc->RunningDeAllocs += 1;
BigPages = g_VMManager.DeallocateSystemMemory(PoolType, reinterpret_cast<VAddr>(addr), 0);
PoolDesc->TotalBigPages -= BigPages;
Unlock();
return;
}
Entry = reinterpret_cast<PPOOL_HEADER>(static_cast<PCHAR>(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<xboxkrnl::PSINGLE_LIST_ENTRY>(Entry));
return;
}
}
Lock();
PoolDesc->RunningDeAllocs += 1;
Combined = false;
NextEntry = reinterpret_cast<PPOOL_HEADER>(reinterpret_cast<PPOOL_BLOCK>(Entry) + Entry->BlockSize);
if (PAGE_END(NextEntry) == false) {
if (NextEntry->PoolType == 0) {
Combined = true;
LIST_ENTRY_REMOVE((reinterpret_cast<xboxkrnl::PLIST_ENTRY>(reinterpret_cast<PCHAR>(NextEntry) + POOL_OVERHEAD)));
Entry->BlockSize += NextEntry->BlockSize;
}
}
if (Entry->PreviousSize != 0) {
NextEntry = reinterpret_cast<PPOOL_HEADER>(reinterpret_cast<PPOOL_BLOCK>(Entry) - Entry->PreviousSize);
if (NextEntry->PoolType == 0) {
Combined = true;
LIST_ENTRY_REMOVE((reinterpret_cast<xboxkrnl::PLIST_ENTRY>(reinterpret_cast<PCHAR>(NextEntry) + POOL_OVERHEAD)));
NextEntry->BlockSize += Entry->BlockSize;
Entry = NextEntry;
}
}
if (CHECK_ALIGNMENT(reinterpret_cast<VAddr>(Entry), PAGE_SIZE) &&
(PAGE_END(reinterpret_cast<PPOOL_BLOCK>(Entry) + Entry->BlockSize) != false)) {
g_VMManager.DeallocateSystemMemory(PoolType, reinterpret_cast<VAddr>(Entry), 0);
PoolDesc->TotalPages -= 1;
}
else {
Entry->PoolType = 0;
Index = Entry->BlockSize;
if (Combined != false) {
NextEntry = reinterpret_cast<PPOOL_HEADER>(reinterpret_cast<PPOOL_BLOCK>(Entry) + Entry->BlockSize);
if (PAGE_END(NextEntry) == false) {
NextEntry->PreviousSize = Entry->BlockSize;
}
LIST_ENTRY_INSERT_TAIL(&PoolDesc->ListHeads[Index - 1], (reinterpret_cast<xboxkrnl::PLIST_ENTRY>(
reinterpret_cast<PCHAR>(Entry) + POOL_OVERHEAD)));
}
else {
LIST_ENTRY_INSERT_HEAD(&PoolDesc->ListHeads[Index - 1], (reinterpret_cast<xboxkrnl::PLIST_ENTRY>(
reinterpret_cast<PCHAR>(Entry) + POOL_OVERHEAD)));
}
}
Unlock();
}
void PoolManager::Lock()
{
EnterCriticalSection(&m_CriticalSection);

View File

@ -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 */