Quellcode durchsuchen

Fix cross-thread ReallocMem in heaptrc.

Rika Ichinose vor 18 Stunden
Ursprung
Commit
d91a4ef56f
1 geänderte Dateien mit 62 neuen und 36 gelöschten Zeilen
  1. 62 36
      rtl/inc/heaptrc.pp

+ 62 - 36
rtl/inc/heaptrc.pp

@@ -824,7 +824,9 @@ end;
 
 function TraceReAllocMem(var p:pointer;size:ptruint):Pointer;
 var
-  i, allocsize : ptruint;
+  newP: pointer;
+  i, allocsize,
+  movesize  : ptruint;
   pl : pdword;
   pp,prevpp{$ifdef EXTRA},ppv{$endif} : pheap_mem_info;
   oldsize,
@@ -885,43 +887,67 @@ begin
    inc(allocsize,tail_size);
   { Try to resize the block, if not possible we need to do a
     getmem, move data, freemem }
-  prevpp:=pp;
-  if (SysReAllocMem(pp,allocsize)<>prevpp) then
-    begin
-      { We need to update the previous/next chains }
-      if assigned(pp^.previous) then
-        pp^.previous^.next:=pp;
-      if assigned(pp^.next) then
-        pp^.next^.previous:=pp;
-      if prevpp=loc_info^.heap_mem_root then
-        loc_info^.heap_mem_root:=pp;
+  if pp^.todolist<>@loc_info^.heap_free_todo then
+   begin
+     { get a new block }
+     newP := TraceGetMem(size);
+     { move the data }
+     if newP <> nil then
+      begin
+        movesize:=TraceMemSize(p);
+        {if the old size is larger than the new size,
+         move only the new size}
+        if movesize>size then
+          movesize:=size;
+        move(p^,newP^,movesize);
+      end;
+     { release p }
+     traceFreeMem(p);
+     { return the new pointer }
+     p:=newp;
+     traceReAllocMem := newp;
+     exit;
+   end
+  else
+   begin
+     prevpp:=pp;
+     if (SysReallocMem(pp,allocsize)<>prevpp) then
+       begin
+         { We need to update the previous/next chains }
+         if assigned(pp^.previous) then
+           pp^.previous^.next:=pp;
+         if assigned(pp^.next) then
+           pp^.next^.previous:=pp;
+         if prevpp=loc_info^.heap_mem_root then
+           loc_info^.heap_mem_root:=pp;
 {$ifdef EXTRA}
-      { remove prevpp from prev_valid chain }
-      ppv:=loc_info^.heap_valid_last;
-      if (ppv=prevpp) then
-        loc_info^.heap_valid_last:=pp^.prev_valid
-      else
-        begin
-          while assigned(ppv) do
-            begin
-              if (ppv^.prev_valid=prevpp) then
-                begin
-                  ppv^.prev_valid:=pp^.prev_valid;
-                  if prevpp=loc_info^.heap_valid_first then
-                    loc_info^.heap_valid_first:=ppv;
-                  ppv:=nil;
-                end
-              else
-                ppv:=ppv^.prev_valid;
-            end;
-        end;
-      { Reinsert new value in last position }
-      pp^.prev_valid:=loc_info^.heap_valid_last;
-      loc_info^.heap_valid_last:=pp;
-      if not assigned(loc_info^.heap_valid_first) then
-        loc_info^.heap_valid_first:=pp;
+         { remove prevpp from prev_valid chain }
+         ppv:=loc_info^.heap_valid_last;
+         if (ppv=prevpp) then
+           loc_info^.heap_valid_last:=pp^.prev_valid
+         else
+           begin
+             while assigned(ppv) do
+               begin
+                 if (ppv^.prev_valid=prevpp) then
+                   begin
+                     ppv^.prev_valid:=pp^.prev_valid;
+                     if prevpp=loc_info^.heap_valid_first then
+                       loc_info^.heap_valid_first:=ppv;
+                     ppv:=nil;
+                   end
+                 else
+                   ppv:=ppv^.prev_valid;
+               end;
+           end;
+         { Reinsert new value in last position }
+         pp^.prev_valid:=loc_info^.heap_valid_last;
+         loc_info^.heap_valid_last:=pp;
+         if not assigned(loc_info^.heap_valid_first) then
+           loc_info^.heap_valid_first:=pp;
 {$endif EXTRA}
-    end;
+       end;
+   end;
 { Recreate the info block }
   pp^.sig:=longword(AllocateSig);
   pp^.size:=size;