Skip to content

Commit 3259c94

Browse files
authored
Merge pull request #2025 from SixLabors/af/TotalAvailableMemoryBytes-workaround
Workaround GC.GetMemoryInfo() ARM32 issue
2 parents c059656 + 7387607 commit 3259c94

File tree

2 files changed

+30
-5
lines changed

2 files changed

+30
-5
lines changed

src/ImageSharp/Memory/Allocators/UniformUnmanagedMemoryPoolMemoryAllocator.cs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
// Copyright (c) Six Labors.
1+
// Copyright (c) Six Labors.
22
// Licensed under the Apache License, Version 2.0.
33

44
using System;
55
using System.Buffers;
66
using System.Runtime.CompilerServices;
77
using System.Runtime.InteropServices;
8-
using System.Threading;
98
using SixLabors.ImageSharp.Memory.Internals;
109

1110
namespace SixLabors.ImageSharp.Memory
@@ -22,7 +21,7 @@ internal sealed class UniformUnmanagedMemoryPoolMemoryAllocator : MemoryAllocato
2221
private readonly int poolCapacity;
2322
private readonly UniformUnmanagedMemoryPool.TrimSettings trimSettings;
2423

25-
private UniformUnmanagedMemoryPool pool;
24+
private readonly UniformUnmanagedMemoryPool pool;
2625
private readonly UnmanagedMemoryAllocator nonPoolAllocator;
2726

2827
public UniformUnmanagedMemoryPoolMemoryAllocator(int? maxPoolSizeMegabytes)
@@ -74,6 +73,12 @@ internal UniformUnmanagedMemoryPoolMemoryAllocator(
7473
this.nonPoolAllocator = new UnmanagedMemoryAllocator(unmanagedBufferSizeInBytes);
7574
}
7675

76+
#if NETCOREAPP3_1_OR_GREATER
77+
// This delegate allows overriding the method returning the available system memory,
78+
// so we can test our workaround for https://github.com/dotnet/runtime/issues/65466
79+
internal static Func<long> GetTotalAvailableMemoryBytes { get; set; } = () => GC.GetGCMemoryInfo().TotalAvailableMemoryBytes;
80+
#endif
81+
7782
/// <inheritdoc />
7883
protected internal override int GetBufferCapacityInBytes() => this.poolBufferSizeInBytes;
7984

@@ -152,8 +157,13 @@ private static long GetDefaultMaxPoolSizeBytes()
152157
// https://github.com/dotnet/runtime/issues/55126#issuecomment-876779327
153158
if (Environment.Is64BitProcess || !RuntimeInformation.FrameworkDescription.StartsWith(".NET 5.0"))
154159
{
155-
GCMemoryInfo info = GC.GetGCMemoryInfo();
156-
return info.TotalAvailableMemoryBytes / 8;
160+
long total = GetTotalAvailableMemoryBytes();
161+
162+
// Workaround for https://github.com/dotnet/runtime/issues/65466
163+
if (total > 0)
164+
{
165+
return total / 8;
166+
}
157167
}
158168
#endif
159169

tests/ImageSharp.Tests/Memory/Allocators/UniformUnmanagedPoolMemoryAllocatorTests.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,5 +379,20 @@ private static void AllocateSingleAndForget(UniformUnmanagedMemoryPoolMemoryAllo
379379
g1.GetSpan()[0] = 42;
380380
}
381381
}
382+
383+
#if NETCOREAPP3_1_OR_GREATER
384+
[Fact]
385+
public void Issue2001_NegativeMemoryReportedByGc()
386+
{
387+
RemoteExecutor.Invoke(RunTest).Dispose();
388+
389+
static void RunTest()
390+
{
391+
// Emulate GC.GetGCMemoryInfo() issue https://github.com/dotnet/runtime/issues/65466
392+
UniformUnmanagedMemoryPoolMemoryAllocator.GetTotalAvailableMemoryBytes = () => -402354176;
393+
_ = MemoryAllocator.Create();
394+
}
395+
}
396+
#endif
382397
}
383398
}

0 commit comments

Comments
 (0)