diff options
author | Jan Kotas <jkotas@microsoft.com> | 2018-06-09 13:39:58 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-09 13:39:58 -0700 |
commit | 911d332c523848023e3c6564788b72b7f419fca1 (patch) | |
tree | ae979e6b048630ed0393983d14bde5d43942459f /src/vm | |
parent | 618f9c2d18e88566ac61f93529bac58123c50cba (diff) | |
download | coreclr-911d332c523848023e3c6564788b72b7f419fca1.tar.gz coreclr-911d332c523848023e3c6564788b72b7f419fca1.tar.bz2 coreclr-911d332c523848023e3c6564788b72b7f419fca1.zip |
Avoid NativeOverlapped pinning by allocating unmanaged memory for it (#18360)
It makes PinnableBufferCache unnecessary
Diffstat (limited to 'src/vm')
-rw-r--r-- | src/vm/appdomain.cpp | 66 | ||||
-rw-r--r-- | src/vm/appdomain.hpp | 1 | ||||
-rw-r--r-- | src/vm/ceemain.cpp | 2 | ||||
-rw-r--r-- | src/vm/class.cpp | 16 | ||||
-rw-r--r-- | src/vm/comcallablewrapper.cpp | 33 | ||||
-rw-r--r-- | src/vm/comcallablewrapper.h | 44 | ||||
-rw-r--r-- | src/vm/comthreadpool.cpp | 37 | ||||
-rw-r--r-- | src/vm/gcenv.ee.cpp | 15 | ||||
-rw-r--r-- | src/vm/mscorlib.cpp | 4 | ||||
-rw-r--r-- | src/vm/mscorlib.h | 19 | ||||
-rw-r--r-- | src/vm/nativeoverlapped.cpp | 407 | ||||
-rw-r--r-- | src/vm/nativeoverlapped.h | 122 | ||||
-rw-r--r-- | src/vm/threads.cpp | 3 | ||||
-rw-r--r-- | src/vm/win32threadpool.cpp | 8 |
14 files changed, 80 insertions, 697 deletions
diff --git a/src/vm/appdomain.cpp b/src/vm/appdomain.cpp index 8a69a997a7..3766ed528a 100644 --- a/src/vm/appdomain.cpp +++ b/src/vm/appdomain.cpp @@ -8966,76 +8966,10 @@ void AppDomain::ClearGCHandles() GCHeapUtilities::GetGCHeap()->WaitUntilConcurrentGCComplete(); - // Keep async pin handles alive by moving them to default domain - HandleAsyncPinHandles(); - // Remove our handle store as a source of GC roots m_handleStore->Uproot(); } -// When an AD is unloaded, we will release all objects in this AD. -// If a future asynchronous operation, like io completion port function, -// we need to keep the memory space fixed so that the gc heap is not corrupted. -void AppDomain::HandleAsyncPinHandles() -{ - CONTRACTL - { - GC_TRIGGERS; - MODE_COOPERATIVE; - NOTHROW; - } - CONTRACTL_END; - - IGCHandleStore *pBucket = m_handleStore; - - // IO completion port picks IO job using FIFO. Here is how we know which AsyncPinHandle can be freed. - // 1. We mark all non-pending AsyncPinHandle with READYTOCLEAN. - // 2. We queue a dump Overlapped to the IO completion as a marker. - // 3. When the Overlapped is picked up by completion port, we wait until all previous IO jobs are processed. - // 4. Then we can delete all AsyncPinHandle marked with READYTOCLEAN. - IGCHandleStore *pBucketInDefault = SystemDomain::System()->DefaultDomain()->m_handleStore; - - auto clearIfComplete = [](Object* object) - { - LIMITED_METHOD_CONTRACT; - - assert(object != nullptr); - if (object->GetGCSafeMethodTable() != g_pOverlappedDataClass) - { - return; - } - - OVERLAPPEDDATAREF overlapped = (OVERLAPPEDDATAREF)(ObjectToOBJECTREF((Object*)object)); - if (overlapped->HasCompleted()) - { - // IO has finished. We don't need to pin the user buffer any longer. - overlapped->m_userObject = NULL; - } - - BashMTForPinnedObject(ObjectToOBJECTREF(object)); - }; - - auto setHandle = [](Object* object, OBJECTHANDLE handle) - { - LIMITED_METHOD_CONTRACT; - - assert(object != nullptr); - assert(handle); - - if (object->GetGCSafeMethodTable() != g_pOverlappedDataClass) - { - return; - } - - OverlappedDataObject* overlapped = (OverlappedDataObject*)object; - overlapped->m_pinSelf = handle; - }; - - pBucket->RelocateAsyncPinnedHandles(pBucketInDefault, clearIfComplete, setHandle); - - OverlappedDataObject::RequestCleanup(); -} - void AppDomain::ClearGCRoots() { CONTRACTL diff --git a/src/vm/appdomain.hpp b/src/vm/appdomain.hpp index d92aabb535..501e2151e4 100644 --- a/src/vm/appdomain.hpp +++ b/src/vm/appdomain.hpp @@ -3438,7 +3438,6 @@ private: void Close(); void ClearGCRoots(); void ClearGCHandles(); - void HandleAsyncPinHandles(); void UnwindThreads(); // Return TRUE if EE is stopped // Return FALSE if more work is needed diff --git a/src/vm/ceemain.cpp b/src/vm/ceemain.cpp index f599a2aa23..fddc12768f 100644 --- a/src/vm/ceemain.cpp +++ b/src/vm/ceemain.cpp @@ -1012,8 +1012,6 @@ void EEStartupHelper(COINITIEE fFlags) // Now we really have fully initialized the garbage collector SetGarbageCollectorFullyInitialized(); - InitializePinHandleTable(); - #ifdef DEBUGGING_SUPPORTED // Make a call to publish the DefaultDomain for the debugger // This should be done before assemblies/modules are loaded into it (i.e. SystemDomain::Init) diff --git a/src/vm/class.cpp b/src/vm/class.cpp index f66a719bb0..4375a340cd 100644 --- a/src/vm/class.cpp +++ b/src/vm/class.cpp @@ -2943,21 +2943,7 @@ void EEClass::Save(DataImage *image, MethodTable *pMT) LOG((LF_ZAP, LL_INFO10000, "EEClass::Save %s (%p)\n", m_szDebugClassName, this)); - // Optimize packable fields before saving into ngen image (the packable fields are located at the end of - // the EEClass or sub-type instance and packing will transform them into a space-efficient format which - // should reduce the result returned by the GetSize() call below). Packing will fail if the compression - // algorithm would result in an increase in size. We track this in the m_fFieldsArePacked data member - // which we use to determine whether to access the fields in their packed or unpacked format. - // Special case: we don't attempt to pack fields for the System.Threading.OverlappedData class since a - // host can change the size of this at runtime. This requires modifying one of the packable fields and we - // don't support updates to such fields if they were successfully packed. - if (g_pOverlappedDataClass == NULL) - { - g_pOverlappedDataClass = MscorlibBinder::GetClass(CLASS__OVERLAPPEDDATA); - _ASSERTE(g_pOverlappedDataClass); - } - if (this != g_pOverlappedDataClass->GetClass()) - m_fFieldsArePacked = GetPackedFields()->PackFields(); + m_fFieldsArePacked = GetPackedFields()->PackFields(); DWORD cbSize = GetSize(); diff --git a/src/vm/comcallablewrapper.cpp b/src/vm/comcallablewrapper.cpp index e2ba05fb37..f6ad1191ae 100644 --- a/src/vm/comcallablewrapper.cpp +++ b/src/vm/comcallablewrapper.cpp @@ -44,7 +44,6 @@ #include "caparser.h" #include "appdomain.inl" #include "rcwwalker.h" -#include "windowsruntimebufferhelper.h" #include "winrttypenameconverter.h" #include "typestring.h" @@ -1085,25 +1084,13 @@ VOID SimpleComCallWrapper::Cleanup() m_pWrap = NULL; m_pMT = NULL; - if (HasOverlappedRef()) + if (m_pCPList) { - if (m_operlappedPtr) - { - WindowsRuntimeBufferHelper::ReleaseOverlapped(m_operlappedPtr); - m_operlappedPtr = NULL; - } - UnMarkOverlappedRef(); - } - else - { - if (m_pCPList) // enum_HasOverlappedRef - { - for (UINT i = 0; i < m_pCPList->Size(); i++) - delete (*m_pCPList)[i]; + for (UINT i = 0; i < m_pCPList->Size(); i++) + delete (*m_pCPList)[i]; - delete m_pCPList; - m_pCPList = NULL; - } + delete m_pCPList; + m_pCPList = NULL; } // if this object was made agile, then we will have stashed away the original handle @@ -1426,8 +1413,6 @@ void SimpleComCallWrapper::SetUpCPList() CQuickArray<MethodTable *> SrcItfList; - _ASSERTE(!HasOverlappedRef()); - // If the list has already been set up, then return. if (m_pCPList) return; @@ -1450,8 +1435,6 @@ void SimpleComCallWrapper::SetUpCPListHelper(MethodTable **apSrcItfMTs, int cSrc PRECONDITION(CheckPointer(apSrcItfMTs)); } CONTRACTL_END; - - _ASSERTE(!HasOverlappedRef()); CPListHolder pCPList = NULL; ComCallWrapper *pWrap = GetMainWrapper(); @@ -2046,9 +2029,7 @@ BOOL SimpleComCallWrapper::FindConnectionPoint(REFIID riid, IConnectionPoint **p PRECONDITION(CheckPointer(ppCP)); } CONTRACTL_END; - - _ASSERTE(!HasOverlappedRef()); - + // If the connection point list hasn't been set up yet, then set it up now. if (!m_pCPList) SetUpCPList(); @@ -2085,8 +2066,6 @@ void SimpleComCallWrapper::EnumConnectionPoints(IEnumConnectionPoints **ppEnumCP } CONTRACTL_END; - _ASSERTE(!HasOverlappedRef()); - // If the connection point list hasn't been set up yet, then set it up now. if (!m_pCPList) SetUpCPList(); diff --git a/src/vm/comcallablewrapper.h b/src/vm/comcallablewrapper.h index 1a68135e77..152830e907 100644 --- a/src/vm/comcallablewrapper.h +++ b/src/vm/comcallablewrapper.h @@ -1493,7 +1493,7 @@ private: enum_IsObjectTP = 0x8, enum_IsAgile = 0x10, enum_IsPegged = 0x80, - enum_HasOverlappedRef = 0x100, + // unused = 0x100, enum_CustomQIRespondsToIMarshal = 0x200, enum_CustomQIRespondsToIMarshal_Inited = 0x400, }; @@ -1795,14 +1795,7 @@ public: FastInterlockAnd((ULONG*)&m_flags, ~enum_IsPegged); } - - inline BOOL HasOverlappedRef() - { - LIMITED_METHOD_DAC_CONTRACT; - - return m_flags & enum_HasOverlappedRef; - } - + // Used for the creation and deletion of simple wrappers static SimpleComCallWrapper* CreateSimpleWrapper(); @@ -2161,14 +2154,6 @@ public: return pWeakRef; } - void StoreOverlappedPointer(LPOVERLAPPED lpOverlapped) - { - LIMITED_METHOD_CONTRACT; - - this->m_operlappedPtr = lpOverlapped; - MarkOverlappedRef(); - } - // Returns TRUE if the ICustomQI implementation returns Handled or Failed for IID_IMarshal. BOOL CustomQIRespondsToIMarshal(); @@ -2210,14 +2195,7 @@ private: // QI for well known interfaces from within the runtime based on an IID. IUnknown* QIStandardInterface(REFIID riid); - // These values are never used at the same time, so we can save a few bytes for each CCW by using a union. - // Use the inline methods HasOverlappedRef(), MarkOverlappedRef(), and UnMarkOverlappedRef() to differentiate - // how this union is to be interpreted. - union - { - CQuickArray<ConnectionPoint*>* m_pCPList; - LPOVERLAPPED m_operlappedPtr; - }; + CQuickArray<ConnectionPoint*>* m_pCPList; // syncblock for the ObjecRef SyncBlock* m_pSyncBlock; @@ -2250,21 +2228,7 @@ private: // This maintains both COM ref and Jupiter ref in 64-bit LONGLONG m_llRefCount; - - inline void MarkOverlappedRef() - { - LIMITED_METHOD_CONTRACT; - - FastInterlockOr((ULONG*)&m_flags, enum_HasOverlappedRef); - } - - inline void UnMarkOverlappedRef() - { - LIMITED_METHOD_CONTRACT; - - FastInterlockAnd((ULONG*)&m_flags, ~enum_HasOverlappedRef); - } -}; + }; inline OBJECTHANDLE ComCallWrapper::GetObjectHandle() { diff --git a/src/vm/comthreadpool.cpp b/src/vm/comthreadpool.cpp index fcb51dc301..b6d4106f9c 100644 --- a/src/vm/comthreadpool.cpp +++ b/src/vm/comthreadpool.cpp @@ -559,7 +559,6 @@ struct BindIoCompletion_Args DWORD ErrorCode; DWORD numBytesTransferred; LPOVERLAPPED lpOverlapped; - BOOL *pfProcessed; }; void SetAsyncResultProperties( @@ -589,7 +588,6 @@ VOID BindIoCompletionCallBack_Worker(LPVOID args) OVERLAPPEDDATAREF overlapped = ObjectToOVERLAPPEDDATAREF(OverlappedDataObject::GetOverlapped(lpOverlapped)); GCPROTECT_BEGIN(overlapped); - *(((BindIoCompletion_Args *)args)->pfProcessed) = TRUE; // we set processed to TRUE, now it's our responsibility to guarantee proper cleanup #ifdef _DEBUG @@ -597,7 +595,7 @@ VOID BindIoCompletionCallBack_Worker(LPVOID args) LogCall(pMeth,"IOCallback"); #endif - if (overlapped->m_iocb != NULL) + if (overlapped->m_callback != NULL) { // Caution: the args are not protected, we have to garantee there's no GC from here till PREPARE_NONVIRTUAL_CALLSITE(METHOD__IOCB_HELPER__PERFORM_IOCOMPLETION_CALLBACK); @@ -612,7 +610,7 @@ VOID BindIoCompletionCallBack_Worker(LPVOID args) else { // no user delegate to callback - _ASSERTE((overlapped->m_iocbHelper == NULL) || !"This is benign, but should be optimized"); + _ASSERTE((overlapped->m_callback == NULL) || !"This is benign, but should be optimized"); SetAsyncResultProperties(overlapped, ErrorCode, numBytesTransferred); @@ -652,33 +650,8 @@ void __stdcall BindIoCompletionCallbackStubEx(DWORD ErrorCode, GCX_COOP(); - // NOTE: there is a potential race between the time we retrieve the app domain pointer, - // and the time which this thread enters the domain. - // - // To solve the race, we rely on the fact that there is a thread sync (via GC) - // between releasing an app domain's handle, and destroying the app domain. Thus - // it is important that we not go into preemptive gc mode in that window. - // - - //IMPORTANT - do not gc protect overlapped here - it belongs to another appdomain - //so if it stops being pinned it should be able to go away - OVERLAPPEDDATAREF overlapped = ObjectToOVERLAPPEDDATAREF(OverlappedDataObject::GetOverlapped(lpOverlapped)); - AppDomainFromIDHolder appDomain(ADID(overlapped->GetAppDomainId()), TRUE); - BOOL fProcessed = FALSE; - if (!appDomain.IsUnloaded()) - { - // this holder resets our thread's security state when exiting this scope, - // but only if setStack is TRUE. - Thread* pHolderThread = NULL; - if (setStack) - { - pHolderThread = pThread; - } - - BindIoCompletion_Args args = {ErrorCode, numBytesTransferred, lpOverlapped, &fProcessed}; - appDomain.Release(); - ManagedThreadBase::ThreadPool(ADID(overlapped->GetAppDomainId()), BindIoCompletionCallBack_Worker, &args); - } + BindIoCompletion_Args args = {ErrorCode, numBytesTransferred, lpOverlapped}; + ManagedThreadBase::ThreadPool((ADID)DefaultADID, BindIoCompletionCallBack_Worker, &args); LOG((LF_INTEROP, LL_INFO10000, "Leaving IO_CallBackStub thread 0x%x retCode 0x%x, overlap 0x%x\n", pThread, ErrorCode, lpOverlapped)); // We should have released all locks. @@ -751,7 +724,7 @@ FCIMPL1(FC_BOOL_RET, ThreadPoolNative::CorPostQueuedCompletionStatus, LPOVERLAPP HELPER_METHOD_FRAME_BEGIN_RET_1(overlapped); // Eventually calls BEGIN_SO_INTOLERANT_CODE_NOTHROW // OS doesn't signal handle, so do it here - overlapped->Internal = 0; + lpOverlapped->Internal = 0; if (ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, ThreadPoolIOEnqueue)) FireEtwThreadPoolIOEnqueue(lpOverlapped, OBJECTREFToObject(overlapped), false, GetClrInstanceId()); diff --git a/src/vm/gcenv.ee.cpp b/src/vm/gcenv.ee.cpp index daf6fe8dbf..7f9d269432 100644 --- a/src/vm/gcenv.ee.cpp +++ b/src/vm/gcenv.ee.cpp @@ -1371,17 +1371,13 @@ void GCToEEInterface::WalkAsyncPinnedForPromotion(Object* object, ScanContext* s OverlappedDataObject *pOverlapped = (OverlappedDataObject *)object; if (pOverlapped->m_userObject != NULL) { - //callback(OBJECTREF_TO_UNCHECKED_OBJECTREF(pOverlapped->m_userObject), (ScanContext *)lp1, GC_CALL_PINNED); - if (pOverlapped->m_isArray) + if (pOverlapped->m_userObject->GetGCSafeMethodTable() == g_pPredefinedArrayTypes[ELEMENT_TYPE_OBJECT]->GetMethodTable()) { // OverlappedDataObject is very special. An async pin handle keeps it alive. // During GC, we also make sure // 1. m_userObject itself does not move if m_userObject is not array // 2. Every object pointed by m_userObject does not move if m_userObject is array - // We do not want to pin m_userObject if it is array. But m_userObject may be updated - // during relocation phase before OverlappedDataObject is doing relocation. - // m_userObjectInternal is used to track the location of the m_userObject before it is updated. - pOverlapped->m_userObjectInternal = static_cast<void*>(OBJECTREFToObject(pOverlapped->m_userObject)); + // We do not want to pin m_userObject if it is array. ArrayBase* pUserObject = (ArrayBase*)OBJECTREFToObject(pOverlapped->m_userObject); Object **ppObj = (Object**)pUserObject->GetDataPtr(TRUE); size_t num = pUserObject->GetNumComponents(); @@ -1395,11 +1391,6 @@ void GCToEEInterface::WalkAsyncPinnedForPromotion(Object* object, ScanContext* s callback(&OBJECTREF_TO_UNCHECKED_OBJECTREF(pOverlapped->m_userObject), (ScanContext *)sc, GC_CALL_PINNED); } } - - if (pOverlapped->GetAppDomainId() != DefaultADID && pOverlapped->GetAppDomainIndex().m_dwIndex == DefaultADID) - { - OverlappedDataObject::MarkCleanupNeededFromGC(); - } } void GCToEEInterface::WalkAsyncPinned(Object* object, void* context, void (*callback)(Object*, Object*, void*)) @@ -1419,7 +1410,7 @@ void GCToEEInterface::WalkAsyncPinned(Object* object, void* context, void (*call { Object * pUserObject = OBJECTREFToObject(pOverlapped->m_userObject); callback(object, pUserObject, context); - if (pOverlapped->m_isArray) + if (pOverlapped->m_userObject->GetGCSafeMethodTable() == g_pPredefinedArrayTypes[ELEMENT_TYPE_OBJECT]->GetMethodTable()) { ArrayBase* pUserArrayObject = (ArrayBase*)pUserObject; Object **pObj = (Object**)pUserArrayObject->GetDataPtr(TRUE); diff --git a/src/vm/mscorlib.cpp b/src/vm/mscorlib.cpp index 53c3044f1a..6cd93ad80a 100644 --- a/src/vm/mscorlib.cpp +++ b/src/vm/mscorlib.cpp @@ -86,10 +86,6 @@ #include "multicorejit.h" #endif -#ifdef FEATURE_COMINTEROP -#include "windowsruntimebufferhelper.h" -#endif - #if defined(FEATURE_EVENTSOURCE_XPLAT) #include "nativeeventsource.h" #include "eventpipe.h" diff --git a/src/vm/mscorlib.h b/src/vm/mscorlib.h index f66931a360..c9715e1396 100644 --- a/src/vm/mscorlib.h +++ b/src/vm/mscorlib.h @@ -677,16 +677,15 @@ DEFINE_CLASS(OLE_AUT_BINDER, System, OleAutBinder) DEFINE_CLASS(MONITOR, Threading, Monitor) DEFINE_METHOD(MONITOR, ENTER, Enter, SM_Obj_RetVoid) -// Note: The size of the OverlappedData can be inflated by the CLR host -DEFINE_CLASS_U(Threading, OverlappedData, NoClass) -DEFINE_FIELD_U(m_asyncResult, OverlappedDataObject, m_asyncResult) -DEFINE_FIELD_U(m_iocb, OverlappedDataObject, m_iocb) -DEFINE_FIELD_U(m_iocbHelper, OverlappedDataObject, m_iocbHelper) -DEFINE_FIELD_U(m_overlapped, OverlappedDataObject, m_overlapped) -DEFINE_FIELD_U(m_userObject, OverlappedDataObject, m_userObject) -DEFINE_FIELD_U(m_pinSelf, OverlappedDataObject, m_pinSelf) -DEFINE_FIELD_U(m_AppDomainId, OverlappedDataObject, m_AppDomainId) -DEFINE_FIELD_U(m_isArray, OverlappedDataObject, m_isArray) +DEFINE_CLASS_U(Threading, OverlappedData, OverlappedDataObject) +DEFINE_FIELD_U(_asyncResult, OverlappedDataObject, m_asyncResult) +DEFINE_FIELD_U(_callback, OverlappedDataObject, m_callback) +DEFINE_FIELD_U(_overlapped, OverlappedDataObject, m_overlapped) +DEFINE_FIELD_U(_userObject, OverlappedDataObject, m_userObject) +DEFINE_FIELD_U(_pNativeOverlapped, OverlappedDataObject, m_pNativeOverlapped) +DEFINE_FIELD_U(_offsetLow, OverlappedDataObject, m_offsetLow) +DEFINE_FIELD_U(_offsetHigh, OverlappedDataObject, m_offsetHigh) +DEFINE_FIELD_U(_eventHandle, OverlappedDataObject, m_eventHandle) DEFINE_CLASS(OVERLAPPEDDATA, Threading, OverlappedData) DEFINE_CLASS(NATIVEOVERLAPPED, Threading, NativeOverlapped) diff --git a/src/vm/nativeoverlapped.cpp b/src/vm/nativeoverlapped.cpp index 6f053ea267..94e61c63fd 100644 --- a/src/vm/nativeoverlapped.cpp +++ b/src/vm/nativeoverlapped.cpp @@ -22,11 +22,6 @@ #include "comthreadpool.h" #include "marshalnative.h" -LONG OverlappedDataObject::s_CleanupRequestCount = 0; -BOOL OverlappedDataObject::s_CleanupInProgress = FALSE; -BOOL OverlappedDataObject::s_GCDetectsCleanup = FALSE; -BOOL OverlappedDataObject::s_CleanupFreeHandle = FALSE; - // //The function is called from managed code to quicly check if a packet is available. //This is a perf-critical function. Even helper method frames are not created. We fall @@ -38,7 +33,6 @@ FCIMPL3(void, CheckVMForIOPacket, LPOVERLAPPED* lpOverlapped, DWORD* errorCode, #ifndef FEATURE_PAL Thread *pThread = GetThread(); - DWORD adid = pThread->GetDomain()->GetId().m_dwId; size_t key=0; _ASSERTE(pThread); @@ -46,7 +40,7 @@ FCIMPL3(void, CheckVMForIOPacket, LPOVERLAPPED* lpOverlapped, DWORD* errorCode, //Poll and wait if GC is in progress, to avoid blocking GC for too long. FC_GC_POLL(); - *lpOverlapped = ThreadpoolMgr::CompletionPortDispatchWorkWithinAppDomain(pThread, errorCode, numBytes, &key, adid); + *lpOverlapped = ThreadpoolMgr::CompletionPortDispatchWorkWithinAppDomain(pThread, errorCode, numBytes, &key, DefaultADID); if(*lpOverlapped == NULL) { return; @@ -54,17 +48,10 @@ FCIMPL3(void, CheckVMForIOPacket, LPOVERLAPPED* lpOverlapped, DWORD* errorCode, OVERLAPPEDDATAREF overlapped = ObjectToOVERLAPPEDDATAREF(OverlappedDataObject::GetOverlapped(*lpOverlapped)); - _ASSERTE(overlapped->GetAppDomainId() == adid); - - if(overlapped->m_iocb == NULL) + if (overlapped->m_callback == NULL) { - // no user delegate to callback - _ASSERTE((overlapped->m_iocbHelper == NULL) || !"This is benign, but should be optimized"); - - { - //We're not initialized yet, go back to the Vm, and process the packet there. - ThreadpoolMgr::StoreOverlappedInfoInThread(pThread, *errorCode, *numBytes, key, *lpOverlapped); - } + //We're not initialized yet, go back to the Vm, and process the packet there. + ThreadpoolMgr::StoreOverlappedInfoInThread(pThread, *errorCode, *numBytes, key, *lpOverlapped); *lpOverlapped = NULL; return; @@ -94,7 +81,7 @@ FCIMPL3(void, CheckVMForIOPacket, LPOVERLAPPED* lpOverlapped, DWORD* errorCode, // if this will be "dispatched" to the managed callback fire the IODequeue event: if (*lpOverlapped != NULL && ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, ThreadPoolIODequeue)) - FireEtwThreadPoolIODequeue(*lpOverlapped, (BYTE*)(*lpOverlapped) - offsetof(OverlappedDataObject, Internal), GetClrInstanceId()); + FireEtwThreadPoolIODequeue(*lpOverlapped, OverlappedDataObject::GetOverlapped(*lpOverlapped), GetClrInstanceId()); #else // !FEATURE_PAL *lpOverlapped = NULL; @@ -104,17 +91,17 @@ FCIMPL3(void, CheckVMForIOPacket, LPOVERLAPPED* lpOverlapped, DWORD* errorCode, } FCIMPLEND -FCIMPL1(void*, AllocateNativeOverlapped, OverlappedDataObject* overlappedUNSAFE) +FCIMPL1(LPOVERLAPPED, AllocateNativeOverlapped, OverlappedDataObject* overlappedUNSAFE) { FCALL_CONTRACT; + LPOVERLAPPED lpOverlapped; + OVERLAPPEDDATAREF overlapped = ObjectToOVERLAPPEDDATAREF(overlappedUNSAFE); OBJECTREF userObject = overlapped->m_userObject; HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_2(Frame::FRAME_ATTR_NONE, overlapped, userObject); - AsyncPinningHandleHolder handle; - if (g_pOverlappedDataClass == NULL) { g_pOverlappedDataClass = MscorlibBinder::GetClass(CLASS__OVERLAPPEDDATA); @@ -126,11 +113,9 @@ FCIMPL1(void*, AllocateNativeOverlapped, OverlappedDataObject* overlappedUNSAFE) CONSISTENCY_CHECK(overlapped->GetMethodTable() == g_pOverlappedDataClass); - overlapped->m_AppDomainId = GetAppDomain()->GetId().m_dwId; - if (userObject != NULL) { - if (overlapped->m_isArray == 1) + if (userObject->GetMethodTable() == g_pPredefinedArrayTypes[ELEMENT_TYPE_OBJECT]->GetMethodTable()) { BASEARRAYREF asArray = (BASEARRAYREF) userObject; OBJECTREF *pObj = (OBJECTREF*)(asArray->GetDataPtr()); @@ -140,33 +125,32 @@ FCIMPL1(void*, AllocateNativeOverlapped, OverlappedDataObject* overlappedUNSAFE) { ValidatePinnedObject(pObj[i]); } - for (i = 0; i < num; i ++) - { - asArray = (BASEARRAYREF) userObject; - AddMTForPinHandle(pObj[i]); - } } else { ValidatePinnedObject(userObject); - AddMTForPinHandle(userObject); } - } - handle = GetAppDomain()->CreateTypedHandle(overlapped, HNDTYPE_ASYNCPINNED); + NewHolder<NATIVEOVERLAPPED_AND_HANDLE> overlappedHolder(new NATIVEOVERLAPPED_AND_HANDLE()); + overlappedHolder->m_handle = GetAppDomain()->CreateTypedHandle(overlapped, HNDTYPE_ASYNCPINNED); + lpOverlapped = &(overlappedHolder.Extract()->m_overlapped); + lpOverlapped->Internal = 0; + lpOverlapped->InternalHigh = 0; + lpOverlapped->Offset = overlapped->m_offsetLow; + lpOverlapped->OffsetHigh = overlapped->m_offsetHigh; + lpOverlapped->hEvent = (HANDLE)overlapped->m_eventHandle; - handle.SuppressRelease(); - overlapped->m_pinSelf = handle; + overlapped->m_pNativeOverlapped = lpOverlapped; HELPER_METHOD_FRAME_END(); LOG((LF_INTEROP, LL_INFO10000, "In AllocNativeOperlapped thread 0x%x\n", GetThread())); if (ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, ThreadPoolIODequeue)) - FireEtwThreadPoolIOPack(&overlapped->Internal, overlappedUNSAFE, GetClrInstanceId()); + FireEtwThreadPoolIOPack(lpOverlapped, overlappedUNSAFE, GetClrInstanceId()); - return &overlapped->Internal; + return lpOverlapped; } FCIMPLEND @@ -176,28 +160,11 @@ FCIMPL1(void, FreeNativeOverlapped, LPOVERLAPPED lpOverlapped) HELPER_METHOD_FRAME_BEGIN_0(); - OVERLAPPEDDATAREF overlapped = ObjectToOVERLAPPEDDATAREF(OverlappedDataObject::GetOverlapped(lpOverlapped)); - CONSISTENCY_CHECK(g_pOverlappedDataClass && (overlapped->GetMethodTable() == g_pOverlappedDataClass)); + CONSISTENCY_CHECK(g_pOverlappedDataClass && (OverlappedDataObject::GetOverlapped(lpOverlapped)->GetMethodTable() == g_pOverlappedDataClass)); - // We don't want to call HasCompleted in the default domain, because we don't have - // overlapped handle support. - if ((!overlapped->HasCompleted ())) - { -#ifdef MDA_SUPPORTED - MdaOverlappedFreeError *pFreeError = MDA_GET_ASSISTANT(OverlappedFreeError); - if (pFreeError) - { - pFreeError->ReportError((LPVOID) OVERLAPPEDDATAREFToObject(overlapped)); - - // If we entered ReportError then our overlapped OBJECTREF became technically invalid, - // since a gc can be triggered. That causes an assert from FreeAsyncPinHandles() below. - // (I say technically because the object is pinned and won't really move) - overlapped = ObjectToOVERLAPPEDDATAREF(OverlappedDataObject::GetOverlapped(lpOverlapped)); - } -#endif // MDA_SUPPORTED - } + DestroyAsyncPinningHandle(((NATIVEOVERLAPPED_AND_HANDLE*)lpOverlapped)->m_handle); + delete lpOverlapped; - overlapped->FreeAsyncPinHandles(); HELPER_METHOD_FRAME_END(); } FCIMPLEND @@ -211,331 +178,3 @@ FCIMPL1(OverlappedDataObject*, GetOverlappedFromNative, LPOVERLAPPED lpOverlappe return OverlappedDataObject::GetOverlapped(lpOverlapped); } FCIMPLEND - -namespace -{ - -// Sets up an enumeration of all async pinned handles, such that all enumerated -// async pinned handles are processed by calling HandleAsyncPinHandle on the -// underlying overlapped instance. -BOOL HandleAsyncPinHandles() -{ - auto callback = [](Object* value, void*) - { - _ASSERTE (value->GetMethodTable() == g_pOverlappedDataClass); - OVERLAPPEDDATAREF overlapped = (OVERLAPPEDDATAREF)(ObjectToOBJECTREF(value)); - if (overlapped->GetAppDomainId() != DefaultADID && overlapped->HasCompleted()) - { - overlapped->HandleAsyncPinHandle(); - return true; - } - - return false; - }; - - IGCHandleManager* mgr = GCHandleUtilities::GetGCHandleManager(); - return mgr->GetGlobalHandleStore()->EnumerateAsyncPinnedHandles(callback, nullptr); -} - -} // anonymous namespace - -void OverlappedDataObject::FreeAsyncPinHandles() -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_COOPERATIVE; - SO_TOLERANT; - } - CONTRACTL_END; - - // This cannot throw or return error, and cannot force SO because it is called - // from CCLRIoCompletionManager::OnComplete which probes. - CONTRACT_VIOLATION(SOToleranceViolation); - - CONSISTENCY_CHECK(g_pOverlappedDataClass && (this->GetMethodTable() == g_pOverlappedDataClass)); - - _ASSERTE(GetThread() != NULL); - - if (m_pinSelf) - { - OBJECTHANDLE h = m_pinSelf; - if (FastInterlockCompareExchangePointer(&m_pinSelf, static_cast<OBJECTHANDLE>(NULL), h) == h) - { - DestroyAsyncPinningHandle(h); - } - } - - EventHandle = 0; -} - - -void OverlappedDataObject::StartCleanup() -{ - CONTRACTL - { - NOTHROW; - if (GetThread()) {MODE_COOPERATIVE;} else {DISABLED(MODE_COOPERATIVE);} - GC_TRIGGERS; - } - CONTRACTL_END; - - if (s_CleanupRequestCount == 0) - { - return; - } - - LONG curCount = s_CleanupRequestCount; - if (FastInterlockExchange((LONG*)&s_CleanupInProgress, TRUE) == FALSE) - { - { - BOOL HasJob = HandleAsyncPinHandles(); - if (!HasJob) - { - s_CleanupInProgress = FALSE; - FastInterlockExchangeAdd (&s_CleanupRequestCount, -curCount); - return; - } - } - - if (!ThreadpoolMgr::DrainCompletionPortQueue()) - { - s_CleanupInProgress = FALSE; - } - else - { - FastInterlockExchangeAdd (&s_CleanupRequestCount, -curCount); - } - } -} - - -void OverlappedDataObject::FinishCleanup(bool wasDrained) -{ - WRAPPER_NO_CONTRACT; - - if (wasDrained) - { - GCX_COOP(); - - s_CleanupFreeHandle = TRUE; - HandleAsyncPinHandles(); - s_CleanupFreeHandle = FALSE; - - s_CleanupInProgress = FALSE; - if (s_CleanupRequestCount > 0) - { - StartCleanup(); - } - } - else - { - s_CleanupInProgress = FALSE; - } -} - - -void OverlappedDataObject::HandleAsyncPinHandle() -{ - WRAPPER_NO_CONTRACT; - - _ASSERTE (s_CleanupInProgress); - if (m_toBeCleaned || !ThreadpoolMgr::IsCompletionPortInitialized()) - { - OBJECTHANDLE h = m_pinSelf; - if (h) - { - if (FastInterlockCompareExchangePointer(&m_pinSelf, (OBJECTHANDLE)NULL, h) == h) - { - DestroyAsyncPinningHandle(h); - } - } - } - else if (!s_CleanupFreeHandle) - { - m_toBeCleaned = 1; - } -} - - -// A hash table to track size of objects that may be moved to default domain -typedef EEHashTable<size_t, EEPtrHashTableHelper<size_t>, FALSE> EEHashTableOfMT; -EEHashTableOfMT *s_pPinHandleTable; - -CrstStatic s_PinHandleTableCrst; - -void InitializePinHandleTable() -{ - WRAPPER_NO_CONTRACT; - - s_PinHandleTableCrst.Init(CrstPinHandle); - LockOwner lock = {&s_PinHandleTableCrst, IsOwnerOfCrst}; - s_pPinHandleTable = new EEHashTableOfMT(); - s_pPinHandleTable->Init(10, &lock); -} - -// We can not fail due to OOM when we move an object to default domain during AD unload. -// If we may need a dummy MethodTable later, we allocate the MethodTable here. -void AddMTForPinHandle(OBJECTREF obj) -{ - CONTRACTL - { - THROWS; - WRAPPER(GC_TRIGGERS); - } - CONTRACTL_END; - - if (obj == NULL) - { - return; - } - - _ASSERTE (g_pOverlappedDataClass != NULL); - - SSIZE_T size = 0; - MethodTable *pMT = obj->GetMethodTable(); - - if (pMT->GetLoaderModule()->IsSystem()) - { - return; - } - - if (pMT->IsArray()) - { -#ifdef _DEBUG - BASEARRAYREF asArray = (BASEARRAYREF) obj; - TypeHandle th = asArray->GetArrayElementTypeHandle(); - _ASSERTE (!th.IsTypeDesc()); - MethodTable *pElemMT = th.AsMethodTable(); - _ASSERTE (pElemMT->IsValueType() && pElemMT->IsBlittable()); - _ASSERTE (!pElemMT->GetLoaderModule()->IsSystem()); -#endif - - // Create an ArrayMethodTable that has the same element size - // Use negative number for arrays of structs - it assumes that - // the maximum type base size is less than 2GB. - size = - (SSIZE_T)pMT->GetComponentSize(); - _ASSERTE(size < 0); - } - else - { - size = pMT->GetBaseSize(); - _ASSERTE(size >= 0); - } - - HashDatum data; - if (s_pPinHandleTable->GetValue(size, &data) == FALSE) - { - CrstHolder csh(&s_PinHandleTableCrst); - if (s_pPinHandleTable->GetValue(size, &data) == FALSE) - { - // We do not need to include GCDescr here, since this - // methodtable does not contain pointers. - BYTE *buffer = new BYTE[sizeof(MethodTable)]; - memset (buffer, 0, sizeof(MethodTable)); - MethodTable *pNewMT = (MethodTable *)buffer; - NewArrayHolder<BYTE> pMTHolder(buffer); - pNewMT->SetIsAsyncPinType(); - if (size >= 0) - { - pNewMT->SetBaseSize(static_cast<DWORD>(size)); - } - else - { - pNewMT->SetBaseSize(ARRAYBASE_BASESIZE); - pNewMT->SetComponentSize(static_cast<WORD>(-size)); - } - s_pPinHandleTable->InsertValue(size, (HashDatum)pNewMT); - pMTHolder.SuppressRelease(); - } - } -} - -// We need to ensure that the MethodTable of an object is valid in default domain when the object -// is move to default domain duing AD unload. -void BashMTForPinnedObject(OBJECTREF obj) -{ - CONTRACTL - { - GC_NOTRIGGER; - NOTHROW; - } - CONTRACTL_END; - - if (obj == NULL) - { - return; - } - - ADIndex adIndx = obj->GetAppDomainIndex(); - ADIndex defaultAdIndx = SystemDomain::System()->DefaultDomain()->GetIndex(); - if (adIndx.m_dwIndex != 0 && adIndx != defaultAdIndx) - { - obj->GetHeader()->ResetAppDomainIndexNoFailure(defaultAdIndx); - } - SSIZE_T size = 0; - MethodTable *pMT = obj->GetMethodTable(); - - if (pMT == g_pOverlappedDataClass) - { - // Managed Overlapped - OVERLAPPEDDATAREF overlapped = (OVERLAPPEDDATAREF)(obj); - overlapped->m_asyncResult = NULL; - overlapped->m_iocb = NULL; - overlapped->m_iocbHelper = NULL; - overlapped->m_overlapped = NULL; - - if (overlapped->m_userObject != NULL) - { - if (overlapped->m_isArray == 1) - { - BASEARRAYREF asArray = (BASEARRAYREF) (overlapped->m_userObject); - OBJECTREF *pObj = (OBJECTREF*)asArray->GetDataPtr (TRUE); - SIZE_T num = asArray->GetNumComponents(); - for (SIZE_T i = 0; i < num; i ++) - { - BashMTForPinnedObject(pObj[i]); - } - } - else - { - BashMTForPinnedObject(overlapped->m_userObject); - } - } - STRESS_LOG1 (LF_APPDOMAIN | LF_GC, LL_INFO100, "OverlappedData %p:MT is bashed\n", OBJECTREFToObject (overlapped)); - return; - } - - if (pMT->GetLoaderModule()->IsSystem()) - { - return; - } - - if (pMT->IsArray()) - { -#ifdef _DEBUG - BASEARRAYREF asArray = (BASEARRAYREF) obj; - TypeHandle th = asArray->GetArrayElementTypeHandle(); - _ASSERTE (!th.IsTypeDesc()); - MethodTable *pElemMT = th.AsMethodTable(); - _ASSERTE (pElemMT->IsValueType() && pElemMT->IsBlittable()); - _ASSERTE (!pElemMT->GetLoaderModule()->IsSystem()); -#endif - - // Create an ArrayMethodTable that has the same element size - size = - (SSIZE_T)pMT->GetComponentSize(); - } - else - { - _ASSERTE (pMT->IsBlittable()); - size = pMT->GetBaseSize(); - } - - HashDatum data = NULL; - BOOL fRet; - fRet = s_pPinHandleTable->GetValue(size, &data); - _ASSERTE(fRet); - PREFIX_ASSUME(data != NULL); - obj->SetMethodTable((MethodTable*)data); -} diff --git a/src/vm/nativeoverlapped.h b/src/vm/nativeoverlapped.h index 7f12f477e8..e1ffb886b6 100644 --- a/src/vm/nativeoverlapped.h +++ b/src/vm/nativeoverlapped.h @@ -16,118 +16,50 @@ #ifndef _OVERLAPPED_H #define _OVERLAPPED_H +struct NATIVEOVERLAPPED_AND_HANDLE +{ + OVERLAPPED m_overlapped; + OBJECTHANDLE m_handle; +}; + // This should match the managed Overlapped object. // If you make any change here, you need to change the managed part Overlapped. class OverlappedDataObject : public Object { public: - OBJECTREF m_asyncResult; - OBJECTREF m_iocb; - OBJECTREF m_iocbHelper; - OBJECTREF m_overlapped; - OBJECTREF m_userObject; - - // - // NOTE! WCF directly accesses m_pinSelf from managed code, using a hard-coded negative - // offset from the Internal member, below. They need this so they can modify the - // contents of m_userObject; after such modification, they need to update this handle - // to be in the correct GC generation. - // - // If you need to add or remove fields between this one and Internal, be sure that - // you also fix the hard-coded offsets in ndp\cdf\src\WCF\ServiceModel\System\ServiceModel\Channels\OverlappedContext.cs. - // - OBJECTHANDLE m_pinSelf; - // OverlappedDataObject is very special. An async pin handle keeps it alive. // During GC, we also make sure // 1. m_userObject itself does not move if m_userObject is not array // 2. Every object pointed by m_userObject does not move if m_userObject is array - // We do not want to pin m_userObject if it is array. But m_userObject may be updated - // during relocation phase before OverlappedDataObject is doing relocation. - // m_userObjectInternal is used to track the location of the m_userObject before it is updated. - void *m_userObjectInternal; - DWORD m_AppDomainId; - unsigned char m_isArray; - unsigned char m_toBeCleaned; - - ULONG_PTR Internal; - ULONG_PTR InternalHigh; - int OffsetLow; - int OffsetHigh; - ULONG_PTR EventHandle; - - static OverlappedDataObject* GetOverlapped (LPOVERLAPPED nativeOverlapped) + OBJECTREF m_asyncResult; + OBJECTREF m_callback; + OBJECTREF m_overlapped; + OBJECTREF m_userObject; + LPOVERLAPPED m_pNativeOverlapped; + ULONG_PTR m_eventHandle; + int m_offsetLow; + int m_offsetHigh; + +#ifndef DACCESS_COMPILE + static OverlappedDataObject* GetOverlapped(LPOVERLAPPED nativeOverlapped) { LIMITED_METHOD_CONTRACT; STATIC_CONTRACT_SO_TOLERANT; _ASSERTE (nativeOverlapped != NULL); - _ASSERTE (GCHeapUtilities::GetGCHeap()->IsHeapPointer((BYTE *) nativeOverlapped)); - - return (OverlappedDataObject*)((BYTE*)nativeOverlapped - offsetof(OverlappedDataObject, Internal)); + return (OverlappedDataObject*)OBJECTREFToObject(ObjectFromHandle(((NATIVEOVERLAPPED_AND_HANDLE*)nativeOverlapped)->m_handle)); } - DWORD GetAppDomainId() - { - return m_AppDomainId; - } - - void HandleAsyncPinHandle(); - - void FreeAsyncPinHandles(); - - BOOL HasCompleted() + // Return the raw OverlappedDataObject* without going into cooperative mode for tracing + static OverlappedDataObject* GetOverlappedForTracing(LPOVERLAPPED nativeOverlapped) { LIMITED_METHOD_CONTRACT; -#ifndef FEATURE_PAL - return HasOverlappedIoCompleted((LPOVERLAPPED) &Internal); -#else // !FEATURE_PAL - return FALSE; -#endif // !FEATURE_PAL - } - -private: - static LONG s_CleanupRequestCount; - static BOOL s_CleanupInProgress; - static BOOL s_GCDetectsCleanup; - static BOOL s_CleanupFreeHandle; - -public: - static void RequestCleanup() - { - WRAPPER_NO_CONTRACT; - - FastInterlockIncrement(&s_CleanupRequestCount); - if (!s_CleanupInProgress) - { - StartCleanup(); - } - } - static void StartCleanup(); - - static void FinishCleanup(bool wasDrained); - - static void MarkCleanupNeededFromGC() - { - LIMITED_METHOD_CONTRACT; - s_GCDetectsCleanup = TRUE; - } - - static BOOL CleanupNeededFromGC() - { - return s_GCDetectsCleanup; - } - - static void RequestCleanupFromGC() - { - WRAPPER_NO_CONTRACT; + STATIC_CONTRACT_SO_TOLERANT; - if (s_GCDetectsCleanup) - { - s_GCDetectsCleanup = FALSE; - RequestCleanup(); - } + _ASSERTE(nativeOverlapped != NULL); + return *(OverlappedDataObject**)(((NATIVEOVERLAPPED_AND_HANDLE*)nativeOverlapped)->m_handle); } +#endif // DACCESS_COMPILE }; #ifdef USE_CHECKED_OBJECTREFS @@ -145,12 +77,8 @@ typedef OverlappedDataObject* OVERLAPPEDDATAREF; #endif FCDECL3(void, CheckVMForIOPacket, LPOVERLAPPED* lpOverlapped, DWORD* errorCode, DWORD* numBytes); -FCDECL1(void*, AllocateNativeOverlapped, OverlappedDataObject* overlapped); +FCDECL1(LPOVERLAPPED, AllocateNativeOverlapped, OverlappedDataObject* overlapped); FCDECL1(void, FreeNativeOverlapped, LPOVERLAPPED lpOverlapped); FCDECL1(OverlappedDataObject*, GetOverlappedFromNative, LPOVERLAPPED lpOverlapped); -void InitializePinHandleTable(); -void AddMTForPinHandle(OBJECTREF obj); -void BashMTForPinnedObject(OBJECTREF obj); - #endif diff --git a/src/vm/threads.cpp b/src/vm/threads.cpp index 5042e52b78..a354d54b0a 100644 --- a/src/vm/threads.cpp +++ b/src/vm/threads.cpp @@ -8546,7 +8546,6 @@ BOOL Thread::HaveExtraWorkForFinalizer() LIMITED_METHOD_CONTRACT; return m_ThreadTasks - || OverlappedDataObject::CleanupNeededFromGC() || ThreadpoolMgr::HaveTimerInfosToFlush() || ExecutionManager::IsCacheCleanupRequired() || Thread::CleanupNeededForFinalizedThread() @@ -8606,8 +8605,6 @@ void Thread::DoExtraWorkForFinalizer() ExecutionManager::ClearCaches(); } - OverlappedDataObject::RequestCleanupFromGC(); - // If there were any TimerInfos waiting to be released, they'll get flushed now ThreadpoolMgr::FlushQueueOfTimerInfos(); diff --git a/src/vm/win32threadpool.cpp b/src/vm/win32threadpool.cpp index 7f9953a0f9..644e2324c6 100644 --- a/src/vm/win32threadpool.cpp +++ b/src/vm/win32threadpool.cpp @@ -1297,7 +1297,6 @@ ThreadpoolMgr::CallbackForInitiateDrainageOfCompletionPortQueue( } FastInterlockAnd(&g_fCompletionPortDrainNeeded, 0); - OverlappedDataObject::FinishCleanup(!fTryNextTime); #endif // !FEATURE_PAL } @@ -3459,7 +3458,9 @@ Top: // abstraction level for managed IO we can remove the IODequeues fired here if (ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, ThreadPoolIODequeue) && !AreEtwIOQueueEventsSpeciallyHandled((LPOVERLAPPED_COMPLETION_ROUTINE)key) && pOverlapped != NULL) - FireEtwThreadPoolIODequeue(pOverlapped, (BYTE*)pOverlapped - offsetof(OverlappedDataObject, Internal), GetClrInstanceId()); + { + FireEtwThreadPoolIODequeue(pOverlapped, OverlappedDataObject::GetOverlappedForTracing(pOverlapped), GetClrInstanceId()); + } bool enterRetirement; @@ -3766,7 +3767,7 @@ LPOVERLAPPED ThreadpoolMgr::CompletionPortDispatchWorkWithinAppDomain( overlapped = ObjectToOVERLAPPEDDATAREF(OverlappedDataObject::GetOverlapped(lpOverlapped)); } - if (ManagedCallback && (overlapped->GetAppDomainId() == adid)) + if (ManagedCallback) { _ASSERTE(*pKey != 0); // should be a valid function address @@ -3775,7 +3776,6 @@ LPOVERLAPPED ThreadpoolMgr::CompletionPortDispatchWorkWithinAppDomain( //Application Bug. return NULL; } - } else { |