Browse Source

* fixed reallocmem with a block at the end of an allocated memoryblock,
had to introduce a flag for such blocks.
* flags are now stored in the first 4 bits instead of the highest bit,
this could be done because the sizes of block are always >= 16

peter 26 years ago
parent
commit
ddb0882789
1 changed files with 65 additions and 28 deletions
  1. 65 28
      rtl/inc/heap.inc

+ 65 - 28
rtl/inc/heap.inc

@@ -37,8 +37,9 @@ const
   maxblock     = maxblocksize div blocksize;
   maxblock     = maxblocksize div blocksize;
   maxreusebigger = 8; { max reuse bigger tries }
   maxreusebigger = 8; { max reuse bigger tries }
 
 
-  usedmask = $80000000;
-  sizemask = not usedmask;
+  usedmask = 1;            { flag if the block is used or not }
+  beforeheapendmask = 2;   { flag if the block is just before a heapptr }
+  sizemask = not(blocksize-1);
 
 
 {****************************************************************************}
 {****************************************************************************}
 
 
@@ -302,7 +303,10 @@ begin
      if heapend-heapptr>size then
      if heapend-heapptr>size then
       begin
       begin
         sysgetmem:=heapptr;
         sysgetmem:=heapptr;
-        pheaprecord(sysgetmem)^.size:=size or usedmask;
+        if (heapptr+size=heapend) then
+         pheaprecord(sysgetmem)^.size:=size or (usedmask or beforeheapendmask)
+        else
+         pheaprecord(sysgetmem)^.size:=size or usedmask;
         inc(sysgetmem,sizeof(theaprecord));
         inc(sysgetmem,sizeof(theaprecord));
         inc(heapptr,size);
         inc(heapptr,size);
         exit;
         exit;
@@ -378,7 +382,8 @@ begin
      if sizeleft>sizeof(tfreerecord) then
      if sizeleft>sizeof(tfreerecord) then
       begin
       begin
         pcurr:=pfreerecord(pointer(pcurr)+size);
         pcurr:=pfreerecord(pointer(pcurr)+size);
-        pcurr^.size:=sizeleft;
+        { inherit the beforeheapendmask }
+        pcurr^.size:=sizeleft or (pheaprecord(sysgetmem)^.size and beforeheapendmask);
         { insert the block in the freelist }
         { insert the block in the freelist }
         pcurr^.prev:=nil;
         pcurr^.prev:=nil;
         s1:=sizeleft shr blockshr;
         s1:=sizeleft shr blockshr;
@@ -388,9 +393,15 @@ begin
         if assigned(freelists[s1]) then
         if assigned(freelists[s1]) then
          freelists[s1]^.prev:=pcurr;
          freelists[s1]^.prev:=pcurr;
         freelists[s1]:=pcurr;
         freelists[s1]:=pcurr;
+        { create the block we need to return }
+        pheaprecord(sysgetmem)^.size:=size or usedmask;
+      end
+     else
+      begin
+        { create the block we need to return }
+        pheaprecord(sysgetmem)^.size:=size or usedmask or (pheaprecord(sysgetmem)^.size and beforeheapendmask);
       end;
       end;
-     { create the block we need to return }
-     pheaprecord(sysgetmem)^.size:=size or usedmask;
+
      inc(sysgetmem,sizeof(theaprecord));
      inc(sysgetmem,sizeof(theaprecord));
      exit;
      exit;
    end;
    end;
@@ -401,7 +412,10 @@ begin
     if heapend-heapptr>size then
     if heapend-heapptr>size then
      begin
      begin
        sysgetmem:=heapptr;
        sysgetmem:=heapptr;
-       pheaprecord(sysgetmem)^.size:=size or usedmask;
+       if (heapptr+size=heapend) then
+        pheaprecord(sysgetmem)^.size:=size or (usedmask or beforeheapendmask)
+       else
+        pheaprecord(sysgetmem)^.size:=size or usedmask;
        inc(sysgetmem,sizeof(theaprecord));
        inc(sysgetmem,sizeof(theaprecord));
        inc(heapptr,size);
        inc(heapptr,size);
        exit;
        exit;
@@ -428,18 +442,19 @@ end;
 
 
 Function SysFreeMem(var p : pointer):Longint;
 Function SysFreeMem(var p : pointer):Longint;
 var
 var
-  s : longint;
+  pcurrsize,s : longint;
   pcurr : pfreerecord;
   pcurr : pfreerecord;
 begin
 begin
   if p=nil then
   if p=nil then
    HandleError(204);
    HandleError(204);
 { fix p to point to the heaprecord }
 { fix p to point to the heaprecord }
   pcurr:=pfreerecord(pointer(p)-sizeof(theaprecord));
   pcurr:=pfreerecord(pointer(p)-sizeof(theaprecord));
-  pcurr^.size:=pcurr^.size and sizemask;
-  inc(internal_memavail,pcurr^.size);
+  pcurrsize:=pcurr^.size and sizemask;
+  inc(internal_memavail,pcurrsize);
 { insert the block in it's freelist }
 { insert the block in it's freelist }
+  pcurr^.size:=pcurr^.size and (not usedmask);
   pcurr^.prev:=nil;
   pcurr^.prev:=nil;
-  s:=pcurr^.size shr blockshr;
+  s:=pcurrsize shr blockshr;
   if s>maxblock then
   if s>maxblock then
    s:=0;
    s:=0;
   pcurr^.next:=freelists[s];
   pcurr^.next:=freelists[s];
@@ -447,7 +462,7 @@ begin
    pcurr^.next^.prev:=pcurr;
    pcurr^.next^.prev:=pcurr;
   freelists[s]:=pcurr;
   freelists[s]:=pcurr;
   p:=nil;
   p:=nil;
-  SysFreeMem:=pcurr^.size;
+  SysFreeMem:=pcurrsize;
 end;
 end;
 
 
 
 
@@ -457,7 +472,7 @@ end;
 
 
 Function SysFreeMemSize(var p : pointer;size : longint):longint;
 Function SysFreeMemSize(var p : pointer;size : longint):longint;
 var
 var
-  s : longint;
+  pcurrsize,s : longint;
   pcurr : pfreerecord;
   pcurr : pfreerecord;
 begin
 begin
   SysFreeMemSize:=0;
   SysFreeMemSize:=0;
@@ -472,15 +487,16 @@ begin
    HandleError(204);
    HandleError(204);
 { fix p to point to the heaprecord }
 { fix p to point to the heaprecord }
   pcurr:=pfreerecord(pointer(p)-sizeof(theaprecord));
   pcurr:=pfreerecord(pointer(p)-sizeof(theaprecord));
-  pcurr^.size:=pcurr^.size and sizemask;
-  inc(internal_memavail,pcurr^.size);
+  pcurrsize:=pcurr^.size and sizemask;
+  inc(internal_memavail,pcurrsize);
 { size check }
 { size check }
   size:=(size+sizeof(theaprecord)+(blocksize-1)) and (not (blocksize-1));
   size:=(size+sizeof(theaprecord)+(blocksize-1)) and (not (blocksize-1));
-  if size<>pcurr^.size then
+  if size<>pcurrsize then
    HandleError(204);
    HandleError(204);
 { insert the block in it's freelist }
 { insert the block in it's freelist }
+  pcurr^.size:=pcurr^.size and (not usedmask);
   pcurr^.prev:=nil;
   pcurr^.prev:=nil;
-  s:=pcurr^.size shr blockshr;
+  s:=pcurrsize shr blockshr;
   if s>maxblock then
   if s>maxblock then
    s:=0;
    s:=0;
   pcurr^.next:=freelists[s];
   pcurr^.next:=freelists[s];
@@ -488,7 +504,7 @@ begin
    pcurr^.next^.prev:=pcurr;
    pcurr^.next^.prev:=pcurr;
   freelists[s]:=pcurr;
   freelists[s]:=pcurr;
   p:=nil;
   p:=nil;
-  SysFreeMemSize:=pcurr^.size;
+  SysFreeMemSize:=pcurrsize;
 end;
 end;
 
 
 
 
@@ -524,6 +540,7 @@ var
   foundsize,
   foundsize,
   sizeleft,
   sizeleft,
   s     : longint;
   s     : longint;
+  wasbeforeheapend : boolean;
   p2    : pointer;
   p2    : pointer;
   hp,
   hp,
   pnew,
   pnew,
@@ -541,6 +558,7 @@ begin
 { fix p to point to the heaprecord }
 { fix p to point to the heaprecord }
   pcurr:=pfreerecord(pointer(p)-sizeof(theaprecord));
   pcurr:=pfreerecord(pointer(p)-sizeof(theaprecord));
   currsize:=pcurr^.size and sizemask;
   currsize:=pcurr^.size and sizemask;
+  wasbeforeheapend:=(pcurr^.size and beforeheapendmask)<>0;
 { is the allocated block still correct? }
 { is the allocated block still correct? }
   if currsize=size then
   if currsize=size then
    begin
    begin
@@ -553,9 +571,16 @@ begin
    { the size is bigger than the previous size, we need to allocated more mem.
    { the size is bigger than the previous size, we need to allocated more mem.
      We first check if the blocks after the current block are free. If not we
      We first check if the blocks after the current block are free. If not we
      simply call getmem/freemem to get the new block }
      simply call getmem/freemem to get the new block }
-     foundsize:=pcurr^.size and sizemask;
+     foundsize:=0;
      hp:=pcurr;
      hp:=pcurr;
      repeat
      repeat
+       inc(foundsize,hp^.size and sizemask);
+       { block used or before a heapptr ? }
+       if (hp^.size and beforeheapendmask)<>0 then
+        begin
+          wasbeforeheapend:=true;
+          break;
+        end;
        { get next block }
        { get next block }
        hp:=pfreerecord(pointer(hp)+(hp^.size and sizemask));
        hp:=pfreerecord(pointer(hp)+(hp^.size and sizemask));
        { when we're at heapptr then we can stop }
        { when we're at heapptr then we can stop }
@@ -564,10 +589,8 @@ begin
           inc(foundsize,heapend-heapptr);
           inc(foundsize,heapend-heapptr);
           break;
           break;
         end;
         end;
-       { block used? }
        if (hp^.size and usedmask)<>0 then
        if (hp^.size and usedmask)<>0 then
         break;
         break;
-       inc(foundsize,hp^.size and sizemask);
      until (foundsize>=size);
      until (foundsize>=size);
    { found enough free blocks? }
    { found enough free blocks? }
      if foundsize>=size then
      if foundsize>=size then
@@ -588,10 +611,10 @@ begin
            end;
            end;
           s:=hp^.size and sizemask;
           s:=hp^.size and sizemask;
           inc(foundsize,s);
           inc(foundsize,s);
+          { remove block from freelist }
           s:=s shr blockshr;
           s:=s shr blockshr;
           if s>maxblock then
           if s>maxblock then
            s:=0;
            s:=0;
-          { remove block from freelist }
           if assigned(hp^.next) then
           if assigned(hp^.next) then
            hp^.next^.prev:=hp^.prev;
            hp^.next^.prev:=hp^.prev;
           if assigned(hp^.prev) then
           if assigned(hp^.prev) then
@@ -599,7 +622,10 @@ begin
           else
           else
            freelists[s]:=hp^.next;
            freelists[s]:=hp^.next;
         until (foundsize>=size);
         until (foundsize>=size);
-        pcurr^.size:=foundsize or usedmask;
+        if wasbeforeheapend then
+         pcurr^.size:=foundsize or usedmask or beforeheapendmask
+        else
+         pcurr^.size:=foundsize or usedmask;
       end
       end
      else
      else
       begin
       begin
@@ -623,7 +649,7 @@ begin
      if sizeleft>sizeof(tfreerecord) then
      if sizeleft>sizeof(tfreerecord) then
       begin
       begin
         pnew:=pfreerecord(pointer(pcurr)+size);
         pnew:=pfreerecord(pointer(pcurr)+size);
-        pnew^.size:=sizeleft;
+        pnew^.size:=sizeleft or (pcurr^.size and beforeheapendmask);
         { insert the block in the freelist }
         { insert the block in the freelist }
         pnew^.prev:=nil;
         pnew^.prev:=nil;
         s:=sizeleft shr blockshr;
         s:=sizeleft shr blockshr;
@@ -633,9 +659,14 @@ begin
         if assigned(freelists[s]) then
         if assigned(freelists[s]) then
          freelists[s]^.prev:=pnew;
          freelists[s]^.prev:=pnew;
         freelists[s]:=pnew;
         freelists[s]:=pnew;
+        { fix the size of the current block and leave }
+        pcurr^.size:=size or usedmask;
+      end
+     else
+      begin
+        { fix the size of the current block and leave }
+        pcurr^.size:=size or usedmask or (pcurr^.size and beforeheapendmask);
       end;
       end;
-     { fix the size of the current block and leave }
-     pcurr^.size:=size or usedmask;
    end;
    end;
   SysReAllocMem:=p;
   SysReAllocMem:=p;
 end;
 end;
@@ -713,7 +744,7 @@ begin
      if sizeleft>sizeof(tfreerecord) then
      if sizeleft>sizeof(tfreerecord) then
       begin
       begin
         pcurr:=pfreerecord(heapptr);
         pcurr:=pfreerecord(heapptr);
-        pcurr^.size:=sizeleft;
+        pcurr^.size:=sizeleft or beforeheapendmask;
         { insert the block in the freelist }
         { insert the block in the freelist }
         pcurr^.next:=freelists[0];
         pcurr^.next:=freelists[0];
         pcurr^.prev:=nil;
         pcurr^.prev:=nil;
@@ -752,7 +783,13 @@ end;
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.23  1999-11-10 22:29:51  michael
+  Revision 1.24  1999-11-14 21:34:21  peter
+    * fixed reallocmem with a block at the end of an allocated memoryblock,
+      had to introduce a flag for such blocks.
+    * flags are now stored in the first 4 bits instead of the highest bit,
+      this could be done because the sizes of block are always >= 16
+
+  Revision 1.23  1999/11/10 22:29:51  michael
   + Fixed sysreallocmem
   + Fixed sysreallocmem
 
 
   Revision 1.22  1999/11/01 13:56:50  peter
   Revision 1.22  1999/11/01 13:56:50  peter