Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixed nasty AV in FastFreeMem w/UseReleaseStack #9

Merged
merged 2 commits into from Feb 23, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
67 changes: 52 additions & 15 deletions FastMM4.pas
Expand Up @@ -1563,6 +1563,10 @@ procedure free(__ptr:pointer);cdecl;external clib name 'free';
function usleep(__useconds:dword):longint;cdecl;external clib name 'usleep';
{$endif}

{$ifdef PerCPUReleaseStack}
function GetCurrentProcessorNumber: DWORD; stdcall; external 'kernel32.dll' delayed;
{$endif}

{Fixed size move procedures. The 64-bit versions assume 16-byte alignment.}
procedure Move4(const ASource; var ADest; ACount: NativeInt); forward;
procedure Move12(const ASource; var ADest; ACount: NativeInt); forward;
Expand Down Expand Up @@ -1802,13 +1806,13 @@ TSmallBlockType = record
{$else}
Reserved1: Pointer;
{$endif}
{$ifdef UseReleaseStack}
ReleaseStack: TLFStack;
{$endif}
{$ifdef 64Bit}
{Pad to 64 bytes for 64-bit}
Reserved2: Pointer;
{$endif}
{$ifdef UseReleaseStack}
ReleaseStack: {$ifdef PerCPUReleaseStack}array [0..63] of{$endif} TLFStack;
{$endif}
{$ifdef LogLockContention}
BlockCollector: TStaticCollector;
{$endif}
Expand Down Expand Up @@ -4579,6 +4583,9 @@ function FastGetMem(ASize: {$ifdef XE2AndUp}NativeInt{$else}{$ifdef fpc}NativeUI
LStackTrace: TStackTrace;
{$endif}
{$endif}
{$ifdef UseReleaseStack}
LPReleaseStack: ^TLFStack;
{$endif}
begin
{$ifdef LogLockContention}
ACollector := nil;
Expand All @@ -4594,7 +4601,8 @@ function FastGetMem(ASize: {$ifdef XE2AndUp}NativeInt{$else}{$ifdef fpc}NativeUI
* (SizeOf(TSmallBlockType) div 4)
+ UIntPtr(@SmallBlockTypes));
{$ifdef UseReleaseStack}
if (not LPSmallBlockType.ReleaseStack.IsEmpty) and LPSmallBlockType.ReleaseStack.Pop(Result) then
LPReleaseStack := @LPSmallBlockType.ReleaseStack{$ifdef PerCPUReleaseStack}[GetCurrentProcessorNumber]{$endif};
if (not LPReleaseStack^.IsEmpty) and LPReleaseStack^.Pop(Result) then
Exit;
{$endif}
{Lock the block type}
Expand Down Expand Up @@ -6047,9 +6055,11 @@ function FastFreeMem(APointer: Pointer): {$ifdef fpc}NativeUInt{$else}Integer{$e
LDidSleep: Boolean;
LStackTrace: TStackTrace;
{$endif}
count: integer;
{$ifdef UseReleaseStack}
LReleaseCount: integer;
LPReleaseStack: ^TLFStack;
{$endif}
begin
count := 0;
{$ifdef fpc}
if APointer = nil then
begin
Expand Down Expand Up @@ -6080,7 +6090,8 @@ function FastFreeMem(APointer: Pointer): {$ifdef fpc}NativeUInt{$else}Integer{$e
while (LockCmpxchg(0, 1, @LPSmallBlockType.BlockTypeLocked) <> 0) do
begin
{$ifdef UseReleaseStack}
if (not LPSmallBlockType.ReleaseStack.IsFull) and LPSmallBlockType.ReleaseStack.Push(APointer) then begin
LPReleaseStack := @LPSmallBlockType.ReleaseStack{$ifdef PerCPUReleaseStack}[GetCurrentProcessorNumber]{$endif};
if (not LPReleaseStack^.IsFull) and LPReleaseStack^.Push(APointer) then begin
{Block will be released later.}
Result := 0;
Exit;
Expand All @@ -6107,6 +6118,9 @@ function FastFreeMem(APointer: Pointer): {$ifdef fpc}NativeUInt{$else}Integer{$e
GetStackTrace(@LStackTrace, StackTraceDepth, 1);
LPSmallBlockType.BlockCollector.Add(@LStackTrace[0], StackTraceDepth);
end;
{$endif}
{$ifdef UseReleaseStack}
LReleaseCount := 0;
{$endif}
repeat
{Get the old first free block}
Expand Down Expand Up @@ -6154,17 +6168,23 @@ function FastFreeMem(APointer: Pointer): {$ifdef fpc}NativeUInt{$else}Integer{$e
begin
{$endif}
{$ifdef UseReleaseStack}
if (count = (ReleaseStackSize div 2)) or
LPSmallBlockType.ReleaseStack.IsEmpty or
(not LPSmallBlockType.ReleaseStack.Pop(APointer)) then
LPReleaseStack := @LPSmallBlockType.ReleaseStack{$ifdef PerCPUReleaseStack}[GetCurrentProcessorNumber]{$endif};
if (LReleaseCount < (ReleaseStackSize div 2)) and
(not LPReleaseStack^.IsEmpty) and
LPReleaseStack^.Pop(APointer) then
begin
LBlockHeader := PNativeUInt(PByte(APointer) - BlockHeaderSize)^;
LPSmallBlockPool := PSmallBlockPoolHeader(LBlockHeader);
Inc(LReleaseCount);
end
else
begin
{$endif}
APointer := nil;
{Unlock this block type}
LPSmallBlockType.BlockTypeLocked := False;
{$ifdef UseReleaseStack}
end;
Inc(count);
{$endif}
{$ifndef FullDebugMode}
end;
Expand Down Expand Up @@ -11978,6 +11998,9 @@ procedure InitializeMemoryManager;
LInd, LSizeInd, LMinimumPoolSize, LOptimalPoolSize, LGroupNumber,
LBlocksPerPool, LPreviousBlockSize: Cardinal;
LPMediumFreeBlock: PMediumFreeBlock;
{$ifdef PerCPUReleaseStack}
LCPU: integer;
{$endif}
begin
{$ifdef FullDebugMode}
{$ifdef LoadDebugDLLDynamically}
Expand Down Expand Up @@ -12061,7 +12084,10 @@ procedure InitializeMemoryManager;
SmallBlockTypes[LInd].OptimalBlockPoolSize :=
((LBlocksPerPool * SmallBlockTypes[LInd].BlockSize + SmallBlockPoolHeaderSize + MediumBlockGranularity - 1 - MediumBlockSizeOffset) and -MediumBlockGranularity) + MediumBlockSizeOffset;
{$ifdef UseReleaseStack}
SmallBlockTypes[LInd].ReleaseStack.Initialize(ReleaseStackSize, SizeOf(pointer));
{$ifdef PerCPUReleaseStack}
for LCPU := 0 to 63 do
{$endif}
SmallBlockTypes[LInd].ReleaseStack{$ifdef PerCPUReleaseStack}[LCPU]{$endif}.Initialize(ReleaseStackSize, SizeOf(pointer));
{$endif}
{$ifdef CheckHeapForCorruption}
{Debug checks}
Expand Down Expand Up @@ -12373,11 +12399,22 @@ procedure CleanupReleaseStacks;
var
LInd: integer;
LMemory: pointer;
{$ifdef PerCPUReleaseStack}
LCPU: Integer;
{$endif}
begin
for LInd := 0 to High(SmallBlockTypes) do begin
while SmallBlockTypes[LInd].ReleaseStack.Pop(LMemory) do
FastFreeMem(LMemory);
SmallBlockTypes[LInd].ReleaseStack.Finalize;
{$ifdef PerCPUReleaseStack}
for LCPU := 0 to 63 do
{$endif}
while SmallBlockTypes[LInd].ReleaseStack{$ifdef PerCPUReleaseStack}[LCPU]{$endif}.Pop(LMemory) do
FastFreeMem(LMemory);
{Finalize all stacks only after all memory for this block has been freed.}
{Otherwise, FastFreeMem could try to access a stack that was already finalized.}
{$ifdef PerCPUReleaseStack}
for LCPU := 0 to 63 do
{$endif}
SmallBlockTypes[LInd].ReleaseStack{$ifdef PerCPUReleaseStack}[LCPU]{$endif}.Finalize;
end;
end;
{$endif}
Expand Down