//TODO: call from ThreadPool internal static unsafe void PerformIOCompletionCallback(uint errorCode, uint numBytes, NativeOverlapped *pNativeOverlapped) { do { OverlappedData overlapped = OverlappedData.GetOverlappedFromNative(pNativeOverlapped); if (overlapped._callback is IOCompletionCallback iocb) { // We got here because of UnsafePack (or) Pack with EC flow suppressed iocb(errorCode, numBytes, pNativeOverlapped); } else { // We got here because of Pack var helper = (_IOCompletionCallback)overlapped._callback !; helper._errorCode = errorCode; helper._numBytes = numBytes; helper._pNativeOverlapped = pNativeOverlapped; ExecutionContext.Run(helper._executionContext, s_ccb, helper); } //Quickly check the VM again, to see if a packet has arrived. //OverlappedData.CheckVMForIOPacket(out pOVERLAP, out errorCode, out numBytes); pNativeOverlapped = null; } while (pNativeOverlapped != null); }
public static void PerformSingleIOCompletionCallback(uint errorCode, uint numBytes, NativeOverlapped *pNativeOverlapped) { Debug.Assert(pNativeOverlapped != null); OverlappedData overlapped = OverlappedData.GetOverlappedFromNative(pNativeOverlapped); object? callback = overlapped._callback; if (callback is IOCompletionCallback iocb) { // We got here because of UnsafePack (or) Pack with EC flow suppressed iocb(errorCode, numBytes, pNativeOverlapped); return; } if (callback == null) { // A callback was not provided return; } // We got here because of Pack Debug.Assert(callback is _IOCompletionCallback); var helper = (_IOCompletionCallback)callback; helper._errorCode = errorCode; helper._numBytes = numBytes; helper._pNativeOverlapped = pNativeOverlapped; ExecutionContext.RunInternal(helper._executionContext, IOCompletionCallback_Context_Delegate, helper); }
internal static void CacheOverlappedData(OverlappedData data) { data.ReInitialize(); // this is, by definition, a recently-used object s_usedSinceLastGC.Push(data); }
internal unsafe static void CompleteWithCallback(uint errorCode, uint bytesWritten, Win32ThreadPoolNativeOverlapped *overlapped) { OverlappedData data = overlapped->Data; Debug.Assert(!data._completed); data._completed = true; ContextCallback callback = s_executionContextCallback; if (callback == null) { s_executionContextCallback = callback = OnExecutionContextCallback; } // Get an args object from the per-thread cache. ExecutionContextCallbackArgs args = t_executionContextCallbackArgs; if (args == null) { args = new ExecutionContextCallbackArgs(); } t_executionContextCallbackArgs = null; args._errorCode = errorCode; args._bytesWritten = bytesWritten; args._overlapped = overlapped; args._data = data; ExecutionContext.Run(data._executionContext, callback, args); }
// call back helper static unsafe internal void PerformIOCompletionCallback(uint errorCode, // Error code uint numBytes, // No. of bytes transferred NativeOverlapped *pOVERLAP // ptr to OVERLAP structure ) { Overlapped overlapped; _IOCompletionCallback helper; do { overlapped = OverlappedData.GetOverlappedFromNative(pOVERLAP).m_overlapped; helper = overlapped.iocbHelper; if (helper == null || helper._executionContext == null || helper._executionContext == ExecutionContext.Default) { // We got here because of UnsafePack (or) Pack with EC flow supressed IOCompletionCallback callback = overlapped.UserCallback; callback(errorCode, numBytes, pOVERLAP); } else { // We got here because of Pack helper._errorCode = errorCode; helper._numBytes = numBytes; helper._pOVERLAP = pOVERLAP; ExecutionContext.Run(helper._executionContext, _ccb, helper); } //Quickly check the VM again, to see if a packet has arrived. OverlappedData.CheckVMForIOPacket(out pOVERLAP, out errorCode, out numBytes); } while (pOVERLAP != null); }
// call back helper internal static unsafe void PerformIOCompletionCallback(uint errorCode, uint numBytes, NativeOverlapped *pNativeOverlapped) { do { OverlappedData overlapped = OverlappedData.GetOverlappedFromNative(pNativeOverlapped); if (overlapped._callback is IOCompletionCallback iocb) { // We got here because of UnsafePack (or) Pack with EC flow suppressed iocb(errorCode, numBytes, pNativeOverlapped); } else { // We got here because of Pack var helper = (_IOCompletionCallback?)overlapped._callback; Debug.Assert(helper != null, "Should only be receiving a completion callback if a delegate was provided."); helper._errorCode = errorCode; helper._numBytes = numBytes; helper._pNativeOverlapped = pNativeOverlapped; ExecutionContext.RunInternal(helper._executionContext, _ccb, helper); } //Quickly check the VM again, to see if a packet has arrived. OverlappedData.CheckVMForIOPacket(out pNativeOverlapped, out errorCode, out numBytes); } while (pNativeOverlapped != null); }
internal static OverlappedData GetOverlappedData(Overlapped overlapped) { OverlappedData data = null; Interlocked.Exchange(ref m_overlappedDataCacheAccessed, 1); while (true) { OverlappedDataCacheLine overlappedDataCache = s_firstFreeCacheLine; if (overlappedDataCache == null) { overlappedDataCache = m_overlappedDataCache; } while (overlappedDataCache != null) { for (short i = 0; i < 0x10; i = (short)(i + 1)) { if (overlappedDataCache.m_items[i] != null) { data = Interlocked.Exchange <OverlappedData>(ref overlappedDataCache.m_items[i], null); if (data != null) { s_firstFreeCacheLine = overlappedDataCache; data.m_overlapped = overlapped; return(data); } } } overlappedDataCache = overlappedDataCache.m_next; } GrowOverlappedDataCache(); } }
public static unsafe Overlapped Unpack(NativeOverlapped *nativeOverlappedPtr) { if ((IntPtr)nativeOverlappedPtr == IntPtr.Zero) { throw new ArgumentNullException("nativeOverlappedPtr"); } return(OverlappedData.GetOverlappedFromNative(nativeOverlappedPtr).m_overlapped); }
public Overlapped(int offsetLo, int offsetHi, IntPtr hEvent, IAsyncResult ar) { m_overlappedData = OverlappedDataCache.GetOverlappedData(this); m_overlappedData.m_nativeOverlapped.OffsetLow = offsetLo; m_overlappedData.m_nativeOverlapped.OffsetHigh = offsetHi; m_overlappedData.UserHandle = hEvent; m_overlappedData.m_asyncResult = ar; }
public Overlapped(int offsetLo, int offsetHi, IntPtr hEvent, IAsyncResult ar) { this.m_overlappedData = OverlappedDataCache.GetOverlappedData(this); this.m_overlappedData.m_nativeOverlapped.OffsetLow = offsetLo; this.m_overlappedData.m_nativeOverlapped.OffsetHigh = offsetHi; this.m_overlappedData.UserHandle = hEvent; this.m_overlappedData.m_asyncResult = ar; }
public Overlapped(int offsetLo, int offsetHi, IntPtr hEvent, IAsyncResult ar) { m_overlappedData = (OverlappedData)s_overlappedDataCache.Allocate(); m_overlappedData.m_overlapped = this; m_overlappedData.m_nativeOverlapped.OffsetLow = offsetLo; m_overlappedData.m_nativeOverlapped.OffsetHigh = offsetHi; m_overlappedData.UserHandle = hEvent; m_overlappedData.m_asyncResult = ar; }
private static unsafe void CalculateNativeOverlappedOffset() { OverlappedData overlappedData = new OverlappedData(); fixed(IntPtr *pEETypePtr = &overlappedData.m_pEEType) fixed(NativeOverlapped * pNativeOverlapped = &overlappedData.m_nativeOverlapped) { s_nativeOverlappedOffset = (int)((byte *)pNativeOverlapped - (byte *)pEETypePtr); } }
private void SetData(IOCompletionCallback callback, object state, object pinData, PreAllocatedOverlapped preAllocated, bool flowExecutionContext) { Debug.Assert(callback != null); OverlappedData data = Data; data._callback = callback; data._state = state; data._executionContext = flowExecutionContext ? ExecutionContext.Capture() : null; data._preAllocated = preAllocated; // // pinData can be any blittable type to be pinned, *or* an instance of object[] each element of which refers to // an instance of a blittable type to be pinned. // if (pinData != null) { object[] objArray = pinData as object[]; if (objArray != null && objArray.GetType() == typeof(object[])) { if (data._pinnedData == null || data._pinnedData.Length < objArray.Length) { Array.Resize(ref data._pinnedData, objArray.Length); } for (int i = 0; i < objArray.Length; i++) { if (!data._pinnedData[i].IsAllocated) { data._pinnedData[i] = GCHandle.Alloc(objArray[i], GCHandleType.Pinned); } else { data._pinnedData[i].Target = objArray[i]; } } } else { if (data._pinnedData == null) { data._pinnedData = new GCHandle[1]; } if (!data._pinnedData[0].IsAllocated) { data._pinnedData[0] = GCHandle.Alloc(pinData, GCHandleType.Pinned); } else { data._pinnedData[0].Target = pinData; } } } }
public static unsafe Overlapped Unpack(NativeOverlapped *nativeOverlappedPtr) { if (nativeOverlappedPtr == null) { throw new ArgumentNullException(nameof(nativeOverlappedPtr)); } Overlapped overlapped = OverlappedData.GetOverlappedFromNative(nativeOverlappedPtr).m_overlapped; return(overlapped); }
unsafe public static Overlapped Unpack(NativeOverlapped *nativeOverlappedPtr) { if (nativeOverlappedPtr == null) { throw new ArgumentNullException("nativeOverlappedPtr"); } Contract.EndContractBlock(); Overlapped overlapped = OverlappedData.GetOverlappedFromNative(nativeOverlappedPtr).m_overlapped; return(overlapped); }
internal OverlappedDataCacheLine() { m_items = new OverlappedData[OverlappedDataCacheLine.CacheSize]; // Allocate some dummy objects before and after the cacheLine. // These objects will allow GC to move two cacheLine's closer. new Object(); for (short i = 0; i < OverlappedDataCacheLine.CacheSize; i++) { m_items[i] = new OverlappedData(this); m_items[i].m_slot = i; } new Object(); }
public static unsafe void Free(NativeOverlapped *nativeOverlappedPtr) { if (nativeOverlappedPtr == null) { throw new ArgumentNullException("nativeOverlappedPtr"); } Overlapped overlapped = OverlappedData.GetOverlappedFromNative(nativeOverlappedPtr).m_overlapped; OverlappedData.FreeNativeOverlapped(nativeOverlappedPtr); OverlappedData overlappedData = overlapped.m_overlappedData; overlapped.m_overlappedData = null; OverlappedDataCache.CacheOverlappedData(overlappedData); }
private static unsafe void OnExecutionContextCallback(object state) { ExecutionContextCallbackArgs args = (ExecutionContextCallbackArgs)state; uint errorCode = args._errorCode; uint bytesWritten = args._bytesWritten; Win32ThreadPoolNativeOverlapped *overlapped = args._overlapped; OverlappedData data = args._data; // Put the args object back in the per-thread cache, now that we're done with it. args._data = null; t_executionContextCallbackArgs = args; data._callback(errorCode, bytesWritten, ToNativeOverlapped(overlapped)); }
public static unsafe void Free(NativeOverlapped *nativeOverlappedPtr) { if (nativeOverlappedPtr == null) { throw new ArgumentNullException(nameof(nativeOverlappedPtr)); } Overlapped overlapped = OverlappedData.GetOverlappedFromNative(nativeOverlappedPtr).m_overlapped; OverlappedData.FreeNativeOverlapped(nativeOverlappedPtr); OverlappedData overlappedData = overlapped.m_overlappedData; overlapped.m_overlappedData = null; overlappedData.ReInitialize(); s_overlappedDataCache.Free(overlappedData); }
// // Retrieve an OverlappedData from the cache, or create a new one // internal static OverlappedData GetOverlappedData(Overlapped overlapped) { EnsureFinalizerRegistered(); OverlappedData result = null; // // First, try to pop a recently-used object. // ConcurrentStack <OverlappedData> stack = s_usedSinceLastGC; stack.TryPop(out result); // // If we didn't get one, try to resurrect an older one. // if (result == null) { stack = s_notUsedSinceLastGC; if (stack != null) { stack.TryPop(out result); } } // // We didn't find anything in the cache, so we need to create a new instance. // if (result == null) { // // To reduce fragmentation, we'll create a whole batch of these, and cache all but the one // we return. Because we're allocating the batch all at once, it is likely that all instances // will be contiguous in memory. // for (int i = 0; i < BatchSize - 1; i++) { s_usedSinceLastGC.Push(new OverlappedData()); } result = new OverlappedData(); } result.m_overlapped = overlapped; return(result); }
unsafe public static void Free(NativeOverlapped *nativeOverlappedPtr) { if (nativeOverlappedPtr == null) { throw new ArgumentNullException("nativeOverlappedPtr"); } Contract.EndContractBlock(); Overlapped overlapped = OverlappedData.GetOverlappedFromNative(nativeOverlappedPtr).m_overlapped; OverlappedData.FreeNativeOverlapped(nativeOverlappedPtr); OverlappedData overlappedData = overlapped.m_overlappedData; overlapped.m_overlappedData = null; overlappedData.ReInitialize(); s_overlappedDataCache.Free(overlappedData); }
public static unsafe void Free(NativeOverlapped *nativeOverlappedPtr) { if ((IntPtr)nativeOverlappedPtr == IntPtr.Zero) { throw new ArgumentNullException("nativeOverlappedPtr"); } Overlapped overlapped = OverlappedData.GetOverlappedFromNative(nativeOverlappedPtr).m_overlapped; OverlappedData.FreeNativeOverlapped(nativeOverlappedPtr); OverlappedData overlappedData = overlapped.m_overlappedData; // ISSUE: variable of the null type __Null local = null; overlapped.m_overlappedData = (OverlappedData)local; overlappedData.ReInitialize(); Overlapped.s_overlappedDataCache.Free((object)overlappedData); }
internal static unsafe void PerformIOCompletionCallback(uint errorCode, uint numBytes, NativeOverlapped *pOVERLAP) { do { Overlapped overlapped = OverlappedData.GetOverlappedFromNative(pOVERLAP).m_overlapped; _IOCompletionCallback iocbHelper = overlapped.iocbHelper; if (((iocbHelper == null) || (iocbHelper._executionContext == null)) || iocbHelper._executionContext.IsDefaultFTContext()) { overlapped.UserCallback(errorCode, numBytes, pOVERLAP); } else { iocbHelper._errorCode = errorCode; iocbHelper._numBytes = numBytes; iocbHelper._pOVERLAP = pOVERLAP; ExecutionContext.Run(iocbHelper._executionContext.CreateCopy(), _ccb, iocbHelper); } OverlappedData.CheckVMForIOPacket(out pOVERLAP, out errorCode, out numBytes); }while (pOVERLAP != null); }
internal static unsafe void PerformIOCompletionCallback(uint errorCode, uint numBytes, NativeOverlapped *pOVERLAP) { do { Overlapped overlapped = OverlappedData.GetOverlappedFromNative(pOVERLAP).m_overlapped; _IOCompletionCallback iocbHelper = overlapped.iocbHelper; if (iocbHelper == null || iocbHelper._executionContext == null || iocbHelper._executionContext.IsDefaultFTContext(true)) { overlapped.UserCallback(errorCode, numBytes, pOVERLAP); } else { iocbHelper._errorCode = errorCode; iocbHelper._numBytes = numBytes; iocbHelper._pOVERLAP = pOVERLAP; using (ExecutionContext copy = iocbHelper._executionContext.CreateCopy()) ExecutionContext.Run(copy, _IOCompletionCallback._ccb, (object)iocbHelper, true); } OverlappedData.CheckVMForIOPacket(out pOVERLAP, out errorCode, out numBytes); }while ((IntPtr)pOVERLAP != IntPtr.Zero); }
// call back helper static unsafe internal void PerformIOCompletionCallback(uint errorCode, // Error code uint numBytes, // No. of bytes transferred NativeOverlapped *pOVERLAP // ptr to OVERLAP structure ) { Overlapped overlapped = OverlappedData.GetOverlappedFromNative(pOVERLAP).m_overlapped; _IOCompletionCallback helper = overlapped.iocbHelper; if (helper == null || helper._executionContext == null || helper._executionContext.IsDefaultFTContext()) { // We got here because of UnsafePack (or) Pack with EC flow supressed IOCompletionCallback callback = overlapped.UserCallback; callback(errorCode, numBytes, pOVERLAP); } else { // We got here because of Pack helper._errorCode = errorCode; helper._numBytes = numBytes; helper._pOVERLAP = pOVERLAP; ExecutionContext.Run(helper._executionContext.CreateCopy(), _ccb, helper); } }
internal static OverlappedData GetOverlappedData(Overlapped overlapped) { OverlappedData overlappedData = null; Interlocked.Exchange(ref m_overlappedDataCacheAccessed, 1); while (true) { OverlappedDataCacheLine walk = m_overlappedDataCache; while (null != walk) { for (short i = 0; i < OverlappedDataCacheLine.CacheSize; i++) { if (walk.m_items[i] != null) { overlappedData = Interlocked.Exchange <OverlappedData>(ref walk.m_items[i], null); if (overlappedData != null) { overlappedData.m_overlapped = overlapped; return(overlappedData); } } } walk = walk.m_next; } GrowOverlappedDataCache(); } /* * Interlocked.Increment(ref m_Total); * Console.WriteLine("OverlappedDataCache get " + m_Total + * " create " + m_Create + * " Cache " + m_Cache); */ }
private static unsafe Win32ThreadPoolNativeOverlapped *AllocateNew() { IntPtr freePtr; Win32ThreadPoolNativeOverlapped *overlapped; OverlappedData data; // Find a free Overlapped while ((freePtr = Volatile.Read(ref s_freeList)) != IntPtr.Zero) { overlapped = (Win32ThreadPoolNativeOverlapped *)freePtr; if (Interlocked.CompareExchange(ref s_freeList, overlapped->_nextFree, freePtr) != freePtr) { continue; } overlapped->_nextFree = IntPtr.Zero; return(overlapped); } // None are free; allocate a new one. overlapped = (Win32ThreadPoolNativeOverlapped *)Marshal.AllocHGlobal(sizeof(Win32ThreadPoolNativeOverlapped)); *overlapped = default(Win32ThreadPoolNativeOverlapped); // Allocate a OverlappedData object, and an index at which to store it in _dataArray. data = new OverlappedData(); int dataIndex = Interlocked.Increment(ref s_dataCount) - 1; // Make sure we didn't wrap around. if (dataIndex < 0) { Environment.FailFast("Too many outstanding Win32ThreadPoolNativeOverlapped instances"); } while (true) { OverlappedData[] dataArray = Volatile.Read(ref s_dataArray); int currentLength = dataArray == null ? 0 : dataArray.Length; // If the current array is too small, create a new, larger one. if (currentLength <= dataIndex) { int newLength = currentLength; if (newLength == 0) { newLength = 128; } while (newLength <= dataIndex) { newLength = (newLength * 3) / 2; } OverlappedData[] newDataArray = dataArray; Array.Resize(ref newDataArray, newLength); if (Interlocked.CompareExchange(ref s_dataArray, newDataArray, dataArray) != dataArray) { continue; // Someone else got the free one, try again } dataArray = newDataArray; } // If we haven't stored this object in the array yet, do so now. Then we need to make another pass through // the loop, in case another thread resized the array before we made this update. if (s_dataArray[dataIndex] == null) { // Full fence so this write can't move past subsequent reads. Interlocked.Exchange(ref dataArray[dataIndex], data); continue; } // We're already in the array, so we're done. Debug.Assert(dataArray[dataIndex] == data); overlapped->_dataIndex = dataIndex; return(overlapped); } }
public Overlapped() { m_overlappedData = (OverlappedData)s_overlappedDataCache.Allocate(); m_overlappedData.m_overlapped = this; }
// // Retrieve an OverlappedData from the cache, or create a new one // internal static OverlappedData GetOverlappedData(Overlapped overlapped) { EnsureFinalizerRegistered(); OverlappedData result = null; // // First, try to pop a recently-used object. // ConcurrentStack<OverlappedData> stack = s_usedSinceLastGC; stack.TryPop(out result); // // If we didn't get one, try to resurrect an older one. // if (result == null) { stack = s_notUsedSinceLastGC; if (stack != null) stack.TryPop(out result); } // // We didn't find anything in the cache, so we need to create a new instance. // if (result == null) { // // To reduce fragmentation, we'll create a whole batch of these, and cache all but the one // we return. Because we're allocating the batch all at once, it is likely that all instances // will be contiguous in memory. // for (int i = 0; i < BatchSize - 1; i++) s_usedSinceLastGC.Push(new OverlappedData()); result = new OverlappedData(); } result.m_overlapped = overlapped; return result; }
internal static unsafe void FreeNativeOverlapped(NativeOverlapped *nativeOverlappedPtr) { OverlappedData overlappedData = OverlappedData.GetOverlappedFromNative(nativeOverlappedPtr); overlappedData.FreeNativeOverlapped(); }
public Overlapped() { m_overlappedData = OverlappedDataCache.GetOverlappedData(this); }
internal static void CacheOverlappedData(OverlappedData data) { data.ReInitialize(); data.m_cacheLine.m_items[data.m_slot] = data; s_firstFreeCacheLine = null; }
internal OverlappedDataCacheLine() { m_items = new OverlappedData[OverlappedDataCacheLine.CacheSize]; // Allocate some dummy objects before and after the cacheLine. // These objects will allow GC to move two cacheLine's closer. new Object(); for (short i = 0; i < OverlappedDataCacheLine.CacheSize; i ++) { m_items[i] = new OverlappedData (this); m_items[i].m_slot = i; } new Object(); }
public Overlapped() { m_overlappedData = (OverlappedData) s_overlappedDataCache.Allocate(); m_overlappedData.m_overlapped = this; }
public Overlapped(int offsetLo, int offsetHi, IntPtr hEvent, IAsyncResult ar) { m_overlappedData = (OverlappedData) s_overlappedDataCache.Allocate(); m_overlappedData.m_overlapped = this; m_overlappedData.m_nativeOverlapped.OffsetLow = offsetLo; m_overlappedData.m_nativeOverlapped.OffsetHigh = offsetHi; m_overlappedData.UserHandle = hEvent; m_overlappedData.m_asyncResult = ar; }
[System.Security.SecuritySafeCritical] // auto-generated #endif public Overlapped() { m_overlappedData = OverlappedDataCache.GetOverlappedData(this); }
private unsafe static Win32ThreadPoolNativeOverlapped* AllocateNew() { IntPtr freePtr; Win32ThreadPoolNativeOverlapped* overlapped; OverlappedData data; // Find a free Overlapped while ((freePtr = Volatile.Read(ref s_freeList)) != IntPtr.Zero) { overlapped = (Win32ThreadPoolNativeOverlapped*)freePtr; if (Interlocked.CompareExchange(ref s_freeList, overlapped->_nextFree, freePtr) != freePtr) continue; overlapped->_nextFree = IntPtr.Zero; return overlapped; } // None are free; allocate a new one. overlapped = (Win32ThreadPoolNativeOverlapped*)Marshal.AllocHGlobal(sizeof(Win32ThreadPoolNativeOverlapped)); *overlapped = default(Win32ThreadPoolNativeOverlapped); // Allocate a OverlappedData object, and an index at which to store it in _dataArray. data = new OverlappedData(); int dataIndex = Interlocked.Increment(ref s_dataCount) - 1; // Make sure we didn't wrap around. if (dataIndex < 0) Environment.FailFast("Too many outstanding Win32ThreadPoolNativeOverlapped instances"); while (true) { OverlappedData[] dataArray = Volatile.Read(ref s_dataArray); int currentLength = dataArray == null ? 0 : dataArray.Length; // If the current array is too small, create a new, larger one. if (currentLength <= dataIndex) { int newLength = currentLength; if (newLength == 0) newLength = 128; while (newLength <= dataIndex) newLength = (newLength * 3) / 2; OverlappedData[] newDataArray = dataArray; Array.Resize(ref newDataArray, newLength); if (Interlocked.CompareExchange(ref s_dataArray, newDataArray, dataArray) != dataArray) continue; // Someone else got the free one, try again dataArray = newDataArray; } // If we haven't stored this object in the array yet, do so now. Then we need to make another pass through // the loop, in case another thread resized the array before we made this update. if (s_dataArray[dataIndex] == null) { // Full fence so this write can't move past subsequent reads. Interlocked.Exchange(ref dataArray[dataIndex], data); continue; } // We're already in the array, so we're done. Debug.Assert(dataArray[dataIndex] == data); overlapped->_dataIndex = dataIndex; return overlapped; } }