mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-10 02:28:22 +02:00
161 lines
4.6 KiB
PHP
161 lines
4.6 KiB
PHP
{
|
|
Basic heap handling for windows platforms
|
|
|
|
This file is part of the Free Pascal run time library.
|
|
Copyright (c) 2001-2005 by Free Pascal development team
|
|
|
|
See the file COPYING.FPC, included in this distribution,
|
|
for details about the copyright.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
**********************************************************************}
|
|
|
|
|
|
{*****************************************************************************
|
|
OS Memory allocation / deallocation
|
|
****************************************************************************}
|
|
|
|
{ In kernel mode we can either use FPC's build in memory manager or we use a
|
|
custom non-chunking manager. The problem with the build in one is that the
|
|
driver developer has far less control of the allocated memory blocks. }
|
|
|
|
{ memory functions }
|
|
{$ifdef KMODE}
|
|
function ExAllocatePoolWithTag(PoolType: LongInt; NumberOfBytes: PtrUInt; Tag: LongWord): Pointer; stdcall; external ntdll name 'ExAllocatePoolWithTag';
|
|
procedure ExFreePoolWithTag(P: Pointer; Tag: LongWord); stdcall; external ntdll name 'ExFreePoolWithTag';
|
|
{$else KMODE}
|
|
function RtlAllocateHeap(hHeap : THandle; dwFlags : LongWord; Size : PtrUInt): Pointer;
|
|
stdcall; external ntdll name 'RtlAllocateHeap';
|
|
function RtlFreeHeap(hHeap : THandle; dwFlags : LongWord; MemoryPointer : Pointer): Boolean;
|
|
stdcall; external ntdll name 'RtlFreeHeap';
|
|
function RtlCreateHeap(Flags: LongWord; Base: Pointer; SizeToReserve: PtrUInt;
|
|
SizeToCommit: PtrUInt; Lock: Pointer; Parameters: Pointer): THandle;
|
|
stdcall; external ntdll name 'RtlCreateHeap';
|
|
|
|
var
|
|
SysHeap: THandle = 0;
|
|
|
|
procedure PrepareSysHeap;
|
|
begin
|
|
if IsLibrary then
|
|
// create a new heap (flag is HEAP_GROWABLE)
|
|
SysHeap := RtlCreateHeap(2, Nil, 65534, 65534, Nil, Nil)
|
|
else
|
|
// use the heap passed on startup
|
|
SysHeap := THandle(PSimplePEB(CurrentPEB)^.ProcessHeap);
|
|
end;
|
|
|
|
{$endif KMODE}
|
|
|
|
{$ifndef KMODE}
|
|
|
|
// default memory manager
|
|
|
|
function SysOSAlloc(size: ptruint): pointer;
|
|
begin
|
|
if SysHeap = 0 then
|
|
PrepareSysHeap;
|
|
SysOSAlloc := RtlAllocateHeap(SysHeap, 0, size);
|
|
end;
|
|
|
|
{$define HAS_SYSOSFREE}
|
|
|
|
procedure SysOSFree(p: pointer; size: ptruint);
|
|
begin
|
|
// if heap isn't set, then nothing was allocated
|
|
if SysHeap <> 0 then
|
|
RtlFreeHeap(SysHeap, 0, p);
|
|
end;
|
|
|
|
{$else KMODE}
|
|
|
|
// custom non-chunking memory manager for kernel mode
|
|
|
|
// memory layout:
|
|
// <PtrUInt>: Size of reserved chunk
|
|
// <Tag>: Tag that was used in ExAllocateFromPoolWithTag (needed in free)
|
|
// <...>: Userdata
|
|
|
|
function SysGetMem(Size: PtrUInt): Pointer;
|
|
var
|
|
tag: LongWord;
|
|
pooltype: LongInt;
|
|
begin
|
|
if HeapUsePagedPool then
|
|
pooltype := 1
|
|
else
|
|
pooltype := 0;
|
|
tag := Ord(HeapPoolTag[1]) + Ord(HeapPoolTag[2]) shl 8 +
|
|
Ord(HeapPoolTag[3]) shl 16 + Ord(HeapPoolTag[4]) shl 24;
|
|
// the kernel keeps track of our memory, but there's no way to ask it
|
|
// so we need to track the size by ourself
|
|
SysGetMem := ExAllocatePoolWithTag(pooltype, Size + SizeOf(PtrUInt) + SizeOf(LongWord), tag);
|
|
// save the size
|
|
PPtrUInt(SysGetMem)^ := Size;
|
|
SysGetMem := SysGetMem + SizeOf(PtrUInt);
|
|
// save the tag
|
|
PLongWord(SysGetMem)^ := tag;
|
|
SysGetMem := SysGetMem + SizeOf(LongWord);
|
|
end;
|
|
|
|
function SysFreeMem(p: Pointer): PtrUInt;
|
|
var
|
|
tag: PLongWord;
|
|
begin
|
|
tag := p - SizeOf(LongWord);
|
|
// we need to pass the tag we used to allocate the memory (else: BSOD)
|
|
ExFreePoolWithTag(p - SizeOf(PtrUInt) - SizeOf(LongWord), tag^);
|
|
SysFreeMem := 0;
|
|
end;
|
|
|
|
function SysFreeMemSize(p: Pointer; Size: PtrUInt): PtrUInt;
|
|
begin
|
|
SysFreeMemSize := 0;
|
|
if (Size > 0) and (p <> nil) then
|
|
Result := SysFreeMem(p);
|
|
end;
|
|
|
|
Function SysAllocMem(Size: PtrUInt): Pointer;
|
|
begin
|
|
SysAllocMem := SysGetMem(Size);
|
|
if SysAllocMem <> nil then
|
|
FillChar(SysAllocMem^, Size, 0);
|
|
end;
|
|
|
|
Function SysReAllocMem (var p: pointer; Size: PtrUInt): Pointer;
|
|
begin
|
|
SysReAllocMem := SysGetMem(Size);
|
|
Move(p^, SysReAllocMem^, Size);
|
|
p := SysReAllocMem;
|
|
end;
|
|
|
|
function SysTryResizeMem(var p: Pointer; size: PtrUInt): Boolean;
|
|
var
|
|
res: pointer;
|
|
begin
|
|
res := SysGetMem(Size);
|
|
SysTryResizeMem := (res <> Nil) or (Size = 0);
|
|
if SysTryResizeMem then
|
|
p := res;
|
|
end;
|
|
|
|
function SysMemSize(P : pointer): PtrUInt;
|
|
begin
|
|
SysMemSize := PPtrUInt(P - SizeOf(PtrUInt) - SizeOf(LongWord))^;
|
|
end;
|
|
|
|
function SysGetHeapStatus: THeapStatus;
|
|
begin
|
|
FillChar(SysGetHeapStatus, SizeOf(SysGetHeapStatus), 0);
|
|
end;
|
|
|
|
function SysGetFPCHeapStatus: TFPCHeapStatus;
|
|
begin
|
|
FillChar(SysGetFPCHeapStatus, SizeOf(SysGetHeapStatus), 0);
|
|
end;
|
|
|
|
{$endif KMODE}
|