|
@@ -21,29 +21,25 @@
|
|
{ DEBUG: Dump info when the heap needs to grow }
|
|
{ DEBUG: Dump info when the heap needs to grow }
|
|
{ define DUMPGROW}
|
|
{ define DUMPGROW}
|
|
|
|
|
|
-{ DEBUG: Test the FreeList on correctness }
|
|
|
|
-
|
|
|
|
-{$ifdef SYSTEMDEBUG}
|
|
|
|
-{$define TestFreeLists}
|
|
|
|
-{$endif SYSTEMDEBUG}
|
|
|
|
-
|
|
|
|
const
|
|
const
|
|
{$ifdef CPU64}
|
|
{$ifdef CPU64}
|
|
blocksize = 32; { at least size of freerecord }
|
|
blocksize = 32; { at least size of freerecord }
|
|
- blockshr = 5; { shr value for blocksize=2^blockshr}
|
|
|
|
|
|
+ blockshift = 5; { shr value for blocksize=2^blockshift}
|
|
maxblocksize = 512+blocksize; { 1024+8 needed for heaprecord }
|
|
maxblocksize = 512+blocksize; { 1024+8 needed for heaprecord }
|
|
{$else}
|
|
{$else}
|
|
blocksize = 16; { at least size of freerecord }
|
|
blocksize = 16; { at least size of freerecord }
|
|
- blockshr = 4; { shr value for blocksize=2^blockshr}
|
|
|
|
|
|
+ blockshift = 4; { shr value for blocksize=2^blockshift}
|
|
maxblocksize = 512+blocksize; { 1024+8 needed for heaprecord }
|
|
maxblocksize = 512+blocksize; { 1024+8 needed for heaprecord }
|
|
{$endif}
|
|
{$endif}
|
|
maxblockindex = maxblocksize div blocksize; { highest index in array of lists of memchunks }
|
|
maxblockindex = maxblocksize div blocksize; { highest index in array of lists of memchunks }
|
|
maxreusebigger = 8; { max reuse bigger tries }
|
|
maxreusebigger = 8; { max reuse bigger tries }
|
|
|
|
|
|
- usedflag = 1; { flag if the block is used or not }
|
|
|
|
- lastblockflag = 2; { flag if the block is the last in os chunk }
|
|
|
|
- firstblockflag = 4; { flag if the block is the first in os chunk }
|
|
|
|
- fixedsizeflag = 8; { flag if the block is of fixed size }
|
|
|
|
|
|
+ { common flags }
|
|
|
|
+ fixedsizeflag = 1; { flag if the block is of fixed size }
|
|
|
|
+ { memchunk var flags }
|
|
|
|
+ usedflag = 2; { flag if the block is used or not }
|
|
|
|
+ lastblockflag = 4; { flag if the block is the last in os chunk }
|
|
|
|
+ firstblockflag = 8; { flag if the block is the first in os chunk }
|
|
sizemask = not(blocksize-1);
|
|
sizemask = not(blocksize-1);
|
|
fixedsizemask = sizemask and $ffff;
|
|
fixedsizemask = sizemask and $ffff;
|
|
|
|
|
|
@@ -81,21 +77,27 @@ const
|
|
);
|
|
);
|
|
|
|
|
|
type
|
|
type
|
|
|
|
+ poschunk = ^toschunk;
|
|
|
|
+ toschunk = record
|
|
|
|
+ size,
|
|
|
|
+ used,
|
|
|
|
+ chunkindex : ptrint;
|
|
|
|
+ next,
|
|
|
|
+ prev : poschunk;
|
|
|
|
+ end;
|
|
|
|
+
|
|
pmemchunk_fixed = ^tmemchunk_fixed;
|
|
pmemchunk_fixed = ^tmemchunk_fixed;
|
|
tmemchunk_fixed = record
|
|
tmemchunk_fixed = record
|
|
-{$ifdef cpusparc}
|
|
|
|
- { Sparc needs to alloc aligned on 8 bytes, to allow doubles }
|
|
|
|
- _dummy : ptrint;
|
|
|
|
-{$endif cpusparc}
|
|
|
|
- size : ptrint;
|
|
|
|
|
|
+ size : ptrint;
|
|
|
|
+ poc : poschunk;
|
|
next_fixed,
|
|
next_fixed,
|
|
prev_fixed : pmemchunk_fixed;
|
|
prev_fixed : pmemchunk_fixed;
|
|
end;
|
|
end;
|
|
|
|
|
|
pmemchunk_var = ^tmemchunk_var;
|
|
pmemchunk_var = ^tmemchunk_var;
|
|
tmemchunk_var = record
|
|
tmemchunk_var = record
|
|
|
|
+ size : ptrint;
|
|
prevsize : ptrint;
|
|
prevsize : ptrint;
|
|
- size : ptrint;
|
|
|
|
next_var,
|
|
next_var,
|
|
prev_var : pmemchunk_var;
|
|
prev_var : pmemchunk_var;
|
|
end;
|
|
end;
|
|
@@ -103,25 +105,16 @@ type
|
|
{ ``header'', ie. size of structure valid when chunk is in use }
|
|
{ ``header'', ie. size of structure valid when chunk is in use }
|
|
{ should correspond to tmemchunk_var_hdr structure starting with the
|
|
{ should correspond to tmemchunk_var_hdr structure starting with the
|
|
last field. Reason is that the overlap is starting from the end of the
|
|
last field. Reason is that the overlap is starting from the end of the
|
|
- record. }
|
|
|
|
|
|
+ record.
|
|
|
|
+ Alignment is 8 bytes for 32bit machines. This required
|
|
|
|
+ for x86 MMX/SSE and for sparc Double values }
|
|
tmemchunk_fixed_hdr = record
|
|
tmemchunk_fixed_hdr = record
|
|
-{$ifdef cpusparc}
|
|
|
|
- { Sparc needs to alloc aligned on 8 bytes, to allow doubles }
|
|
|
|
- _dummy : ptrint;
|
|
|
|
-{$endif cpusparc}
|
|
|
|
- size : ptrint;
|
|
|
|
|
|
+ size : ptrint;
|
|
|
|
+ poschunk : pointer;
|
|
end;
|
|
end;
|
|
tmemchunk_var_hdr = record
|
|
tmemchunk_var_hdr = record
|
|
- prevsize : ptrint;
|
|
|
|
- size : ptrint;
|
|
|
|
- end;
|
|
|
|
-
|
|
|
|
- poschunk = ^toschunk;
|
|
|
|
- toschunk = record
|
|
|
|
- size : ptrint;
|
|
|
|
- next,
|
|
|
|
- prev : poschunk;
|
|
|
|
- used : ptrint;
|
|
|
|
|
|
+ prevsize,
|
|
|
|
+ size : ptrint;
|
|
end;
|
|
end;
|
|
|
|
|
|
tfreelists = array[1..maxblockindex] of pmemchunk_fixed;
|
|
tfreelists = array[1..maxblockindex] of pmemchunk_fixed;
|
|
@@ -136,11 +129,6 @@ var
|
|
freeoslist : poschunk;
|
|
freeoslist : poschunk;
|
|
freeoslistcount : dword;
|
|
freeoslistcount : dword;
|
|
|
|
|
|
-{$ifdef TestFreeLists}
|
|
|
|
-{ this can be turned on by debugger }
|
|
|
|
-const
|
|
|
|
- test_each : boolean = false;
|
|
|
|
-{$endif TestFreeLists}
|
|
|
|
|
|
|
|
{*****************************************************************************
|
|
{*****************************************************************************
|
|
Memory Manager
|
|
Memory Manager
|
|
@@ -505,41 +493,12 @@ end;
|
|
{$endif}
|
|
{$endif}
|
|
|
|
|
|
|
|
|
|
-{$ifdef TestFreeLists}
|
|
|
|
-procedure TestFreeLists;
|
|
|
|
-var
|
|
|
|
- i,j : ptrint;
|
|
|
|
- mc : pmemchunk_fixed;
|
|
|
|
-begin
|
|
|
|
- for i := 1 to maxblockindex do
|
|
|
|
- begin
|
|
|
|
- j := 0;
|
|
|
|
- mc := freelists_fixed[i];
|
|
|
|
- while assigned(mc) do
|
|
|
|
- begin
|
|
|
|
- inc(j);
|
|
|
|
- if ((mc^.size and fixedsizemask) <> i * blocksize) then
|
|
|
|
- RunError(204);
|
|
|
|
- mc := mc^.next_fixed;
|
|
|
|
- end;
|
|
|
|
- end;
|
|
|
|
-end;
|
|
|
|
-{$endif TestFreeLists}
|
|
|
|
|
|
|
|
{*****************************************************************************
|
|
{*****************************************************************************
|
|
List adding/removal
|
|
List adding/removal
|
|
*****************************************************************************}
|
|
*****************************************************************************}
|
|
|
|
|
|
-procedure append_to_list_fixed(blockindex: ptrint; pmc: pmemchunk_fixed);
|
|
|
|
-begin
|
|
|
|
- pmc^.prev_fixed := nil;
|
|
|
|
- pmc^.next_fixed := freelists_fixed[blockindex];
|
|
|
|
- if freelists_fixed[blockindex]<>nil then
|
|
|
|
- freelists_fixed[blockindex]^.prev_fixed := pmc;
|
|
|
|
- freelists_fixed[blockindex] := pmc;
|
|
|
|
-end;
|
|
|
|
-
|
|
|
|
-procedure append_to_list_var(pmc: pmemchunk_var);
|
|
|
|
|
|
+procedure append_to_list_var(pmc: pmemchunk_var);inline;
|
|
begin
|
|
begin
|
|
pmc^.prev_var := nil;
|
|
pmc^.prev_var := nil;
|
|
pmc^.next_var := freelist_var;
|
|
pmc^.next_var := freelist_var;
|
|
@@ -548,17 +507,7 @@ begin
|
|
freelist_var := pmc;
|
|
freelist_var := pmc;
|
|
end;
|
|
end;
|
|
|
|
|
|
-procedure remove_from_list_fixed(blockindex: ptrint; pmc: pmemchunk_fixed);
|
|
|
|
-begin
|
|
|
|
- if assigned(pmc^.next_fixed) then
|
|
|
|
- pmc^.next_fixed^.prev_fixed := pmc^.prev_fixed;
|
|
|
|
- if assigned(pmc^.prev_fixed) then
|
|
|
|
- pmc^.prev_fixed^.next_fixed := pmc^.next_fixed
|
|
|
|
- else
|
|
|
|
- freelists_fixed[blockindex] := pmc^.next_fixed;
|
|
|
|
-end;
|
|
|
|
-
|
|
|
|
-procedure remove_from_list_var(pmc: pmemchunk_var);
|
|
|
|
|
|
+procedure remove_from_list_var(pmc: pmemchunk_var);inline;
|
|
begin
|
|
begin
|
|
if assigned(pmc^.next_var) then
|
|
if assigned(pmc^.next_var) then
|
|
pmc^.next_var^.prev_var := pmc^.prev_var;
|
|
pmc^.next_var^.prev_var := pmc^.prev_var;
|
|
@@ -572,8 +521,8 @@ procedure append_to_oslist(poc: poschunk);
|
|
begin
|
|
begin
|
|
{ decide whether to free block or add to list }
|
|
{ decide whether to free block or add to list }
|
|
{$ifdef HAS_SYSOSFREE}
|
|
{$ifdef HAS_SYSOSFREE}
|
|
- if (freeoslistcount >= MaxKeptOSChunks)
|
|
|
|
- or (poc^.size > growheapsize2) then
|
|
|
|
|
|
+ if (freeoslistcount >= MaxKeptOSChunks) or
|
|
|
|
+ (poc^.size > growheapsize2) then
|
|
begin
|
|
begin
|
|
dec(internal_status.currheapsize, poc^.size);
|
|
dec(internal_status.currheapsize, poc^.size);
|
|
SysOSFree(poc, poc^.size);
|
|
SysOSFree(poc, poc^.size);
|
|
@@ -613,16 +562,25 @@ begin
|
|
append_to_oslist(poc);
|
|
append_to_oslist(poc);
|
|
end;
|
|
end;
|
|
|
|
|
|
-procedure append_to_oslist_fixed(blockindex, chunksize: ptrint; poc: poschunk);
|
|
|
|
|
|
+procedure append_to_oslist_fixed(poc: poschunk);
|
|
var
|
|
var
|
|
pmc: pmemchunk_fixed;
|
|
pmc: pmemchunk_fixed;
|
|
|
|
+ chunksize,
|
|
|
|
+ chunkindex,
|
|
i, count: ptrint;
|
|
i, count: ptrint;
|
|
begin
|
|
begin
|
|
- count := (poc^.size - sizeof(toschunk)) div chunksize;
|
|
|
|
|
|
+ chunkindex:=poc^.chunkindex;
|
|
|
|
+ chunksize:=chunkindex shl blockshift;
|
|
pmc := pmemchunk_fixed(pointer(poc)+sizeof(toschunk));
|
|
pmc := pmemchunk_fixed(pointer(poc)+sizeof(toschunk));
|
|
|
|
+ count := (poc^.size - sizeof(toschunk)) div chunksize;
|
|
for i := 0 to count - 1 do
|
|
for i := 0 to count - 1 do
|
|
begin
|
|
begin
|
|
- remove_from_list_fixed(blockindex, pmc);
|
|
|
|
|
|
+ if assigned(pmc^.next_fixed) then
|
|
|
|
+ pmc^.next_fixed^.prev_fixed := pmc^.prev_fixed;
|
|
|
|
+ if assigned(pmc^.prev_fixed) then
|
|
|
|
+ pmc^.prev_fixed^.next_fixed := pmc^.next_fixed
|
|
|
|
+ else
|
|
|
|
+ freelists_fixed[chunkindex] := pmc^.next_fixed;
|
|
pmc := pointer(pmc)+chunksize;
|
|
pmc := pointer(pmc)+chunksize;
|
|
end;
|
|
end;
|
|
append_to_oslist(poc);
|
|
append_to_oslist(poc);
|
|
@@ -655,6 +613,7 @@ begin
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+
|
|
{*****************************************************************************
|
|
{*****************************************************************************
|
|
Try concat freerecords
|
|
Try concat freerecords
|
|
*****************************************************************************}
|
|
*****************************************************************************}
|
|
@@ -751,35 +710,40 @@ end;
|
|
Grow Heap
|
|
Grow Heap
|
|
*****************************************************************************}
|
|
*****************************************************************************}
|
|
|
|
|
|
-function alloc_oschunk(blockindex, size: ptrint): pointer;
|
|
|
|
|
|
+function alloc_oschunk(chunkindex, size: ptrint):pointer;
|
|
var
|
|
var
|
|
|
|
+ pmcfirst,
|
|
|
|
+ pmclast,
|
|
pmc : pmemchunk_fixed;
|
|
pmc : pmemchunk_fixed;
|
|
pmcv : pmemchunk_var;
|
|
pmcv : pmemchunk_var;
|
|
|
|
+ poc : poschunk;
|
|
|
|
+ chunksize,
|
|
minsize,
|
|
minsize,
|
|
maxsize,
|
|
maxsize,
|
|
i, count : ptrint;
|
|
i, count : ptrint;
|
|
- chunksize : ptrint;
|
|
|
|
begin
|
|
begin
|
|
|
|
+ result:=nil;
|
|
|
|
+ chunksize:=chunkindex shl blockshift;
|
|
{ increase size by size needed for os block header }
|
|
{ increase size by size needed for os block header }
|
|
minsize := size + sizeof(toschunk);
|
|
minsize := size + sizeof(toschunk);
|
|
- if blockindex<>0 then
|
|
|
|
- maxsize := (size * $ffff) + sizeof(toschunk)
|
|
|
|
|
|
+ if chunkindex<>0 then
|
|
|
|
+ maxsize := (chunksize * $ffff) + sizeof(toschunk)
|
|
else
|
|
else
|
|
maxsize := high(ptrint);
|
|
maxsize := high(ptrint);
|
|
{ blocks available in freelist? }
|
|
{ blocks available in freelist? }
|
|
- result := freeoslist;
|
|
|
|
- while result <> nil do
|
|
|
|
|
|
+ poc := freeoslist;
|
|
|
|
+ while poc <> nil do
|
|
begin
|
|
begin
|
|
- if (poschunk(result)^.size >= minsize) and
|
|
|
|
- (poschunk(result)^.size <= maxsize) then
|
|
|
|
|
|
+ if (poc^.size >= minsize) and
|
|
|
|
+ (poc^.size <= maxsize) then
|
|
begin
|
|
begin
|
|
- size := poschunk(result)^.size;
|
|
|
|
- remove_from_oslist(poschunk(result));
|
|
|
|
|
|
+ size := poc^.size;
|
|
|
|
+ remove_from_oslist(poc);
|
|
break;
|
|
break;
|
|
end;
|
|
end;
|
|
- result := poschunk(result)^.next;
|
|
|
|
|
|
+ poc := poc^.next;
|
|
end;
|
|
end;
|
|
- if result = nil then
|
|
|
|
|
|
+ if poc = nil then
|
|
begin
|
|
begin
|
|
{$ifdef DUMPGROW}
|
|
{$ifdef DUMPGROW}
|
|
writeln('growheap(',size,') allocating ',(size+sizeof(toschunk)+$ffff) and $ffff0000);
|
|
writeln('growheap(',size,') allocating ',(size+sizeof(toschunk)+$ffff) and $ffff0000);
|
|
@@ -788,135 +752,131 @@ begin
|
|
{ allocate by 64K size }
|
|
{ allocate by 64K size }
|
|
size := (size+sizeof(toschunk)+$ffff) and not $ffff;
|
|
size := (size+sizeof(toschunk)+$ffff) and not $ffff;
|
|
{ allocate smaller blocks for fixed-size chunks }
|
|
{ allocate smaller blocks for fixed-size chunks }
|
|
- if blockindex<>0 then
|
|
|
|
|
|
+ if chunksize<>0 then
|
|
begin
|
|
begin
|
|
- result := SysOSAlloc(GrowHeapSizeSmall);
|
|
|
|
- if result<>nil then
|
|
|
|
|
|
+ poc := SysOSAlloc(GrowHeapSizeSmall);
|
|
|
|
+ if poc<>nil then
|
|
size := GrowHeapSizeSmall;
|
|
size := GrowHeapSizeSmall;
|
|
end
|
|
end
|
|
- { first try 256K (default) }
|
|
|
|
- else if size<=GrowHeapSize1 then
|
|
|
|
- begin
|
|
|
|
- result := SysOSAlloc(GrowHeapSize1);
|
|
|
|
- if result<>nil then
|
|
|
|
- size := GrowHeapSize1;
|
|
|
|
- end
|
|
|
|
- { second try 1024K (default) }
|
|
|
|
- else if size<=GrowHeapSize2 then
|
|
|
|
- begin
|
|
|
|
- result := SysOSAlloc(GrowHeapSize2);
|
|
|
|
- if result<>nil then
|
|
|
|
- size := GrowHeapSize2;
|
|
|
|
- end
|
|
|
|
- { else allocate the needed bytes }
|
|
|
|
- else
|
|
|
|
- result := SysOSAlloc(size);
|
|
|
|
- { try again }
|
|
|
|
- if result=nil then
|
|
|
|
- begin
|
|
|
|
- result := SysOSAlloc(size);
|
|
|
|
- if (result=nil) then
|
|
|
|
|
|
+ { first try 256K (default) }
|
|
|
|
+ else if size<=GrowHeapSize1 then
|
|
|
|
+ begin
|
|
|
|
+ poc := SysOSAlloc(GrowHeapSize1);
|
|
|
|
+ if poc<>nil then
|
|
|
|
+ size := GrowHeapSize1;
|
|
|
|
+ end
|
|
|
|
+ { second try 1024K (default) }
|
|
|
|
+ else if size<=GrowHeapSize2 then
|
|
|
|
+ begin
|
|
|
|
+ poc := SysOSAlloc(GrowHeapSize2);
|
|
|
|
+ if poc<>nil then
|
|
|
|
+ size := GrowHeapSize2;
|
|
|
|
+ end
|
|
|
|
+ { else allocate the needed bytes }
|
|
|
|
+ else
|
|
|
|
+ poc := SysOSAlloc(size);
|
|
|
|
+ { try again }
|
|
|
|
+ if poc=nil then
|
|
begin
|
|
begin
|
|
- if ReturnNilIfGrowHeapFails then
|
|
|
|
- exit
|
|
|
|
- else
|
|
|
|
- HandleError(203);
|
|
|
|
|
|
+ poc := SysOSAlloc(size);
|
|
|
|
+ if (poc=nil) then
|
|
|
|
+ begin
|
|
|
|
+ if ReturnNilIfGrowHeapFails then
|
|
|
|
+ exit
|
|
|
|
+ else
|
|
|
|
+ HandleError(203);
|
|
|
|
+ end;
|
|
end;
|
|
end;
|
|
|
|
+ { set the total new heap size }
|
|
|
|
+ inc(internal_status.currheapsize,size);
|
|
|
|
+ if internal_status.currheapsize>internal_status.maxheapsize then
|
|
|
|
+ internal_status.maxheapsize:=internal_status.currheapsize;
|
|
end;
|
|
end;
|
|
- { set the total new heap size }
|
|
|
|
- inc(internal_status.currheapsize,size);
|
|
|
|
- if internal_status.currheapsize>internal_status.maxheapsize then
|
|
|
|
- internal_status.maxheapsize:=internal_status.currheapsize;
|
|
|
|
- end;
|
|
|
|
{ initialize os-block }
|
|
{ initialize os-block }
|
|
- poschunk(result)^.used := 0;
|
|
|
|
- poschunk(result)^.size := size;
|
|
|
|
- inc(result, sizeof(toschunk));
|
|
|
|
- if blockindex<>0 then
|
|
|
|
|
|
+ poc^.used := 0;
|
|
|
|
+ poc^.size := size;
|
|
|
|
+ poc^.chunkindex := chunkindex;
|
|
|
|
+ { initialized oschunck for fixed chunks }
|
|
|
|
+ if chunkindex<>0 then
|
|
begin
|
|
begin
|
|
{ chop os chunk in fixedsize parts,
|
|
{ chop os chunk in fixedsize parts,
|
|
maximum of $ffff elements are allowed, otherwise
|
|
maximum of $ffff elements are allowed, otherwise
|
|
there will be an overflow }
|
|
there will be an overflow }
|
|
- chunksize := blockindex shl blockshr;
|
|
|
|
count := (size-sizeof(toschunk)) div chunksize;
|
|
count := (size-sizeof(toschunk)) div chunksize;
|
|
if count>$ffff then
|
|
if count>$ffff then
|
|
HandleError(204);
|
|
HandleError(204);
|
|
- pmc := pmemchunk_fixed(result);
|
|
|
|
- pmc^.prev_fixed := nil;
|
|
|
|
- i := 0;
|
|
|
|
- repeat
|
|
|
|
- pmc^.size := fixedsizeflag or chunksize or (i shl 16);
|
|
|
|
- pmc^.next_fixed := pointer(pmc)+chunksize;
|
|
|
|
- inc(i);
|
|
|
|
- if i < count then
|
|
|
|
- begin
|
|
|
|
- pmc := pmemchunk_fixed(pointer(pmc)+chunksize);
|
|
|
|
- pmc^.prev_fixed := pointer(pmc)-chunksize;
|
|
|
|
- end
|
|
|
|
- else
|
|
|
|
- begin
|
|
|
|
- break;
|
|
|
|
- end;
|
|
|
|
- until false;
|
|
|
|
- append_to_list_fixed(blockindex, pmc);
|
|
|
|
- pmc^.prev_fixed := pointer(pmc)-chunksize;
|
|
|
|
- freelists_fixed[blockindex] := pmemchunk_fixed(result);
|
|
|
|
|
|
+ { Initialize linkedlist of chunks, the first chunk
|
|
|
|
+ is pmemchunk_fixed(poc) and the last chunk will be in pmc at
|
|
|
|
+ the end of the loop }
|
|
|
|
+ pmcfirst := pmemchunk_fixed(pointer(poc)+sizeof(toschunk));
|
|
|
|
+ pmc:=pmcfirst;
|
|
|
|
+ for i:=1 to count do
|
|
|
|
+ begin
|
|
|
|
+ pmc^.poc:=poc;
|
|
|
|
+ pmc^.size:=chunksize or fixedsizeflag;
|
|
|
|
+ pmc^.prev_fixed := pointer(pmc)-chunksize;
|
|
|
|
+ pmc^.next_fixed := pointer(pmc)+chunksize;
|
|
|
|
+ pmc := pmemchunk_fixed(pointer(pmc)+chunksize);
|
|
|
|
+ end;
|
|
|
|
+ { undo last increase to get last chunk }
|
|
|
|
+ pmclast := pmemchunk_fixed(pointer(pmc)-chunksize);
|
|
|
|
+ { Add to freelist and fixup first and last chunk }
|
|
|
|
+ pmclast^.next_fixed := freelists_fixed[chunkindex];
|
|
|
|
+ if freelists_fixed[chunkindex]<>nil then
|
|
|
|
+ freelists_fixed[chunkindex]^.prev_fixed := pmclast;
|
|
|
|
+ freelists_fixed[chunkindex] := pmcfirst;
|
|
|
|
+ pmemchunk_fixed(poc)^.prev_fixed:=nil;
|
|
|
|
+ result:=pmcfirst;
|
|
end
|
|
end
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
- pmcv := pmemchunk_var(result);
|
|
|
|
|
|
+ pmcv := pmemchunk_var(pointer(poc)+sizeof(toschunk));
|
|
append_to_list_var(pmcv);
|
|
append_to_list_var(pmcv);
|
|
pmcv^.size := ((size-sizeof(toschunk)) and sizemask) or (firstblockflag or lastblockflag);
|
|
pmcv^.size := ((size-sizeof(toschunk)) and sizemask) or (firstblockflag or lastblockflag);
|
|
pmcv^.prevsize := 0;
|
|
pmcv^.prevsize := 0;
|
|
|
|
+ result:=pmcv;
|
|
end;
|
|
end;
|
|
-{$ifdef TestFreeLists}
|
|
|
|
- TestFreeLists;
|
|
|
|
-{$endif TestFreeLists}
|
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+
|
|
{*****************************************************************************
|
|
{*****************************************************************************
|
|
SysGetMem
|
|
SysGetMem
|
|
*****************************************************************************}
|
|
*****************************************************************************}
|
|
|
|
|
|
function SysGetMem_Fixed(size: ptrint): pointer;
|
|
function SysGetMem_Fixed(size: ptrint): pointer;
|
|
var
|
|
var
|
|
- pcurr: pmemchunk_fixed;
|
|
|
|
- poc: poschunk;
|
|
|
|
- s: ptrint;
|
|
|
|
|
|
+ pmc : pmemchunk_fixed;
|
|
|
|
+ poc : poschunk;
|
|
|
|
+ chunkindex : ptrint;
|
|
begin
|
|
begin
|
|
result:=nil;
|
|
result:=nil;
|
|
{ try to find a block in one of the freelists per size }
|
|
{ try to find a block in one of the freelists per size }
|
|
- s := size shr blockshr;
|
|
|
|
- pcurr := freelists_fixed[s];
|
|
|
|
|
|
+ chunkindex := size shr blockshift;
|
|
|
|
+ pmc := freelists_fixed[chunkindex];
|
|
{ no free blocks ? }
|
|
{ no free blocks ? }
|
|
- if not assigned(pcurr) then
|
|
|
|
|
|
+ if not assigned(pmc) then
|
|
begin
|
|
begin
|
|
- pcurr := alloc_oschunk(s, size);
|
|
|
|
- if not assigned(pcurr) then
|
|
|
|
|
|
+ pmc:=alloc_oschunk(chunkindex, size);
|
|
|
|
+ if not assigned(pmc) then
|
|
exit;
|
|
exit;
|
|
end;
|
|
end;
|
|
{ get a pointer to the block we should return }
|
|
{ get a pointer to the block we should return }
|
|
- result := pointer(pcurr)+sizeof(tmemchunk_fixed_hdr);
|
|
|
|
- { flag as in-use }
|
|
|
|
- pcurr^.size := pcurr^.size or usedflag;
|
|
|
|
|
|
+ result := pointer(pmc)+sizeof(tmemchunk_fixed_hdr);
|
|
{ update freelist }
|
|
{ update freelist }
|
|
- freelists_fixed[s] := pcurr^.next_fixed;
|
|
|
|
- if assigned(freelists_fixed[s]) then
|
|
|
|
- freelists_fixed[s]^.prev_fixed := nil;
|
|
|
|
- poc := poschunk(pointer(pcurr)-((pcurr^.size shr 16)*(pcurr^.size and fixedsizemask)+sizeof(toschunk)));
|
|
|
|
|
|
+ freelists_fixed[chunkindex] := pmc^.next_fixed;
|
|
|
|
+ if assigned(freelists_fixed[chunkindex]) then
|
|
|
|
+ freelists_fixed[chunkindex]^.prev_fixed := nil;
|
|
|
|
+ poc := pmc^.poc;
|
|
if (poc^.used = 0) then
|
|
if (poc^.used = 0) then
|
|
- freelists_free_chunk[s] := false;
|
|
|
|
|
|
+ freelists_free_chunk[chunkindex] := false;
|
|
inc(poc^.used);
|
|
inc(poc^.used);
|
|
{ statistics }
|
|
{ statistics }
|
|
inc(internal_status.currheapused,size);
|
|
inc(internal_status.currheapused,size);
|
|
if internal_status.currheapused>internal_status.maxheapused then
|
|
if internal_status.currheapused>internal_status.maxheapused then
|
|
internal_status.maxheapused:=internal_status.currheapused;
|
|
internal_status.maxheapused:=internal_status.currheapused;
|
|
-{$ifdef TestFreeLists}
|
|
|
|
- if test_each then
|
|
|
|
- TestFreeLists;
|
|
|
|
-{$endif TestFreeLists}
|
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+
|
|
function SysGetMem_Var(size: ptrint): pointer;
|
|
function SysGetMem_Var(size: ptrint): pointer;
|
|
var
|
|
var
|
|
pcurr : pmemchunk_var;
|
|
pcurr : pmemchunk_var;
|
|
@@ -976,10 +936,6 @@ begin
|
|
inc(internal_status.currheapused,size);
|
|
inc(internal_status.currheapused,size);
|
|
if internal_status.currheapused>internal_status.maxheapused then
|
|
if internal_status.currheapused>internal_status.maxheapused then
|
|
internal_status.maxheapused:=internal_status.currheapused;
|
|
internal_status.maxheapused:=internal_status.currheapused;
|
|
-{$ifdef TestFreeLists}
|
|
|
|
- if test_each then
|
|
|
|
- TestFreeLists;
|
|
|
|
-{$endif TestFreeLists}
|
|
|
|
end;
|
|
end;
|
|
|
|
|
|
function SysGetMem(size : ptrint):pointer;
|
|
function SysGetMem(size : ptrint):pointer;
|
|
@@ -998,12 +954,12 @@ begin
|
|
if size <= (maxblocksize - sizeof(tmemchunk_fixed_hdr)) then
|
|
if size <= (maxblocksize - sizeof(tmemchunk_fixed_hdr)) then
|
|
begin
|
|
begin
|
|
size := (size+sizeof(tmemchunk_fixed_hdr)+(blocksize-1)) and fixedsizemask;
|
|
size := (size+sizeof(tmemchunk_fixed_hdr)+(blocksize-1)) and fixedsizemask;
|
|
- sysgetmem := sysgetmem_fixed(size);
|
|
|
|
|
|
+ result := sysgetmem_fixed(size);
|
|
end
|
|
end
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
size := (size+sizeof(tmemchunk_var_hdr)+(blocksize-1)) and sizemask;
|
|
size := (size+sizeof(tmemchunk_var_hdr)+(blocksize-1)) and sizemask;
|
|
- sysgetmem := sysgetmem_var(size);
|
|
|
|
|
|
+ result := sysgetmem_var(size);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -1012,83 +968,70 @@ end;
|
|
SysFreeMem
|
|
SysFreeMem
|
|
*****************************************************************************}
|
|
*****************************************************************************}
|
|
|
|
|
|
-function SysFreeMem_Fixed(pcurr: pmemchunk_fixed; size: ptrint): ptrint;
|
|
|
|
|
|
+function SysFreeMem_Fixed(pmc: pmemchunk_fixed): ptrint;
|
|
var
|
|
var
|
|
- pcurrsize: ptrint;
|
|
|
|
- blockindex: ptrint;
|
|
|
|
- poc: poschunk;
|
|
|
|
|
|
+ chunksize,
|
|
|
|
+ chunkindex : ptrint;
|
|
|
|
+ poc : poschunk;
|
|
begin
|
|
begin
|
|
- pcurrsize := pcurr^.size and fixedsizemask;
|
|
|
|
- if size<>pcurrsize then
|
|
|
|
- HandleError(204);
|
|
|
|
- dec(internal_status.currheapused,pcurrsize);
|
|
|
|
|
|
+ poc := pmc^.poc;
|
|
|
|
+ chunkindex:=poc^.chunkindex;
|
|
|
|
+ chunksize:=chunkindex shl blockshift;
|
|
|
|
+ { statistics }
|
|
|
|
+ dec(internal_status.currheapused,chunksize);
|
|
{ insert the block in it's freelist }
|
|
{ insert the block in it's freelist }
|
|
- pcurr^.size := pcurr^.size and (not usedflag);
|
|
|
|
- blockindex := pcurrsize shr blockshr;
|
|
|
|
- append_to_list_fixed(blockindex, pcurr);
|
|
|
|
|
|
+ pmc^.prev_fixed := nil;
|
|
|
|
+ pmc^.next_fixed := freelists_fixed[chunkindex];
|
|
|
|
+ if freelists_fixed[chunkindex]<>nil then
|
|
|
|
+ freelists_fixed[chunkindex]^.prev_fixed := pmc;
|
|
|
|
+ freelists_fixed[chunkindex] := pmc;
|
|
{ decrease used blocks count }
|
|
{ decrease used blocks count }
|
|
- poc := poschunk(pointer(pcurr)-(pcurr^.size shr 16)*pcurrsize-sizeof(toschunk));
|
|
|
|
if poc^.used = 0 then
|
|
if poc^.used = 0 then
|
|
HandleError(204);
|
|
HandleError(204);
|
|
dec(poc^.used);
|
|
dec(poc^.used);
|
|
if poc^.used = 0 then
|
|
if poc^.used = 0 then
|
|
- begin
|
|
|
|
- if (freelists_free_chunk[blockindex]) then
|
|
|
|
- // block eligable for freeing
|
|
|
|
- append_to_oslist_fixed(blockindex, pcurrsize, poc)
|
|
|
|
- else
|
|
|
|
- freelists_free_chunk[blockindex] := true;
|
|
|
|
- end;
|
|
|
|
- SysFreeMem_Fixed := pcurrsize;
|
|
|
|
-{$ifdef TestFreeLists}
|
|
|
|
- if test_each then
|
|
|
|
- TestFreeLists;
|
|
|
|
-{$endif TestFreeLists}
|
|
|
|
|
|
+ begin
|
|
|
|
+ { osblock can be freed? }
|
|
|
|
+ if freelists_free_chunk[chunkindex] then
|
|
|
|
+ append_to_oslist_fixed(poc)
|
|
|
|
+ else
|
|
|
|
+ freelists_free_chunk[chunkindex] := true;
|
|
|
|
+ end;
|
|
|
|
+ result := chunksize;
|
|
end;
|
|
end;
|
|
|
|
|
|
-function SysFreeMem_Var(pcurr: pmemchunk_var; size: ptrint): ptrint;
|
|
|
|
|
|
+
|
|
|
|
+function SysFreeMem_Var(pcurr: pmemchunk_var): ptrint;
|
|
var
|
|
var
|
|
- pcurrsize: ptrint;
|
|
|
|
|
|
+ chunksize: ptrint;
|
|
begin
|
|
begin
|
|
- pcurrsize := pcurr^.size and sizemask;
|
|
|
|
- if size<>pcurrsize then
|
|
|
|
- HandleError(204);
|
|
|
|
- dec(internal_status.currheapused,pcurrsize);
|
|
|
|
|
|
+ chunksize := pcurr^.size and sizemask;
|
|
|
|
+ dec(internal_status.currheapused,chunksize);
|
|
{ insert the block in it's freelist }
|
|
{ insert the block in it's freelist }
|
|
pcurr^.size := pcurr^.size and (not usedflag);
|
|
pcurr^.size := pcurr^.size and (not usedflag);
|
|
append_to_list_var(pcurr);
|
|
append_to_list_var(pcurr);
|
|
- SysFreeMem_Var := pcurrsize;
|
|
|
|
|
|
+ result := chunksize;
|
|
pcurr := try_concat_free_chunk(pcurr);
|
|
pcurr := try_concat_free_chunk(pcurr);
|
|
if (pcurr^.size and (firstblockflag or lastblockflag)) = (firstblockflag or lastblockflag) then
|
|
if (pcurr^.size and (firstblockflag or lastblockflag)) = (firstblockflag or lastblockflag) then
|
|
- begin
|
|
|
|
append_to_oslist_var(pcurr);
|
|
append_to_oslist_var(pcurr);
|
|
- end;
|
|
|
|
-{$ifdef TestFreeLists}
|
|
|
|
- if test_each then
|
|
|
|
- TestFreeLists;
|
|
|
|
-{$endif TestFreeLists}
|
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
function SysFreeMem(p: pointer): ptrint;
|
|
function SysFreeMem(p: pointer): ptrint;
|
|
var
|
|
var
|
|
- pcurrsize: ptrint;
|
|
|
|
|
|
+ size : ptrint;
|
|
begin
|
|
begin
|
|
if p=nil then
|
|
if p=nil then
|
|
begin
|
|
begin
|
|
result:=0;
|
|
result:=0;
|
|
exit;
|
|
exit;
|
|
end;
|
|
end;
|
|
- pcurrsize := pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr))^.size;
|
|
|
|
|
|
+ size := pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr))^.size;
|
|
{ check if this is a fixed- or var-sized chunk }
|
|
{ check if this is a fixed- or var-sized chunk }
|
|
- if (pcurrsize and fixedsizeflag) = 0 then
|
|
|
|
- begin
|
|
|
|
- result := sysfreemem_var(pmemchunk_var(p-sizeof(tmemchunk_var_hdr)), pcurrsize and sizemask);
|
|
|
|
- end
|
|
|
|
|
|
+ if (size and fixedsizeflag) = 0 then
|
|
|
|
+ result := sysfreemem_var(pmemchunk_var(p-sizeof(tmemchunk_var_hdr)))
|
|
else
|
|
else
|
|
- begin
|
|
|
|
- result := sysfreemem_fixed(pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr)), pcurrsize and fixedsizemask);
|
|
|
|
- end;
|
|
|
|
|
|
+ result := sysfreemem_fixed(pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr)));
|
|
end;
|
|
end;
|
|
|
|
|
|
{*****************************************************************************
|
|
{*****************************************************************************
|
|
@@ -1097,7 +1040,7 @@ end;
|
|
|
|
|
|
Function SysFreeMemSize(p: pointer; size: ptrint):ptrint;
|
|
Function SysFreeMemSize(p: pointer; size: ptrint):ptrint;
|
|
var
|
|
var
|
|
- pcurrsize: ptrint;
|
|
|
|
|
|
+ chunksize: ptrint;
|
|
begin
|
|
begin
|
|
SysFreeMemSize := 0;
|
|
SysFreeMemSize := 0;
|
|
if p=nil then
|
|
if p=nil then
|
|
@@ -1109,18 +1052,14 @@ begin
|
|
exit;
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
|
|
- pcurrsize := pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr))^.size;
|
|
|
|
- { check if this is a fixed- or var-sized chunk }
|
|
|
|
- if (pcurrsize and fixedsizeflag) = 0 then
|
|
|
|
- begin
|
|
|
|
- size := (size+sizeof(tmemchunk_var_hdr)+(blocksize-1)) and sizemask;
|
|
|
|
- result := sysfreemem_var(pmemchunk_var(p-sizeof(tmemchunk_var_hdr)), size);
|
|
|
|
- end
|
|
|
|
|
|
+ chunksize := pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr))^.size;
|
|
|
|
+ { check if this is a fixed- or var-sized chunk. We can't check the passed
|
|
|
|
+ size parameter since the block can be resized (by reallocmem) to an
|
|
|
|
+ optimized value that the user doesn't know }
|
|
|
|
+ if (chunksize and fixedsizeflag) = 0 then
|
|
|
|
+ result := sysfreemem_var(pmemchunk_var(p-sizeof(tmemchunk_var_hdr)))
|
|
else
|
|
else
|
|
- begin
|
|
|
|
- size := (size+sizeof(tmemchunk_fixed_hdr)+(blocksize-1)) and fixedsizemask;
|
|
|
|
- result := sysfreemem_fixed(pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr)), size);
|
|
|
|
- end;
|
|
|
|
|
|
+ result := sysfreemem_fixed(pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr)));
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
@@ -1130,16 +1069,16 @@ end;
|
|
|
|
|
|
function SysMemSize(p: pointer): ptrint;
|
|
function SysMemSize(p: pointer): ptrint;
|
|
begin
|
|
begin
|
|
- SysMemSize := pmemchunk_fixed(pointer(p)-sizeof(tmemchunk_fixed_hdr))^.size;
|
|
|
|
- if (SysMemSize and fixedsizeflag) = 0 then
|
|
|
|
|
|
+ result := pmemchunk_fixed(pointer(p)-sizeof(tmemchunk_fixed_hdr))^.size;
|
|
|
|
+ if (result and fixedsizeflag) = 0 then
|
|
begin
|
|
begin
|
|
- SysMemSize := SysMemSize and sizemask;
|
|
|
|
- dec(SysMemSize, sizeof(tmemchunk_var_hdr));
|
|
|
|
|
|
+ result := SysMemSize and sizemask;
|
|
|
|
+ dec(result, sizeof(tmemchunk_var_hdr));
|
|
end
|
|
end
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
- SysMemSize := SysMemSize and fixedsizemask;
|
|
|
|
- dec(SysMemSize, sizeof(tmemchunk_fixed_hdr));
|
|
|
|
|
|
+ result := SysMemSize and fixedsizemask;
|
|
|
|
+ dec(result, sizeof(tmemchunk_fixed_hdr));
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -1150,9 +1089,9 @@ end;
|
|
|
|
|
|
function SysAllocMem(size: ptrint): pointer;
|
|
function SysAllocMem(size: ptrint): pointer;
|
|
begin
|
|
begin
|
|
- sysallocmem := MemoryManager.GetMem(size);
|
|
|
|
- if sysallocmem<>nil then
|
|
|
|
- FillChar(sysallocmem^,MemoryManager.MemSize(sysallocmem),0);
|
|
|
|
|
|
+ result := MemoryManager.GetMem(size);
|
|
|
|
+ if result<>nil then
|
|
|
|
+ FillChar(result^,MemoryManager.MemSize(result),0);
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
@@ -1162,7 +1101,7 @@ end;
|
|
|
|
|
|
function SysTryResizeMem(var p: pointer; size: ptrint): boolean;
|
|
function SysTryResizeMem(var p: pointer; size: ptrint): boolean;
|
|
var
|
|
var
|
|
- pcurrsize,
|
|
|
|
|
|
+ chunksize,
|
|
oldsize,
|
|
oldsize,
|
|
currsize : ptrint;
|
|
currsize : ptrint;
|
|
pcurr : pmemchunk_var;
|
|
pcurr : pmemchunk_var;
|
|
@@ -1170,13 +1109,13 @@ begin
|
|
SysTryResizeMem := false;
|
|
SysTryResizeMem := false;
|
|
|
|
|
|
{ fix p to point to the heaprecord }
|
|
{ fix p to point to the heaprecord }
|
|
- pcurrsize := pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr))^.size;
|
|
|
|
|
|
+ chunksize := pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr))^.size;
|
|
|
|
|
|
{ handle fixed memchuncks separate. Only allow resizes when the
|
|
{ handle fixed memchuncks separate. Only allow resizes when the
|
|
new size fits in the same block }
|
|
new size fits in the same block }
|
|
- if (pcurrsize and fixedsizeflag) <> 0 then
|
|
|
|
|
|
+ if (chunksize and fixedsizeflag) <> 0 then
|
|
begin
|
|
begin
|
|
- currsize := pcurrsize and fixedsizemask;
|
|
|
|
|
|
+ currsize := chunksize and fixedsizemask;
|
|
|
|
|
|
{ first check if the size fits in the fixed block range to prevent
|
|
{ first check if the size fits in the fixed block range to prevent
|
|
"truncating" the size by the fixedsizemask }
|
|
"truncating" the size by the fixedsizemask }
|
|
@@ -1186,24 +1125,19 @@ begin
|
|
systryresizemem:=true;
|
|
systryresizemem:=true;
|
|
exit;
|
|
exit;
|
|
end;
|
|
end;
|
|
-
|
|
|
|
{ we need to allocate a new fixed or var memchunck }
|
|
{ we need to allocate a new fixed or var memchunck }
|
|
exit;
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
|
|
{ var memchunck }
|
|
{ var memchunck }
|
|
- currsize := pcurrsize and sizemask;
|
|
|
|
|
|
+ currsize := chunksize and sizemask;
|
|
size := (size+sizeof(tmemchunk_var_hdr)+(blocksize-1)) and sizemask;
|
|
size := (size+sizeof(tmemchunk_var_hdr)+(blocksize-1)) and sizemask;
|
|
|
|
|
|
{ is the allocated block still correct? }
|
|
{ is the allocated block still correct? }
|
|
if (currsize>=size) and (size>(currsize-blocksize)) then
|
|
if (currsize>=size) and (size>(currsize-blocksize)) then
|
|
begin
|
|
begin
|
|
SysTryResizeMem := true;
|
|
SysTryResizeMem := true;
|
|
-{$ifdef TestFreeLists}
|
|
|
|
- if test_each then
|
|
|
|
- TestFreeLists;
|
|
|
|
-{$endif TestFreeLists}
|
|
|
|
- exit;
|
|
|
|
|
|
+ exit;
|
|
end;
|
|
end;
|
|
|
|
|
|
{ get pointer to block }
|
|
{ get pointer to block }
|
|
@@ -1231,11 +1165,6 @@ begin
|
|
|
|
|
|
inc(internal_status.currheapused,size-oldsize);
|
|
inc(internal_status.currheapused,size-oldsize);
|
|
SysTryResizeMem := true;
|
|
SysTryResizeMem := true;
|
|
-
|
|
|
|
-{$ifdef TestFreeLists}
|
|
|
|
- if test_each then
|
|
|
|
- TestFreeLists;
|
|
|
|
-{$endif TestFreeLists}
|
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
@@ -1245,6 +1174,8 @@ end;
|
|
|
|
|
|
function SysReAllocMem(var p: pointer; size: ptrint):pointer;
|
|
function SysReAllocMem(var p: pointer; size: ptrint):pointer;
|
|
var
|
|
var
|
|
|
|
+ newsize,
|
|
|
|
+ oldsize,
|
|
minsize : ptrint;
|
|
minsize : ptrint;
|
|
p2 : pointer;
|
|
p2 : pointer;
|
|
begin
|
|
begin
|
|
@@ -1267,10 +1198,23 @@ begin
|
|
{ Resize block }
|
|
{ Resize block }
|
|
if not SysTryResizeMem(p,size) then
|
|
if not SysTryResizeMem(p,size) then
|
|
begin
|
|
begin
|
|
- minsize := MemoryManager.MemSize(p);
|
|
|
|
- if size < minsize then
|
|
|
|
- minsize := size;
|
|
|
|
- p2 := MemoryManager.GetMem(size);
|
|
|
|
|
|
+ oldsize:=MemoryManager.MemSize(p);
|
|
|
|
+ { Grow with bigger steps to prevent the need for
|
|
|
|
+ multiple getmem/freemem calls for fixed blocks. It might cost a bit
|
|
|
|
+ of extra memory, but in most cases a reallocmem is done multiple times. }
|
|
|
|
+ if oldsize<maxblocksize then
|
|
|
|
+ begin
|
|
|
|
+ newsize:=oldsize*2+blocksize;
|
|
|
|
+ if size>newsize then
|
|
|
|
+ newsize:=size;
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ newsize:=size;
|
|
|
|
+ { calc size of data to move }
|
|
|
|
+ minsize:=oldsize;
|
|
|
|
+ if newsize < minsize then
|
|
|
|
+ minsize := newsize;
|
|
|
|
+ p2 := MemoryManager.GetMem(newsize);
|
|
if p2<>nil then
|
|
if p2<>nil then
|
|
Move(p^,p2^,minsize);
|
|
Move(p^,p2^,minsize);
|
|
MemoryManager.FreeMem(p);
|
|
MemoryManager.FreeMem(p);
|
|
@@ -1324,5 +1268,3 @@ begin
|
|
freeoslistcount := 0;
|
|
freeoslistcount := 0;
|
|
fillchar(internal_status,sizeof(internal_status),0);
|
|
fillchar(internal_status,sizeof(internal_status),0);
|
|
end;
|
|
end;
|
|
-
|
|
|
|
-
|
|
|