// // This method pins unmanaged objects for Win9x and systems where completion ports are not found // protected void PinUnmanagedObjects(object objectsToPin) { if (m_Cache != null) { m_Cache.Free(); m_Cache = null; } if (objectsToPin != null) { if (objectsToPin.GetType() == typeof(object[])) { object [] objectsArray = (object [])objectsToPin; m_GCHandles = new GCHandle[objectsArray.Length]; for (int i = 0; i < objectsArray.Length; i++) { if (objectsArray[i] != null) { m_GCHandles[i] = GCHandle.Alloc(objectsArray[i], GCHandleType.Pinned); } } } else { m_GCHandles = new GCHandle[1]; m_GCHandles[0] = GCHandle.Alloc(objectsToPin, GCHandleType.Pinned); } } }
internal void ExtractCache(ref OverlappedCache overlappedCache) { if (!m_UseOverlappedIO && !m_DisableOverlapped) { // Have to be super careful. Socket isn't synchronized, so if a user calls End() twice, we don't want to // copy out this cache twice which could result in posting an IO with a deleted NativeOverlapped. OverlappedCache cache = m_Cache == null ? null : Interlocked.Exchange <OverlappedCache>(ref m_Cache, null); if (cache != null) { // If overlappedCache is null, just slap it in there. There's a chance for a conflict, // resulting in a OverlappedCache getting finalized, but it's better than // the interlocked. This won't be an issue in most 'correct' cases. if (overlappedCache == null) { overlappedCache = cache; } else { OverlappedCache oldCache = Interlocked.Exchange <OverlappedCache>(ref overlappedCache, cache); if (oldCache != null) { oldCache.Free(); } } } ReleaseUnmanagedStructures(); } }
internal static void InterlockedFree(ref OverlappedCache overlappedCache) { OverlappedCache cache = (overlappedCache == null) ? null : Interlocked.Exchange<OverlappedCache>(ref overlappedCache, null); if (cache != null) { cache.Free(); } }
protected void SetupCache(ref OverlappedCache overlappedCache) { if (!this.m_UseOverlappedIO && !this.m_DisableOverlapped) { this.m_Cache = (overlappedCache == null) ? null : Interlocked.Exchange <OverlappedCache>(ref overlappedCache, null); this.m_CleanupCount++; } }
internal static void InterlockedFree(ref OverlappedCache overlappedCache) { OverlappedCache cache = overlappedCache == null ? null : Interlocked.Exchange <OverlappedCache>(ref overlappedCache, null); if (cache != null) { cache.Free(); } }
/* * // * internal void SetUnmanagedStructures(object objectsToPin, ref OverlappedCache overlappedCache) * { * SetupCache(ref overlappedCache); * SetUnmanagedStructures(objectsToPin); * } */ protected void SetupCache(ref OverlappedCache overlappedCache) { GlobalLog.Assert(m_Cache == null, "BaseOverlappedAsyncResult#{0}::SetUnmanagedStructures()|Cache already set up. (Called twice?)", ValidationHelper.HashString(this)); if (!m_UseOverlappedIO && !m_DisableOverlapped) { m_Cache = overlappedCache == null ? null : Interlocked.Exchange <OverlappedCache>(ref overlappedCache, null); // Need to hold on to the unmanaged structures until the cache is extracted. m_CleanupCount++; } }
protected virtual void ForceReleaseUnmanagedStructures() { this.ReleaseGCHandles(); GC.SuppressFinalize(this); if ((this.m_UnmanagedBlob != null) && !this.m_UnmanagedBlob.IsInvalid) { this.m_UnmanagedBlob.Close(true); this.m_UnmanagedBlob = null; } OverlappedCache.InterlockedFree(ref this.m_Cache); if (this.m_OverlappedEvent != null) { this.m_OverlappedEvent.Close(); this.m_OverlappedEvent = null; } }
// Utility cleanup routine. Frees the overlapped structure. // This should be overriden to free pinned and unmanaged memory in the subclass. // It needs to also be invoked from the subclass. protected virtual void ForceReleaseUnmanagedStructures() { // // free the unmanaged memory if allocated. // ReleaseGCHandles(); GC.SuppressFinalize(this); if (m_UnmanagedBlob != null && !m_UnmanagedBlob.IsInvalid) { m_UnmanagedBlob.Close(true); m_UnmanagedBlob = null; } // This is interlocked because Cleanup() can be called simultaneously with ExtractCache(). OverlappedCache.InterlockedFree(ref m_Cache); if (m_OverlappedEvent != null) { m_OverlappedEvent.Close(); m_OverlappedEvent = null; } }
internal void ExtractCache(ref OverlappedCache overlappedCache) { if (!this.m_UseOverlappedIO && !this.m_DisableOverlapped) { OverlappedCache cache = (this.m_Cache == null) ? null : Interlocked.Exchange <OverlappedCache>(ref this.m_Cache, null); if (cache != null) { if (overlappedCache == null) { overlappedCache = cache; } else { OverlappedCache cache2 = Interlocked.Exchange <OverlappedCache>(ref overlappedCache, cache); if (cache2 != null) { cache2.Free(); } } } this.ReleaseUnmanagedStructures(); } }
internal void SetUnmanagedStructures(byte[] buffer, int offset, int size, System.Net.SocketAddress socketAddress, SocketFlags socketFlags, ref OverlappedCache overlappedCache) { base.SetupCache(ref overlappedCache); this.SetUnmanagedStructures(buffer, offset, size, socketAddress, socketFlags); }
// // SetUnmanagedStructures - // // This needs to be called for overlapped IO to function properly. // // Fills in Overlapped Structures used in an Async Overlapped Winsock call // these calls are outside the runtime and are unmanaged code, so we need // to prepare specific structures and ints that lie in unmanaged memory // since the Overlapped calls can be Async // internal void SetUnmanagedStructures(object objectsToPin) { if (!m_DisableOverlapped) { // Casting to object[] is very expensive. Only do it once. object[] objectsToPinArray = null; bool triedCastingToArray = false; bool useCache = false; if (m_Cache != null) { if (objectsToPin == null && m_Cache.PinnedObjects == null) { useCache = true; } else if (m_Cache.PinnedObjects != null) { if (m_Cache.PinnedObjectsArray == null) { if (objectsToPin == m_Cache.PinnedObjects) { useCache = true; } } else if (objectsToPin != null) { triedCastingToArray = true; objectsToPinArray = objectsToPin as object[]; if (objectsToPinArray != null && objectsToPinArray.Length == 0) { objectsToPinArray = null; } if (objectsToPinArray != null && objectsToPinArray.Length == m_Cache.PinnedObjectsArray.Length) { useCache = true; for (int i = 0; i < objectsToPinArray.Length; i++) { if (objectsToPinArray[i] != m_Cache.PinnedObjectsArray[i]) { useCache = false; break; } } } } } } if (!useCache && m_Cache != null) { GlobalLog.Print("BaseOverlappedAsyncResult#" + ValidationHelper.HashString(this) + "::SetUnmanagedStructures() Cache miss - freeing cache."); m_Cache.Free(); m_Cache = null; } Socket s = (Socket)AsyncObject; if (m_UseOverlappedIO) { GlobalLog.Assert(m_UnmanagedBlob == null, "BaseOverlappedAsyncResult#{0}::SetUnmanagedStructures()|Unmanaged blob already allocated. (Called twice?)", ValidationHelper.HashString(this)); m_UnmanagedBlob = SafeOverlappedFree.Alloc(s.SafeHandle); PinUnmanagedObjects(objectsToPin); // // create the event handle // m_OverlappedEvent = new AutoResetEvent(false); // // fill in the overlapped structure with the event handle. // Marshal.WriteIntPtr(m_UnmanagedBlob.DangerousGetHandle(), Win32.OverlappedhEventOffset, m_OverlappedEvent.SafeWaitHandle.DangerousGetHandle()); } else { // // Bind the Win32 Socket Handle to the ThreadPool // s.BindToCompletionPort(); if (m_Cache == null) { GlobalLog.Print("BaseOverlappedAsyncResult#" + ValidationHelper.HashString(this) + "::EnableCompletionPort() Creating new overlapped cache."); if (objectsToPinArray != null) { m_Cache = new OverlappedCache(new Overlapped(), objectsToPinArray, s_IOCallback); } else { m_Cache = new OverlappedCache(new Overlapped(), objectsToPin, s_IOCallback, triedCastingToArray); } } else { GlobalLog.Print("BaseOverlappedAsyncResult#" + ValidationHelper.HashString(this) + "::EnableCompletionPort() Using cached overlapped."); } m_Cache.Overlapped.AsyncResult = this; #if DEBUG unsafe { m_InitialNativeOverlapped = *((NativeOverlapped *)m_Cache.NativeOverlapped); } #endif GlobalLog.Print("BaseOverlappedAsyncResult#" + ValidationHelper.HashString(this) + "::EnableCompletionPort() overlapped:" + ValidationHelper.HashString(m_Cache.Overlapped) + " NativeOverlapped = " + m_Cache.NativeOverlapped.ToString("x")); } } }
internal void SetUnmanagedStructures(IList<ArraySegment<byte>> buffers, ref OverlappedCache overlappedCache) { SetupCache(ref overlappedCache); SetUnmanagedStructures(buffers); }
internal void SetUnmanagedStructures(BufferOffsetSize[] buffers, ref OverlappedCache overlappedCache) { SetupCache(ref overlappedCache); SetUnmanagedStructures(buffers); }
// // SetUnmanagedStructures - // // This needs to be called for overlapped IO to function properly. // // Fills in Overlapped Structures used in an Async Overlapped Winsock call // these calls are outside the runtime and are unmanaged code, so we need // to prepare specific structures and ints that lie in unmanaged memory // since the Overlapped calls can be Async // internal void SetUnmanagedStructures(object objectsToPin) { if (!m_DisableOverlapped) { // Casting to object[] is very expensive. Only do it once. object[] objectsToPinArray = null; bool triedCastingToArray = false; bool useCache = false; if (m_Cache != null) { if (objectsToPin == null && m_Cache.PinnedObjects == null) { useCache = true; } else if (m_Cache.PinnedObjects != null) { if (m_Cache.PinnedObjectsArray == null) { if (objectsToPin == m_Cache.PinnedObjects) { useCache = true; } } else if (objectsToPin != null) { triedCastingToArray = true; objectsToPinArray = objectsToPin as object[]; if (objectsToPinArray != null && objectsToPinArray.Length == 0) { objectsToPinArray = null; } if (objectsToPinArray != null && objectsToPinArray.Length == m_Cache.PinnedObjectsArray.Length) { useCache = true; for (int i = 0; i < objectsToPinArray.Length; i++) { if (objectsToPinArray[i] != m_Cache.PinnedObjectsArray[i]) { useCache = false; break; } } } } } } if (!useCache && m_Cache != null) { GlobalLog.Print("BaseOverlappedAsyncResult#" + ValidationHelper.HashString(this) + "::SetUnmanagedStructures() Cache miss - freeing cache."); m_Cache.Free(); m_Cache = null; } Socket s = (Socket) AsyncObject; if (m_UseOverlappedIO) { GlobalLog.Assert(m_UnmanagedBlob == null, "BaseOverlappedAsyncResult#{0}::SetUnmanagedStructures()|Unmanaged blob already allocated. (Called twice?)", ValidationHelper.HashString(this)); m_UnmanagedBlob = SafeOverlappedFree.Alloc(s.SafeHandle); PinUnmanagedObjects(objectsToPin); // // create the event handle // m_OverlappedEvent = new AutoResetEvent(false); // // fill in the overlapped structure with the event handle. // Marshal.WriteIntPtr( m_UnmanagedBlob.DangerousGetHandle(), Win32.OverlappedhEventOffset, m_OverlappedEvent.SafeWaitHandle.DangerousGetHandle() ); } else { // // Bind the Win32 Socket Handle to the ThreadPool // s.BindToCompletionPort(); if (m_Cache == null) { GlobalLog.Print("BaseOverlappedAsyncResult#" + ValidationHelper.HashString(this) + "::EnableCompletionPort() Creating new overlapped cache."); if (objectsToPinArray != null) { m_Cache = new OverlappedCache(new Overlapped(), objectsToPinArray, s_IOCallback); } else { m_Cache = new OverlappedCache(new Overlapped(), objectsToPin, s_IOCallback, triedCastingToArray); } } else { GlobalLog.Print("BaseOverlappedAsyncResult#" + ValidationHelper.HashString(this) + "::EnableCompletionPort() Using cached overlapped."); } m_Cache.Overlapped.AsyncResult = this; #if DEBUG unsafe { m_InitialNativeOverlapped = *((NativeOverlapped *) m_Cache.NativeOverlapped); } #endif GlobalLog.Print("BaseOverlappedAsyncResult#" + ValidationHelper.HashString(this) + "::EnableCompletionPort() overlapped:" + ValidationHelper.HashString(m_Cache.Overlapped) + " NativeOverlapped = " + m_Cache.NativeOverlapped.ToString("x")); } } }
} // SetUnmanagedStructures() internal void SetUnmanagedStructures(byte[] preBuffer, byte[] postBuffer, FileStream fileStream, TransmitFileOptions flags, ref OverlappedCache overlappedCache) { SetupCache(ref overlappedCache); SetUnmanagedStructures(preBuffer, postBuffer, fileStream, flags, false); }
internal void ExtractCache(ref OverlappedCache overlappedCache) { if (!m_UseOverlappedIO && !m_DisableOverlapped) { // Have to be super careful. Socket isn't synchronized, so if a user calls End() twice, we don't want to // copy out this cache twice which could result in posting an IO with a deleted NativeOverlapped. OverlappedCache cache = m_Cache == null ? null : Interlocked.Exchange<OverlappedCache>(ref m_Cache, null); if (cache != null) { // If overlappedCache is null, just slap it in there. There's a chance for a conflict, // resulting in a OverlappedCache getting finalized, but it's better than // the interlocked. This won't be an issue in most 'correct' cases. if (overlappedCache == null) { overlappedCache = cache; } else { OverlappedCache oldCache = Interlocked.Exchange<OverlappedCache>(ref overlappedCache, cache); if (oldCache != null) { oldCache.Free(); } } } ReleaseUnmanagedStructures(); } }
// // This method pins unmanaged objects for Win9x and systems where completion ports are not found // protected void PinUnmanagedObjects(object objectsToPin) { if (m_Cache != null) { m_Cache.Free(); m_Cache = null; } if (objectsToPin != null) { if (objectsToPin.GetType() == typeof(object[])) { object [] objectsArray = (object []) objectsToPin; m_GCHandles = new GCHandle[objectsArray.Length]; for (int i=0; i<objectsArray.Length; i++) { if (objectsArray[i] != null) { m_GCHandles[i] = GCHandle.Alloc(objectsArray[i], GCHandleType.Pinned); } } } else { m_GCHandles = new GCHandle[1]; m_GCHandles[0] = GCHandle.Alloc(objectsToPin, GCHandleType.Pinned); } } }
/* // internal void SetUnmanagedStructures(object objectsToPin, ref OverlappedCache overlappedCache) { SetupCache(ref overlappedCache); SetUnmanagedStructures(objectsToPin); } */ protected void SetupCache(ref OverlappedCache overlappedCache) { GlobalLog.Assert(m_Cache == null, "BaseOverlappedAsyncResult#{0}::SetUnmanagedStructures()|Cache already set up. (Called twice?)", ValidationHelper.HashString(this)); if (!m_UseOverlappedIO && !m_DisableOverlapped) { m_Cache = overlappedCache == null ? null : Interlocked.Exchange<OverlappedCache>(ref overlappedCache, null); // Need to hold on to the unmanaged structures until the cache is extracted. m_CleanupCount++; } }
protected void SetupCache(ref OverlappedCache overlappedCache) { if (!this.m_UseOverlappedIO && !this.m_DisableOverlapped) { this.m_Cache = (overlappedCache == null) ? null : Interlocked.Exchange<OverlappedCache>(ref overlappedCache, null); this.m_CleanupCount++; } }
internal void SetUnmanagedStructures(object objectsToPin) { if (!this.m_DisableOverlapped) { object[] pinnedObjectsArray = null; bool alreadyTriedCast = false; bool flag2 = false; if (this.m_Cache != null) { if ((objectsToPin == null) && (this.m_Cache.PinnedObjects == null)) { flag2 = true; } else if (this.m_Cache.PinnedObjects != null) { if (this.m_Cache.PinnedObjectsArray == null) { if (objectsToPin == this.m_Cache.PinnedObjects) { flag2 = true; } } else if (objectsToPin != null) { alreadyTriedCast = true; pinnedObjectsArray = objectsToPin as object[]; if ((pinnedObjectsArray != null) && (pinnedObjectsArray.Length == 0)) { pinnedObjectsArray = null; } if ((pinnedObjectsArray != null) && (pinnedObjectsArray.Length == this.m_Cache.PinnedObjectsArray.Length)) { flag2 = true; for (int i = 0; i < pinnedObjectsArray.Length; i++) { if (pinnedObjectsArray[i] != this.m_Cache.PinnedObjectsArray[i]) { flag2 = false; break; } } } } } } if (!flag2 && (this.m_Cache != null)) { this.m_Cache.Free(); this.m_Cache = null; } Socket asyncObject = (Socket) base.AsyncObject; if (this.m_UseOverlappedIO) { this.m_UnmanagedBlob = SafeOverlappedFree.Alloc(asyncObject.SafeHandle); this.PinUnmanagedObjects(objectsToPin); this.m_OverlappedEvent = new AutoResetEvent(false); Marshal.WriteIntPtr(this.m_UnmanagedBlob.DangerousGetHandle(), Win32.OverlappedhEventOffset, this.m_OverlappedEvent.SafeWaitHandle.DangerousGetHandle()); } else { asyncObject.BindToCompletionPort(); if (this.m_Cache == null) { if (pinnedObjectsArray != null) { this.m_Cache = new OverlappedCache(new Overlapped(), pinnedObjectsArray, s_IOCallback); } else { this.m_Cache = new OverlappedCache(new Overlapped(), objectsToPin, s_IOCallback, alreadyTriedCast); } } this.m_Cache.Overlapped.AsyncResult = this; } } }
// // This method is called after an asynchronous call is made for the user, // it checks and acts accordingly if the IO: // 1) completed synchronously. // 2) was pended. // 3) failed. // internal unsafe SocketError CheckAsyncCallOverlappedResult(SocketError errorCode) { #if DEBUG m_SavedErrorCode = errorCode; #endif // // Check if the Async IO call: // 1) was pended. // 2) completed synchronously. // 3) failed. // if (m_UseOverlappedIO) { // // we're using overlapped IO under Win9x (or NT with registry setting overriding // completion port usage) // switch (errorCode) { case 0: case SocketError.IOPending: // // the Async IO call was pended: // Queue our event to the thread pool. // GlobalLog.Assert(m_UnmanagedBlob != null, "BaseOverlappedAsyncResult#{0}::CheckAsyncCallOverlappedResult()|Unmanaged blob isn't allocated.", ValidationHelper.HashString(this)); ThreadPool.UnsafeRegisterWaitForSingleObject( m_OverlappedEvent, new WaitOrTimerCallback(OverlappedCallback), this, -1, true); // // we're done, completion will be asynchronous // in the callback. return // return(SocketError.Success); default: // // the Async IO call failed: // set the number of bytes transferred to -1 (error) // ErrorCode = (int)errorCode; Result = -1; ReleaseUnmanagedStructures(); break; } } else { #if DEBUG OverlappedCache cache = m_Cache; if (cache != null) { unsafe { NativeOverlapped *nativeOverlappedPtr = (NativeOverlapped *)cache.NativeOverlapped; if (nativeOverlappedPtr != null) { m_IntermediateNativeOverlapped = *nativeOverlappedPtr; } } } #endif // // We're using completion ports under WinNT. Release one reference on the structures for // the main thread. // ReleaseUnmanagedStructures(); switch (errorCode) { // // ignore cases in which a completion packet will be queued: // we'll deal with this IO in the callback // case 0: case SocketError.IOPending: // // ignore, do nothing // return(SocketError.Success); // // in the remaining cases a completion packet will NOT be queued: // we'll have to call the callback explicitly signaling an error // default: // // call the callback with error code // ErrorCode = (int)errorCode; Result = -1; // The AsyncResult must be cleared since the callback isn't going to be called. // Not doing so leads to a leak where the pinned cached OverlappedData continues to point to the async result object, // which points to the Socket (as well as user data) and to the OverlappedCache, preventing the OverlappedCache // finalizer from freeing the pinned OverlappedData. if (m_Cache != null) { // Could be null only if SetUnmanagedStructures weren't called. m_Cache.Overlapped.AsyncResult = null; } ReleaseUnmanagedStructures(); // Additional release for the completion that won't happen. break; } } return(errorCode); }
internal void SetUnmanagedStructures(byte[] buffer, int offset, int size, SocketAddress socketAddress, bool pinSocketAddress, ref OverlappedCache overlappedCache) { SetupCache(ref overlappedCache); SetUnmanagedStructures(buffer, offset, size, socketAddress, pinSocketAddress); }
internal void SetUnmanagedStructures(object objectsToPin) { if (!this.m_DisableOverlapped) { object[] pinnedObjectsArray = null; bool alreadyTriedCast = false; bool flag2 = false; if (this.m_Cache != null) { if ((objectsToPin == null) && (this.m_Cache.PinnedObjects == null)) { flag2 = true; } else if (this.m_Cache.PinnedObjects != null) { if (this.m_Cache.PinnedObjectsArray == null) { if (objectsToPin == this.m_Cache.PinnedObjects) { flag2 = true; } } else if (objectsToPin != null) { alreadyTriedCast = true; pinnedObjectsArray = objectsToPin as object[]; if ((pinnedObjectsArray != null) && (pinnedObjectsArray.Length == 0)) { pinnedObjectsArray = null; } if ((pinnedObjectsArray != null) && (pinnedObjectsArray.Length == this.m_Cache.PinnedObjectsArray.Length)) { flag2 = true; for (int i = 0; i < pinnedObjectsArray.Length; i++) { if (pinnedObjectsArray[i] != this.m_Cache.PinnedObjectsArray[i]) { flag2 = false; break; } } } } } } if (!flag2 && (this.m_Cache != null)) { this.m_Cache.Free(); this.m_Cache = null; } Socket asyncObject = (Socket)base.AsyncObject; if (this.m_UseOverlappedIO) { this.m_UnmanagedBlob = SafeOverlappedFree.Alloc(asyncObject.SafeHandle); this.PinUnmanagedObjects(objectsToPin); this.m_OverlappedEvent = new AutoResetEvent(false); Marshal.WriteIntPtr(this.m_UnmanagedBlob.DangerousGetHandle(), Win32.OverlappedhEventOffset, this.m_OverlappedEvent.SafeWaitHandle.DangerousGetHandle()); } else { asyncObject.BindToCompletionPort(); if (this.m_Cache == null) { if (pinnedObjectsArray != null) { this.m_Cache = new OverlappedCache(new Overlapped(), pinnedObjectsArray, s_IOCallback); } else { this.m_Cache = new OverlappedCache(new Overlapped(), objectsToPin, s_IOCallback, alreadyTriedCast); } } this.m_Cache.Overlapped.AsyncResult = this; } } }
internal void SetUnmanagedStructures(IList <ArraySegment <byte> > buffers, ref OverlappedCache overlappedCache) { SetupCache(ref overlappedCache); SetUnmanagedStructures(buffers); }
internal void ExtractCache(ref OverlappedCache overlappedCache) { if (!this.m_UseOverlappedIO && !this.m_DisableOverlapped) { OverlappedCache cache = (this.m_Cache == null) ? null : Interlocked.Exchange<OverlappedCache>(ref this.m_Cache, null); if (cache != null) { if (overlappedCache == null) { overlappedCache = cache; } else { OverlappedCache cache2 = Interlocked.Exchange<OverlappedCache>(ref overlappedCache, cache); if (cache2 != null) { cache2.Free(); } } } this.ReleaseUnmanagedStructures(); } }