Skip to content

Commit

Permalink
quick fix for much better locking improvement
Browse files Browse the repository at this point in the history
the pending free queue wasn't cleared properly, so it kept waiting/sleeping
  • Loading branch information
andremussche committed Feb 23, 2016
1 parent 0895298 commit 589c87a
Showing 1 changed file with 50 additions and 26 deletions.
76 changes: 50 additions & 26 deletions FastMM4.pas
@@ -1,3 +1,7 @@
{$Include FastMM4Options.inc}

{$define UseReleaseStack}

(*
Fast Memory Manager 4.991
Expand Down Expand Up @@ -160,8 +164,8 @@
- Kristofer Skaug for reporting the bug that sometimes causes the leak report
to be shown, even when all the leaks have been registered as expected leaks.
Also for some useful enhancement suggestions.
- Günther Schoch for the "RequireDebuggerPresenceForLeakReporting" option.
- Jan Schlüter for the "ForceMMX" option.
- Günther Schoch for the "RequireDebuggerPresenceForLeakReporting" option.
- Jan Schlüter for the "ForceMMX" option.
- Hallvard Vassbotn for various good enhancement suggestions.
- Mark Edington for some good suggestions and bug reports.
- Paul Ishenin for reporting the compilation error when the NoMessageBoxes
Expand Down Expand Up @@ -219,7 +223,7 @@
not work in FullDebugMode.
- Ionut Muntean for the Romanian translation.
- Florent Ouchet for the French translation.
- Marcus Mönnig for the ScanMemoryPoolForCorruptions suggestion and the
- Marcus Mönnig for the ScanMemoryPoolForCorruptions suggestion and the
suggestion to have the option to scan the memory pool before every
operation when in FullDebugMode.
- Francois Piette for bringing under my attention that
Expand Down Expand Up @@ -438,10 +442,10 @@
leaks were registered as expected leaks. (Thanks to Kristofer Skaug.)
Version 4.29 (30 September 2005):
- Added the "RequireDebuggerPresenceForLeakReporting" option to only display
the leak report if the application is run inside the IDE. (Thanks to Günther
the leak report if the application is run inside the IDE. (Thanks to Günther
Schoch.)
- Added the "ForceMMX" option, which when disabled will check the CPU for
MMX compatibility before using MMX. (Thanks to Jan Schlüter.)
MMX compatibility before using MMX. (Thanks to Jan Schlüter.)
- Added the module name to the title of error dialogs to more easily identify
which application caused the error. (Thanks to Kristofer Skaug.)
- Added an ASCII dump to the "FullDebugMode" memory dumps. (Thanks to Hallvard
Expand Down Expand Up @@ -670,14 +674,14 @@
- Added a ScanMemoryPoolForCorruptions procedure that checks the entire
memory pool for corruptions and raises an exception if one is found. It can
be called at any time, but is only available in FullDebugMode. (Thanks to
Marcus Mönnig.)
Marcus Mönnig.)
- Added a global variable "FullDebugModeScanMemoryPoolBeforeEveryOperation".
When this variable is set to true and FullDebugMode is enabled, then the
entire memory pool is checked for consistency before every GetMem, FreeMem
and ReallocMem operation. An "Out of Memory" error is raised if a
corruption is found (and this variable is set to false to prevent recursive
errors). This obviously incurs a massive performance hit, so enable it only
when hunting for elusive memory corruption bugs. (Thanks to Marcus Mönnig.)
when hunting for elusive memory corruption bugs. (Thanks to Marcus Mönnig.)
- Fixed a bug in AllocMem that caused the FPU stack to be shifted by one
position.
- Changed the default for option "EnableMMX" to false, since using MMX may
Expand Down Expand Up @@ -840,7 +844,7 @@
- Included the average block size in the memory state log file. (Thanks to
Hallvard Vassbotn)
- Support added for Free Pascal's OS X and Linux targets, both i386 and
x86-64. (Thanks to Zoë Peterson - some fixes by Arnaud Bouchez)
x86-64. (Thanks to Zoë Peterson - some fixes by Arnaud Bouchez)
- Added the LogLockContention option which may be used to track down areas
in the application that lead to frequent lock contentions in the memory
manager. (Primoz Gabrijelcic)
Expand Down Expand Up @@ -6044,9 +6048,9 @@ function FastFreeMem(APointer: Pointer): {$ifdef fpc}NativeUInt{$else}Integer{$e
LDidSleep: Boolean;
LStackTrace: TStackTrace;
{$endif}
count: integer;
//count: integer;
begin
count := 0;
//count := 0;
{$ifdef fpc}
if APointer = nil then
begin
Expand Down Expand Up @@ -6077,7 +6081,7 @@ function FastFreeMem(APointer: Pointer): {$ifdef fpc}NativeUInt{$else}Integer{$e
while (LockCmpxchg(0, 1, @LPSmallBlockType.BlockTypeLocked) <> 0) do
begin
{$ifdef UseReleaseStack}
if LPSmallBlockType.ReleaseStack.Push(APointer) then begin
if (not LPSmallBlockType.ReleaseStack.IsFull) and LPSmallBlockType.ReleaseStack.Push(APointer) then begin
{Block will be released later.}
Result := 0;
Exit;
Expand Down Expand Up @@ -6105,6 +6109,7 @@ function FastFreeMem(APointer: Pointer): {$ifdef fpc}NativeUInt{$else}Integer{$e
LPSmallBlockType.BlockCollector.Add(@LStackTrace[0], StackTraceDepth);
end;
{$endif}

repeat
{Get the old first free block}
LOldFirstFreeBlock := LPSmallBlockPool.FirstFreeBlock;
Expand All @@ -6128,6 +6133,7 @@ function FastFreeMem(APointer: Pointer): {$ifdef fpc}NativeUInt{$else}Integer{$e
likehood of success in catching objects still being used after being
destroyed.}
{$ifndef FullDebugMode}
(* don't free the pool for now, it gives AV with ReleaseStack!
{Is the entire pool now free? -> Free it.}
if LPSmallBlockPool.BlocksInUse = 0 then
begin
Expand All @@ -6146,25 +6152,43 @@ function FastFreeMem(APointer: Pointer): {$ifdef fpc}NativeUInt{$else}Integer{$e
FreeMediumBlock(LPSmallBlockPool);
{Stop unwinding the release stack.}
APointer := nil;
end
else
begin
{$endif}
{$ifdef UseReleaseStack}
if (count = (ReleaseStackSize div 2)) or (not LPSmallBlockType.ReleaseStack.Pop(APointer)) then
begin
{$endif}
Result := 0;
Exit;
end;
*)
// else
// begin
{$endif}
//{$ifdef UseReleaseStack}
// if (count = (ReleaseStackSize div 2)) or
// LPSmallBlockType.ReleaseStack.IsEmpty or
// (not LPSmallBlockType.ReleaseStack.Pop(APointer)) then
// begin
//{$endif}
APointer := nil;
{Unlock this block type}
LPSmallBlockType.BlockTypeLocked := False;
// {Unlock this block type}
// LPSmallBlockType.BlockTypeLocked := False; don't unlock it here already, keep the lock
//{$endif}

//{$ifdef UseReleaseStack}
// end;
// Inc(count);
//{$endif}
//{$ifndef FullDebugMode}
// end;
//{$endif}

{$ifdef UseReleaseStack}
end;
Inc(count);
{$endif}
{$ifndef FullDebugMode}
end;
//we still have the lock, so free everything from the pending queue
if not LPSmallBlockType.ReleaseStack.IsEmpty then
LPSmallBlockType.ReleaseStack.Pop(APointer);
{$endif}
until not assigned(APointer);

{Unlock this block type}
LPSmallBlockType.BlockTypeLocked := False; //unlock it here, after processing the queue

{No error}
Result := 0;
end
Expand Down

0 comments on commit 589c87a

Please sign in to comment.