diff --git a/arch/i386/hardware.c b/arch/i386/hardware.c
index 2309ec5c540..a43e17d40c8 100644
--- a/arch/i386/hardware.c
+++ b/arch/i386/hardware.c
@@ -581,7 +581,7 @@ DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA ComponentRoot,
(int)DiskCount, (DiskCount == 1) ? "": "s"));
/* Create DiskController */
- DiskComponentData = (PCONFIGURATION_COMPONENT_DATA)MmAllocateMemory(sizeof(CONFIGURATION_COMPONENT_DATA));
+ DiskComponentData = (PCONFIGURATION_COMPONENT_DATA)MmHeapAlloc(sizeof(CONFIGURATION_COMPONENT_DATA));
RtlZeroMemory(DiskComponentData, sizeof(CONFIGURATION_COMPONENT_DATA));
DiskComponent = &DiskComponentData->ComponentEntry;
@@ -634,7 +634,7 @@ DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA ComponentRoot,
}
/* Get harddisk Int13 geometry data */
- Int13Drives = MmAllocateMemory(sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount);
+ Int13Drives = MmHeapAlloc(sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount);
memset(Int13Drives, 0, sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount);
for (i = 0; i < DiskCount; i++)
@@ -744,7 +744,7 @@ DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA ComponentRoot,
DeviceData = (PVOID)((ULONG_PTR)ResourceList + sizeof(CM_PARTIAL_RESOURCE_LIST));
memcpy(DeviceData, (PVOID)Int13Drives, DeviceDataSize);
- MmFreeMemory(Int13Drives);
+ MmHeapFree(Int13Drives);
/* Now fill the 2nd partial resource descriptor */
ResourceDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)((ULONG_PTR)ResourceList +
diff --git a/cache/blocklist.c b/cache/blocklist.c
index a7af67bf7ab..309d02287e1 100644
--- a/cache/blocklist.c
+++ b/cache/blocklist.c
@@ -98,7 +98,7 @@ PCACHE_BLOCK CacheInternalAddBlockToCache(PCACHE_DRIVE CacheDrive, ULONG BlockNu
// We will need to add the block to the
// drive's list of cached blocks. So allocate
// the block memory.
- CacheBlock = MmAllocateMemory(sizeof(CACHE_BLOCK));
+ CacheBlock = MmHeapAlloc(sizeof(CACHE_BLOCK));
if (CacheBlock == NULL)
{
return NULL;
@@ -111,7 +111,7 @@ PCACHE_BLOCK CacheInternalAddBlockToCache(PCACHE_DRIVE CacheDrive, ULONG BlockNu
CacheBlock->BlockData = MmAllocateMemory(CacheDrive->BlockSize * CacheDrive->BytesPerSector);
if (CacheBlock->BlockData ==NULL)
{
- MmFreeMemory(CacheBlock);
+ MmHeapFree(CacheBlock);
return NULL;
}
@@ -119,7 +119,7 @@ PCACHE_BLOCK CacheInternalAddBlockToCache(PCACHE_DRIVE CacheDrive, ULONG BlockNu
if (!MachDiskReadLogicalSectors(CacheDrive->DriveNumber, (BlockNumber * CacheDrive->BlockSize), CacheDrive->BlockSize, (PVOID)DISKREADBUFFER))
{
MmFreeMemory(CacheBlock->BlockData);
- MmFreeMemory(CacheBlock);
+ MmHeapFree(CacheBlock);
return NULL;
}
RtlCopyMemory(CacheBlock->BlockData, (PVOID)DISKREADBUFFER, CacheDrive->BlockSize * CacheDrive->BytesPerSector);
@@ -177,7 +177,7 @@ BOOLEAN CacheInternalFreeBlock(PCACHE_DRIVE CacheDrive)
// Free the block memory and the block structure
MmFreeMemory(CacheBlockToFree->BlockData);
- MmFreeMemory(CacheBlockToFree);
+ MmHeapFree(CacheBlockToFree);
// Update the cache data
CacheBlockCount--;
diff --git a/freeldr_base.rbuild b/freeldr_base.rbuild
index 53e3e0da268..2a7ee7fce7d 100644
--- a/freeldr_base.rbuild
+++ b/freeldr_base.rbuild
@@ -49,6 +49,7 @@
reactos.c
+ bget.c
libsupp.c
list.c
diff --git a/fs/fat.c b/fs/fat.c
index 14cf1d4ab98..bce67191977 100644
--- a/fs/fat.c
+++ b/fs/fat.c
@@ -51,7 +51,7 @@ BOOLEAN FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartSector, ULONG Partitio
//
// Allocate the memory to hold the boot sector
//
- FatVolumeBootSector = (PFAT_BOOTSECTOR) MmAllocateMemory(512);
+ FatVolumeBootSector = (PFAT_BOOTSECTOR) MmHeapAlloc(512);
Fat32VolumeBootSector = (PFAT32_BOOTSECTOR) FatVolumeBootSector;
FatXVolumeBootSector = (PFATX_BOOTSECTOR) FatVolumeBootSector;
@@ -68,7 +68,7 @@ BOOLEAN FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartSector, ULONG Partitio
// If this fails then abort
if (!MachDiskReadLogicalSectors(DriveNumber, VolumeStartSector, 1, (PVOID)DISKREADBUFFER))
{
- MmFreeMemory(FatVolumeBootSector);
+ MmHeapFree(FatVolumeBootSector);
return FALSE;
}
RtlCopyMemory(FatVolumeBootSector, (PVOID)DISKREADBUFFER, 512);
@@ -164,7 +164,7 @@ BOOLEAN FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartSector, ULONG Partitio
sprintf(ErrMsg, "Invalid boot sector magic on drive 0x%x (expected 0xaa55 found 0x%x)",
DriveNumber, FatVolumeBootSector->BootSectorMagic);
FileSystemError(ErrMsg);
- MmFreeMemory(FatVolumeBootSector);
+ MmHeapFree(FatVolumeBootSector);
return FALSE;
}
@@ -176,7 +176,7 @@ BOOLEAN FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartSector, ULONG Partitio
(! ISFATX(FatType) && 64 * 1024 < FatVolumeBootSector->SectorsPerCluster * FatVolumeBootSector->BytesPerSector))
{
FileSystemError("This file system has cluster sizes bigger than 64k.\nFreeLoader does not support this.");
- MmFreeMemory(FatVolumeBootSector);
+ MmHeapFree(FatVolumeBootSector);
return FALSE;
}
@@ -249,8 +249,9 @@ BOOLEAN FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartSector, ULONG Partitio
return FALSE;
}
}
- MmFreeMemory(FatVolumeBootSector);
+ MmHeapFree(FatVolumeBootSector);
+#ifdef CACHE_ENABLED
//
// Initialize the disk cache for this drive
//
@@ -271,6 +272,20 @@ BOOLEAN FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartSector, ULONG Partitio
return FALSE;
}
}
+#else
+ {
+ GEOMETRY DriveGeometry;
+ ULONG BlockSize;
+
+ // Initialize drive by getting its geometry
+ if (!MachDiskGetDriveGeometry(DriveNumber, &DriveGeometry))
+ {
+ return FALSE;
+ }
+
+ BlockSize = MachDiskGetCacheableBlockCount(DriveNumber);
+ }
+#endif
return TRUE;
}
@@ -362,7 +377,7 @@ PVOID FatBufferDirectory(ULONG DirectoryStartCluster, ULONG *DirectorySize, BOOL
// Attempt to allocate memory for directory buffer
//
DbgPrint((DPRINT_FILESYSTEM, "Trying to allocate (DirectorySize) %d bytes.\n", *DirectorySize));
- DirectoryBuffer = MmAllocateMemory(*DirectorySize);
+ DirectoryBuffer = MmHeapAlloc(*DirectorySize);
if (DirectoryBuffer == NULL)
{
@@ -376,7 +391,7 @@ PVOID FatBufferDirectory(ULONG DirectoryStartCluster, ULONG *DirectorySize, BOOL
{
if (!FatReadVolumeSectors(FatDriveNumber, RootDirSectorStart, RootDirSectors, DirectoryBuffer))
{
- MmFreeMemory(DirectoryBuffer);
+ MmHeapFree(DirectoryBuffer);
return NULL;
}
}
@@ -384,7 +399,7 @@ PVOID FatBufferDirectory(ULONG DirectoryStartCluster, ULONG *DirectorySize, BOOL
{
if (!FatReadClusterChain(DirectoryStartCluster, 0xFFFFFFFF, DirectoryBuffer))
{
- MmFreeMemory(DirectoryBuffer);
+ MmHeapFree(DirectoryBuffer);
return NULL;
}
}
@@ -727,7 +742,7 @@ BOOLEAN FatLookupFile(PCSTR FileName, PFAT_FILE_INFO FatFileInfoPointer)
{
if (!FatXSearchDirectoryBufferForFile(DirectoryBuffer, DirectorySize, PathPart, &FatFileInfo))
{
- MmFreeMemory(DirectoryBuffer);
+ MmHeapFree(DirectoryBuffer);
return FALSE;
}
}
@@ -735,12 +750,12 @@ BOOLEAN FatLookupFile(PCSTR FileName, PFAT_FILE_INFO FatFileInfoPointer)
{
if (!FatSearchDirectoryBufferForFile(DirectoryBuffer, DirectorySize, PathPart, &FatFileInfo))
{
- MmFreeMemory(DirectoryBuffer);
+ MmHeapFree(DirectoryBuffer);
return FALSE;
}
}
- MmFreeMemory(DirectoryBuffer);
+ MmHeapFree(DirectoryBuffer);
//
// If we have another sub-directory to go then
@@ -749,7 +764,7 @@ BOOLEAN FatLookupFile(PCSTR FileName, PFAT_FILE_INFO FatFileInfoPointer)
if ((i+1) < NumberOfPathParts)
{
DirectoryStartCluster = FatFileInfo.FileFatChain[0];
- MmFreeMemory(FatFileInfo.FileFatChain);
+ MmHeapFree(FatFileInfo.FileFatChain);
}
}
@@ -914,7 +929,7 @@ FILE* FatOpenFile(PCSTR FileName)
return NULL;
}
- FileHandle = MmAllocateMemory(sizeof(FAT_FILE_INFO));
+ FileHandle = MmHeapAlloc(sizeof(FAT_FILE_INFO));
if (FileHandle == NULL)
{
@@ -978,7 +993,7 @@ ULONG* FatGetClusterChainArray(ULONG StartCluster)
//
// Allocate array memory
//
- ArrayPointer = MmAllocateMemory(ArraySize);
+ ArrayPointer = MmHeapAlloc(ArraySize);
if (ArrayPointer == NULL)
{
@@ -1011,7 +1026,7 @@ ULONG* FatGetClusterChainArray(ULONG StartCluster)
//
if (!FatGetFatEntry(StartCluster, &StartCluster))
{
- MmFreeMemory(ArrayPointer);
+ MmHeapFree(ArrayPointer);
return NULL;
}
}
@@ -1312,5 +1327,19 @@ ULONG FatGetFilePointer(FILE *FileHandle)
BOOLEAN FatReadVolumeSectors(ULONG DriveNumber, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer)
{
+#ifdef CACHE_ENABLED
return CacheReadDiskSectors(DriveNumber, SectorNumber + FatVolumeStartSector, SectorCount, Buffer);
+#else
+ // Now try to read in the block
+ if (!MachDiskReadLogicalSectors(DriveNumber, SectorNumber + FatVolumeStartSector, SectorCount, (PVOID)DISKREADBUFFER))
+ {
+ return FALSE;
+ }
+
+ // Copy data to the caller
+ RtlCopyMemory(Buffer, (PVOID)DISKREADBUFFER, SectorCount * BytesPerSector);
+
+ // Return success
+ return TRUE;
+#endif
}
diff --git a/include/bget.h b/include/bget.h
new file mode 100644
index 00000000000..0c72d0e55b2
--- /dev/null
+++ b/include/bget.h
@@ -0,0 +1,30 @@
+/*
+
+ Interface definitions for bget.c, the memory management package.
+
+*/
+
+#ifndef _
+#ifdef PROTOTYPES
+#define _(x) x /* If compiler knows prototypes */
+#else
+#define _(x) () /* It it doesn't */
+#endif /* PROTOTYPES */
+#endif
+
+typedef long bufsize;
+void bpool _((void *buffer, bufsize len));
+void *bget _((bufsize size));
+void *bgetz _((bufsize size));
+void *bgetr _((void *buffer, bufsize newsize));
+void brel _((void *buf));
+void bectl _((int (*compact)(bufsize sizereq, int sequence),
+ void *(*acquire)(bufsize size),
+ void (*release)(void *buf), bufsize pool_incr));
+void bstats _((bufsize *curalloc, bufsize *totfree, bufsize *maxfree,
+ long *nget, long *nrel));
+void bstatse _((bufsize *pool_incr, long *npool, long *npget,
+ long *nprel, long *ndget, long *ndrel));
+void bufdump _((void *buf));
+void bpoold _((void *pool, int dumpalloc, int dumpfree));
+int bpoolv _((void *pool));
diff --git a/include/freeldr.h b/include/freeldr.h
index 57f307adfe5..bde6b09297f 100644
--- a/include/freeldr.h
+++ b/include/freeldr.h
@@ -74,6 +74,7 @@
#include
#include
#include
+#include
/* Needed by boot manager */
#include
#include
diff --git a/include/mm.h b/include/mm.h
index bdc0bf9e416..a708be10b14 100644
--- a/include/mm.h
+++ b/include/mm.h
@@ -52,6 +52,10 @@ typedef struct
//
#define LOADER_HIGH_ZONE ((16*1024*1024) >> MM_PAGE_SHIFT) //16Mb page
+// HEAP and STACK size
+#define HEAP_PAGES 0x100//0x18
+#define STACK_PAGES 0x00
+
typedef struct
{
TYPE_OF_MEMORY PageAllocated; // Type of allocated memory (LoaderFree if this memory is free)
@@ -97,6 +101,7 @@ PPAGE_LOOKUP_TABLE_ITEM MmGetMemoryMap(ULONG *NoEntries); // Returns a pointer
//BOOLEAN MmInitializeMemoryManager(ULONG LowMemoryStart, ULONG LowMemoryLength);
BOOLEAN MmInitializeMemoryManager(VOID);
+VOID MmInitializeHeap(PVOID PageLookupTable);
PVOID MmAllocateMemory(ULONG MemorySize);
PVOID MmAllocateMemoryWithType(ULONG MemorySize, TYPE_OF_MEMORY MemoryType);
VOID MmFreeMemory(PVOID MemoryPointer);
@@ -106,4 +111,7 @@ VOID MmChangeAllocationPolicy(BOOLEAN PolicyAllocatePagesFromEnd);
PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress, TYPE_OF_MEMORY MemoryType);
PVOID MmAllocateHighestMemoryBelowAddress(ULONG MemorySize, PVOID DesiredAddress, TYPE_OF_MEMORY MemoryType);
+PVOID MmHeapAlloc(ULONG MemorySize);
+VOID MmHeapFree(PVOID MemoryPointer);
+
#endif // defined __MEMORY_H
diff --git a/mm/meminit.c b/mm/meminit.c
index d47ca29f4bb..c4c186315c1 100644
--- a/mm/meminit.c
+++ b/mm/meminit.c
@@ -44,6 +44,9 @@ ULONG TotalPagesInLookupTable = 0;
ULONG FreePagesInLookupTable = 0;
ULONG LastFreePageHint = 0;
+extern ULONG_PTR MmHeapPointer;
+extern ULONG_PTR MmHeapStart;
+
BOOLEAN MmInitializeMemoryManager(VOID)
{
BIOS_MEMORY_MAP BiosMemoryMap[32];
@@ -110,10 +113,42 @@ BOOLEAN MmInitializeMemoryManager(VOID)
FreePagesInLookupTable = MmCountFreePagesInLookupTable(PageLookupTableAddress, TotalPagesInLookupTable);
+ MmInitializeHeap(PageLookupTableAddress);
+
DbgPrint((DPRINT_MEMORY, "Memory Manager initialized. %d pages available.\n", FreePagesInLookupTable));
return TRUE;
}
+VOID MmInitializeHeap(PVOID PageLookupTable)
+{
+ ULONG PagesNeeded;
+ ULONG HeapStart;
+
+ // HACK: Make it so it doesn't overlap kernel space
+ MmMarkPagesInLookupTable(PageLookupTableAddress, 0x100, 0xFF, LoaderSystemCode);
+
+ // Find contigious memory block for HEAP:STACK
+ PagesNeeded = HEAP_PAGES + STACK_PAGES;
+ HeapStart = MmFindAvailablePages(PageLookupTable, TotalPagesInLookupTable, PagesNeeded, FALSE);
+
+ // Unapply the hack
+ MmMarkPagesInLookupTable(PageLookupTableAddress, 0x100, 0xFF, LoaderFree);
+
+ if (HeapStart == 0)
+ {
+ UiMessageBox("Critical error: Can't allocate heap!");
+ return;
+ }
+
+ // Initialize BGET
+ bpool(HeapStart << MM_PAGE_SHIFT, PagesNeeded << MM_PAGE_SHIFT);
+
+ // Mark those pages as used
+ MmMarkPagesInLookupTable(PageLookupTableAddress, HeapStart, PagesNeeded, LoaderOsloaderHeap);
+
+ DbgPrint((DPRINT_MEMORY, "Heap initialized, base 0x%08x, pages %d\n", (HeapStart << MM_PAGE_SHIFT), PagesNeeded));
+}
+
#ifdef DBG
PUCHAR MmGetSystemMemoryMapTypeString(ULONG Type)
{
@@ -295,10 +330,12 @@ VOID MmMarkPagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG Page
for (Index=StartPage; Index<(StartPage+PageCount); Index++)
{
+#if 0
if ((Index <= (StartPage + 16)) || (Index >= (StartPage+PageCount-16)))
{
DbgPrint((DPRINT_MEMORY, "Index = %d StartPage = %d PageCount = %d\n", Index, StartPage, PageCount));
}
+#endif
RealPageLookupTable[Index].PageAllocated = PageAllocated;
RealPageLookupTable[Index].PageAllocationLength = (PageAllocated != LoaderFree) ? 1 : 0;
}
diff --git a/mm/mm.c b/mm/mm.c
index ff95805fa55..1e4045b77b6 100644
--- a/mm/mm.c
+++ b/mm/mm.c
@@ -21,36 +21,11 @@
#include
#include
-ULONG AllocationCount = 0;
-
#ifdef DBG
-VOID VerifyHeap(VOID);
VOID DumpMemoryAllocMap(VOID);
-VOID IncrementAllocationCount(VOID);
-VOID DecrementAllocationCount(VOID);
VOID MemAllocTest(VOID);
#endif // DBG
-/*
- * Hack alert
- * Normally, we allocate whole pages. This is ofcourse wastefull for small
- * allocations (a few bytes). So, for small allocations (smaller than a page)
- * we sub-allocate. When the first small allocation is done, a page is
- * requested. We keep a pointer to that page in SubAllocationPage. The alloc
- * is satisfied by returning a pointer to the beginning of the page. We also
- * keep track of how many bytes are still available in the page in SubAllocationRest.
- * When the next small request comes in, we try to allocate it just after the
- * memory previously allocated. If it won't fit, we allocate a new page and
- * the whole process starts again.
- * Note that suballocations are done back-to-back, there's no bookkeeping at all.
- * That also means that we cannot really free suballocations. So, when a free is
- * done and it is determined that this might be a free of a sub-allocation, we
- * just no-op the free.
- * Perhaps we should use the heap routines from ntdll here.
- */
-static PVOID SubAllocationPage = NULL;
-static unsigned SubAllocationRest = 0;
-
BOOLEAN AllocateFromEnd = TRUE;
VOID MmChangeAllocationPolicy(BOOLEAN PolicyAllocatePagesFromEnd)
@@ -72,12 +47,6 @@ PVOID MmAllocateMemoryWithType(ULONG MemorySize, TYPE_OF_MEMORY MemoryType)
}
MemorySize = ROUND_UP(MemorySize, 4);
- if (MemorySize <= SubAllocationRest)
- {
- MemPointer = (PVOID)((ULONG_PTR)SubAllocationPage + MM_PAGE_SIZE - SubAllocationRest);
- SubAllocationRest -= MemorySize;
- return MemPointer;
- }
// Find out how many blocks it will take to
// satisfy this allocation
@@ -87,7 +56,7 @@ PVOID MmAllocateMemoryWithType(ULONG MemorySize, TYPE_OF_MEMORY MemoryType)
// then return NULL
if (FreePagesInLookupTable < PagesNeeded)
{
- DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateMemory(). Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount));
+ DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateMemory(). Not enough free memory to allocate %d bytes.\n", MemorySize));
UiMessageBoxCritical("Memory allocation failed: out of memory.");
return NULL;
}
@@ -96,7 +65,7 @@ PVOID MmAllocateMemoryWithType(ULONG MemorySize, TYPE_OF_MEMORY MemoryType)
if (FirstFreePageFromEnd == (ULONG)-1)
{
- DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateMemory(). Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount));
+ DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateMemory(). Not enough free memory to allocate %d bytes.\n", MemorySize));
UiMessageBoxCritical("Memory allocation failed: out of memory.");
return NULL;
}
@@ -106,16 +75,8 @@ PVOID MmAllocateMemoryWithType(ULONG MemorySize, TYPE_OF_MEMORY MemoryType)
FreePagesInLookupTable -= PagesNeeded;
MemPointer = (PVOID)(FirstFreePageFromEnd * MM_PAGE_SIZE);
- if (MemorySize < MM_PAGE_SIZE)
- {
- SubAllocationPage = MemPointer;
- SubAllocationRest = MM_PAGE_SIZE - MemorySize;
- }
-
-
#ifdef DBG
- IncrementAllocationCount();
- DbgPrint((DPRINT_MEMORY, "Allocated %d bytes (%d pages) of memory starting at page %d. AllocCount: %d\n", MemorySize, PagesNeeded, FirstFreePageFromEnd, AllocationCount));
+ DbgPrint((DPRINT_MEMORY, "Allocated %d bytes (%d pages) of memory starting at page %d.\n", MemorySize, PagesNeeded, FirstFreePageFromEnd));
DbgPrint((DPRINT_MEMORY, "Memory allocation pointer: 0x%x\n", MemPointer));
//VerifyHeap();
#endif // DBG
@@ -124,10 +85,42 @@ PVOID MmAllocateMemoryWithType(ULONG MemorySize, TYPE_OF_MEMORY MemoryType)
return MemPointer;
}
+PVOID MmHeapAlloc(ULONG MemorySize)
+{
+ PVOID Result;
+ LONG CurAlloc, TotalFree, MaxFree, NumberOfGets, NumberOfRels;
+
+ if (MemorySize > MM_PAGE_SIZE)
+ {
+ DbgPrint((DPRINT_MEMORY, "Consider using other functions to allocate %d bytes of memory!\n", MemorySize));
+ }
+
+ // Get the buffer from BGET pool
+ Result = bget(MemorySize);
+
+ if (Result == NULL)
+ {
+ DbgPrint((DPRINT_MEMORY, "Heap allocation for %d bytes failed\n", MemorySize));
+ }
+
+ // Gather some stats
+ bstats(&CurAlloc, &TotalFree, &MaxFree, &NumberOfGets, &NumberOfRels);
+
+ DbgPrint((DPRINT_MEMORY, "Current alloced %d bytes, free %d bytes, allocs %d, frees %d\n",
+ CurAlloc, TotalFree, NumberOfGets, NumberOfRels));
+
+ return Result;
+}
+
+VOID MmHeapFree(PVOID MemoryPointer)
+{
+ // Release the buffer to the pool
+ brel(MemoryPointer);
+}
PVOID MmAllocateMemory(ULONG MemorySize)
{
- // Allocate it as "heap"
+ // Temporary forwarder...
return MmAllocateMemoryWithType(MemorySize, LoaderOsloaderHeap);
}
@@ -157,7 +150,7 @@ PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress, TYPE_OF_
{
DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateMemoryAtAddress(). "
"Not enough free memory to allocate %d bytes (requesting %d pages but have only %d). "
- "AllocationCount: %d\n", MemorySize, PagesNeeded, FreePagesInLookupTable, AllocationCount));
+ "\n", MemorySize, PagesNeeded, FreePagesInLookupTable));
UiMessageBoxCritical("Memory allocation failed: out of memory.");
return NULL;
}
@@ -165,8 +158,8 @@ PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress, TYPE_OF_
if (MmAreMemoryPagesAvailable(PageLookupTableAddress, TotalPagesInLookupTable, DesiredAddress, PagesNeeded) == FALSE)
{
DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateMemoryAtAddress(). "
- "Not enough free memory to allocate %d bytes at address %p. AllocationCount: %d\n",
- MemorySize, DesiredAddress, AllocationCount));
+ "Not enough free memory to allocate %d bytes at address %p.\n",
+ MemorySize, DesiredAddress));
// Don't tell this to user since caller should try to alloc this memory
// at a different address
@@ -180,8 +173,7 @@ PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress, TYPE_OF_
MemPointer = (PVOID)(StartPageNumber * MM_PAGE_SIZE);
#ifdef DBG
- IncrementAllocationCount();
- DbgPrint((DPRINT_MEMORY, "Allocated %d bytes (%d pages) of memory starting at page %d. AllocCount: %d\n", MemorySize, PagesNeeded, StartPageNumber, AllocationCount));
+ DbgPrint((DPRINT_MEMORY, "Allocated %d bytes (%d pages) of memory starting at page %d.\n", MemorySize, PagesNeeded, StartPageNumber));
DbgPrint((DPRINT_MEMORY, "Memory allocation pointer: 0x%x\n", MemPointer));
//VerifyHeap();
#endif // DBG
@@ -215,7 +207,7 @@ PVOID MmAllocateHighestMemoryBelowAddress(ULONG MemorySize, PVOID DesiredAddress
// then return NULL
if (FreePagesInLookupTable < PagesNeeded)
{
- DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateHighestMemoryBelowAddress(). Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount));
+ DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateHighestMemoryBelowAddress(). Not enough free memory to allocate %d bytes.\n", MemorySize));
UiMessageBoxCritical("Memory allocation failed: out of memory.");
return NULL;
}
@@ -224,7 +216,7 @@ PVOID MmAllocateHighestMemoryBelowAddress(ULONG MemorySize, PVOID DesiredAddress
if (FirstFreePageFromEnd == 0)
{
- DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateHighestMemoryBelowAddress(). Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount));
+ DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateHighestMemoryBelowAddress(). Not enough free memory to allocate %d bytes.\n", MemorySize));
UiMessageBoxCritical("Memory allocation failed: out of memory.");
return NULL;
}
@@ -235,8 +227,7 @@ PVOID MmAllocateHighestMemoryBelowAddress(ULONG MemorySize, PVOID DesiredAddress
MemPointer = (PVOID)(FirstFreePageFromEnd * MM_PAGE_SIZE);
#ifdef DBG
- IncrementAllocationCount();
- DbgPrint((DPRINT_MEMORY, "Allocated %d bytes (%d pages) of memory starting at page %d. AllocCount: %d\n", MemorySize, PagesNeeded, FirstFreePageFromEnd, AllocationCount));
+ DbgPrint((DPRINT_MEMORY, "Allocated %d bytes (%d pages) of memory starting at page %d.\n", MemorySize, PagesNeeded, FirstFreePageFromEnd));
DbgPrint((DPRINT_MEMORY, "Memory allocation pointer: 0x%x\n", MemPointer));
//VerifyHeap();
#endif // DBG
@@ -247,129 +238,9 @@ PVOID MmAllocateHighestMemoryBelowAddress(ULONG MemorySize, PVOID DesiredAddress
VOID MmFreeMemory(PVOID MemoryPointer)
{
- ULONG PageNumber;
- ULONG PageCount;
- ULONG Idx;
- PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTableAddress;
-
-#ifdef DBG
-
- // Make sure we didn't get a bogus pointer
- if (MemoryPointer >= (PVOID)(TotalPagesInLookupTable * MM_PAGE_SIZE))
- {
- BugCheck((DPRINT_MEMORY, "Bogus memory pointer (0x%x) passed to MmFreeMemory()\n", MemoryPointer));
- }
-#endif // DBG
-
- // Find out the page number of the first
- // page of memory they allocated
- PageNumber = MmGetPageNumberFromAddress(MemoryPointer);
- PageCount = RealPageLookupTable[PageNumber].PageAllocationLength;
-
-#ifdef DBG
- // Make sure we didn't get a bogus pointer
- if ((PageCount < 1) || (PageCount > (TotalPagesInLookupTable - PageNumber)))
- {
- BugCheck((DPRINT_MEMORY, "Invalid page count in lookup table. PageLookupTable[%d].PageAllocationLength = %d\n", PageNumber, RealPageLookupTable[PageNumber].PageAllocationLength));
- }
-
- // Loop through our array check all the pages
- // to make sure they are allocated with a length of 0
- for (Idx=PageNumber+1; Idx<(PageNumber + PageCount); Idx++)
- {
- if ((RealPageLookupTable[Idx].PageAllocated == LoaderFree) ||
- (RealPageLookupTable[Idx].PageAllocationLength != 0))
- {
- BugCheck((DPRINT_MEMORY, "Invalid page entry in lookup table, PageAllocated should = 1 and PageAllocationLength should = 0 because this is not the first block in the run. PageLookupTable[%d].PageAllocated = %d PageLookupTable[%d].PageAllocationLength = %d\n", PageNumber, RealPageLookupTable[PageNumber].PageAllocated, PageNumber, RealPageLookupTable[PageNumber].PageAllocationLength));
- }
- }
-
-#endif
-
- /* If this allocation is only a single page, it could be a sub-allocated page.
- * Just don't free it */
- if (1 == PageCount)
- {
- return;
- }
-
- // Loop through our array and mark all the
- // blocks as free
- for (Idx=PageNumber; Idx<(PageNumber + PageCount); Idx++)
- {
- RealPageLookupTable[Idx].PageAllocated = LoaderFree;
- RealPageLookupTable[Idx].PageAllocationLength = 0;
- }
-
- FreePagesInLookupTable += PageCount;
-
-#ifdef DBG
- DecrementAllocationCount();
- DbgPrint((DPRINT_MEMORY, "Freed %d pages of memory starting at page %d. AllocationCount: %d\n", PageCount, PageNumber, AllocationCount));
- //VerifyHeap();
-#endif // DBG
}
#ifdef DBG
-VOID VerifyHeap(VOID)
-{
- ULONG Idx;
- ULONG Idx2;
- ULONG Count;
- PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTableAddress;
-
- if (DUMP_MEM_MAP_ON_VERIFY)
- {
- DumpMemoryAllocMap();
- }
-
- // Loop through the array and verify that
- // everything is kosher
- for (Idx=0; Idx (TotalPagesInLookupTable - Idx)))
- {
- BugCheck((DPRINT_MEMORY, "Allocation length out of range in heap table. PageLookupTable[Idx].PageAllocationLength = %d\n", RealPageLookupTable[Idx].PageAllocationLength));
- }
-
- // Now go through and verify that the rest of
- // this run has the blocks marked allocated
- // with a length of zero but don't check the
- // first one because we already did
- Count = RealPageLookupTable[Idx].PageAllocationLength;
- for (Idx2=1; Idx2Flags & REG_VALUE_NAME_PACKED)
{
- wName = MmAllocateMemory ((ValueCell->NameSize + 1)*sizeof(WCHAR));
+ wName = MmHeapAlloc((ValueCell->NameSize + 1)*sizeof(WCHAR));
for (i = 0; i < ValueCell->NameSize; i++)
{
wName[i] = ((PCHAR)ValueCell->Name)[i];
@@ -547,7 +547,7 @@ RegImportValue (PHHIVE Hive,
}
else
{
- wName = MmAllocateMemory (ValueCell->NameSize + sizeof(WCHAR));
+ wName = MmHeapAlloc(ValueCell->NameSize + sizeof(WCHAR));
memcpy (wName,
ValueCell->Name,
ValueCell->NameSize);
@@ -569,7 +569,7 @@ RegImportValue (PHHIVE Hive,
if (Error != ERROR_SUCCESS)
{
DbgPrint((DPRINT_REGISTRY, "RegSetValue() failed!\n"));
- MmFreeMemory (wName);
+ MmHeapFree(wName);
return FALSE;
}
}
@@ -587,12 +587,12 @@ RegImportValue (PHHIVE Hive,
if (Error != ERROR_SUCCESS)
{
DbgPrint((DPRINT_REGISTRY, "RegSetValue() failed!\n"));
- MmFreeMemory (wName);
+ MmHeapFree(wName);
return FALSE;
}
}
- MmFreeMemory (wName);
+ MmHeapFree (wName);
return TRUE;
}
@@ -623,7 +623,7 @@ RegImportSubKey(PHHIVE Hive,
if (KeyCell->Flags & REG_KEY_NAME_PACKED)
{
- wName = MmAllocateMemory ((KeyCell->NameSize + 1) * sizeof(WCHAR));
+ wName = MmHeapAlloc ((KeyCell->NameSize + 1) * sizeof(WCHAR));
for (i = 0; i < KeyCell->NameSize; i++)
{
wName[i] = ((PCHAR)KeyCell->Name)[i];
@@ -632,7 +632,7 @@ RegImportSubKey(PHHIVE Hive,
}
else
{
- wName = MmAllocateMemory (KeyCell->NameSize + sizeof(WCHAR));
+ wName = MmHeapAlloc (KeyCell->NameSize + sizeof(WCHAR));
memcpy (wName,
KeyCell->Name,
KeyCell->NameSize);
@@ -645,7 +645,7 @@ RegImportSubKey(PHHIVE Hive,
Error = RegCreateKey (ParentKey,
wName,
&SubKey);
- MmFreeMemory (wName);
+ MmHeapFree (wName);
if (Error != ERROR_SUCCESS)
{
DbgPrint((DPRINT_REGISTRY, "RegCreateKey() failed!\n"));
diff --git a/reactos/registry.c b/reactos/registry.c
index 89c440428ee..f02ef8796c5 100644
--- a/reactos/registry.c
+++ b/reactos/registry.c
@@ -33,7 +33,7 @@ RegInitializeRegistry (VOID)
#endif
/* Create root key */
- RootKey = (FRLDRHKEY) MmAllocateMemory (sizeof(KEY));
+ RootKey = (FRLDRHKEY) MmHeapAlloc (sizeof(KEY));
InitializeListHead (&RootKey->SubKeyList);
InitializeListHead (&RootKey->ValueList);
@@ -43,7 +43,7 @@ RegInitializeRegistry (VOID)
RootKey->ValueCount = 0;
RootKey->NameSize = 4;
- RootKey->Name = MmAllocateMemory (4);
+ RootKey->Name = MmHeapAlloc (4);
wcscpy (RootKey->Name, L"\\");
RootKey->DataType = 0;
@@ -282,7 +282,7 @@ RegCreateKey(FRLDRHKEY ParentKey,
if (CmpResult != 0)
{
/* no key found -> create new subkey */
- NewKey = (FRLDRHKEY)MmAllocateMemory(sizeof(KEY));
+ NewKey = (FRLDRHKEY)MmHeapAlloc(sizeof(KEY));
if (NewKey == NULL)
return(ERROR_OUTOFMEMORY);
@@ -300,7 +300,7 @@ RegCreateKey(FRLDRHKEY ParentKey,
CurrentKey->SubKeyCount++;
NewKey->NameSize = NameSize;
- NewKey->Name = (PWCHAR)MmAllocateMemory(NewKey->NameSize);
+ NewKey->Name = (PWCHAR)MmHeapAlloc(NewKey->NameSize);
if (NewKey->Name == NULL)
return(ERROR_OUTOFMEMORY);
memcpy(NewKey->Name, name, NewKey->NameSize - sizeof(WCHAR));
@@ -517,7 +517,7 @@ RegSetValue(FRLDRHKEY Key,
}
else
{
- Key->Data = MmAllocateMemory(DataSize);
+ Key->Data = MmHeapAlloc(DataSize);
Key->DataSize = DataSize;
Key->DataType = Type;
memcpy(Key->Data, Data, DataSize);
@@ -546,7 +546,7 @@ RegSetValue(FRLDRHKEY Key,
/* add new value */
DbgPrint((DPRINT_REGISTRY, "No value found - adding new value\n"));
- Value = (PVALUE)MmAllocateMemory(sizeof(VALUE));
+ Value = (PVALUE)MmHeapAlloc(sizeof(VALUE));
if (Value == NULL)
return(ERROR_OUTOFMEMORY);
@@ -554,7 +554,7 @@ RegSetValue(FRLDRHKEY Key,
Key->ValueCount++;
Value->NameSize = (wcslen(ValueName)+1)*sizeof(WCHAR);
- Value->Name = (PWCHAR)MmAllocateMemory(Value->NameSize);
+ Value->Name = (PWCHAR)MmHeapAlloc(Value->NameSize);
if (Value->Name == NULL)
return(ERROR_OUTOFMEMORY);
wcscpy(Value->Name, ValueName);
@@ -577,7 +577,7 @@ RegSetValue(FRLDRHKEY Key,
}
else
{
- Value->Data = MmAllocateMemory(DataSize);
+ Value->Data = MmHeapAlloc(DataSize);
if (Value->Data == NULL)
return(ERROR_OUTOFMEMORY);
Value->DataType = Type;
diff --git a/rtl/bget.c b/rtl/bget.c
new file mode 100644
index 00000000000..f290a708afa
--- /dev/null
+++ b/rtl/bget.c
@@ -0,0 +1,1593 @@
+/*
+
+ B G E T
+
+ Buffer allocator
+
+ Designed and implemented in April of 1972 by John Walker, based on the
+ Case Algol OPRO$ algorithm implemented in 1966.
+
+ Reimplemented in 1975 by John Walker for the Interdata 70.
+ Reimplemented in 1977 by John Walker for the Marinchip 9900.
+ Reimplemented in 1982 by Duff Kurland for the Intel 8080.
+
+ Portable C version implemented in September of 1990 by an older, wiser
+ instance of the original implementor.
+
+ Souped up and/or weighed down slightly shortly thereafter by Greg
+ Lutz.
+
+ AMIX edition, including the new compaction call-back option, prepared
+ by John Walker in July of 1992.
+
+ Bug in built-in test program fixed, ANSI compiler warnings eradicated,
+ buffer pool validator implemented, and guaranteed repeatable test
+ added by John Walker in October of 1995.
+
+ This program is in the public domain.
+
+ 1. This is the book of the generations of Adam. In the day that God
+ created man, in the likeness of God made he him;
+ 2. Male and female created he them; and blessed them, and called
+ their name Adam, in the day when they were created.
+ 3. And Adam lived an hundred and thirty years, and begat a son in
+ his own likeness, and after his image; and called his name Seth:
+ 4. And the days of Adam after he had begotten Seth were eight
+ hundred years: and he begat sons and daughters:
+ 5. And all the days that Adam lived were nine hundred and thirty
+ years: and he died.
+ 6. And Seth lived an hundred and five years, and begat Enos:
+ 7. And Seth lived after he begat Enos eight hundred and seven years,
+ and begat sons and daughters:
+ 8. And all the days of Seth were nine hundred and twelve years: and
+ he died.
+ 9. And Enos lived ninety years, and begat Cainan:
+ 10. And Enos lived after he begat Cainan eight hundred and fifteen
+ years, and begat sons and daughters:
+ 11. And all the days of Enos were nine hundred and five years: and
+ he died.
+ 12. And Cainan lived seventy years and begat Mahalaleel:
+ 13. And Cainan lived after he begat Mahalaleel eight hundred and
+ forty years, and begat sons and daughters:
+ 14. And all the days of Cainan were nine hundred and ten years: and
+ he died.
+ 15. And Mahalaleel lived sixty and five years, and begat Jared:
+ 16. And Mahalaleel lived after he begat Jared eight hundred and
+ thirty years, and begat sons and daughters:
+ 17. And all the days of Mahalaleel were eight hundred ninety and
+ five years: and he died.
+ 18. And Jared lived an hundred sixty and two years, and he begat
+ Enoch:
+ 19. And Jared lived after he begat Enoch eight hundred years, and
+ begat sons and daughters:
+ 20. And all the days of Jared were nine hundred sixty and two years:
+ and he died.
+ 21. And Enoch lived sixty and five years, and begat Methuselah:
+ 22. And Enoch walked with God after he begat Methuselah three
+ hundred years, and begat sons and daughters:
+ 23. And all the days of Enoch were three hundred sixty and five
+ years:
+ 24. And Enoch walked with God: and he was not; for God took him.
+ 25. And Methuselah lived an hundred eighty and seven years, and
+ begat Lamech.
+ 26. And Methuselah lived after he begat Lamech seven hundred eighty
+ and two years, and begat sons and daughters:
+ 27. And all the days of Methuselah were nine hundred sixty and nine
+ years: and he died.
+ 28. And Lamech lived an hundred eighty and two years, and begat a
+ son:
+ 29. And he called his name Noah, saying, This same shall comfort us
+ concerning our work and toil of our hands, because of the ground
+ which the LORD hath cursed.
+ 30. And Lamech lived after he begat Noah five hundred ninety and
+ five years, and begat sons and daughters:
+ 31. And all the days of Lamech were seven hundred seventy and seven
+ years: and he died.
+ 32. And Noah was five hundred years old: and Noah begat Shem, Ham,
+ and Japheth.
+
+ And buffers begat buffers, and links begat links, and buffer pools
+ begat links to chains of buffer pools containing buffers, and lo the
+ buffers and links and pools of buffers and pools of links to chains of
+ pools of buffers were fruitful and they multiplied and the Operating
+ System looked down upon them and said that it was Good.
+
+
+ INTRODUCTION
+ ============
+
+ BGET is a comprehensive memory allocation package which is easily
+ configured to the needs of an application. BGET is efficient in
+ both the time needed to allocate and release buffers and in the
+ memory overhead required for buffer pool management. It
+ automatically consolidates contiguous space to minimise
+ fragmentation. BGET is configured by compile-time definitions,
+ Major options include:
+
+ * A built-in test program to exercise BGET and
+ demonstrate how the various functions are used.
+
+ * Allocation by either the "first fit" or "best fit"
+ method.
+
+ * Wiping buffers at release time to catch code which
+ references previously released storage.
+
+ * Built-in routines to dump individual buffers or the
+ entire buffer pool.
+
+ * Retrieval of allocation and pool size statistics.
+
+ * Quantisation of buffer sizes to a power of two to
+ satisfy hardware alignment constraints.
+
+ * Automatic pool compaction, growth, and shrinkage by
+ means of call-backs to user defined functions.
+
+ Applications of BGET can range from storage management in
+ ROM-based embedded programs to providing the framework upon which
+ a multitasking system incorporating garbage collection is
+ constructed. BGET incorporates extensive internal consistency
+ checking using the mechanism; all these checks can be
+ turned off by compiling with NDEBUG defined, yielding a version of
+ BGET with minimal size and maximum speed.
+
+ The basic algorithm underlying BGET has withstood the test of
+ time; more than 25 years have passed since the first
+ implementation of this code. And yet, it is substantially more
+ efficient than the native allocation schemes of many operating
+ systems: the Macintosh and Microsoft Windows to name two, on which
+ programs have obtained substantial speed-ups by layering BGET as
+ an application level memory manager atop the underlying system's.
+
+ BGET has been implemented on the largest mainframes and the lowest
+ of microprocessors. It has served as the core for multitasking
+ operating systems, multi-thread applications, embedded software in
+ data network switching processors, and a host of C programs. And
+ while it has accreted flexibility and additional options over the
+ years, it remains fast, memory efficient, portable, and easy to
+ integrate into your program.
+
+
+ BGET IMPLEMENTATION ASSUMPTIONS
+ ===============================
+
+ BGET is written in as portable a dialect of C as possible. The
+ only fundamental assumption about the underlying hardware
+ architecture is that memory is allocated is a linear array which
+ can be addressed as a vector of C "char" objects. On segmented
+ address space architectures, this generally means that BGET should
+ be used to allocate storage within a single segment (although some
+ compilers simulate linear address spaces on segmented
+ architectures). On segmented architectures, then, BGET buffer
+ pools may not be larger than a segment, but since BGET allows any
+ number of separate buffer pools, there is no limit on the total
+ storage which can be managed, only on the largest individual
+ object which can be allocated. Machines with a linear address
+ architecture, such as the VAX, 680x0, Sparc, MIPS, or the Intel
+ 80386 and above in native mode, may use BGET without restriction.
+
+
+ GETTING STARTED WITH BGET
+ =========================
+
+ Although BGET can be configured in a multitude of fashions, there
+ are three basic ways of working with BGET. The functions
+ mentioned below are documented in the following section. Please
+ excuse the forward references which are made in the interest of
+ providing a roadmap to guide you to the BGET functions you're
+ likely to need.
+
+ Embedded Applications
+ ---------------------
+
+ Embedded applications typically have a fixed area of memory
+ dedicated to buffer allocation (often in a separate RAM address
+ space distinct from the ROM that contains the executable code).
+ To use BGET in such an environment, simply call bpool() with the
+ start address and length of the buffer pool area in RAM, then
+ allocate buffers with bget() and release them with brel().
+ Embedded applications with very limited RAM but abundant CPU speed
+ may benefit by configuring BGET for BestFit allocation (which is
+ usually not worth it in other environments).
+
+ Malloc() Emulation
+ ------------------
+
+ If the C library malloc() function is too slow, not present in
+ your development environment (for example, an a native Windows or
+ Macintosh program), or otherwise unsuitable, you can replace it
+ with BGET. Initially define a buffer pool of an appropriate size
+ with bpool()--usually obtained by making a call to the operating
+ system's low-level memory allocator. Then allocate buffers with
+ bget(), bgetz(), and bgetr() (the last two permit the allocation
+ of buffers initialised to zero and [inefficient] re-allocation of
+ existing buffers for compatibility with C library functions).
+ Release buffers by calling brel(). If a buffer allocation request
+ fails, obtain more storage from the underlying operating system,
+ add it to the buffer pool by another call to bpool(), and continue
+ execution.
+
+ Automatic Storage Management
+ ----------------------------
+
+ You can use BGET as your application's native memory manager and
+ implement automatic storage pool expansion, contraction, and
+ optionally application-specific memory compaction by compiling
+ BGET with the BECtl variable defined, then calling bectl() and
+ supplying functions for storage compaction, acquisition, and
+ release, as well as a standard pool expansion increment. All of
+ these functions are optional (although it doesn't make much sense
+ to provide a release function without an acquisition function,
+ does it?). Once the call-back functions have been defined with
+ bectl(), you simply use bget() and brel() to allocate and release
+ storage as before. You can supply an initial buffer pool with
+ bpool() or rely on automatic allocation to acquire the entire
+ pool. When a call on bget() cannot be satisfied, BGET first
+ checks if a compaction function has been supplied. If so, it is
+ called (with the space required to satisfy the allocation request
+ and a sequence number to allow the compaction routine to be called
+ successively without looping). If the compaction function is able
+ to free any storage (it needn't know whether the storage it freed
+ was adequate) it should return a nonzero value, whereupon BGET
+ will retry the allocation request and, if it fails again, call the
+ compaction function again with the next-higher sequence number.
+
+ If the compaction function returns zero, indicating failure to
+ free space, or no compaction function is defined, BGET next tests
+ whether a non-NULL allocation function was supplied to bectl().
+ If so, that function is called with an argument indicating how
+ many bytes of additional space are required. This will be the
+ standard pool expansion increment supplied in the call to bectl()
+ unless the original bget() call requested a buffer larger than
+ this; buffers larger than the standard pool block can be managed
+ "off the books" by BGET in this mode. If the allocation function
+ succeeds in obtaining the storage, it returns a pointer to the new
+ block and BGET expands the buffer pool; if it fails, the
+ allocation request fails and returns NULL to the caller. If a
+ non-NULL release function is supplied, expansion blocks which
+ become totally empty are released to the global free pool by
+ passing their addresses to the release function.
+
+ Equipped with appropriate allocation, release, and compaction
+ functions, BGET can be used as part of very sophisticated memory
+ management strategies, including garbage collection. (Note,
+ however, that BGET is *not* a garbage collector by itself, and
+ that developing such a system requires much additional logic and
+ careful design of the application's memory allocation strategy.)
+
+
+ BGET FUNCTION DESCRIPTIONS
+ ==========================
+
+ Functions implemented in this file (some are enabled by certain of
+ the optional settings below):
+
+ void bpool(void *buffer, bufsize len);
+
+ Create a buffer pool of bytes, using the storage starting at
+ . You can call bpool() subsequently to contribute
+ additional storage to the overall buffer pool.
+
+ void *bget(bufsize size);
+
+ Allocate a buffer of bytes. The address of the buffer is
+ returned, or NULL if insufficient memory was available to allocate
+ the buffer.
+
+ void *bgetz(bufsize size);
+
+ Allocate a buffer of bytes and clear it to all zeroes. The
+ address of the buffer is returned, or NULL if insufficient memory
+ was available to allocate the buffer.
+
+ void *bgetr(void *buffer, bufsize newsize);
+
+ Reallocate a buffer previously allocated by bget(), changing its
+ size to and preserving all existing data. NULL is
+ returned if insufficient memory is available to reallocate the
+ buffer, in which case the original buffer remains intact.
+
+ void brel(void *buf);
+
+ Return the buffer , previously allocated by bget(), to the
+ free space pool.
+
+ void bectl(int (*compact)(bufsize sizereq, int sequence),
+ void *(*acquire)(bufsize size),
+ void (*release)(void *buf),
+ bufsize pool_incr);
+
+ Expansion control: specify functions through which the package may
+ compact storage (or take other appropriate action) when an
+ allocation request fails, and optionally automatically acquire
+ storage for expansion blocks when necessary, and release such
+ blocks when they become empty. If is non-NULL, whenever
+ a buffer allocation request fails, the function will be
+ called with arguments specifying the number of bytes (total buffer
+ size, including header overhead) required to satisfy the
+ allocation request, and a sequence number indicating the number of
+ consecutive calls on attempting to satisfy this
+ allocation request. The sequence number is 1 for the first call
+ on for a given allocation request, and increments on
+ subsequent calls, permitting the function to take
+ increasingly dire measures in an attempt to free up storage. If
+ the function returns a nonzero value, the allocation
+ attempt is re-tried. If returns 0 (as it must if it
+ isn't able to release any space or add storage to the buffer
+ pool), the allocation request fails, which can trigger automatic
+ pool expansion if the argument is non-NULL. At the time
+ the function is called, the state of the buffer
+ allocator is identical to that at the moment the allocation
+ request was made; consequently, the function may call
+ brel(), bpool(), bstats(), and/or directly manipulate the buffer
+ pool in any manner which would be valid were the application in
+ control. This does not, however, relieve the function
+ of the need to ensure that whatever actions it takes do not change
+ things underneath the application that made the allocation
+ request. For example, a function that released a buffer
+ in the process of being reallocated with bgetr() would lead to
+ disaster. Implementing a safe and effective mechanism
+ requires careful design of an application's memory architecture,
+ and cannot generally be easily retrofitted into existing code.
+
+ If is non-NULL, that function will be called whenever an
+ allocation request fails. If the function succeeds in
+ allocating the requested space and returns a pointer to the new
+ area, allocation will proceed using the expanded buffer pool. If
+ cannot obtain the requested space, it should return NULL
+ and the entire allocation process will fail.
+ specifies the normal expansion block size. Providing an
+ function will cause subsequent bget() requests for buffers too
+ large to be managed in the linked-block scheme (in other words,
+ larger than minus the buffer overhead) to be satisfied
+ directly by calls to the function. Automatic release of
+ empty pool blocks will occur only if all pool blocks in the system
+ are the size given by .
+
+ void bstats(bufsize *curalloc, bufsize *totfree,
+ bufsize *maxfree, long *nget, long *nrel);
+
+ The amount of space currently allocated is stored into the
+ variable pointed to by . The total free space (sum of
+ all free blocks in the pool) is stored into the variable pointed
+ to by , and the size of the largest single block in the
+ free space pool is stored into the variable pointed to by
+ . The variables pointed to by and are
+ filled, respectively, with the number of successful (non-NULL
+ return) bget() calls and the number of brel() calls.
+
+ void bstatse(bufsize *pool_incr, long *npool,
+ long *npget, long *nprel,
+ long *ndget, long *ndrel);
+
+ Extended statistics: The expansion block size will be stored into
+ the variable pointed to by , or the negative thereof if
+ automatic expansion block releases are disabled. The number of
+ currently active pool blocks will be stored into the variable
+ pointed to by . The variables pointed to by and
+ will be filled with, respectively, the number of expansion
+ block acquisitions and releases which have occurred. The
+ variables pointed to by and will be filled with
+ the number of bget() and brel() calls, respectively, managed
+ through blocks directly allocated by the acquisition and release
+ functions.
+
+ void bufdump(void *buf);
+
+ The buffer pointed to by is dumped on standard output.
+
+ void bpoold(void *pool, int dumpalloc, int dumpfree);
+
+ All buffers in the buffer pool , previously initialised by a
+ call on bpool(), are listed in ascending memory address order. If
+ is nonzero, the contents of allocated buffers are
+ dumped; if is nonzero, the contents of free blocks are
+ dumped.
+
+ int bpoolv(void *pool);
+
+ The named buffer pool, previously initialised by a call on
+ bpool(), is validated for bad pointers, overwritten data, etc. If
+ compiled with NDEBUG not defined, any error generates an assertion
+ failure. Otherwise 1 is returned if the pool is valid, 0 if an
+ error is found.
+
+
+ BGET CONFIGURATION
+ ==================
+*/
+
+/*#define TestProg 20000*/ /* Generate built-in test program
+ if defined. The value specifies
+ how many buffer allocation attempts
+ the test program should make. */
+
+#define SizeQuant 4 /* Buffer allocation size quantum:
+ all buffers allocated are a
+ multiple of this size. This
+ MUST be a power of two. */
+
+#define BufDump 1 /* Define this symbol to enable the
+ bpoold() function which dumps the
+ buffers in a buffer pool. */
+
+#define BufValid 1 /* Define this symbol to enable the
+ bpoolv() function for validating
+ a buffer pool. */
+
+#define DumpData 1 /* Define this symbol to enable the
+ bufdump() function which allows
+ dumping the contents of an allocated
+ or free buffer. */
+
+#define BufStats 1 /* Define this symbol to enable the
+ bstats() function which calculates
+ the total free space in the buffer
+ pool, the largest available
+ buffer, and the total space
+ currently allocated. */
+
+#define FreeWipe 1 /* Wipe free buffers to a guaranteed
+ pattern of garbage to trip up
+ miscreants who attempt to use
+ pointers into released buffers. */
+
+#define BestFit 1 /* Use a best fit algorithm when
+ searching for space for an
+ allocation request. This uses
+ memory more efficiently, but
+ allocation will be much slower. */
+
+#define BECtl 1 /* Define this symbol to enable the
+ bectl() function for automatic
+ pool space control. */
+
+#include
+
+#ifdef lint
+#define NDEBUG /* Exits in asserts confuse lint */
+/* LINTLIBRARY */ /* Don't complain about def, no ref */
+extern char *sprintf(); /* Sun includes don't define sprintf */
+#endif
+
+#define NDEBUG
+
+#include
+#include
+
+#ifdef BufDump /* BufDump implies DumpData */
+#ifndef DumpData
+#define DumpData 1
+#endif
+#endif
+
+#ifdef DumpData
+#include
+#endif
+
+/* Declare the interface, including the requested buffer size type,
+ bufsize. */
+
+#include "bget.h"
+
+#define MemSize int /* Type for size arguments to memxxx()
+ functions such as memcmp(). */
+
+/* Queue links */
+
+struct qlinks {
+ struct bfhead *flink; /* Forward link */
+ struct bfhead *blink; /* Backward link */
+};
+
+/* Header in allocated and free buffers */
+
+struct bhead {
+ bufsize prevfree; /* Relative link back to previous
+ free buffer in memory or 0 if
+ previous buffer is allocated. */
+ bufsize bsize; /* Buffer size: positive if free,
+ negative if allocated. */
+};
+#define BH(p) ((struct bhead *) (p))
+
+/* Header in directly allocated buffers (by acqfcn) */
+
+struct bdhead {
+ bufsize tsize; /* Total size, including overhead */
+ struct bhead bh; /* Common header */
+};
+#define BDH(p) ((struct bdhead *) (p))
+
+/* Header in free buffers */
+
+struct bfhead {
+ struct bhead bh; /* Common allocated/free header */
+ struct qlinks ql; /* Links on free list */
+};
+#define BFH(p) ((struct bfhead *) (p))
+
+static struct bfhead freelist = { /* List of free buffers */
+ {0, 0},
+ {&freelist, &freelist}
+};
+
+
+#ifdef BufStats
+static bufsize totalloc = 0; /* Total space currently allocated */
+static long numget = 0, numrel = 0; /* Number of bget() and brel() calls */
+#ifdef BECtl
+static long numpblk = 0; /* Number of pool blocks */
+static long numpget = 0, numprel = 0; /* Number of block gets and rels */
+static long numdget = 0, numdrel = 0; /* Number of direct gets and rels */
+#endif /* BECtl */
+#endif /* BufStats */
+
+#ifdef BECtl
+
+/* Automatic expansion block management functions */
+
+static int (*compfcn) _((bufsize sizereq, int sequence)) = NULL;
+static void *(*acqfcn) _((bufsize size)) = NULL;
+static void (*relfcn) _((void *buf)) = NULL;
+
+static bufsize exp_incr = 0; /* Expansion block size */
+static bufsize pool_len = 0; /* 0: no bpool calls have been made
+ -1: not all pool blocks are
+ the same size
+ >0: (common) block size for all
+ bpool calls made so far
+ */
+#endif
+
+/* Minimum allocation quantum: */
+
+#define QLSize (sizeof(struct qlinks))
+#define SizeQ ((SizeQuant > QLSize) ? SizeQuant : QLSize)
+
+#define V (void) /* To denote unwanted returned values */
+
+/* End sentinel: value placed in bsize field of dummy block delimiting
+ end of pool block. The most negative number which will fit in a
+ bufsize, defined in a way that the compiler will accept. */
+
+#define ESent ((bufsize) (-(((1L << (sizeof(bufsize) * 8 - 2)) - 1) * 2) - 2))
+
+/* BGET -- Allocate a buffer. */
+
+void *bget(requested_size)
+ bufsize requested_size;
+{
+ bufsize size = requested_size;
+ struct bfhead *b;
+#ifdef BestFit
+ struct bfhead *best;
+#endif
+ void *buf;
+#ifdef BECtl
+ int compactseq = 0;
+#endif
+
+ assert(size > 0);
+
+ if (size < SizeQ) { /* Need at least room for the */
+ size = SizeQ; /* queue links. */
+ }
+#ifdef SizeQuant
+#if SizeQuant > 1
+ size = (size + (SizeQuant - 1)) & (~(SizeQuant - 1));
+#endif
+#endif
+
+ size += sizeof(struct bhead); /* Add overhead in allocated buffer
+ to size required. */
+
+#ifdef BECtl
+ /* If a compact function was provided in the call to bectl(), wrap
+ a loop around the allocation process to allow compaction to
+ intervene in case we don't find a suitable buffer in the chain. */
+
+ while (1) {
+#endif
+ b = freelist.ql.flink;
+#ifdef BestFit
+ best = &freelist;
+#endif
+
+
+ /* Scan the free list searching for the first buffer big enough
+ to hold the requested size buffer. */
+
+#ifdef BestFit
+ while (b != &freelist) {
+ if (b->bh.bsize >= size) {
+ if ((best == &freelist) || (b->bh.bsize < best->bh.bsize)) {
+ best = b;
+ }
+ }
+ b = b->ql.flink; /* Link to next buffer */
+ }
+ b = best;
+#endif /* BestFit */
+
+ while (b != &freelist) {
+ if ((bufsize) b->bh.bsize >= size) {
+
+ /* Buffer is big enough to satisfy the request. Allocate it
+ to the caller. We must decide whether the buffer is large
+ enough to split into the part given to the caller and a
+ free buffer that remains on the free list, or whether the
+ entire buffer should be removed from the free list and
+ given to the caller in its entirety. We only split the
+ buffer if enough room remains for a header plus the minimum
+ quantum of allocation. */
+
+ if ((b->bh.bsize - size) > (SizeQ + (sizeof(struct bhead)))) {
+ struct bhead *ba, *bn;
+
+ ba = BH(((char *) b) + (b->bh.bsize - size));
+ bn = BH(((char *) ba) + size);
+ assert(bn->prevfree == b->bh.bsize);
+ /* Subtract size from length of free block. */
+ b->bh.bsize -= size;
+ /* Link allocated buffer to the previous free buffer. */
+ ba->prevfree = b->bh.bsize;
+ /* Plug negative size into user buffer. */
+ ba->bsize = -(bufsize) size;
+ /* Mark buffer after this one not preceded by free block. */
+ bn->prevfree = 0;
+
+#ifdef BufStats
+ totalloc += size;
+ numget++; /* Increment number of bget() calls */
+#endif
+ buf = (void *) ((((char *) ba) + sizeof(struct bhead)));
+ return buf;
+ } else {
+ struct bhead *ba;
+
+ ba = BH(((char *) b) + b->bh.bsize);
+ assert(ba->prevfree == b->bh.bsize);
+
+ /* The buffer isn't big enough to split. Give the whole
+ shebang to the caller and remove it from the free list. */
+
+ assert(b->ql.blink->ql.flink == b);
+ assert(b->ql.flink->ql.blink == b);
+ b->ql.blink->ql.flink = b->ql.flink;
+ b->ql.flink->ql.blink = b->ql.blink;
+
+#ifdef BufStats
+ totalloc += b->bh.bsize;
+ numget++; /* Increment number of bget() calls */
+#endif
+ /* Negate size to mark buffer allocated. */
+ b->bh.bsize = -(b->bh.bsize);
+
+ /* Zero the back pointer in the next buffer in memory
+ to indicate that this buffer is allocated. */
+ ba->prevfree = 0;
+
+ /* Give user buffer starting at queue links. */
+ buf = (void *) &(b->ql);
+ return buf;
+ }
+ }
+ b = b->ql.flink; /* Link to next buffer */
+ }
+#ifdef BECtl
+
+ /* We failed to find a buffer. If there's a compact function
+ defined, notify it of the size requested. If it returns
+ TRUE, try the allocation again. */
+
+ if ((compfcn == NULL) || (!(*compfcn)(size, ++compactseq))) {
+ break;
+ }
+ }
+
+ /* No buffer available with requested size free. */
+
+ /* Don't give up yet -- look in the reserve supply. */
+
+ if (acqfcn != NULL) {
+ if (size > exp_incr - sizeof(struct bhead)) {
+
+ /* Request is too large to fit in a single expansion
+ block. Try to satisy it by a direct buffer acquisition. */
+
+ struct bdhead *bdh;
+
+ size += sizeof(struct bdhead) - sizeof(struct bhead);
+ if ((bdh = BDH((*acqfcn)((bufsize) size))) != NULL) {
+
+ /* Mark the buffer special by setting the size field
+ of its header to zero. */
+ bdh->bh.bsize = 0;
+ bdh->bh.prevfree = 0;
+ bdh->tsize = size;
+#ifdef BufStats
+ totalloc += size;
+ numget++; /* Increment number of bget() calls */
+ numdget++; /* Direct bget() call count */
+#endif
+ buf = (void *) (bdh + 1);
+ return buf;
+ }
+
+ } else {
+
+ /* Try to obtain a new expansion block */
+
+ void *newpool;
+
+ if ((newpool = (*acqfcn)((bufsize) exp_incr)) != NULL) {
+ bpool(newpool, exp_incr);
+ buf = bget(requested_size); /* This can't, I say, can't
+ get into a loop. */
+ return buf;
+ }
+ }
+ }
+
+ /* Still no buffer available */
+
+#endif /* BECtl */
+
+ return NULL;
+}
+
+/* BGETZ -- Allocate a buffer and clear its contents to zero. We clear
+ the entire contents of the buffer to zero, not just the
+ region requested by the caller. */
+
+void *bgetz(size)
+ bufsize size;
+{
+ char *buf = (char *) bget(size);
+
+ if (buf != NULL) {
+ struct bhead *b;
+ bufsize rsize;
+
+ b = BH(buf - sizeof(struct bhead));
+ rsize = -(b->bsize);
+ if (rsize == 0) {
+ struct bdhead *bd;
+
+ bd = BDH(buf - sizeof(struct bdhead));
+ rsize = bd->tsize - sizeof(struct bdhead);
+ } else {
+ rsize -= sizeof(struct bhead);
+ }
+ assert(rsize >= size);
+ V memset(buf, 0, (MemSize) rsize);
+ }
+ return ((void *) buf);
+}
+
+/* BGETR -- Reallocate a buffer. This is a minimal implementation,
+ simply in terms of brel() and bget(). It could be
+ enhanced to allow the buffer to grow into adjacent free
+ blocks and to avoid moving data unnecessarily. */
+
+void *bgetr(buf, size)
+ void *buf;
+ bufsize size;
+{
+ void *nbuf;
+ bufsize osize; /* Old size of buffer */
+ struct bhead *b;
+
+ if ((nbuf = bget(size)) == NULL) { /* Acquire new buffer */
+ return NULL;
+ }
+ if (buf == NULL) {
+ return nbuf;
+ }
+ b = BH(((char *) buf) - sizeof(struct bhead));
+ osize = -b->bsize;
+#ifdef BECtl
+ if (osize == 0) {
+ /* Buffer acquired directly through acqfcn. */
+ struct bdhead *bd;
+
+ bd = BDH(((char *) buf) - sizeof(struct bdhead));
+ osize = bd->tsize - sizeof(struct bdhead);
+ } else
+#endif
+ osize -= sizeof(struct bhead);
+ assert(osize > 0);
+ V memcpy((char *) nbuf, (char *) buf, /* Copy the data */
+ (MemSize) ((size < osize) ? size : osize));
+ brel(buf);
+ return nbuf;
+}
+
+/* BREL -- Release a buffer. */
+
+void brel(buf)
+ void *buf;
+{
+ struct bfhead *b, *bn;
+
+ b = BFH(((char *) buf) - sizeof(struct bhead));
+#ifdef BufStats
+ numrel++; /* Increment number of brel() calls */
+#endif
+ assert(buf != NULL);
+
+#ifdef BECtl
+ if (b->bh.bsize == 0) { /* Directly-acquired buffer? */
+ struct bdhead *bdh;
+
+ bdh = BDH(((char *) buf) - sizeof(struct bdhead));
+ assert(b->bh.prevfree == 0);
+#ifdef BufStats
+ totalloc -= bdh->tsize;
+ assert(totalloc >= 0);
+ numdrel++; /* Number of direct releases */
+#endif /* BufStats */
+#ifdef FreeWipe
+ V memset((char *) buf, 0x55,
+ (MemSize) (bdh->tsize - sizeof(struct bdhead)));
+#endif /* FreeWipe */
+ assert(relfcn != NULL);
+ (*relfcn)((void *) bdh); /* Release it directly. */
+ return;
+ }
+#endif /* BECtl */
+
+ /* Buffer size must be negative, indicating that the buffer is
+ allocated. */
+
+ if (b->bh.bsize >= 0) {
+ bn = NULL;
+ }
+ assert(b->bh.bsize < 0);
+
+ /* Back pointer in next buffer must be zero, indicating the
+ same thing: */
+
+ assert(BH((char *) b - b->bh.bsize)->prevfree == 0);
+
+#ifdef BufStats
+ totalloc += b->bh.bsize;
+ assert(totalloc >= 0);
+#endif
+
+ /* If the back link is nonzero, the previous buffer is free. */
+
+ if (b->bh.prevfree != 0) {
+
+ /* The previous buffer is free. Consolidate this buffer with it
+ by adding the length of this buffer to the previous free
+ buffer. Note that we subtract the size in the buffer being
+ released, since it's negative to indicate that the buffer is
+ allocated. */
+
+ register bufsize size = b->bh.bsize;
+
+ /* Make the previous buffer the one we're working on. */
+ assert(BH((char *) b - b->bh.prevfree)->bsize == b->bh.prevfree);
+ b = BFH(((char *) b) - b->bh.prevfree);
+ b->bh.bsize -= size;
+ } else {
+
+ /* The previous buffer isn't allocated. Insert this buffer
+ on the free list as an isolated free block. */
+
+ assert(freelist.ql.blink->ql.flink == &freelist);
+ assert(freelist.ql.flink->ql.blink == &freelist);
+ b->ql.flink = &freelist;
+ b->ql.blink = freelist.ql.blink;
+ freelist.ql.blink = b;
+ b->ql.blink->ql.flink = b;
+ b->bh.bsize = -b->bh.bsize;
+ }
+
+ /* Now we look at the next buffer in memory, located by advancing from
+ the start of this buffer by its size, to see if that buffer is
+ free. If it is, we combine this buffer with the next one in
+ memory, dechaining the second buffer from the free list. */
+
+ bn = BFH(((char *) b) + b->bh.bsize);
+ if (bn->bh.bsize > 0) {
+
+ /* The buffer is free. Remove it from the free list and add
+ its size to that of our buffer. */
+
+ assert(BH((char *) bn + bn->bh.bsize)->prevfree == bn->bh.bsize);
+ assert(bn->ql.blink->ql.flink == bn);
+ assert(bn->ql.flink->ql.blink == bn);
+ bn->ql.blink->ql.flink = bn->ql.flink;
+ bn->ql.flink->ql.blink = bn->ql.blink;
+ b->bh.bsize += bn->bh.bsize;
+
+ /* Finally, advance to the buffer that follows the newly
+ consolidated free block. We must set its backpointer to the
+ head of the consolidated free block. We know the next block
+ must be an allocated block because the process of recombination
+ guarantees that two free blocks will never be contiguous in
+ memory. */
+
+ bn = BFH(((char *) b) + b->bh.bsize);
+ }
+#ifdef FreeWipe
+ V memset(((char *) b) + sizeof(struct bfhead), 0x55,
+ (MemSize) (b->bh.bsize - sizeof(struct bfhead)));
+#endif
+ assert(bn->bh.bsize < 0);
+
+ /* The next buffer is allocated. Set the backpointer in it to point
+ to this buffer; the previous free buffer in memory. */
+
+ bn->bh.prevfree = b->bh.bsize;
+
+#ifdef BECtl
+
+ /* If a block-release function is defined, and this free buffer
+ constitutes the entire block, release it. Note that pool_len
+ is defined in such a way that the test will fail unless all
+ pool blocks are the same size. */
+
+ if (relfcn != NULL &&
+ ((bufsize) b->bh.bsize) == (pool_len - sizeof(struct bhead))) {
+
+ assert(b->bh.prevfree == 0);
+ assert(BH((char *) b + b->bh.bsize)->bsize == ESent);
+ assert(BH((char *) b + b->bh.bsize)->prevfree == b->bh.bsize);
+ /* Unlink the buffer from the free list */
+ b->ql.blink->ql.flink = b->ql.flink;
+ b->ql.flink->ql.blink = b->ql.blink;
+
+ (*relfcn)(b);
+#ifdef BufStats
+ numprel++; /* Nr of expansion block releases */
+ numpblk--; /* Total number of blocks */
+ assert(numpblk == numpget - numprel);
+#endif /* BufStats */
+ }
+#endif /* BECtl */
+}
+
+#ifdef BECtl
+
+/* BECTL -- Establish automatic pool expansion control */
+
+void bectl(compact, acquire, release, pool_incr)
+ int (*compact) _((bufsize sizereq, int sequence));
+ void *(*acquire) _((bufsize size));
+ void (*release) _((void *buf));
+ bufsize pool_incr;
+{
+ compfcn = compact;
+ acqfcn = acquire;
+ relfcn = release;
+ exp_incr = pool_incr;
+}
+#endif
+
+/* BPOOL -- Add a region of memory to the buffer pool. */
+
+void bpool(buf, len)
+ void *buf;
+ bufsize len;
+{
+ struct bfhead *b = BFH(buf);
+ struct bhead *bn;
+
+#ifdef SizeQuant
+ len &= ~(SizeQuant - 1);
+#endif
+#ifdef BECtl
+ if (pool_len == 0) {
+ pool_len = len;
+ } else if (len != pool_len) {
+ pool_len = -1;
+ }
+#ifdef BufStats
+ numpget++; /* Number of block acquisitions */
+ numpblk++; /* Number of blocks total */
+ assert(numpblk == numpget - numprel);
+#endif /* BufStats */
+#endif /* BECtl */
+
+ /* Since the block is initially occupied by a single free buffer,
+ it had better not be (much) larger than the largest buffer
+ whose size we can store in bhead.bsize. */
+
+ assert(len - sizeof(struct bhead) <= -((bufsize) ESent + 1));
+
+ /* Clear the backpointer at the start of the block to indicate that
+ there is no free block prior to this one. That blocks
+ recombination when the first block in memory is released. */
+
+ b->bh.prevfree = 0;
+
+ /* Chain the new block to the free list. */
+
+ assert(freelist.ql.blink->ql.flink == &freelist);
+ assert(freelist.ql.flink->ql.blink == &freelist);
+ b->ql.flink = &freelist;
+ b->ql.blink = freelist.ql.blink;
+ freelist.ql.blink = b;
+ b->ql.blink->ql.flink = b;
+
+ /* Create a dummy allocated buffer at the end of the pool. This dummy
+ buffer is seen when a buffer at the end of the pool is released and
+ blocks recombination of the last buffer with the dummy buffer at
+ the end. The length in the dummy buffer is set to the largest
+ negative number to denote the end of the pool for diagnostic
+ routines (this specific value is not counted on by the actual
+ allocation and release functions). */
+
+ len -= sizeof(struct bhead);
+ b->bh.bsize = (bufsize) len;
+#ifdef FreeWipe
+ V memset(((char *) b) + sizeof(struct bfhead), 0x55,
+ (MemSize) (len - sizeof(struct bfhead)));
+#endif
+ bn = BH(((char *) b) + len);
+ bn->prevfree = (bufsize) len;
+ /* Definition of ESent assumes two's complement! */
+ assert((~0) == -1);
+ bn->bsize = ESent;
+}
+
+#ifdef BufStats
+
+/* BSTATS -- Return buffer allocation free space statistics. */
+
+void bstats(curalloc, totfree, maxfree, nget, nrel)
+ bufsize *curalloc, *totfree, *maxfree;
+ long *nget, *nrel;
+{
+ struct bfhead *b = freelist.ql.flink;
+
+ *nget = numget;
+ *nrel = numrel;
+ *curalloc = totalloc;
+ *totfree = 0;
+ *maxfree = -1;
+ while (b != &freelist) {
+ assert(b->bh.bsize > 0);
+ *totfree += b->bh.bsize;
+ if (b->bh.bsize > *maxfree) {
+ *maxfree = b->bh.bsize;
+ }
+ b = b->ql.flink; /* Link to next buffer */
+ }
+}
+
+#ifdef BECtl
+
+/* BSTATSE -- Return extended statistics */
+
+void bstatse(pool_incr, npool, npget, nprel, ndget, ndrel)
+ bufsize *pool_incr;
+ long *npool, *npget, *nprel, *ndget, *ndrel;
+{
+ *pool_incr = (pool_len < 0) ? -exp_incr : exp_incr;
+ *npool = numpblk;
+ *npget = numpget;
+ *nprel = numprel;
+ *ndget = numdget;
+ *ndrel = numdrel;
+}
+#endif /* BECtl */
+#endif /* BufStats */
+
+#ifdef DumpData
+
+/* BUFDUMP -- Dump the data in a buffer. This is called with the user
+ data pointer, and backs up to the buffer header. It will
+ dump either a free block or an allocated one. */
+
+void bufdump(buf)
+ void *buf;
+{
+ struct bfhead *b;
+ unsigned char *bdump;
+ bufsize bdlen;
+
+ b = BFH(((char *) buf) - sizeof(struct bhead));
+ assert(b->bh.bsize != 0);
+ if (b->bh.bsize < 0) {
+ bdump = (unsigned char *) buf;
+ bdlen = (-b->bh.bsize) - sizeof(struct bhead);
+ } else {
+ bdump = (unsigned char *) (((char *) b) + sizeof(struct bfhead));
+ bdlen = b->bh.bsize - sizeof(struct bfhead);
+ }
+
+ while (bdlen > 0) {
+ int i, dupes = 0;
+ bufsize l = bdlen;
+ char bhex[50], bascii[20];
+
+ if (l > 16) {
+ l = 16;
+ }
+
+ for (i = 0; i < l; i++) {
+ V sprintf(bhex + i * 3, "%02X ", bdump[i]);
+ bascii[i] = isprint(bdump[i]) ? bdump[i] : ' ';
+ }
+ bascii[i] = 0;
+ V printf("%-48s %s\n", bhex, bascii);
+ bdump += l;
+ bdlen -= l;
+ while ((bdlen > 16) && (memcmp((char *) (bdump - 16),
+ (char *) bdump, 16) == 0)) {
+ dupes++;
+ bdump += 16;
+ bdlen -= 16;
+ }
+ if (dupes > 1) {
+ V printf(
+ " (%d lines [%d bytes] identical to above line skipped)\n",
+ dupes, dupes * 16);
+ } else if (dupes == 1) {
+ bdump -= 16;
+ bdlen += 16;
+ }
+ }
+}
+#endif
+
+#ifdef BufDump
+
+/* BPOOLD -- Dump a buffer pool. The buffer headers are always listed.
+ If DUMPALLOC is nonzero, the contents of allocated buffers
+ are dumped. If DUMPFREE is nonzero, free blocks are
+ dumped as well. If FreeWipe checking is enabled, free
+ blocks which have been clobbered will always be dumped. */
+
+void bpoold(buf, dumpalloc, dumpfree)
+ void *buf;
+ int dumpalloc, dumpfree;
+{
+ struct bfhead *b = BFH(buf);
+
+ while (b->bh.bsize != ESent) {
+ bufsize bs = b->bh.bsize;
+
+ if (bs < 0) {
+ bs = -bs;
+ V printf("Allocated buffer: size %6ld bytes.\n", (long) bs);
+ if (dumpalloc) {
+ bufdump((void *) (((char *) b) + sizeof(struct bhead)));
+ }
+ } else {
+ char *lerr = "";
+
+ assert(bs > 0);
+ if ((b->ql.blink->ql.flink != b) ||
+ (b->ql.flink->ql.blink != b)) {
+ lerr = " (Bad free list links)";
+ }
+ V printf("Free block: size %6ld bytes.%s\n",
+ (long) bs, lerr);
+#ifdef FreeWipe
+ lerr = ((char *) b) + sizeof(struct bfhead);
+ if ((bs > sizeof(struct bfhead)) && ((*lerr != 0x55) ||
+ (memcmp(lerr, lerr + 1,
+ (MemSize) (bs - (sizeof(struct bfhead) + 1))) != 0))) {
+ V printf(
+ "(Contents of above free block have been overstored.)\n");
+ bufdump((void *) (((char *) b) + sizeof(struct bhead)));
+ } else
+#endif
+ if (dumpfree) {
+ bufdump((void *) (((char *) b) + sizeof(struct bhead)));
+ }
+ }
+ b = BFH(((char *) b) + bs);
+ }
+}
+#endif /* BufDump */
+
+#ifdef BufValid
+
+/* BPOOLV -- Validate a buffer pool. If NDEBUG isn't defined,
+ any error generates an assertion failure. */
+
+int bpoolv(buf)
+ void *buf;
+{
+ struct bfhead *b = BFH(buf);
+
+ while (b->bh.bsize != ESent) {
+ bufsize bs = b->bh.bsize;
+
+ if (bs < 0) {
+ bs = -bs;
+ } else {
+ char *lerr = "";
+
+ assert(bs > 0);
+ if (bs <= 0) {
+ return 0;
+ }
+ if ((b->ql.blink->ql.flink != b) ||
+ (b->ql.flink->ql.blink != b)) {
+ V printf("Free block: size %6ld bytes. (Bad free list links)\n",
+ (long) bs);
+ assert(0);
+ return 0;
+ }
+#ifdef FreeWipe
+ lerr = ((char *) b) + sizeof(struct bfhead);
+ if ((bs > sizeof(struct bfhead)) && ((*lerr != 0x55) ||
+ (memcmp(lerr, lerr + 1,
+ (MemSize) (bs - (sizeof(struct bfhead) + 1))) != 0))) {
+ V printf(
+ "(Contents of above free block have been overstored.)\n");
+ bufdump((void *) (((char *) b) + sizeof(struct bhead)));
+ assert(0);
+ return 0;
+ }
+#endif
+ }
+ b = BFH(((char *) b) + bs);
+ }
+ return 1;
+}
+#endif /* BufValid */
+
+ /***********************\
+ * *
+ * Built-in test program *
+ * *
+ \***********************/
+
+#ifdef TestProg
+
+#define Repeatable 1 /* Repeatable pseudorandom sequence */
+ /* If Repeatable is not defined, a
+ time-seeded pseudorandom sequence
+ is generated, exercising BGET with
+ a different pattern of calls on each
+ run. */
+#define OUR_RAND /* Use our own built-in version of
+ rand() to guarantee the test is
+ 100% repeatable. */
+
+#ifdef BECtl
+#define PoolSize 300000 /* Test buffer pool size */
+#else
+#define PoolSize 50000 /* Test buffer pool size */
+#endif
+#define ExpIncr 32768 /* Test expansion block size */
+#define CompactTries 10 /* Maximum tries at compacting */
+
+#define dumpAlloc 0 /* Dump allocated buffers ? */
+#define dumpFree 0 /* Dump free buffers ? */
+
+#ifndef Repeatable
+extern long time();
+#endif
+
+extern char *malloc();
+extern int free _((char *));
+
+static char *bchain = NULL; /* Our private buffer chain */
+static char *bp = NULL; /* Our initial buffer pool */
+
+#include
+
+#ifdef OUR_RAND
+
+static unsigned long int next = 1;
+
+/* Return next random integer */
+
+int rand()
+{
+ next = next * 1103515245L + 12345;
+ return (unsigned int) (next / 65536L) % 32768L;
+}
+
+/* Set seed for random generator */
+
+void srand(seed)
+ unsigned int seed;
+{
+ next = seed;
+}
+#endif
+
+/* STATS -- Edit statistics returned by bstats() or bstatse(). */
+
+static void stats(when)
+ char *when;
+{
+ bufsize cural, totfree, maxfree;
+ long nget, nfree;
+#ifdef BECtl
+ bufsize pincr;
+ long totblocks, npget, nprel, ndget, ndrel;
+#endif
+
+ bstats(&cural, &totfree, &maxfree, &nget, &nfree);
+ V printf(
+ "%s: %ld gets, %ld releases. %ld in use, %ld free, largest = %ld\n",
+ when, nget, nfree, (long) cural, (long) totfree, (long) maxfree);
+#ifdef BECtl
+ bstatse(&pincr, &totblocks, &npget, &nprel, &ndget, &ndrel);
+ V printf(
+ " Blocks: size = %ld, %ld (%ld bytes) in use, %ld gets, %ld frees\n",
+ (long)pincr, totblocks, pincr * totblocks, npget, nprel);
+ V printf(" %ld direct gets, %ld direct frees\n", ndget, ndrel);
+#endif /* BECtl */
+}
+
+#ifdef BECtl
+static int protect = 0; /* Disable compaction during bgetr() */
+
+/* BCOMPACT -- Compaction call-back function. */
+
+static int bcompact(bsize, seq)
+ bufsize bsize;
+ int seq;
+{
+#ifdef CompactTries
+ char *bc = bchain;
+ int i = rand() & 0x3;
+
+#ifdef COMPACTRACE
+ V printf("Compaction requested. %ld bytes needed, sequence %d.\n",
+ (long) bsize, seq);
+#endif
+
+ if (protect || (seq > CompactTries)) {
+#ifdef COMPACTRACE
+ V printf("Compaction gave up.\n");
+#endif
+ return 0;
+ }
+
+ /* Based on a random cast, release a random buffer in the list
+ of allocated buffers. */
+
+ while (i > 0 && bc != NULL) {
+ bc = *((char **) bc);
+ i--;
+ }
+ if (bc != NULL) {
+ char *fb;
+
+ fb = *((char **) bc);
+ if (fb != NULL) {
+ *((char **) bc) = *((char **) fb);
+ brel((void *) fb);
+ return 1;
+ }
+ }
+
+#ifdef COMPACTRACE
+ V printf("Compaction bailed out.\n");
+#endif
+#endif /* CompactTries */
+ return 0;
+}
+
+/* BEXPAND -- Expand pool call-back function. */
+
+static void *bexpand(size)
+ bufsize size;
+{
+ void *np = NULL;
+ bufsize cural, totfree, maxfree;
+ long nget, nfree;
+
+ /* Don't expand beyond the total allocated size given by PoolSize. */
+
+ bstats(&cural, &totfree, &maxfree, &nget, &nfree);
+
+ if (cural < PoolSize) {
+ np = (void *) malloc((unsigned) size);
+ }
+#ifdef EXPTRACE
+ V printf("Expand pool by %ld -- %s.\n", (long) size,
+ np == NULL ? "failed" : "succeeded");
+#endif
+ return np;
+}
+
+/* BSHRINK -- Shrink buffer pool call-back function. */
+
+static void bshrink(buf)
+ void *buf;
+{
+ if (((char *) buf) == bp) {
+#ifdef EXPTRACE
+ V printf("Initial pool released.\n");
+#endif
+ bp = NULL;
+ }
+#ifdef EXPTRACE
+ V printf("Shrink pool.\n");
+#endif
+ free((char *) buf);
+}
+
+#endif /* BECtl */
+
+/* Restrict buffer requests to those large enough to contain our pointer and
+ small enough for the CPU architecture. */
+
+static bufsize blimit(bs)
+ bufsize bs;
+{
+ if (bs < sizeof(char *)) {
+ bs = sizeof(char *);
+ }
+
+ /* This is written out in this ugly fashion because the
+ cool expression in sizeof(int) that auto-configured
+ to any length int befuddled some compilers. */
+
+ if (sizeof(int) == 2) {
+ if (bs > 32767) {
+ bs = 32767;
+ }
+ } else {
+ if (bs > 200000) {
+ bs = 200000;
+ }
+ }
+ return bs;
+}
+
+int main()
+{
+ int i;
+ double x;
+
+ /* Seed the random number generator. If Repeatable is defined, we
+ always use the same seed. Otherwise, we seed from the clock to
+ shake things up from run to run. */
+
+#ifdef Repeatable
+ V srand(1234);
+#else
+ V srand((int) time((long *) NULL));
+#endif
+
+ /* Compute x such that pow(x, p) ranges between 1 and 4*ExpIncr as
+ p ranges from 0 to ExpIncr-1, with a concentration in the lower
+ numbers. */
+
+ x = 4.0 * ExpIncr;
+ x = log(x);
+ x = exp(log(4.0 * ExpIncr) / (ExpIncr - 1.0));
+
+#ifdef BECtl
+ bectl(bcompact, bexpand, bshrink, (bufsize) ExpIncr);
+ bp = malloc(ExpIncr);
+ assert(bp != NULL);
+ bpool((void *) bp, (bufsize) ExpIncr);
+#else
+ bp = malloc(PoolSize);
+ assert(bp != NULL);
+ bpool((void *) bp, (bufsize) PoolSize);
+#endif
+
+ stats("Create pool");
+ V bpoolv((void *) bp);
+ bpoold((void *) bp, dumpAlloc, dumpFree);
+
+ for (i = 0; i < TestProg; i++) {
+ char *cb;
+ bufsize bs = pow(x, (double) (rand() & (ExpIncr - 1)));
+
+ assert(bs <= (((bufsize) 4) * ExpIncr));
+ bs = blimit(bs);
+ if (rand() & 0x400) {
+ cb = (char *) bgetz(bs);
+ } else {
+ cb = (char *) bget(bs);
+ }
+ if (cb == NULL) {
+#ifdef EasyOut
+ break;
+#else
+ char *bc = bchain;
+
+ if (bc != NULL) {
+ char *fb;
+
+ fb = *((char **) bc);
+ if (fb != NULL) {
+ *((char **) bc) = *((char **) fb);
+ brel((void *) fb);
+ }
+ continue;
+ }
+#endif
+ }
+ *((char **) cb) = (char *) bchain;
+ bchain = cb;
+
+ /* Based on a random cast, release a random buffer in the list
+ of allocated buffers. */
+
+ if ((rand() & 0x10) == 0) {
+ char *bc = bchain;
+ int i = rand() & 0x3;
+
+ while (i > 0 && bc != NULL) {
+ bc = *((char **) bc);
+ i--;
+ }
+ if (bc != NULL) {
+ char *fb;
+
+ fb = *((char **) bc);
+ if (fb != NULL) {
+ *((char **) bc) = *((char **) fb);
+ brel((void *) fb);
+ }
+ }
+ }
+
+ /* Based on a random cast, reallocate a random buffer in the list
+ to a random size */
+
+ if ((rand() & 0x20) == 0) {
+ char *bc = bchain;
+ int i = rand() & 0x3;
+
+ while (i > 0 && bc != NULL) {
+ bc = *((char **) bc);
+ i--;
+ }
+ if (bc != NULL) {
+ char *fb;
+
+ fb = *((char **) bc);
+ if (fb != NULL) {
+ char *newb;
+
+ bs = pow(x, (double) (rand() & (ExpIncr - 1)));
+ bs = blimit(bs);
+#ifdef BECtl
+ protect = 1; /* Protect against compaction */
+#endif
+ newb = (char *) bgetr((void *) fb, bs);
+#ifdef BECtl
+ protect = 0;
+#endif
+ if (newb != NULL) {
+ *((char **) bc) = newb;
+ }
+ }
+ }
+ }
+ }
+ stats("\nAfter allocation");
+ if (bp != NULL) {
+ V bpoolv((void *) bp);
+ bpoold((void *) bp, dumpAlloc, dumpFree);
+ }
+
+ while (bchain != NULL) {
+ char *buf = bchain;
+
+ bchain = *((char **) buf);
+ brel((void *) buf);
+ }
+ stats("\nAfter release");
+#ifndef BECtl
+ if (bp != NULL) {
+ V bpoolv((void *) bp);
+ bpoold((void *) bp, dumpAlloc, dumpFree);
+ }
+#endif
+
+ return 0;
+}
+#endif
diff --git a/rtl/libsupp.c b/rtl/libsupp.c
index 6236367e414..2c14e3ac997 100644
--- a/rtl/libsupp.c
+++ b/rtl/libsupp.c
@@ -33,7 +33,7 @@ STDCALL
RtlpAllocateMemory(ULONG Bytes,
ULONG Tag)
{
- return MmAllocateMemory(Bytes);
+ return MmHeapAlloc(Bytes);
}
@@ -42,5 +42,5 @@ STDCALL
RtlpFreeMemory(PVOID Mem,
ULONG Tag)
{
- return MmFreeMemory(Mem);
+ return MmHeapFree(Mem);
}
diff --git a/ui/ui.c b/ui/ui.c
index 044d521239a..2e0ba7fb535 100644
--- a/ui/ui.c
+++ b/ui/ui.c
@@ -604,7 +604,7 @@ VOID UiShowMessageBoxesInSection(PCSTR SectionName)
//if (MessageBoxTextSize > 0)
{
// Allocate enough memory to hold the text
- MessageBoxText = MmAllocateMemory(MessageBoxTextSize);
+ MessageBoxText = MmHeapAlloc(MessageBoxTextSize);
if (MessageBoxText)
{
@@ -618,7 +618,7 @@ VOID UiShowMessageBoxesInSection(PCSTR SectionName)
UiMessageBox(MessageBoxText);
// Free the memory
- MmFreeMemory(MessageBoxText);
+ MmHeapFree(MessageBoxText);
}
}
}
diff --git a/windows/peloader.c b/windows/peloader.c
index 93bf88be5d7..cc89a33a391 100644
--- a/windows/peloader.c
+++ b/windows/peloader.c
@@ -170,7 +170,7 @@ WinLdrAllocateDataTableEntry(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
USHORT Length;
/* Allocate memory for a data table entry, zero-initialize it */
- DataTableEntry = (PLDR_DATA_TABLE_ENTRY)MmAllocateMemory(sizeof(LDR_DATA_TABLE_ENTRY));
+ DataTableEntry = (PLDR_DATA_TABLE_ENTRY)MmHeapAlloc(sizeof(LDR_DATA_TABLE_ENTRY));
if (DataTableEntry == NULL)
return FALSE;
RtlZeroMemory(DataTableEntry, sizeof(LDR_DATA_TABLE_ENTRY));
@@ -188,9 +188,12 @@ WinLdrAllocateDataTableEntry(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
/* Initialize BaseDllName field (UNICODE_STRING) from the Ansi BaseDllName
by simple conversion - copying each character */
Length = (USHORT)(strlen(BaseDllName) * sizeof(WCHAR));
- Buffer = (PWSTR)MmAllocateMemory(Length);
+ Buffer = (PWSTR)MmHeapAlloc(Length);
if (Buffer == NULL)
+ {
+ MmHeapFree(DataTableEntry);
return FALSE;
+ }
RtlZeroMemory(Buffer, Length);
DataTableEntry->BaseDllName.Length = Length;
@@ -204,9 +207,12 @@ WinLdrAllocateDataTableEntry(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
/* Initialize FullDllName field (UNICODE_STRING) from the Ansi FullDllName
using the same method */
Length = (USHORT)(strlen(FullDllName) * sizeof(WCHAR));
- Buffer = (PWSTR)MmAllocateMemory(Length);
+ Buffer = (PWSTR)MmHeapAlloc(Length);
if (Buffer == NULL)
+ {
+ MmHeapFree(DataTableEntry);
return FALSE;
+ }
RtlZeroMemory(Buffer, Length);
DataTableEntry->FullDllName.Length = Length;
diff --git a/windows/winldr.c b/windows/winldr.c
index bf184810ca9..db7f51f71cb 100644
--- a/windows/winldr.c
+++ b/windows/winldr.c
@@ -51,7 +51,7 @@ AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK *OutLoaderBlock)
PLOADER_PARAMETER_BLOCK LoaderBlock;
/* Allocate and zero-init the LPB */
- LoaderBlock = MmAllocateMemory(sizeof(LOADER_PARAMETER_BLOCK));
+ LoaderBlock = MmHeapAlloc(sizeof(LOADER_PARAMETER_BLOCK));
RtlZeroMemory(LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
/* Init three critical lists, used right away */
@@ -60,7 +60,7 @@ AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK *OutLoaderBlock)
InitializeListHead(&LoaderBlock->BootDriverListHead);
/* Alloc space for NLS (it will be converted to VA in WinLdrLoadNLS) */
- LoaderBlock->NlsData = MmAllocateMemory(sizeof(NLS_DATA_BLOCK));
+ LoaderBlock->NlsData = MmHeapAlloc(sizeof(NLS_DATA_BLOCK));
if (LoaderBlock->NlsData == NULL)
{
UiMessageBox("Failed to allocate memory for NLS table data!");
@@ -104,32 +104,32 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
DbgPrint((DPRINT_WINDOWS, "Options: %s\n", Options));
/* Fill Arc BootDevice */
- LoaderBlock->ArcBootDeviceName = MmAllocateMemory(strlen(ArcBoot)+1);
+ LoaderBlock->ArcBootDeviceName = MmHeapAlloc(strlen(ArcBoot)+1);
strcpy(LoaderBlock->ArcBootDeviceName, ArcBoot);
LoaderBlock->ArcBootDeviceName = PaToVa(LoaderBlock->ArcBootDeviceName);
/* Fill Arc HalDevice, it matches ArcBoot path */
- LoaderBlock->ArcHalDeviceName = MmAllocateMemory(strlen(ArcBoot)+1);
+ LoaderBlock->ArcHalDeviceName = MmHeapAlloc(strlen(ArcBoot)+1);
strcpy(LoaderBlock->ArcHalDeviceName, ArcBoot);
LoaderBlock->ArcHalDeviceName = PaToVa(LoaderBlock->ArcHalDeviceName);
/* Fill SystemRoot */
- LoaderBlock->NtBootPathName = MmAllocateMemory(strlen(SystemRoot)+1);
+ LoaderBlock->NtBootPathName = MmHeapAlloc(strlen(SystemRoot)+1);
strcpy(LoaderBlock->NtBootPathName, SystemRoot);
LoaderBlock->NtBootPathName = PaToVa(LoaderBlock->NtBootPathName);
/* Fill NtHalPathName */
- LoaderBlock->NtHalPathName = MmAllocateMemory(strlen(HalPath)+1);
+ LoaderBlock->NtHalPathName = MmHeapAlloc(strlen(HalPath)+1);
strcpy(LoaderBlock->NtHalPathName, HalPath);
LoaderBlock->NtHalPathName = PaToVa(LoaderBlock->NtHalPathName);
/* Fill load options */
- LoaderBlock->LoadOptions = MmAllocateMemory(strlen(Options)+1);
+ LoaderBlock->LoadOptions = MmHeapAlloc(strlen(Options)+1);
strcpy(LoaderBlock->LoadOptions, Options);
LoaderBlock->LoadOptions = PaToVa(LoaderBlock->LoadOptions);
/* Arc devices */
- LoaderBlock->ArcDiskInformation = (PARC_DISK_INFORMATION)MmAllocateMemory(sizeof(ARC_DISK_INFORMATION));
+ LoaderBlock->ArcDiskInformation = (PARC_DISK_INFORMATION)MmHeapAlloc(sizeof(ARC_DISK_INFORMATION));
InitializeListHead(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead);
/* Convert ARC disk information from freeldr to a correct format */
@@ -138,7 +138,7 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
PARC_DISK_SIGNATURE ArcDiskInfo;
/* Get the ARC structure */
- ArcDiskInfo = (PARC_DISK_SIGNATURE)MmAllocateMemory(sizeof(ARC_DISK_SIGNATURE));//&BldrDiskInfo[i];
+ ArcDiskInfo = (PARC_DISK_SIGNATURE)MmHeapAlloc(sizeof(ARC_DISK_SIGNATURE));//&BldrDiskInfo[i];
RtlZeroMemory(ArcDiskInfo, sizeof(ARC_DISK_SIGNATURE));
/* Copy the data over */
@@ -179,7 +179,7 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
List_PaToVa(&LoaderBlock->BootDriverListHead);
/* Initialize Extension now */
- Extension = MmAllocateMemory(sizeof(LOADER_PARAMETER_EXTENSION));
+ Extension = MmHeapAlloc(sizeof(LOADER_PARAMETER_EXTENSION));
if (Extension == NULL)
{
UiMessageBox("Failed to allocate LPB Extension!");
diff --git a/windows/wlmemory.c b/windows/wlmemory.c
index 9fa72ae562c..8835702a0f5 100644
--- a/windows/wlmemory.c
+++ b/windows/wlmemory.c
@@ -162,6 +162,9 @@ MempAllocatePageTables()
PhysicalPageTablesBuffer = &Buffer[MM_PAGE_SIZE*2];
KernelPageTablesBuffer = PhysicalPageTablesBuffer + NumPageTables*MM_PAGE_SIZE;
+ // Mark physical PTE's buffer as FirmwareTemporary
+ //MmSetMemoryType(KernelPageTablesBuffer, NumPageTables*MM_PAGE_SIZE, LoaderFirmwareTemporary);
+
// Zero counters of page tables used
PhysicalPageTables = 0;
KernelPageTables = 0;
@@ -842,118 +845,9 @@ WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss)
// Some unused descriptors should go here
// ...
- //
- // Fill IDT with Traps
- //
-#if 0
- pIdt[0].Offset = (i386DivideByZero | KSEG0_BASE) & 0xFFFF;
- pIdt[0].ExtendedOffset = 0x8; // Selector
- pIdt[0].Access = 0x8F00;
- pIdt[0].Selector = (i386DivideByZero | KSEG0_BASE) >> 16; // Extended Offset
-
- pIdt[1].Offset = (i386DebugException | KSEG0_BASE) & 0xFFFF;
- pIdt[1].ExtendedOffset = 0x8; // Selector
- pIdt[1].Access = 0x8F00;
- pIdt[1].Selector = (i386DebugException | KSEG0_BASE) >> 16; // Extended Offset
-
- pIdt[2].Offset = (i386NMIException | KSEG0_BASE) & 0xFFFF;
- pIdt[2].ExtendedOffset = 0x8; // Selector
- pIdt[2].Access = 0x8F00;
- pIdt[2].Selector = (i386NMIException | KSEG0_BASE) >> 16; // Extended Offset
-
- pIdt[3].Offset = (i386Breakpoint | KSEG0_BASE) & 0xFFFF;
- pIdt[3].ExtendedOffset = 0x8; // Selector
- pIdt[3].Access = 0x8F00;
- pIdt[3].Selector = (i386Breakpoint | KSEG0_BASE) >> 16; // Extended Offset
-
- pIdt[4].Offset = (i386Overflow | KSEG0_BASE) & 0xFFFF;
- pIdt[4].ExtendedOffset = 0x8; // Selector
- pIdt[4].Access = 0x8F00;
- pIdt[4].Selector = (i386Overflow | KSEG0_BASE) >> 16; // Extended Offset
-
- pIdt[5].Selector = (i386BoundException | KSEG0_BASE) >> 16; // Extended Offset
- pIdt[5].Offset = (i386BoundException | KSEG0_BASE) & 0xFFFF;
- pIdt[5].ExtendedOffset = 0x8; // Selector
- pIdt[5].Access = 0x8F00;
-
- pIdt[6].Selector = (i386InvalidOpcode | KSEG0_BASE) >> 16; // Extended Offset
- pIdt[6].Offset = (i386InvalidOpcode | KSEG0_BASE) & 0xFFFF;
- pIdt[6].ExtendedOffset = 0x8; // Selector
- pIdt[6].Access = 0x8F00;
-
- pIdt[7].Selector = (i386FPUNotAvailable | KSEG0_BASE) >> 16; // Extended Offset
- pIdt[7].Offset = (i386FPUNotAvailable | KSEG0_BASE) & 0xFFFF;
- pIdt[7].ExtendedOffset = 0x8; // Selector
- pIdt[7].Access = 0x8F00;
-
- pIdt[8].Selector = (i386DoubleFault | KSEG0_BASE) >> 16; // Extended Offset
- pIdt[8].Offset = (i386DoubleFault | KSEG0_BASE) & 0xFFFF;
- pIdt[8].ExtendedOffset = 0x8; // Selector
- pIdt[8].Access = 0x8F00;
-
- pIdt[9].Selector = (i386CoprocessorSegment | KSEG0_BASE) >> 16; // Extended Offset
- pIdt[9].Offset = (i386CoprocessorSegment | KSEG0_BASE) & 0xFFFF;
- pIdt[9].ExtendedOffset = 0x8; // Selector
- pIdt[9].Access = 0x8F00;
-
- pIdt[10].Selector = (i386InvalidTSS | KSEG0_BASE) >> 16; // Extended Offset
- pIdt[10].Offset = (i386InvalidTSS | KSEG0_BASE) & 0xFFFF;
- pIdt[10].ExtendedOffset = 0x8; // Selector
- pIdt[10].Access = 0x8F00;
-
- pIdt[11].Selector = (i386SegmentNotPresent | KSEG0_BASE) >> 16; // Extended Offset
- pIdt[11].Offset = (i386SegmentNotPresent | KSEG0_BASE) & 0xFFFF;
- pIdt[11].ExtendedOffset = 0x8; // Selector
- pIdt[11].Access = 0x8F00;
-
- pIdt[12].Selector = (i386StackException | KSEG0_BASE) >> 16; // Extended Offset
- pIdt[12].Offset = (i386StackException | KSEG0_BASE) & 0xFFFF;
- pIdt[12].ExtendedOffset = 0x8; // Selector
- pIdt[12].Access = 0x8F00;
-
- pIdt[13].Selector = (i386GeneralProtectionFault | KSEG0_BASE) >> 16; // Extended Offset
- pIdt[13].Offset = (i386GeneralProtectionFault | KSEG0_BASE) & 0xFFFF;
- pIdt[13].ExtendedOffset = 0x8; // Selector
- pIdt[13].Access = 0x8F00;
-
- pIdt[14].Selector = (i386PageFault | KSEG0_BASE) >> 16; // Extended Offset
- pIdt[14].Offset = (i386PageFault | KSEG0_BASE) & 0xFFFF;
- pIdt[14].ExtendedOffset = 0x8; // Selector
- pIdt[14].Access = 0x8F00;
-
- pIdt[15].Selector = 0; // Extended Offset
- pIdt[15].Offset = 0;
- pIdt[15].ExtendedOffset = 0; // Selector
- pIdt[15].Access = 0;
-
- pIdt[16].Selector = (i386CoprocessorError | KSEG0_BASE) >> 16; // Extended Offset
- pIdt[16].Offset = (i386CoprocessorError | KSEG0_BASE) & 0xFFFF;
- pIdt[16].ExtendedOffset = 0x8; // Selector
- pIdt[16].Access = 0x8F00;
-
- pIdt[17].Selector = (i386AlignmentCheck | KSEG0_BASE) >> 16; // Extended Offset
- pIdt[17].Offset = (i386AlignmentCheck | KSEG0_BASE) & 0xFFFF;
- pIdt[17].ExtendedOffset = 0x8; // Selector
- pIdt[17].Access = 0x8F00;
-#endif
-
- /*for (i=0; i<16; i++)
- {
- //pIdt[i].Offset = ((ULONG_PTR)i386GeneralProtectionFault | KSEG0_BASE) & 0xFFFF;
- //pIdt[i].ExtendedOffset = 0x8; // Selector
- //pIdt[i].Access = 0x8F00;
- //pIdt[i].Selector = ((ULONG_PTR)i386GeneralProtectionFault | KSEG0_BASE) >> 16; // Extended Offset
-
- pIdt[i].Offset = ((ULONG_PTR)i386GeneralProtectionFault | KSEG0_BASE) & 0xFFFF;
- pIdt[i].ExtendedOffset = ((ULONG_PTR)i386GeneralProtectionFault | KSEG0_BASE) >> 16; // Extended Offset
- pIdt[i].Access = 0x8F00;
- pIdt[i].Selector = 0x8;
- }*/
-
// Copy the old IDT
RtlCopyMemory(pIdt, (PVOID)OldIdt.Base, OldIdt.Limit);
-
// Mask interrupts
//asm("cli\n"); // they are already masked before enabling paged mode
diff --git a/windows/wlregistry.c b/windows/wlregistry.c
index 95690b8eb22..278a1afd870 100644
--- a/windows/wlregistry.c
+++ b/windows/wlregistry.c
@@ -669,7 +669,7 @@ WinLdrAddDriverToList(LIST_ENTRY *BootDriverListHead,
NTSTATUS Status;
ULONG PathLength;
- BootDriverEntry = MmAllocateMemory(sizeof(BOOT_DRIVER_LIST_ENTRY));
+ BootDriverEntry = MmHeapAlloc(sizeof(BOOT_DRIVER_LIST_ENTRY));
if (!BootDriverEntry)
return FALSE;
@@ -686,14 +686,21 @@ WinLdrAddDriverToList(LIST_ENTRY *BootDriverListHead,
BootDriverEntry->FilePath.Length = 0;
BootDriverEntry->FilePath.MaximumLength = PathLength + sizeof(WCHAR);
- BootDriverEntry->FilePath.Buffer = MmAllocateMemory(PathLength);
+ BootDriverEntry->FilePath.Buffer = MmHeapAlloc(PathLength);
if (!BootDriverEntry->FilePath.Buffer)
+ {
+ MmHeapFree(BootDriverEntry);
return FALSE;
+ }
Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, ImagePath);
if (!NT_SUCCESS(Status))
+ {
+ MmHeapFree(BootDriverEntry->FilePath.Buffer);
+ MmHeapFree(BootDriverEntry);
return FALSE;
+ }
}
else
{
@@ -701,29 +708,44 @@ WinLdrAddDriverToList(LIST_ENTRY *BootDriverListHead,
PathLength = wcslen(ServiceName)*sizeof(WCHAR) + sizeof(L"system32\\drivers\\.sys");;
BootDriverEntry->FilePath.Length = 0;
BootDriverEntry->FilePath.MaximumLength = PathLength+sizeof(WCHAR);
- BootDriverEntry->FilePath.Buffer = MmAllocateMemory(PathLength);
+ BootDriverEntry->FilePath.Buffer = MmHeapAlloc(PathLength);
if (!BootDriverEntry->FilePath.Buffer)
+ {
+ MmHeapFree(BootDriverEntry);
return FALSE;
+ }
Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, L"system32\\drivers\\");
if (!NT_SUCCESS(Status))
+ {
+ MmHeapFree(BootDriverEntry->FilePath.Buffer);
+ MmHeapFree(BootDriverEntry);
return FALSE;
+ }
Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, ServiceName);
if (!NT_SUCCESS(Status))
+ {
+ MmHeapFree(BootDriverEntry->FilePath.Buffer);
+ MmHeapFree(BootDriverEntry);
return FALSE;
+ }
Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, L".sys");
if (!NT_SUCCESS(Status))
+ {
+ MmHeapFree(BootDriverEntry->FilePath.Buffer);
+ MmHeapFree(BootDriverEntry);
return FALSE;
+ }
}
// Add registry path
PathLength = (wcslen(RegistryPath)+wcslen(ServiceName))*sizeof(WCHAR);
BootDriverEntry->RegistryPath.Length = 0;
BootDriverEntry->RegistryPath.MaximumLength = PathLength;//+sizeof(WCHAR);
- BootDriverEntry->RegistryPath.Buffer = MmAllocateMemory(PathLength);
+ BootDriverEntry->RegistryPath.Buffer = MmHeapAlloc(PathLength);
if (!BootDriverEntry->RegistryPath.Buffer)
return FALSE;