summaryrefslogtreecommitdiff
path: root/src/vm
diff options
context:
space:
mode:
authorJan Kotas <jkotas@microsoft.com>2018-06-09 13:39:58 -0700
committerGitHub <noreply@github.com>2018-06-09 13:39:58 -0700
commit911d332c523848023e3c6564788b72b7f419fca1 (patch)
treeae979e6b048630ed0393983d14bde5d43942459f /src/vm
parent618f9c2d18e88566ac61f93529bac58123c50cba (diff)
downloadcoreclr-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.cpp66
-rw-r--r--src/vm/appdomain.hpp1
-rw-r--r--src/vm/ceemain.cpp2
-rw-r--r--src/vm/class.cpp16
-rw-r--r--src/vm/comcallablewrapper.cpp33
-rw-r--r--src/vm/comcallablewrapper.h44
-rw-r--r--src/vm/comthreadpool.cpp37
-rw-r--r--src/vm/gcenv.ee.cpp15
-rw-r--r--src/vm/mscorlib.cpp4
-rw-r--r--src/vm/mscorlib.h19
-rw-r--r--src/vm/nativeoverlapped.cpp407
-rw-r--r--src/vm/nativeoverlapped.h122
-rw-r--r--src/vm/threads.cpp3
-rw-r--r--src/vm/win32threadpool.cpp8
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
{