mirror of
https://github.com/reactos/reactos.git
synced 2024-09-10 12:54:51 +00:00
350 lines
11 KiB
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;
|
|
}
|