281 lines
6.4 KiB
C
281 lines
6.4 KiB
C
/*++
|
||
|
||
Copyright (c) 1991 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
oscheap.c
|
||
|
||
Abstract:
|
||
|
||
This module contains "local" heap management code for OS Chooser.
|
||
|
||
Author:
|
||
|
||
Geoff Pease (gpease) May 28 1998
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#ifdef i386
|
||
#include "bldrx86.h"
|
||
#endif
|
||
|
||
#if defined(_IA64_)
|
||
#include "bldria64.h"
|
||
#endif
|
||
|
||
#include "netfs.h"
|
||
#include "oscheap.h"
|
||
|
||
#define FREE_POOL_TAG 0x0
|
||
#define ALLOC_POOL_TAG 0x1
|
||
|
||
typedef struct _LOCAL_MEMORY_DESCRIPTOR {
|
||
|
||
//
|
||
// We create a union to make sure that this struct is always at least the size of a
|
||
// pointer, and thus will be pointer aligned.
|
||
//
|
||
union {
|
||
|
||
struct {
|
||
ULONG Tag;
|
||
ULONG Size;
|
||
};
|
||
|
||
struct {
|
||
void *Align;
|
||
};
|
||
|
||
};
|
||
|
||
} LOCAL_MEMORY_DESCRIPTOR, *PLOCAL_MEMORY_DESCRIPTOR;
|
||
|
||
|
||
//
|
||
// Variable for holding our memory together.
|
||
//
|
||
#define OSCHEAPSIZE 0x2000 // 8k
|
||
CHAR OscHeap[ OSCHEAPSIZE ];
|
||
|
||
//
|
||
// Functions
|
||
//
|
||
void
|
||
OscHeapInitialize(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initializes the internal memory management system.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PLOCAL_MEMORY_DESCRIPTOR LocalDescriptor;
|
||
|
||
LocalDescriptor = (PLOCAL_MEMORY_DESCRIPTOR)OscHeap;
|
||
|
||
LocalDescriptor->Tag = FREE_POOL_TAG;
|
||
LocalDescriptor->Size = OSCHEAPSIZE - sizeof(LOCAL_MEMORY_DESCRIPTOR);
|
||
|
||
memset((PVOID)(LocalDescriptor + 1), 0, LocalDescriptor->Size);
|
||
}
|
||
|
||
PCHAR
|
||
OscHeapAlloc(
|
||
IN UINT iSize
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine allocates memory from our internal structures.
|
||
|
||
Arguments:
|
||
|
||
iSize - Number of bytes the client wants.
|
||
|
||
Return Value:
|
||
|
||
A pointer to the allocated block if successful, else NULL
|
||
|
||
--*/
|
||
|
||
{
|
||
PLOCAL_MEMORY_DESCRIPTOR LocalDescriptor;
|
||
PLOCAL_MEMORY_DESCRIPTOR NextDescriptor;
|
||
LONG ThisBlockSize;
|
||
ULONG BytesToAllocate;
|
||
|
||
//
|
||
// Always allocate in increments of a pointer, minmally.
|
||
//
|
||
if (iSize & (sizeof(void *) - 1)) {
|
||
iSize += sizeof(void *) - (iSize & (sizeof(void *) - 1));
|
||
}
|
||
|
||
LocalDescriptor = (PLOCAL_MEMORY_DESCRIPTOR)OscHeap;
|
||
ThisBlockSize = OSCHEAPSIZE - sizeof(LOCAL_MEMORY_DESCRIPTOR);
|
||
|
||
while (ThisBlockSize > 0) {
|
||
|
||
if ((LocalDescriptor->Tag == FREE_POOL_TAG) &&
|
||
(LocalDescriptor->Size >= iSize)) {
|
||
|
||
goto FoundBlock;
|
||
}
|
||
|
||
ThisBlockSize -= (LocalDescriptor->Size + sizeof(LOCAL_MEMORY_DESCRIPTOR));
|
||
LocalDescriptor = (PLOCAL_MEMORY_DESCRIPTOR)(((PUCHAR)LocalDescriptor) +
|
||
LocalDescriptor->Size +
|
||
sizeof(LOCAL_MEMORY_DESCRIPTOR)
|
||
);
|
||
}
|
||
|
||
//
|
||
// There is no memory block big enough to hold the request.
|
||
//
|
||
return NULL;
|
||
|
||
FoundBlock:
|
||
|
||
//
|
||
// Jump to here when a memory descriptor of the right size has been found. It is expected that
|
||
// LocalDescriptor points to the correct block.
|
||
//
|
||
if (LocalDescriptor->Size > iSize + sizeof(LOCAL_MEMORY_DESCRIPTOR)) {
|
||
|
||
//
|
||
// Make a descriptor of the left over parts of this block.
|
||
//
|
||
NextDescriptor = (PLOCAL_MEMORY_DESCRIPTOR)(((PUCHAR)LocalDescriptor) +
|
||
sizeof(LOCAL_MEMORY_DESCRIPTOR) +
|
||
iSize
|
||
);
|
||
|
||
NextDescriptor->Tag = FREE_POOL_TAG;
|
||
NextDescriptor->Size = (ULONG)(LocalDescriptor->Size - iSize - sizeof(LOCAL_MEMORY_DESCRIPTOR));
|
||
LocalDescriptor->Size = (ULONG)iSize;
|
||
|
||
}
|
||
|
||
LocalDescriptor->Tag = ALLOC_POOL_TAG;
|
||
|
||
memset((LocalDescriptor+1), 0, iSize);
|
||
|
||
return (PCHAR)(LocalDescriptor + 1);
|
||
|
||
}
|
||
|
||
PCHAR
|
||
OscHeapFree(
|
||
IN PCHAR Pointer
|
||
)
|
||
|
||
/*++
|
||
|
||
|
||
Routine Description:
|
||
|
||
This routine frees a block previously allocated from the internal memory management system.
|
||
|
||
Arguments:
|
||
|
||
Pointer - A pointer to free.
|
||
|
||
Return Value:
|
||
|
||
NULL.
|
||
|
||
--*/
|
||
|
||
{
|
||
LONG ThisBlockSize;
|
||
PLOCAL_MEMORY_DESCRIPTOR LocalDescriptor;
|
||
PLOCAL_MEMORY_DESCRIPTOR PrevDescriptor;
|
||
PLOCAL_MEMORY_DESCRIPTOR ThisDescriptor;
|
||
|
||
LocalDescriptor = (PLOCAL_MEMORY_DESCRIPTOR)(((PUCHAR)Pointer) - sizeof(LOCAL_MEMORY_DESCRIPTOR));
|
||
|
||
//
|
||
// Find the memory block in the heap
|
||
//
|
||
PrevDescriptor = NULL;
|
||
ThisDescriptor = (PLOCAL_MEMORY_DESCRIPTOR)OscHeap;
|
||
ThisBlockSize = OSCHEAPSIZE - sizeof(LOCAL_MEMORY_DESCRIPTOR);
|
||
|
||
while (ThisBlockSize > 0) {
|
||
|
||
if (ThisDescriptor == LocalDescriptor) {
|
||
goto FoundBlock;
|
||
}
|
||
|
||
ThisBlockSize -= (ThisDescriptor->Size + sizeof(LOCAL_MEMORY_DESCRIPTOR));
|
||
|
||
PrevDescriptor = ThisDescriptor;
|
||
ThisDescriptor = (PLOCAL_MEMORY_DESCRIPTOR)(((PUCHAR)ThisDescriptor) +
|
||
ThisDescriptor->Size +
|
||
sizeof(LOCAL_MEMORY_DESCRIPTOR)
|
||
);
|
||
}
|
||
|
||
return NULL;
|
||
|
||
FoundBlock:
|
||
|
||
//
|
||
// Jump to here when the proper memory descriptor has been found.
|
||
//
|
||
|
||
if (LocalDescriptor->Tag == FREE_POOL_TAG) {
|
||
//
|
||
// Ouch! We tried to free something twice, skip it before bad things happen.
|
||
//
|
||
return NULL;
|
||
}
|
||
|
||
LocalDescriptor->Tag = FREE_POOL_TAG;
|
||
|
||
//
|
||
// If possible, merge this memory block with the next one.
|
||
//
|
||
if ((ULONG)ThisBlockSize > (LocalDescriptor->Size + sizeof(LOCAL_MEMORY_DESCRIPTOR))) {
|
||
ThisDescriptor = (PLOCAL_MEMORY_DESCRIPTOR)(((PUCHAR)LocalDescriptor) +
|
||
LocalDescriptor->Size +
|
||
sizeof(LOCAL_MEMORY_DESCRIPTOR)
|
||
);
|
||
if (ThisDescriptor->Tag == FREE_POOL_TAG) {
|
||
LocalDescriptor->Size += ThisDescriptor->Size + sizeof(LOCAL_MEMORY_DESCRIPTOR);
|
||
ThisDescriptor->Tag = 0;
|
||
ThisDescriptor->Size = 0;
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// Now see if we can merge this block with a previous block.
|
||
//
|
||
if ((PrevDescriptor != NULL) && (PrevDescriptor->Tag == FREE_POOL_TAG)) {
|
||
PrevDescriptor->Size += LocalDescriptor->Size + sizeof(LOCAL_MEMORY_DESCRIPTOR);
|
||
LocalDescriptor->Tag = 0;
|
||
LocalDescriptor->Size = 0;
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|