277 lines
6.8 KiB
Plaintext
277 lines
6.8 KiB
Plaintext
|
/*++
|
||
|
|
||
|
Copyright (c) 1992 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
suballoc.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module contains code for managing a paritially commited address
|
||
|
space. It handles allocation of chunks of memory smaller than the
|
||
|
commit granularity. It commits and decommits memory as needed using
|
||
|
the supplied function for committing and decommitting memory. The
|
||
|
structures used for tracking the address space are allocated outside
|
||
|
of the specified addresss space.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Dave Hastings (daveh) creation-date 21-Jan-1994
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
Since this package does not actually access memory in the address space
|
||
|
it is managing, it will work as well with real linear addresses or
|
||
|
"Intel Addresses" such as would be encountered with the Insignia Emulator
|
||
|
on risc.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
|
||
|
--*/
|
||
|
|
||
|
//
|
||
|
// Constants
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Smallest chunk that will be sub allocated
|
||
|
// 1024 was chosen currently, because that is the
|
||
|
// smallest chunk XMS will allocate.
|
||
|
//
|
||
|
#define SUBALLOC_GRANULARITY 1024
|
||
|
|
||
|
//
|
||
|
// The size of the character array require to hold the
|
||
|
// bits defining whether the individual allocation entities
|
||
|
// in the commited chunk are allocated or free
|
||
|
//
|
||
|
// BUGBUG Assert that COMMIT_GRANULARITY is a multiple of SUBALLOC_GRANULARITY
|
||
|
//
|
||
|
#define SUBALLOC_BITFIELD_SIZE COMMIT_GRANULARITY / SUBALLOC_GRANULARITY
|
||
|
|
||
|
//
|
||
|
// Types
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Routine for committing a specific region of of the address
|
||
|
// space. Although the return type is NTSTATUS, the only value
|
||
|
// that is checked is 0 (for STATUS_SUCCESS). If STATUS_SUCCESS
|
||
|
// is returned, it is assumed that the function worked. If not,
|
||
|
// it is assumed that it failed. No special meaning is attached to
|
||
|
// particular non-zero values.
|
||
|
//
|
||
|
typedef
|
||
|
NTSTATUS
|
||
|
(*PSACOMMITROUTINE)(
|
||
|
ULONG BaseAddress,
|
||
|
ULONG Size
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// Structure for tracking the address space. Each chunk of
|
||
|
// memory of SUBALLOC_GRANULARITY in size is represented by
|
||
|
// a bit. Each chunk of memory of COMMIT_GRANULARITY is
|
||
|
// represented by one element of the array of bitfields.
|
||
|
// The FreeCheck array half of the union allows us to check
|
||
|
// whether the entire committed chunk is free more quickly.
|
||
|
//
|
||
|
// ?? Should we add a field to indicate whether the chunk is
|
||
|
// committed? We can always check for all allocated bits
|
||
|
// zero, and use that as an indication that the chunk is
|
||
|
// not committed.
|
||
|
//
|
||
|
// BUGBUG Assert that the bits fit into memory the way we think
|
||
|
// they do.
|
||
|
//
|
||
|
typedef struct _SubAllocation {
|
||
|
PSACOMMITROUTINE CommitRoutine;
|
||
|
ULONG BaseAddress;
|
||
|
ULONG Size;
|
||
|
union {
|
||
|
//
|
||
|
// bitfield with one bit per chunk. Bit set indicates
|
||
|
// allocated. Bit clear indicates free. All bits
|
||
|
// clear indicates un committed
|
||
|
//
|
||
|
UINT Allocated[SUBALLOC_BITFIELD_SIZE] : 1;
|
||
|
//
|
||
|
// Hopefully a faster way to check all bits.
|
||
|
//
|
||
|
UINT FreeCheck[SUBALLOC_BITFIELD_SIZE / sizeof(UINT)];
|
||
|
} CommitedChunk;
|
||
|
} SUBALLOCATIONDATA, *PSUBALLOCATIONDATA
|
||
|
|
||
|
|
||
|
PVOID
|
||
|
SAInitialize(
|
||
|
ULONG BaseAddress,
|
||
|
ULONG Size,
|
||
|
PSACOMMITROUTINE CommitRoutine
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function performs initialization of the sub allocation package
|
||
|
for the specified addresss range. It allocates the data structures
|
||
|
necessary to track the allocations
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
BaseAddress -- Supplies the base address of the address space to
|
||
|
sub allocate.
|
||
|
Size -- Supplies the size in bytes of the address space to sub allocate.
|
||
|
CommitRoutine -- Supplies a pointer to the routine used to commit regions
|
||
|
of the address space.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
If the function was successful it returns a pointer to the sub-allocation
|
||
|
data structures. Otherwise it returns NULL.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
SAQueryFree(
|
||
|
PVOID SubAllocation,
|
||
|
PULONG FreeBytes
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine returns the number of free bytes in the
|
||
|
sub allocated address space.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
SubAllocation -- Supplies the pointer returned by SAInitialize
|
||
|
FreeBytes -- Returns the number of free bytes
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE -- if successful, and FreeBytes contains the number of free bytes.
|
||
|
FALSE otherwise
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
SAAllocate(
|
||
|
PVOID SubAllocation,
|
||
|
ULONG Size,
|
||
|
PULONG Address
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function allocates a portion of the address space described by
|
||
|
SubAllocation. If necessary, it will commit additional blocks. Address is
|
||
|
rounded down to the next lower SUBALLOC_GRANULARITY boundary.
|
||
|
size is rounded up to the next higher multiple of SUBALLOC_GRANULARITY.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
SubAllocation -- Supplies the pointer returned by SAInitialize.
|
||
|
Size -- Supplies the size in bytes of the region to allocate.
|
||
|
Address -- Returns the address of the region allocated.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if successful. If false is returned, no address is returned.
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
Zero is a valid value for the returned address.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
SAFree(
|
||
|
PVOID SubAllocation,
|
||
|
ULONG Size,
|
||
|
ULONG Address
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine frees a sub-allocated chunk of memory. If the
|
||
|
entire commited block (or blocks) that the specified chunk
|
||
|
belongs to are free, the chunks are decommitted. Address is
|
||
|
rounded down to the next lower SUBALLOC_GRANULARITY boundary.
|
||
|
size is rounded up to the next higher multiple of SUBALLOC_GRANULARITY.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
SubAllocation -- Supplies the pointer returned by SAInitialize.
|
||
|
Size -- Supplies the size in bytes of the region to free.
|
||
|
Address -- Supplies the address of the region to free.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if successful.
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
It is possible to free a different size at a particular
|
||
|
address than was allocated. This will not cause the
|
||
|
SubAllocation package any problems.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
SAReallocate(
|
||
|
PVOID SubAllocation,
|
||
|
ULONG OriginalSize,
|
||
|
ULONG OriginalAddress,
|
||
|
ULONG NewSize,
|
||
|
PULONG NewAddress
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine reallocates a sub allocated block of memory.
|
||
|
The sizes are rounded up to the next SUBALLOC_GRANULARITY.
|
||
|
The Original address is rounded down to the next SUBALLOC_GRANULARITY
|
||
|
boundary. Only min(OriginalSize, NewSize) bytes of data are copied to
|
||
|
the new block. The block changed in place if possible.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
SubAllocation -- Supplies the pointer returned by SAInitialize.
|
||
|
OriginalSize -- Supplies the old size in bytes of the block.
|
||
|
OriginalAddress -- Supplies the old address of the block.
|
||
|
NewSize -- Supplies the new size in bytes of the block.
|
||
|
NewAddress -- Returns the new address of the block.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
True if successful. If unsucessful, no allocation is changed.
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
If the caller does not supply the correct original size for the block,
|
||
|
some memory may be lost, and the block may be moved unnecessarily.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
|
||
|
}
|