Skip to content
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Factor the cleaning-up of the segment buffers into a separate method.
  • Loading branch information
teo-tsirpanis authored and github-actions committed Aug 31, 2021
commit 0b1aaf0c85ceb86f9ba6e110e6827d6758656949
Original file line number Diff line number Diff line change
Expand Up @@ -432,8 +432,10 @@ private static bool CanUseScatterGatherWindowsAPIs(SafeFileHandle handle)
// 3. not bigger than 2^32 - 1 in total
// This function is also responsible for pinning the buffers if they
// are suitable and they must be unpinned after the I/O operation completes.
// It also returns a pointer with the segments to be passed to the Windows API and to be
// freed by NativeMemory.Free, and the total size of the buffers that is needed as well.
// It also returns a pointer with the segments to be passed to the
// Windows API, and the total size of the buffers that is needed as well.
// The pinned MemoryHandles and the pointer to the segments must be cleaned-up
// with the CleanupScatterGatherBuffers method.
private static unsafe bool TryPrepareScatterGatherBuffers<T, THandler>(IReadOnlyList<T> buffers,
THandler handler, out MemoryHandle[] handlesToDispose, out IntPtr segmentsPtr, out int totalBytes)
where THandler: struct, IMemoryHandler<T>
Expand All @@ -450,8 +452,8 @@ private static unsafe bool TryPrepareScatterGatherBuffers<T, THandler>(IReadOnly
totalBytes = 0;

// "The array must contain enough elements to store nNumberOfBytesToWrite bytes of data, and one element for the terminating NULL. "
long* segmentsArray = (long*) NativeMemory.Alloc((nuint)(buffersCount + 1), sizeof(long));
segmentsArray[buffersCount] = 0;
long* segments = (long*) NativeMemory.Alloc((nuint)(buffersCount + 1), sizeof(long));
segments[buffersCount] = 0;

bool success = false;
try
Expand All @@ -468,14 +470,14 @@ private static unsafe bool TryPrepareScatterGatherBuffers<T, THandler>(IReadOnly
}

MemoryHandle handle = handlesToDispose[i] = handler.Pin(in buffer);
long ptr = segmentsArray[i] = (long)handle.Pointer;
long ptr = segments[i] = (long)handle.Pointer;
if ((ptr & alignedAtPageSizeMask) != 0)
{
return false;
}
}

segmentsPtr = (IntPtr)segmentsArray;
segmentsPtr = (IntPtr)segments;
totalBytes = (int)totalBytes64;
success = true;
return true;
Expand All @@ -484,16 +486,21 @@ private static unsafe bool TryPrepareScatterGatherBuffers<T, THandler>(IReadOnly
{
if (!success)
{
foreach (MemoryHandle handle in handlesToDispose)
{
handle.Dispose();
}

NativeMemory.Free(segmentsArray);
CleanupScatterGatherBuffers(handlesToDispose, (IntPtr) segments);
}
}
}

private static unsafe void CleanupScatterGatherBuffers(MemoryHandle[] handlesToDispose, IntPtr segmentsPtr)
{
foreach (MemoryHandle handle in handlesToDispose)
{
handle.Dispose();
}

NativeMemory.Free((void*) segmentsPtr);
}

private static ValueTask<long> ReadScatterAtOffsetAsync(SafeFileHandle handle, IReadOnlyList<Memory<byte>> buffers,
long fileOffset, CancellationToken cancellationToken)
{
Expand All @@ -519,15 +526,7 @@ private static async ValueTask<long> ReadScatterAtOffsetSingleSyscallAsync(SafeF
}
finally
{
foreach (MemoryHandle memoryHandle in handlesToDispose)
{
memoryHandle.Dispose();
}

unsafe
{
NativeMemory.Free(segmentsPtr.ToPointer());
}
CleanupScatterGatherBuffers(handlesToDispose, segmentsPtr);
}
}

Expand Down Expand Up @@ -624,15 +623,7 @@ private static async ValueTask WriteGatherAtOffsetSingleSyscallAsync(SafeFileHan
}
finally
{
foreach (MemoryHandle memoryHandle in handlesToDispose)
{
memoryHandle.Dispose();
}

unsafe
{
NativeMemory.Free(segmentsPtr.ToPointer());
}
CleanupScatterGatherBuffers(handlesToDispose, segmentsPtr);
}
}

Expand Down