reactos/drivers/sac/driver/memory.c

350 lines
11 KiB
C

/*
* PROJECT: ReactOS Drivers
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: drivers/sac/driver/memory.c
* PURPOSE: Driver for the Server Administration Console (SAC) for EMS
* PROGRAMMERS: ReactOS Portable Systems Group
*/
/* INCLUDES *******************************************************************/
#include "sacdrv.h"
/* GLOBALS ********************************************************************/
LONG TotalFrees, TotalBytesFreed, TotalAllocations, TotalBytesAllocated;
KSPIN_LOCK MemoryLock;
PSAC_MEMORY_LIST GlobalMemoryList;
/* FUNCTIONS ******************************************************************/
BOOLEAN
NTAPI
InitializeMemoryManagement(VOID)
{
PSAC_MEMORY_ENTRY Entry;
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Entering\n");
/* Allocate a nonpaged heap for us to use */
GlobalMemoryList = ExAllocatePoolWithTagPriority(NonPagedPool,
SAC_MEMORY_LIST_SIZE,
INITIAL_BLOCK_TAG,
HighPoolPriority);
if (GlobalMemoryList)
{
/* Initialize a lock for it */
KeInitializeSpinLock(&MemoryLock);
/* Initialize the head of the list */
GlobalMemoryList->Signature = GLOBAL_MEMORY_SIGNATURE;
GlobalMemoryList->LocalDescriptor = (PSAC_MEMORY_ENTRY)(GlobalMemoryList + 1);
GlobalMemoryList->Size = SAC_MEMORY_LIST_SIZE - sizeof(SAC_MEMORY_LIST);
GlobalMemoryList->Next = NULL;
/* Initialize the first free entry */
Entry = GlobalMemoryList->LocalDescriptor;
Entry->Signature = LOCAL_MEMORY_SIGNATURE;
Entry->Tag = FREE_POOL_TAG;
Entry->Size = GlobalMemoryList->Size - sizeof(SAC_MEMORY_ENTRY);
/* All done */
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting with TRUE.\n");
return TRUE;
}
/* No pool available to manage our heap */
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting with FALSE. No pool.\n");
return FALSE;
}
VOID
NTAPI
FreeMemoryManagement(VOID)
{
PSAC_MEMORY_LIST Next;
KIRQL OldIrql;
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Entering\n");
/* Acquire the memory lock while freeing the list(s) */
KeAcquireSpinLock(&MemoryLock, &OldIrql);
while (GlobalMemoryList)
{
ASSERT(GlobalMemoryList->Signature == GLOBAL_MEMORY_SIGNATURE);
/* While outside of the lock, save the next list and free this one */
KeReleaseSpinLock(&MemoryLock, OldIrql);
Next = GlobalMemoryList->Next;
ExFreePoolWithTag(GlobalMemoryList, 0);
/* Reacquire the lock and see if there was another list to free */
KeAcquireSpinLock(&MemoryLock, &OldIrql);
GlobalMemoryList = Next;
}
/* All done */
KeReleaseSpinLock(&MemoryLock, OldIrql);
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting\n");
}
PVOID
NTAPI
MyAllocatePool(IN SIZE_T PoolSize,
IN ULONG Tag,
IN PCHAR File,
IN ULONG Line)
{
PVOID p;
p = ExAllocatePoolWithTag(NonPagedPool, PoolSize, 'HACK');
RtlZeroMemory(p, PoolSize);
SAC_DBG(SAC_DBG_MM, "Returning block 0x%X.\n", p);
return p;
#if 0
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");
/* Acquire the memory allocation lock and align the size request */
KeAcquireSpinLock(&MemoryLock, &OldIrql);
PoolSize = ALIGN_UP(PoolSize, ULONGLONG);
#if _USE_SAC_HEAP_ALLOCATOR_
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(NonPagedPool,
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;
}
}
#else
/* Shut the compiler up */
NewDescriptor = GlobalDescriptor = NULL;
GlobalSize = (ULONG)NewDescriptor;
ActualSize = GlobalSize;
NextDescriptor = (PVOID)ActualSize;
NewDescriptor = (PVOID)NextDescriptor;
/* Use the NT pool allocator */
LocalDescriptor = ExAllocatePoolWithTag(NonPagedPool,
PoolSize + sizeof(*LocalDescriptor),
Tag);
LocalDescriptor->Size = PoolSize;
#endif
/* Set the tag, and release the lock */
LocalDescriptor->Tag = Tag;
KeReleaseSpinLock(&MemoryLock, OldIrql);
/* Update our performance counters */
InterlockedIncrement(&TotalAllocations);
InterlockedExchangeAdd(&TotalBytesAllocated, LocalDescriptor->Size);
/* Return the buffer and zero it */
SAC_DBG(SAC_DBG_MM, "Returning block 0x%X.\n", LocalDescriptor);
Buffer = LocalDescriptor + 1;
RtlZeroMemory(Buffer, PoolSize);
return Buffer;
#endif
}
VOID
NTAPI
MyFreePool(IN PVOID *Block)
{
#if 0
PSAC_MEMORY_ENTRY NextDescriptor;
PSAC_MEMORY_ENTRY ThisDescriptor, FoundDescriptor;
PSAC_MEMORY_ENTRY LocalDescriptor = (PVOID)((ULONG_PTR)(*Block) - sizeof(SAC_MEMORY_ENTRY));
ULONG GlobalSize, LocalSize;
PSAC_MEMORY_LIST GlobalDescriptor;
KIRQL OldIrql;
SAC_DBG(SAC_DBG_MM, "Entering with block 0x%X.\n", LocalDescriptor);
/* Make sure this was a valid entry */
ASSERT(LocalDescriptor->Size > 0);
ASSERT(LocalDescriptor->Signature == LOCAL_MEMORY_SIGNATURE);
/* Update performance counters */
InterlockedIncrement(&TotalFrees);
InterlockedExchangeAdd(&TotalBytesFreed, LocalDescriptor->Size);
/* Acquire the memory allocation lock */
GlobalDescriptor = GlobalMemoryList;
KeAcquireSpinLock(&MemoryLock, &OldIrql);
#if _USE_SAC_HEAP_ALLOCATOR_
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));
}
#else
/* Shut the compiler up */
LocalSize = GlobalSize = 0;
ThisDescriptor = (PVOID)LocalSize;
NextDescriptor = (PVOID)GlobalSize;
GlobalDescriptor = (PVOID)ThisDescriptor;
FoundDescriptor = (PVOID)GlobalDescriptor;
GlobalDescriptor = (PVOID)NextDescriptor;
NextDescriptor = (PVOID)FoundDescriptor;
/* Use the NT pool allocator*/
ExFreePool(LocalDescriptor);
#endif
/* Release the lock, delete the address, and return */
KeReleaseSpinLock(&MemoryLock, OldIrql);
#endif
SAC_DBG(SAC_DBG_MM, "exiting: 0x%p.\n", *Block);
ExFreePoolWithTag(*Block, 'HACK');
*Block = NULL;
}