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

Add NativeMemory.ZeroMemory API #69500

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,19 @@ public static unsafe partial class NativeMemory
return AllocZeroed(byteCount, elementSize: 1);
}

/// <summary>Clears a block of memory.</summary>
/// <param name="ptr">A pointer to the block of memory that should be cleared.</param>
/// <param name="byteCount">The size, in bytes, of the block to clear.</param>
/// <remarks>
/// <para>If this method is called with <paramref name="ptr" /> being <see langword="null"/> and <paramref name="byteCount" /> being <c>0</c>, it will be equivalent to a no-op.</para>
/// <para>The behavior when <paramref name="ptr" /> is <see langword="null"/> and <paramref name="byteCount" /> is greater than <c>0</c> is undefined.</para>
/// </remarks>
[CLSCompliant(false)]
public static unsafe void ZeroMemory(void* ptr, nuint byteCount)
{
SpanHelpers.ClearWithoutReferences(ref *(byte*)ptr, byteCount);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static nuint GetByteCount(nuint elementCount, nuint elementSize)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,8 @@ public static void AlignedFree(void* ptr) { }
public static void Free(void* ptr) { }
[System.CLSCompliantAttribute(false)]
public static void* Realloc(void* ptr, nuint byteCount) { throw null; }
[System.CLSCompliantAttribute(false)]
public static void ZeroMemory(void* ptr, nuint byteCount) { throw null; }
}
public readonly partial struct NFloat : System.IComparable, System.IComparable<System.Runtime.InteropServices.NFloat>, System.IEquatable<System.Runtime.InteropServices.NFloat>, System.IFormattable, System.IParsable<System.Runtime.InteropServices.NFloat>, System.ISpanFormattable, System.ISpanParsable<System.Runtime.InteropServices.NFloat>, System.Numerics.IAdditionOperators<System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat>, System.Numerics.IAdditiveIdentity<System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat>, System.Numerics.IBinaryFloatingPointIeee754<System.Runtime.InteropServices.NFloat>, System.Numerics.IBinaryNumber<System.Runtime.InteropServices.NFloat>, System.Numerics.IBitwiseOperators<System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat>, System.Numerics.IComparisonOperators<System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat>, System.Numerics.IDecrementOperators<System.Runtime.InteropServices.NFloat>, System.Numerics.IDivisionOperators<System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat>, System.Numerics.IEqualityOperators<System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat>, System.Numerics.IExponentialFunctions<System.Runtime.InteropServices.NFloat>, System.Numerics.IFloatingPoint<System.Runtime.InteropServices.NFloat>, System.Numerics.IFloatingPointIeee754<System.Runtime.InteropServices.NFloat>, System.Numerics.IHyperbolicFunctions<System.Runtime.InteropServices.NFloat>, System.Numerics.IIncrementOperators<System.Runtime.InteropServices.NFloat>, System.Numerics.ILogarithmicFunctions<System.Runtime.InteropServices.NFloat>, System.Numerics.IMinMaxValue<System.Runtime.InteropServices.NFloat>, System.Numerics.IModulusOperators<System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat>, System.Numerics.IMultiplicativeIdentity<System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat>, System.Numerics.IMultiplyOperators<System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat>, System.Numerics.INumber<System.Runtime.InteropServices.NFloat>, System.Numerics.INumberBase<System.Runtime.InteropServices.NFloat>, System.Numerics.IPowerFunctions<System.Runtime.InteropServices.NFloat>, System.Numerics.IRootFunctions<System.Runtime.InteropServices.NFloat>, System.Numerics.ISignedNumber<System.Runtime.InteropServices.NFloat>, System.Numerics.ISubtractionOperators<System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat>, System.Numerics.ITrigonometricFunctions<System.Runtime.InteropServices.NFloat>, System.Numerics.IUnaryNegationOperators<System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat>, System.Numerics.IUnaryPlusOperators<System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -435,5 +435,128 @@ public void ReallocSmallerToLargerTest()

NativeMemory.Free(newPtr);
}

[Theory]
[InlineData(1, 0)]
AaronRobinsonMSFT marked this conversation as resolved.
Show resolved Hide resolved
[InlineData(1, 1)]
[InlineData(1, 2)]
[InlineData(1, 3)]
[InlineData(2, 0)]
[InlineData(3, 0)]
[InlineData(4, 0)]
[InlineData(8, 0)]
[InlineData(9, 0)]
[InlineData(16, 0)]
[InlineData(16, 1)]
[InlineData(16, 3)]
[InlineData(16, 7)]
[InlineData(32, 0)]
[InlineData(64, 0)]
[InlineData(128, 0)]
[InlineData(256, 0)]
[InlineData(256, 1)]
[InlineData(256, 2)]
[InlineData(256, 3)]
[InlineData(256, 5)]
[InlineData(512, 0)]
[InlineData(547, 0)]
[InlineData(1 * 1024, 0)]
public void ZeroMemoryTest(int size, int offset)
{
byte* ptr = (byte*)NativeMemory.AlignedAlloc((nuint)(size + offset), 8);

Assert.True(ptr != null);
Assert.True((nuint)ptr % 8 == 0);

new Span<byte>(ptr, size + offset).Fill(0b10101010);

NativeMemory.ZeroMemory(ptr + offset, (nuint)size);

Assert.Equal(-1, new Span<byte>(ptr + offset, size).IndexOfAnyExcept((byte)0));

NativeMemory.AlignedFree(ptr);
}

[Theory]
[InlineData(1, 0)]
[InlineData(1, 1)]
[InlineData(1, 2)]
[InlineData(1, 3)]
[InlineData(1, 44)]
[InlineData(1, 367)]
[InlineData(2, 0)]
[InlineData(3, 0)]
[InlineData(4, 0)]
[InlineData(8, 0)]
[InlineData(9, 0)]
[InlineData(9, 2)]
[InlineData(9, 111)]
[InlineData(9, 289)]
[InlineData(16, 0)]
[InlineData(16, 1)]
[InlineData(16, 3)]
[InlineData(16, 7)]
[InlineData(32, 0)]
[InlineData(64, 0)]
[InlineData(128, 0)]
[InlineData(256, 0)]
[InlineData(256, 1)]
[InlineData(256, 2)]
[InlineData(256, 3)]
[InlineData(256, 5)]
[InlineData(256, 67)]
[InlineData(256, 143)]
public void ZeroMemoryWithExactRangeTest(int size, int offset)
{
int headLength = offset;
int bodyLength = size;
int tailLength = 512 - headLength - bodyLength;
int headOffset = 0;
int bodyOffset = headLength;
int tailOffset = headLength + bodyLength;

byte* ptr = (byte*)NativeMemory.AlignedAlloc(512, 8);

Assert.True(ptr != null);
Assert.True((nuint)ptr % 8 == 0);

new Span<byte>(ptr, 512).Fill(0b10101010);

NativeMemory.ZeroMemory(ptr + bodyOffset, (nuint)bodyLength);

Assert.Equal(-1, new Span<byte>(ptr + headOffset, headLength).IndexOfAnyExcept((byte)0b10101010));
Assert.Equal(-1, new Span<byte>(ptr + bodyOffset, bodyLength).IndexOfAnyExcept((byte)0));
Assert.Equal(-1, new Span<byte>(ptr + tailOffset, tailLength).IndexOfAnyExcept((byte)0b10101010));

Sergio0694 marked this conversation as resolved.
Show resolved Hide resolved
NativeMemory.AlignedFree(ptr);
}

[Theory]
[InlineData(0)]
[InlineData(1)]
[InlineData(167)]
public void ZeroMemoryWithSizeEqualTo0ShouldNoOpTest(int offset)
{
byte* ptr = (byte*)NativeMemory.AlignedAlloc(512, 8);

Assert.True(ptr != null);
Assert.True((nuint)ptr % 8 == 0);

new Span<byte>(ptr, 512).Fill(0b10101010);

NativeMemory.ZeroMemory(ptr + offset, 0);

Assert.Equal(-1, new Span<byte>(ptr, 512).IndexOfAnyExcept((byte)0b10101010));

NativeMemory.AlignedFree(ptr);
}

[Fact]
public void ZeroMemoryWithNullPointerAndZeroByteCountTest()
{
NativeMemory.ZeroMemory(null, 0);

// This test method just needs to check that no exceptions are thrown
}
}
}