Skip to content

Commit 4ea55fc

Browse files
committed
PR feedback
- Move NativeOverlapped* to the AsyncAcceptContext. This removes the SafeNativeOverlapped allocation as the lifetime is managed by the AsyncAcceptContext - Rename tcs
1 parent 0038f1f commit 4ea55fc

File tree

3 files changed

+31
-25
lines changed

3 files changed

+31
-25
lines changed

src/Servers/HttpSys/src/AsyncAcceptContext.cs

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ internal unsafe class AsyncAcceptContext : IValueTaskSource<RequestContext>, IDi
1313
{
1414
private static readonly IOCompletionCallback IOCallback = IOWaitCallback;
1515
private readonly PreAllocatedOverlapped _preallocatedOverlapped;
16+
private NativeOverlapped* _overlapped;
1617

1718
// mutable struct; do not make this readonly
18-
private ManualResetValueTaskSourceCore<RequestContext> _tcs = new()
19+
private ManualResetValueTaskSourceCore<RequestContext> _mrvts = new()
1920
{
2021
// We want to run continuations on the IO threads
2122
RunContinuationsAsynchronously = false
@@ -33,7 +34,7 @@ internal AsyncAcceptContext(HttpSysListener server)
3334

3435
internal ValueTask<RequestContext> AcceptAsync()
3536
{
36-
_tcs.Reset();
37+
_mrvts.Reset();
3738

3839
AllocateNativeRequest();
3940

@@ -46,7 +47,7 @@ internal ValueTask<RequestContext> AcceptAsync()
4647
return ValueTask.FromException<RequestContext>(new HttpSysException((int)statusCode));
4748
}
4849

49-
return new ValueTask<RequestContext>(this, _tcs.Version);
50+
return new ValueTask<RequestContext>(this, _mrvts.Version);
5051
}
5152

5253
private static void IOCompleted(AsyncAcceptContext asyncContext, uint errorCode, uint numBytes)
@@ -58,7 +59,7 @@ private static void IOCompleted(AsyncAcceptContext asyncContext, uint errorCode,
5859
if (errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
5960
errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_MORE_DATA)
6061
{
61-
asyncContext._tcs.SetException(new HttpSysException((int)errorCode));
62+
asyncContext._mrvts.SetException(new HttpSysException((int)errorCode));
6263
return;
6364
}
6465

@@ -78,14 +79,14 @@ private static void IOCompleted(AsyncAcceptContext asyncContext, uint errorCode,
7879
asyncContext._nativeRequestContext = null;
7980

8081
var requestContext = new RequestContext(server, nativeContext);
81-
asyncContext._tcs.SetResult(requestContext);
82+
asyncContext._mrvts.SetResult(requestContext);
8283

8384
complete = true;
8485
}
8586
}
8687
catch (Exception ex)
8788
{
88-
asyncContext._tcs.SetException(ex);
89+
asyncContext._mrvts.SetException(ex);
8990
}
9091
finally
9192
{
@@ -111,13 +112,13 @@ private static void IOCompleted(AsyncAcceptContext asyncContext, uint errorCode,
111112
{
112113
// someother bad error, possible(?) return values are:
113114
// ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
114-
asyncContext._tcs.SetException(new HttpSysException((int)statusCode));
115+
asyncContext._mrvts.SetException(new HttpSysException((int)statusCode));
115116
}
116117
}
117118
}
118119
catch (Exception exception)
119120
{
120-
asyncContext._tcs.SetException(exception);
121+
asyncContext._mrvts.SetException(exception);
121122
}
122123
}
123124

@@ -144,7 +145,7 @@ private uint QueueBeginGetContext()
144145
_nativeRequestContext.NativeRequest,
145146
_nativeRequestContext.Size,
146147
&bytesTransferred,
147-
_nativeRequestContext.NativeOverlapped);
148+
_overlapped);
148149

149150
if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_INVALID_PARAMETER && _nativeRequestContext.RequestId != 0)
150151
{
@@ -179,10 +180,14 @@ private void AllocateNativeRequest(uint? size = null, ulong requestId = 0)
179180
_nativeRequestContext?.Dispose();
180181

181182
var boundHandle = Server.RequestQueue.BoundHandle;
182-
var nativeOverlapped = new SafeNativeOverlapped(boundHandle,
183-
boundHandle.AllocateNativeOverlapped(_preallocatedOverlapped));
184183

185-
_nativeRequestContext = new NativeRequestContext(nativeOverlapped, Server.MemoryPool, size, requestId);
184+
if (_overlapped != null)
185+
{
186+
boundHandle.FreeNativeOverlapped(_overlapped);
187+
}
188+
189+
_nativeRequestContext = new NativeRequestContext(Server.MemoryPool, size, requestId);
190+
_overlapped = boundHandle.AllocateNativeOverlapped(_preallocatedOverlapped);
186191
}
187192

188193
public void Dispose()
@@ -199,23 +204,31 @@ protected virtual void Dispose(bool disposing)
199204
_nativeRequestContext.ReleasePins();
200205
_nativeRequestContext.Dispose();
201206
_nativeRequestContext = null;
207+
208+
var boundHandle = Server.RequestQueue.BoundHandle;
209+
210+
if (_overlapped != null)
211+
{
212+
boundHandle.FreeNativeOverlapped(_overlapped);
213+
_overlapped = null;
214+
}
202215
}
203216
}
204217
}
205218

206219
public RequestContext GetResult(short token)
207220
{
208-
return _tcs.GetResult(token);
221+
return _mrvts.GetResult(token);
209222
}
210223

211224
public ValueTaskSourceStatus GetStatus(short token)
212225
{
213-
return _tcs.GetStatus(token);
226+
return _mrvts.GetStatus(token);
214227
}
215228

216229
public void OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags)
217230
{
218-
_tcs.OnCompleted(continuation, state, token, flags);
231+
_mrvts.OnCompleted(continuation, state, token, flags);
219232
}
220233
}
221234
}

src/Servers/HttpSys/src/NativeInterop/HttpApi.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Runtime.InteropServices;
6+
using System.Threading;
67
using Microsoft.AspNetCore.HttpSys.Internal;
78
using static Microsoft.AspNetCore.HttpSys.Internal.HttpApiTypes;
89

@@ -25,7 +26,7 @@ internal static unsafe class HttpApi
2526
internal static extern uint HttpReceiveClientCertificate(SafeHandle requestQueueHandle, ulong connectionId, uint flags, byte* pSslClientCertInfo, uint sslClientCertInfoSize, uint* pBytesReceived, SafeNativeOverlapped pOverlapped);
2627

2728
[DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
28-
internal static extern uint HttpReceiveHttpRequest(SafeHandle requestQueueHandle, ulong requestId, uint flags, HTTP_REQUEST* pRequestBuffer, uint requestBufferLength, uint* pBytesReturned, SafeNativeOverlapped pOverlapped);
29+
internal static extern uint HttpReceiveHttpRequest(SafeHandle requestQueueHandle, ulong requestId, uint flags, HTTP_REQUEST* pRequestBuffer, uint requestBufferLength, uint* pBytesReturned, NativeOverlapped* pOverlapped);
2930

3031
[DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
3132
internal static extern uint HttpSendHttpResponse(SafeHandle requestQueueHandle, ulong requestId, uint flags, HTTP_RESPONSE_V2* pHttpResponse, HTTP_CACHE_POLICY* pCachePolicy, uint* pBytesSent, IntPtr pReserved1, uint Reserved2, SafeNativeOverlapped pOverlapped, IntPtr pLogData);

src/Shared/HttpSys/RequestProcessing/NativeRequestContext.cs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,12 @@ internal unsafe class NativeRequestContext : IDisposable
2525
private IMemoryOwner<byte> _backingBuffer;
2626
private MemoryHandle _memoryHandle;
2727
private int _bufferAlignment;
28-
private SafeNativeOverlapped _nativeOverlapped;
2928
private bool _permanentlyPinned;
3029
private bool _disposed;
3130

3231
// To be used by HttpSys
33-
internal NativeRequestContext(SafeNativeOverlapped nativeOverlapped, MemoryPool<Byte> memoryPool, uint? bufferSize, ulong requestId)
32+
internal NativeRequestContext(MemoryPool<byte> memoryPool, uint? bufferSize, ulong requestId)
3433
{
35-
_nativeOverlapped = nativeOverlapped;
36-
3734
// TODO:
3835
// Apparently the HttpReceiveHttpRequest memory alignment requirements for non - ARM processors
3936
// are different than for ARM processors. We have seen 4 - byte - aligned buffers allocated on
@@ -70,8 +67,6 @@ internal NativeRequestContext(HttpApiTypes.HTTP_REQUEST* request, bool useLatin1
7067
_permanentlyPinned = true;
7168
}
7269

73-
internal SafeNativeOverlapped NativeOverlapped => _nativeOverlapped;
74-
7570
internal HttpApiTypes.HTTP_REQUEST* NativeRequest
7671
{
7772
get
@@ -130,8 +125,6 @@ internal void ReleasePins()
130125
_memoryHandle.Dispose();
131126
_memoryHandle = default;
132127
_nativeRequest = null;
133-
_nativeOverlapped?.Dispose();
134-
_nativeOverlapped = null;
135128
}
136129

137130
public virtual void Dispose()
@@ -140,7 +133,6 @@ public virtual void Dispose()
140133
{
141134
_disposed = true;
142135
Debug.Assert(_nativeRequest == null, "RequestContextBase::Dispose()|Dispose() called before ReleasePins().");
143-
_nativeOverlapped?.Dispose();
144136
_memoryHandle.Dispose();
145137
_backingBuffer.Dispose();
146138
}

0 commit comments

Comments
 (0)