You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
284 lines
10 KiB
284 lines
10 KiB
// Ruler
|
|
// 1 2 3 4 5 6 7 8
|
|
//345678901234567890123456789012345678901234567890123456789012345678901234567890
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* The standard layout. */
|
|
/* */
|
|
/* The standard layout for 'cpp' files in this code is as */
|
|
/* follows: */
|
|
/* */
|
|
/* 1. Include files. */
|
|
/* 2. Constants local to the class. */
|
|
/* 3. Data structures local to the class. */
|
|
/* 4. Data initializations. */
|
|
/* 5. Static functions. */
|
|
/* 6. Class functions. */
|
|
/* */
|
|
/* The constructor is typically the first function, class */
|
|
/* member functions appear in alphabetical order with the */
|
|
/* destructor appearing at the end of the file. Any section */
|
|
/* or function this is not required is simply omitted. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
#include "InterfacePCH.hpp"
|
|
|
|
#include "Common.hpp"
|
|
#include "RockallBackEnd.hpp"
|
|
#include "RockallFrontEnd.hpp"
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* Static member initialization. */
|
|
/* */
|
|
/* Static member initialization sets the initial value for all */
|
|
/* static members. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
#pragma init_seg(compiler)
|
|
ROCKALL_BACK_END ROCKALL_BACK_END::DefaultBaseClass;
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* Class constructor. */
|
|
/* */
|
|
/* The may be a situation where the Rockall Back End needs a */
|
|
/* constructor but this is certainly not expected to be */
|
|
/* very common. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
ROCKALL_BACK_END::ROCKALL_BACK_END( void )
|
|
{ /* void */ }
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* Delete allocation area. */
|
|
/* */
|
|
/* All memory requests are eventually sent back to the external */
|
|
/* deallocator. This function can be overloaded so that memory */
|
|
/* can be provided from any source. The default is to send */
|
|
/* it back to the operating system. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
void ROCKALL_BACK_END::DeleteArea( void *Memory,int Size,bool User )
|
|
{
|
|
REGISTER DWORD NewSize = ((Size == 0) ? Size : 0);
|
|
|
|
#ifdef DEBUGGING
|
|
#ifdef ENABLE_ALLOCATION_STATISTICS
|
|
//
|
|
// When we are debugging print out trace information.
|
|
//
|
|
DebugPrint( "Delete\t 0x%08x %d bytes\n",Memory,Size );
|
|
|
|
#endif
|
|
#endif
|
|
//
|
|
// The NT 'VirtualFree' call requires the 'Size'
|
|
// to be zero. This may not be true of all
|
|
// deallocators so we pass the value and then
|
|
// replace it with zero above.
|
|
//
|
|
if ( VirtualFree( Memory,NewSize,MEM_RELEASE ) == NULL )
|
|
{ Failure( "Delete fails in DeleteArea" ); }
|
|
}
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* The natural allocation size. */
|
|
/* */
|
|
/* We would like to know a good default size for allocations. */
|
|
/* We really don't have a clue so we ask the operating system */
|
|
/* for the size of an allocation granual. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
int ROCKALL_BACK_END::NaturalSize( void )
|
|
{
|
|
STATIC SBIT32 AllocationSize = 0;
|
|
|
|
//
|
|
// Ask the operation system for the allocation
|
|
// granularity.
|
|
//
|
|
if ( AllocationSize <= 0 )
|
|
{
|
|
AUTO SYSTEM_INFO SystemInformation;
|
|
|
|
GetSystemInfo( & SystemInformation );
|
|
|
|
AllocationSize = (SBIT32) SystemInformation.dwAllocationGranularity;
|
|
}
|
|
|
|
return ((int) AllocationSize);
|
|
}
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* New allocation area. */
|
|
/* */
|
|
/* All memory requests are eventually sent to the new external */
|
|
/* allocator. This function can be overloaded so that memory */
|
|
/* can be provided from any source. The default is to get */
|
|
/* new memory from the operating system. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
void *ROCKALL_BACK_END::NewArea( int AlignMask,int Size,bool User )
|
|
{
|
|
//
|
|
// When there is an alignment requirement greater
|
|
// than the natural alignment provided by the
|
|
// operating system we have to play various tricks
|
|
// to allocate a suitable block. If not then we
|
|
// just do a normal allocation call.
|
|
//
|
|
if ( AlignMask > NaturalSize() )
|
|
{
|
|
REGISTER SBIT32 NewSize = (AlignMask + Size);
|
|
|
|
//
|
|
// We need to allocate a block with an
|
|
// alignment requirement greater than
|
|
// the operating system default. So we
|
|
// allocate a much larger block and
|
|
// release the parts we don't need.
|
|
//
|
|
while ( True )
|
|
{
|
|
REGISTER VOID *Reserved =
|
|
(
|
|
VirtualAlloc
|
|
(
|
|
NULL,
|
|
((DWORD) NewSize),
|
|
MEM_RESERVE,
|
|
PAGE_READWRITE
|
|
)
|
|
);
|
|
|
|
//
|
|
// Lets ensure we were able to find a suitable
|
|
// memory block. If not then we exit.
|
|
//
|
|
if ( Reserved != NULL )
|
|
{
|
|
//
|
|
// We just want to return the parts of
|
|
// the block we don't need but 'NT' is
|
|
// not smart enough. So we free the
|
|
// entire block.
|
|
//
|
|
if ( VirtualFree( Reserved,0,MEM_RELEASE ) )
|
|
{
|
|
REGISTER LONG Address = ((LONG) Reserved);
|
|
REGISTER VOID *NewMemory;
|
|
|
|
//
|
|
// Compute the base address of the part
|
|
// of the block we really want to allocate.
|
|
//
|
|
Address = ((Address + AlignMask) & ~AlignMask);
|
|
|
|
//
|
|
// Finally, lets reallocate the part of
|
|
// the block we wanted but just released
|
|
// and hope that nobody else got it before
|
|
// us.
|
|
//
|
|
NewMemory =
|
|
(
|
|
VirtualAlloc
|
|
(
|
|
((LPVOID) Address),
|
|
((DWORD) Size),
|
|
(MEM_RESERVE | MEM_COMMIT),
|
|
PAGE_READWRITE
|
|
)
|
|
);
|
|
|
|
//
|
|
// If it all worked we can exit.
|
|
//
|
|
if ( NewMemory != NULL )
|
|
{
|
|
#ifdef DEBUGGING
|
|
#ifdef ENABLE_ALLOCATION_STATISTICS
|
|
//
|
|
// When we are debugging output
|
|
// out trace information.
|
|
//
|
|
DebugPrint
|
|
(
|
|
"New\t\t 0x%08x %d bytes\n",
|
|
NewMemory,
|
|
Size
|
|
);
|
|
|
|
#endif
|
|
#endif
|
|
return ((void*) NewMemory);
|
|
}
|
|
}
|
|
else
|
|
{ return ((void*) AllocationFailure); }
|
|
|
|
}
|
|
else
|
|
{ return ((void*) AllocationFailure); }
|
|
}
|
|
}
|
|
else
|
|
{
|
|
REGISTER VOID *NewMemory;
|
|
|
|
//
|
|
// We can allocate directly from the operating
|
|
// system as the default alignment requirement
|
|
// is enough for this case.
|
|
//
|
|
NewMemory =
|
|
(
|
|
VirtualAlloc
|
|
(
|
|
NULL,
|
|
((DWORD) Size),
|
|
MEM_COMMIT,
|
|
PAGE_READWRITE
|
|
)
|
|
);
|
|
#ifdef DEBUGGING
|
|
#ifdef ENABLE_ALLOCATION_STATISTICS
|
|
|
|
if ( NewMemory != NULL )
|
|
{
|
|
//
|
|
// When we are debugging output out trace
|
|
// information.
|
|
//
|
|
DebugPrint( "New\t\t 0x%08x %d bytes\n",NewMemory,Size );
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
return ((void*) NewMemory);
|
|
}
|
|
}
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* Class destructor. */
|
|
/* */
|
|
/* The may be a situation where the Rockall Back End needs a */
|
|
/* destructor but this is certainly not expected to be */
|
|
/* very common. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
ROCKALL_BACK_END::~ROCKALL_BACK_END( void )
|
|
{ /* void */ }
|