AllocatePool
This commit is contained in:
parent
125bc23d4f
commit
e14b775b7e
|
@ -363,22 +363,24 @@ LIST_ENTRY, *PLIST_ENTRY;
|
|||
#define LIST_ENTRY_ACCESS_RECORD(address, type, field) \
|
||||
((type*)((UCHAR*)(address) - (ULONG)(&((type*)0)->field)))
|
||||
|
||||
#define IS_LIST_EMPTY(ListHead) ((ListHead)->Flink == (ListHead))
|
||||
|
||||
#define LIST_ENTRY_INSERT_HEAD(ListHead, Entry) {\
|
||||
xboxkrnl::PLIST_ENTRY Flink;\
|
||||
Flink = ListHead->Flink;\
|
||||
Flink = (ListHead)->Flink;\
|
||||
(Entry)->Flink = Flink;\
|
||||
(Entry)->Blink = ListHead;\
|
||||
Flink->Blink = Entry;\
|
||||
ListHead->Flink = Entry;\
|
||||
(Entry)->Blink = (ListHead);\
|
||||
(Flink)->Blink = Entry;\
|
||||
(ListHead)->Flink = Entry;\
|
||||
}
|
||||
|
||||
#define LIST_ENTRY_INSERT_TAIL(ListHead, Entry) {\
|
||||
xboxkrnl::PLIST_ENTRY Blink;\
|
||||
Blink = ListHead->Blink;\
|
||||
Blink = (ListHead)->Blink;\
|
||||
(Entry)->Flink = ListHead;\
|
||||
(Entry)->Blink = Blink;\
|
||||
Blink->Flink = Entry;\
|
||||
ListHead->Blink = Entry;\
|
||||
(Blink)->Flink = Entry;\
|
||||
(ListHead)->Blink = Entry;\
|
||||
}
|
||||
|
||||
#define LIST_ENTRY_REMOVE(Entry) {\
|
||||
|
@ -386,14 +388,18 @@ xboxkrnl::PLIST_ENTRY ExFlink;\
|
|||
xboxkrnl::PLIST_ENTRY ExBlink;\
|
||||
ExFlink = (Entry)->Flink;\
|
||||
ExBlink = (Entry)->Blink;\
|
||||
ExFlink->Blink = ExBlink;\
|
||||
ExBlink->Flink = ExFlink;\
|
||||
(ExFlink)->Blink = ExBlink;\
|
||||
(ExBlink)->Flink = ExFlink;\
|
||||
}
|
||||
|
||||
#define LIST_ENTRY_REMOVE_AT_HEAD(ListHead) \
|
||||
(ListHead)->Flink;\
|
||||
LIST_ENTRY_REMOVE((ListHead)->Flink)
|
||||
|
||||
#define REMOVE_HEAD_LIST(ListHead) \
|
||||
(ListHead)->Flink;\
|
||||
{LIST_ENTRY_REMOVE((ListHead)->Flink)}
|
||||
|
||||
// ******************************************************************
|
||||
// * SLIST_ENTRY
|
||||
// ******************************************************************
|
||||
|
|
|
@ -47,12 +47,12 @@ namespace xboxkrnl
|
|||
#include "Logging.h" // For LOG_FUNC()
|
||||
#include "EmuEEPROM.h" // For EmuFindEEPROMInfo, EEPROM, XboxFactoryGameRegion
|
||||
#include "EmuKrnlLogging.h"
|
||||
#include "VMManager.h"
|
||||
#include "PoolManager.h"
|
||||
|
||||
// prevent name collisions
|
||||
namespace NtDll
|
||||
{
|
||||
#include "EmuNtDll.h" // For NtDelayExecution(), etc.
|
||||
#include "EmuNtDll.h" // For NtDelayExecution(), etc.
|
||||
};
|
||||
|
||||
#include "CxbxKrnl.h" // For CxbxKrnlCleanup
|
||||
|
@ -212,11 +212,9 @@ XBSYSAPI EXPORTNUM(15) xboxkrnl::PVOID NTAPI xboxkrnl::ExAllocatePoolWithTag
|
|||
LOG_FUNC_BEGIN
|
||||
LOG_FUNC_ARG(NumberOfBytes)
|
||||
LOG_FUNC_ARG(Tag)
|
||||
LOG_FUNC_END;
|
||||
LOG_FUNC_END;
|
||||
|
||||
PVOID pRet = (xboxkrnl::PVOID)g_VMManager.AllocateZeroed(NumberOfBytes); // Clear, to prevent side-effects on random contents
|
||||
|
||||
LOG_INCOMPLETE(); // TODO : Actually implement ExAllocatePoolWithTag
|
||||
PVOID pRet = g_PoolManager.AllocatePool(NumberOfBytes, Tag);
|
||||
|
||||
RETURN(pRet);
|
||||
}
|
||||
|
@ -245,7 +243,7 @@ XBSYSAPI EXPORTNUM(17) xboxkrnl::VOID NTAPI xboxkrnl::ExFreePool
|
|||
{
|
||||
LOG_FUNC_ONE_ARG(P);
|
||||
|
||||
g_VMManager.Deallocate((VAddr)P);
|
||||
g_PoolManager.DeallocatePool(P);
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
@ -371,8 +369,7 @@ XBSYSAPI EXPORTNUM(23) xboxkrnl::ULONG NTAPI xboxkrnl::ExQueryPoolBlockSize
|
|||
{
|
||||
LOG_FUNC_ONE_ARG(PoolBlock);
|
||||
|
||||
// Not strictly correct, but it will do for now
|
||||
ULONG ret = g_VMManager.QuerySize((VAddr)PoolBlock);
|
||||
ULONG ret = g_PoolManager.QueryPoolSize(PoolBlock);
|
||||
|
||||
RETURN(ret);
|
||||
}
|
||||
|
|
|
@ -199,6 +199,7 @@ typedef enum _PageType
|
|||
#define PAGES_SPANNED_LARGE(Va, Size) ((ULONG)((((VAddr)(Va) & (PAGE_SIZE_LARGE - 1)) + (Size) + (PAGE_SIZE_LARGE - 1)) >> PAGE_SHIFT_LARGE))
|
||||
#define BYTE_OFFSET(Va) ((ULONG)((VAddr)(Va) & (PAGE_SIZE - 1)))
|
||||
#define BYTE_OFFSET_LARGE(Va) ((ULONG)((VAddr)(Va) & (PAGE_SIZE_LARGE - 1)))
|
||||
#define PAGE_END(Va) (((ULONG_PTR)(Va) & (PAGE_SIZE - 1)) == 0)
|
||||
|
||||
|
||||
/* These macros check if the supplied address is inside a known range */
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
// ******************************************************************
|
||||
|
||||
#include "PoolManager.h"
|
||||
#include <assert.h>
|
||||
|
||||
#define LOG_PREFIX "PMEM"
|
||||
|
||||
|
@ -76,6 +77,151 @@ void PoolManager::InitializePool()
|
|||
printf(LOG_PREFIX " Pool manager initialized!\n");
|
||||
}
|
||||
|
||||
void* PoolManager::AllocatePool(size_t Size, uint32_t Tag)
|
||||
{
|
||||
PVOID Block;
|
||||
PPOOL_HEADER Entry;
|
||||
PPOOL_LOOKASIDE_LIST LookasideList;
|
||||
PPOOL_HEADER NextEntry;
|
||||
PPOOL_HEADER SplitEntry;
|
||||
PPOOL_DESCRIPTOR PoolDesc = &m_NonPagedPoolDescriptor;
|
||||
ULONG Index;
|
||||
ULONG ListNumber;
|
||||
ULONG NeededSize;
|
||||
xboxkrnl::PLIST_ENTRY ListHead;
|
||||
ULONG NumberOfPages;
|
||||
|
||||
assert(Size);
|
||||
|
||||
|
||||
if (Size > POOL_BUDDY_MAX) {
|
||||
Lock();
|
||||
|
||||
PoolDesc->RunningAllocs += 1;
|
||||
Entry = reinterpret_cast<PPOOL_HEADER>(g_VMManager.AllocateSystemMemory(PoolType, XBOX_PAGE_READWRITE, Size, false));
|
||||
|
||||
if (Entry != nullptr) {
|
||||
NumberOfPages = ROUND_UP_4K(Size) >> PAGE_SHIFT;
|
||||
PoolDesc->TotalBigPages += NumberOfPages;
|
||||
Unlock();
|
||||
}
|
||||
else {
|
||||
EmuWarning("AllocatePool returns nullptr");
|
||||
Unlock();
|
||||
}
|
||||
|
||||
return Entry;
|
||||
}
|
||||
|
||||
ListNumber = ((Size + POOL_OVERHEAD + (POOL_SMALLEST_BLOCK - 1)) >> POOL_BLOCK_SHIFT);
|
||||
NeededSize = ListNumber;
|
||||
|
||||
if (NeededSize <= POOL_SMALL_LISTS) {
|
||||
LookasideList = &m_ExpSmallNPagedPoolLookasideLists[NeededSize - 1];
|
||||
LookasideList->TotalAllocates += 1;
|
||||
|
||||
Entry = reinterpret_cast<PPOOL_HEADER>(xboxkrnl::KRNL(InterlockedPopEntrySList(&LookasideList->ListHead)));
|
||||
|
||||
if (Entry != nullptr) {
|
||||
Entry -= 1;
|
||||
LookasideList->AllocateHits += 1;
|
||||
|
||||
Entry->PoolType = static_cast<UCHAR>(1);
|
||||
MARK_POOL_HEADER_ALLOCATED(Entry);
|
||||
|
||||
Entry->PoolTag = Tag;
|
||||
(reinterpret_cast<PULONG>((reinterpret_cast<PCHAR>(Entry) + POOL_OVERHEAD)))[0] = 0;
|
||||
|
||||
return reinterpret_cast<PUCHAR>(Entry) + POOL_OVERHEAD;
|
||||
}
|
||||
}
|
||||
|
||||
Lock();
|
||||
|
||||
PoolDesc->RunningAllocs += 1;
|
||||
ListHead = &PoolDesc->ListHeads[ListNumber];
|
||||
|
||||
do {
|
||||
do {
|
||||
if (IS_LIST_EMPTY(ListHead) == false) {
|
||||
Block = REMOVE_HEAD_LIST(ListHead);
|
||||
Entry = reinterpret_cast<PPOOL_HEADER>((static_cast<PCHAR>(Block) - POOL_OVERHEAD));
|
||||
|
||||
assert(Entry->BlockSize >= NeededSize);
|
||||
assert(Entry->PoolType == 0);
|
||||
|
||||
if (Entry->BlockSize != NeededSize) {
|
||||
if (Entry->PreviousSize == 0) {
|
||||
SplitEntry = reinterpret_cast<PPOOL_HEADER>((reinterpret_cast<PPOOL_BLOCK>(Entry) + NeededSize));
|
||||
SplitEntry->BlockSize = Entry->BlockSize - static_cast<UCHAR>(NeededSize);
|
||||
SplitEntry->PreviousSize = static_cast<UCHAR>(NeededSize);
|
||||
|
||||
NextEntry = reinterpret_cast<PPOOL_HEADER>((reinterpret_cast<PPOOL_BLOCK>(SplitEntry) + SplitEntry->BlockSize));
|
||||
if (PAGE_END(NextEntry) == false) {
|
||||
NextEntry->PreviousSize = SplitEntry->BlockSize;
|
||||
}
|
||||
}
|
||||
else {
|
||||
SplitEntry = Entry;
|
||||
Entry->BlockSize -= static_cast<UCHAR>(NeededSize);
|
||||
Entry = reinterpret_cast<PPOOL_HEADER>(reinterpret_cast<PPOOL_BLOCK>(Entry) + Entry->BlockSize);
|
||||
Entry->PreviousSize = SplitEntry->BlockSize;
|
||||
|
||||
NextEntry = reinterpret_cast<PPOOL_HEADER>(reinterpret_cast<PPOOL_BLOCK>(Entry) + NeededSize);
|
||||
if (PAGE_END(NextEntry) == false) {
|
||||
NextEntry->PreviousSize = static_cast<UCHAR>(NeededSize);
|
||||
}
|
||||
}
|
||||
Entry->BlockSize = static_cast<UCHAR>(NeededSize);
|
||||
SplitEntry->PoolType = 0;
|
||||
Index = SplitEntry->BlockSize;
|
||||
|
||||
LIST_ENTRY_INSERT_TAIL(&PoolDesc->ListHeads[Index - 1], (reinterpret_cast<xboxkrnl::PLIST_ENTRY>((reinterpret_cast<PCHAR>(SplitEntry)
|
||||
+ POOL_OVERHEAD))));
|
||||
}
|
||||
|
||||
Entry->PoolType = static_cast<UCHAR>(1);
|
||||
|
||||
MARK_POOL_HEADER_ALLOCATED(Entry);
|
||||
|
||||
Unlock();
|
||||
|
||||
Entry->PoolTag = Tag;
|
||||
(reinterpret_cast<PULONGLONG>((reinterpret_cast<PCHAR>(Entry) + POOL_OVERHEAD)))[0] = 0;
|
||||
|
||||
return reinterpret_cast<PCHAR>(Entry) + POOL_OVERHEAD;
|
||||
}
|
||||
ListHead += 1;
|
||||
|
||||
} while (ListHead != &PoolDesc->ListHeads[POOL_LIST_HEADS]);
|
||||
|
||||
Entry = reinterpret_cast<PPOOL_HEADER>(g_VMManager.AllocateSystemMemory(PoolType, XBOX_PAGE_READWRITE, PAGE_SIZE, false));
|
||||
|
||||
if (Entry == nullptr) {
|
||||
EmuWarning("AllocatePool returns nullptr");
|
||||
Unlock();
|
||||
|
||||
return Entry;
|
||||
}
|
||||
PoolDesc->TotalPages += 1;
|
||||
Entry->PoolType = 0;
|
||||
|
||||
if ((PAGE_SIZE / POOL_SMALLEST_BLOCK) > 255) {
|
||||
Entry->BlockSize = 255;
|
||||
|
||||
}
|
||||
else {
|
||||
Entry->BlockSize = static_cast<UCHAR>((PAGE_SIZE / POOL_SMALLEST_BLOCK));
|
||||
}
|
||||
|
||||
Entry->PreviousSize = 0;
|
||||
ListHead = &PoolDesc->ListHeads[POOL_LIST_HEADS - 1];
|
||||
|
||||
LIST_ENTRY_INSERT_HEAD(ListHead, (reinterpret_cast<xboxkrnl::PLIST_ENTRY>((reinterpret_cast<UCHAR>(Entry) + POOL_OVERHEAD))));
|
||||
|
||||
} while (true);
|
||||
}
|
||||
|
||||
void PoolManager::Lock()
|
||||
{
|
||||
EnterCriticalSection(&m_CriticalSection);
|
||||
|
|
|
@ -53,6 +53,7 @@ typedef struct _POOL_DESCRIPTOR {
|
|||
xboxkrnl::LIST_ENTRY ListHeads[POOL_LIST_HEADS];
|
||||
} POOL_DESCRIPTOR, *PPOOL_DESCRIPTOR;
|
||||
|
||||
|
||||
typedef struct _POOL_LOOKASIDE_LIST {
|
||||
xboxkrnl::SLIST_HEADER ListHead;
|
||||
USHORT Depth;
|
||||
|
@ -62,6 +63,32 @@ typedef struct _POOL_LOOKASIDE_LIST {
|
|||
} POOL_LOOKASIDE_LIST, *PPOOL_LOOKASIDE_LIST;
|
||||
|
||||
|
||||
typedef struct _POOL_HEADER {
|
||||
union {
|
||||
struct {
|
||||
UCHAR PreviousSize;
|
||||
UCHAR PoolIndex;
|
||||
UCHAR PoolType;
|
||||
UCHAR BlockSize;
|
||||
};
|
||||
ULONG Ulong1;
|
||||
};
|
||||
ULONG PoolTag;
|
||||
} POOL_HEADER, *PPOOL_HEADER;
|
||||
|
||||
|
||||
typedef struct _POOL_BLOCK {
|
||||
UCHAR Fill[1 << POOL_BLOCK_SHIFT];
|
||||
} POOL_BLOCK, *PPOOL_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 ))
|
||||
|
||||
|
||||
/* PoolManager class */
|
||||
class PoolManager
|
||||
{
|
||||
public:
|
||||
|
@ -71,6 +98,13 @@ class PoolManager
|
|||
~PoolManager() { DeleteCriticalSection(&m_CriticalSection); }
|
||||
// initializes the pool manager to the default configuration
|
||||
void InitializePool();
|
||||
// allocates pool memory
|
||||
void* AllocatePool(size_t Size, uint32_t Tag);
|
||||
// deallocates pool memory
|
||||
void DeallocatePool(void* addr);
|
||||
// queries the pool block size
|
||||
size_t QueryPoolSize(void* addr);
|
||||
|
||||
|
||||
private:
|
||||
// main (and only) pool type available on the Xbox
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
|
||||
#define LOG_PREFIX "VMEM"
|
||||
|
||||
#include "VMManager.h"
|
||||
#include "PoolManager.h"
|
||||
#include "Logging.h"
|
||||
#include "EmuShared.h"
|
||||
|
|
Loading…
Reference in New Issue