Author: sir_richard Date: Fri Jun 17 12:54:05 2011 New Revision: 52311
URL: http://svn.reactos.org/svn/reactos?rev=52311&view=rev Log: Patch by Anton Yarotsky: [SACDRV]: Implement memory manager. [SACDRV]: Define debugging macros.
Modified: trunk/reactos/drivers/sac/driver/data.c trunk/reactos/drivers/sac/driver/memory.c trunk/reactos/drivers/sac/driver/sacdrv.h
Modified: trunk/reactos/drivers/sac/driver/data.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/sac/driver/data.c?r... ============================================================================== --- trunk/reactos/drivers/sac/driver/data.c [iso-8859-1] (original) +++ trunk/reactos/drivers/sac/driver/data.c [iso-8859-1] Fri Jun 17 12:54:05 2011 @@ -11,6 +11,8 @@ #include "sacdrv.h"
/* GLOBALS ********************************************************************/ + +ULONG SACDebug;
/* FUNCTIONS ******************************************************************/
Modified: trunk/reactos/drivers/sac/driver/memory.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/sac/driver/memory.c... ============================================================================== --- trunk/reactos/drivers/sac/driver/memory.c [iso-8859-1] (original) +++ trunk/reactos/drivers/sac/driver/memory.c [iso-8859-1] Fri Jun 17 12:54:05 2011 @@ -12,11 +12,43 @@
/* GLOBALS ********************************************************************/
+LONG TotalFrees, TotalBytesFreed, TotalAllocations, TotalBytesAllocated; +KSPIN_LOCK MemoryLock; +PSAC_MEMORY_LIST GlobalMemoryList; + /* FUNCTIONS ******************************************************************/
BOOLEAN InitializeMemoryManagement(VOID) { + PSAC_MEMORY_ENTRY Entry; + + SAC_DBG(SAC_DBG_ENTRY_EXIT, "Entering\n"); + + GlobalMemoryList = ExAllocatePoolWithTagPriority( + NonPagedPool, + SAC_MEMORY_LIST_SIZE, + INITIAL_BLOCK_TAG, + HighPoolPriority); + if (GlobalMemoryList) + { + KeInitializeSpinLock(&MemoryLock); + + GlobalMemoryList->Signature = GLOBAL_MEMORY_SIGNATURE; + GlobalMemoryList->LocalDescriptor = + (PSAC_MEMORY_ENTRY)(GlobalMemoryList + 1); + GlobalMemoryList->Size = SAC_MEMORY_LIST_SIZE - sizeof(SAC_MEMORY_LIST); + + Entry = GlobalMemoryList->LocalDescriptor; + Entry->Signature = LOCAL_MEMORY_SIGNATURE; + Entry->Tag = FREE_POOL_TAG; + Entry->Size = GlobalMemoryList->Size - sizeof(SAC_MEMORY_ENTRY); + + SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting with TRUE.\n"); + return TRUE; + } + + SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting with FALSE. No pool.\n"); return FALSE; }
@@ -25,7 +57,28 @@ VOID ) { - + PSAC_MEMORY_LIST Next; + KIRQL OldIrql; + + SAC_DBG(SAC_DBG_ENTRY_EXIT, "Entering\n"); + + KeAcquireSpinLock(&MemoryLock, &OldIrql); + while (GlobalMemoryList) + { + ASSERT(GlobalMemoryList->Signature == GLOBAL_MEMORY_SIGNATURE); + + KeReleaseSpinLock(&MemoryLock, OldIrql); + + Next = GlobalMemoryList->Next; + + ExFreePoolWithTag(GlobalMemoryList, 0); + + KeAcquireSpinLock(&MemoryLock, &OldIrql); + GlobalMemoryList = Next; + } + + KeReleaseSpinLock(&MemoryLock, OldIrql); + SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting\n"); }
PVOID @@ -36,7 +89,117 @@ IN ULONG Line ) { - return NULL; + KIRQL OldIrql; + PSAC_MEMORY_LIST GlobalDescriptor, NewDescriptor; + PSAC_MEMORY_ENTRY LocalDescriptor, NextDescriptor; + ULONG GlobalSize, ActualSize; + PVOID Buffer; + + ASSERT("Tag != FREE_POOL_TAG"); + + SAC_DBG(SAC_DBG_MM, "Entering.\n"); + + OldIrql = KfAcquireSpinLock(&MemoryLock); + PoolSize = ALIGN_UP(PoolSize, ULONGLONG); + + GlobalDescriptor = GlobalMemoryList; + KeAcquireSpinLock(&MemoryLock, &OldIrql); + while (GlobalDescriptor) + { + ASSERT(GlobalMemoryList->Signature == GLOBAL_MEMORY_SIGNATURE); + + LocalDescriptor = GlobalDescriptor->LocalDescriptor; + + GlobalSize = GlobalDescriptor->Size; + while (GlobalSize) + { + ASSERT(LocalDescriptor->Signature == LOCAL_MEMORY_SIGNATURE); + + if ((LocalDescriptor->Tag == FREE_POOL_TAG) && + (LocalDescriptor->Size >= PoolSize)) + { + break; + } + + GlobalSize -= (LocalDescriptor->Size + sizeof(SAC_MEMORY_ENTRY)); + + LocalDescriptor = + (PSAC_MEMORY_ENTRY)((ULONG_PTR)LocalDescriptor + + LocalDescriptor->Size + + sizeof(SAC_MEMORY_ENTRY)); + } + + GlobalDescriptor = GlobalDescriptor->Next; + } + + if (!GlobalDescriptor) + { + KeReleaseSpinLock(&MemoryLock, OldIrql); + + ActualSize = min( + PAGE_SIZE, + PoolSize + sizeof(SAC_MEMORY_ENTRY) + sizeof(SAC_MEMORY_LIST)); + + SAC_DBG(SAC_DBG_MM, "Allocating new space.\n"); + + NewDescriptor = ExAllocatePoolWithTagPriority( + 0, + ActualSize, + ALLOC_BLOCK_TAG, + HighPoolPriority); + if (!NewDescriptor) + { + SAC_DBG(SAC_DBG_MM, "No more memory, returning NULL.\n"); + return NULL; + } + + KeAcquireSpinLock(&MemoryLock, &OldIrql); + + NewDescriptor->Signature = GLOBAL_MEMORY_SIGNATURE; + NewDescriptor->LocalDescriptor = (PSAC_MEMORY_ENTRY)(NewDescriptor + 1); + NewDescriptor->Size = ActualSize - 16; + NewDescriptor->Next = GlobalMemoryList; + + GlobalMemoryList = NewDescriptor; + + LocalDescriptor = NewDescriptor->LocalDescriptor; + LocalDescriptor->Signature = LOCAL_MEMORY_SIGNATURE; + LocalDescriptor->Tag = FREE_POOL_TAG; + LocalDescriptor->Size = + GlobalMemoryList->Size - sizeof(SAC_MEMORY_ENTRY); + } + + SAC_DBG(SAC_DBG_MM, "Found a good sized block.\n"); + ASSERT(LocalDescriptor->Tag == FREE_POOL_TAG); + ASSERT(LocalDescriptor->Signature == LOCAL_MEMORY_SIGNATURE); + + if (LocalDescriptor->Size > (PoolSize + sizeof(SAC_MEMORY_ENTRY))) + { + NextDescriptor = + (PSAC_MEMORY_ENTRY)((ULONG_PTR)LocalDescriptor + + PoolSize + + sizeof(SAC_MEMORY_ENTRY)); + if (NextDescriptor->Tag == FREE_POOL_TAG) + { + NextDescriptor->Tag = FREE_POOL_TAG; + NextDescriptor->Signature = LOCAL_MEMORY_SIGNATURE; + NextDescriptor->Size = + (LocalDescriptor->Size - PoolSize - sizeof(SAC_MEMORY_ENTRY)); + + LocalDescriptor->Size = PoolSize; + } + } + + LocalDescriptor->Tag = Tag; + KeReleaseSpinLock(&MemoryLock, OldIrql); + + InterlockedIncrement(&TotalAllocations); + InterlockedExchangeAdd(&TotalBytesAllocated, LocalDescriptor->Size); + SAC_DBG(1, "Returning block 0x%X.\n", LocalDescriptor); + + Buffer = LocalDescriptor + 1; + RtlZeroMemory(Buffer, PoolSize); + return Buffer; }
VOID @@ -44,5 +207,100 @@ IN PVOID *Block ) { - + PSAC_MEMORY_ENTRY LocalDescriptor, NextDescriptor; + PSAC_MEMORY_ENTRY ThisDescriptor, FoundDescriptor; + ULONG GlobalSize, LocalSize; + PSAC_MEMORY_LIST GlobalDescriptor; + KIRQL OldIrql; + + LocalDescriptor = (PVOID)((ULONG_PTR)(*Block) - sizeof(SAC_MEMORY_ENTRY)); + + SAC_DBG(SAC_DBG_MM, "Entering with block 0x%X.\n", LocalDescriptor); + + ASSERT(LocalDescriptor->Size > 0); + ASSERT(LocalDescriptor->Signature == LOCAL_MEMORY_SIGNATURE); + + InterlockedIncrement(&TotalFrees); + + InterlockedExchangeAdd(&TotalBytesFreed, LocalDescriptor->Size); + + GlobalDescriptor = GlobalMemoryList; + KeAcquireSpinLock(&MemoryLock, &OldIrql); + while (GlobalDescriptor) + { + ASSERT(GlobalMemoryList->Signature == GLOBAL_MEMORY_SIGNATURE); + + FoundDescriptor = NULL; + + ThisDescriptor = GlobalDescriptor->LocalDescriptor; + + GlobalSize = GlobalDescriptor->Size; + while (GlobalSize) + { + ASSERT(ThisDescriptor->Signature == LOCAL_MEMORY_SIGNATURE); + + if (ThisDescriptor == LocalDescriptor) break; + + GlobalSize -= (ThisDescriptor->Size + sizeof(SAC_MEMORY_ENTRY)); + + ThisDescriptor = + (PSAC_MEMORY_ENTRY)((ULONG_PTR)ThisDescriptor + + ThisDescriptor->Size + + sizeof(SAC_MEMORY_ENTRY)); + } + + if (ThisDescriptor == LocalDescriptor) break; + + GlobalDescriptor = GlobalDescriptor->Next; + } + + if (!GlobalDescriptor) + { + KeReleaseSpinLock(&MemoryLock, OldIrql); + SAC_DBG(SAC_DBG_MM, "Could not find block.\n"); + return; + } + + ASSERT(ThisDescriptor->Signature == LOCAL_MEMORY_SIGNATURE); + + if (LocalDescriptor->Tag == FREE_POOL_TAG) + { + KeReleaseSpinLock(&MemoryLock, OldIrql); + SAC_DBG(SAC_DBG_MM, "Attempted to free something twice.\n"); + return; + } + + LocalSize = LocalDescriptor->Size; + LocalDescriptor->Tag = FREE_POOL_TAG; + + if (GlobalSize > (LocalSize + sizeof(SAC_MEMORY_ENTRY))) + { + NextDescriptor = + (PSAC_MEMORY_ENTRY)((ULONG_PTR)LocalDescriptor + + LocalSize + + sizeof(SAC_MEMORY_ENTRY)); + if (NextDescriptor->Tag == FREE_POOL_TAG) + { + NextDescriptor->Tag = 0; + NextDescriptor->Signature = 0; + + LocalDescriptor->Size += + (NextDescriptor->Size + sizeof(SAC_MEMORY_ENTRY)); + } + } + + if ((FoundDescriptor) && (FoundDescriptor->Tag == FREE_POOL_TAG)) + { + LocalDescriptor->Signature = 0; + LocalDescriptor->Tag = 0; + + FoundDescriptor->Size += + (LocalDescriptor->Size + sizeof(SAC_MEMORY_ENTRY)); + } + + KeReleaseSpinLock(&MemoryLock, OldIrql); + *Block = NULL; + + SAC_DBG(SAC_DBG_MM, "exiting.\n"); + return; }
Modified: trunk/reactos/drivers/sac/driver/sacdrv.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/sac/driver/sacdrv.h... ============================================================================== --- trunk/reactos/drivers/sac/driver/sacdrv.h [iso-8859-1] (original) +++ trunk/reactos/drivers/sac/driver/sacdrv.h [iso-8859-1] Fri Jun 17 12:54:05 2011 @@ -8,6 +8,46 @@
/* INCLUDES *******************************************************************/ #include <ntddk.h> + +#define SAC_DBG_ENTRY_EXIT 0x01 +#define SAC_DBG_MM 0x1000 + +#define SAC_DBG(x, ...) \ + if (SACDebug & x) \ + { \ + DbgPrint("SAC %s: ", __FUNCTION__); \ + DbgPrint(__VA_ARGS__); \ + } + +//Rcp? - sacdrv.sys - SAC Driver (Headless) +//RcpA - sacdrv.sys - Internal memory mgr alloc block +//RcpI - sacdrv.sys - Internal memory mgr initial heap block +//RcpS - sacdrv.sys - Security related block +#define GENERIC_TAG '?pcR' +#define ALLOC_BLOCK_TAG 'ApcR' +#define INITIAL_BLOCK_TAG 'IpcR' +#define SECURITY_BLOCK_TAG 'SpcR' +#define FREE_POOL_TAG 'FpcR' + +#define LOCAL_MEMORY_SIGNATURE 'SSEL' +#define GLOBAL_MEMORY_SIGNATURE 'DAEH' + +#define SAC_MEMORY_LIST_SIZE (1 * 1024 * 1024) + +typedef struct _SAC_MEMORY_ENTRY +{ + ULONG Signature; + ULONG Tag; + ULONG Size; +} SAC_MEMORY_ENTRY, *PSAC_MEMORY_ENTRY; + +typedef struct _SAC_MEMORY_LIST +{ + ULONG Signature; + PSAC_MEMORY_ENTRY LocalDescriptor; + ULONG Size; + struct _SAC_MEMORY_LIST* Next; +} SAC_MEMORY_LIST, *PSAC_MEMORY_LIST;
typedef enum _SAC_CHANNEL_TYPE { @@ -116,3 +156,6 @@ PKEVENT RedrawEvent; GUID ChannelId; } SAC_CHANNEL_ATTRIBUTES, *PSAC_CHANNEL_ATTRIBUTES; + +extern ULONG SACDebug; +