summaryrefslogtreecommitdiff
path: root/src/vm
diff options
context:
space:
mode:
authorJan Kotas <jkotas@microsoft.com>2017-12-13 19:46:50 -0800
committerGitHub <noreply@github.com>2017-12-13 19:46:50 -0800
commitbc5a76d93f21392acbdfb8ec820fa287b31f09e4 (patch)
tree4c8521fa7bd5024b531ec43485d7f2a8738cb338 /src/vm
parentb3dc9a728ac9ee10ea7df713c8002678120c2e4d (diff)
downloadcoreclr-bc5a76d93f21392acbdfb8ec820fa287b31f09e4.tar.gz
coreclr-bc5a76d93f21392acbdfb8ec820fa287b31f09e4.tar.bz2
coreclr-bc5a76d93f21392acbdfb8ec820fa287b31f09e4.zip
Revert " Revert "[Local GC] Move knowledge of overlapped I/O objects to the EE through four callbacks (#14982)""
Diffstat (limited to 'src/vm')
-rw-r--r--src/vm/appdomain.cpp38
-rw-r--r--src/vm/gcenv.ee.cpp81
-rw-r--r--src/vm/gcenv.ee.h2
-rw-r--r--src/vm/gcenv.ee.standalone.cpp3
-rw-r--r--src/vm/gcenv.ee.static.cpp3
5 files changed, 122 insertions, 5 deletions
diff --git a/src/vm/appdomain.cpp b/src/vm/appdomain.cpp
index 370847c9a2..07e3280342 100644
--- a/src/vm/appdomain.cpp
+++ b/src/vm/appdomain.cpp
@@ -9053,7 +9053,43 @@ void AppDomain::HandleAsyncPinHandles()
// 4. Then we can delete all AsyncPinHandle marked with READYTOCLEAN.
IGCHandleStore *pBucketInDefault = SystemDomain::System()->DefaultDomain()->m_handleStore;
- pBucket->RelocateAsyncPinnedHandles(pBucketInDefault);
+ 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();
}
diff --git a/src/vm/gcenv.ee.cpp b/src/vm/gcenv.ee.cpp
index e5da889a64..a880fdbca6 100644
--- a/src/vm/gcenv.ee.cpp
+++ b/src/vm/gcenv.ee.cpp
@@ -1201,7 +1201,7 @@ namespace
};
InlineSString<MaxThreadNameSize> wideName;
- const WCHAR* namePtr;
+ const WCHAR* namePtr = nullptr;
EX_TRY
{
if (name != nullptr)
@@ -1214,7 +1214,6 @@ namespace
{
// we're not obligated to provide a name - if it's not valid,
// just report nullptr as the name.
- namePtr = nullptr;
}
EX_END_CATCH(SwallowAllExceptions)
@@ -1307,3 +1306,81 @@ bool GCToEEInterface::CreateThread(void (*threadStart)(void*), void* arg, bool i
return CreateNonSuspendableThread(threadStart, arg, name);
}
}
+
+void GCToEEInterface::WalkAsyncPinnedForPromotion(Object* object, ScanContext* sc, promote_func* callback)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ assert(object != nullptr);
+ assert(sc != nullptr);
+ assert(callback != nullptr);
+ if (object->GetGCSafeMethodTable() != g_pOverlappedDataClass)
+ {
+ // not an overlapped data object - nothing to do.
+ return;
+ }
+
+ // reporting the pinned user objects
+ 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)
+ {
+ // 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));
+ ArrayBase* pUserObject = (ArrayBase*)OBJECTREFToObject(pOverlapped->m_userObject);
+ Object **ppObj = (Object**)pUserObject->GetDataPtr(TRUE);
+ size_t num = pUserObject->GetNumComponents();
+ for (size_t i = 0; i < num; i++)
+ {
+ callback(ppObj + i, sc, GC_CALL_PINNED);
+ }
+ }
+ else
+ {
+ 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*))
+{
+ LIMITED_METHOD_CONTRACT;
+
+ assert(object != nullptr);
+ assert(callback != nullptr);
+
+ if (object->GetGCSafeMethodTable() != g_pOverlappedDataClass)
+ {
+ return;
+ }
+
+ OverlappedDataObject *pOverlapped = (OverlappedDataObject *)(object);
+ if (pOverlapped->m_userObject != NULL)
+ {
+ Object * pUserObject = OBJECTREFToObject(pOverlapped->m_userObject);
+ callback(object, pUserObject, context);
+ if (pOverlapped->m_isArray)
+ {
+ ArrayBase* pUserArrayObject = (ArrayBase*)pUserObject;
+ Object **pObj = (Object**)pUserArrayObject->GetDataPtr(TRUE);
+ size_t num = pUserArrayObject->GetNumComponents();
+ for (size_t i = 0; i < num; i ++)
+ {
+ callback(pUserObject, pObj[i], context);
+ }
+ }
+ }
+}
diff --git a/src/vm/gcenv.ee.h b/src/vm/gcenv.ee.h
index b2ada36bcd..e3867b7e98 100644
--- a/src/vm/gcenv.ee.h
+++ b/src/vm/gcenv.ee.h
@@ -60,6 +60,8 @@ public:
bool IsGCThread();
bool WasCurrentThreadCreatedByGC();
bool CreateThread(void (*threadStart)(void*), void* arg, bool is_suspendable, const char* name);
+ void WalkAsyncPinnedForPromotion(Object* object, ScanContext* sc, promote_func* callback);
+ void WalkAsyncPinned(Object* object, void* context, void(*callback)(Object*, Object*, void*));
};
} // namespace standalone
diff --git a/src/vm/gcenv.ee.standalone.cpp b/src/vm/gcenv.ee.standalone.cpp
index 5ba2aca812..be8ceca0c1 100644
--- a/src/vm/gcenv.ee.standalone.cpp
+++ b/src/vm/gcenv.ee.standalone.cpp
@@ -6,6 +6,7 @@
#include "gcenv.h"
#include "gcenv.ee.h"
#include "threadsuspend.h"
+#include "nativeoverlapped.h"
#ifdef FEATURE_COMINTEROP
#include "runtimecallablewrapper.h"
@@ -27,4 +28,4 @@ namespace standalone
#include "gcenv.ee.cpp"
-} // namespace standalone \ No newline at end of file
+} // namespace standalone
diff --git a/src/vm/gcenv.ee.static.cpp b/src/vm/gcenv.ee.static.cpp
index 240e325a9e..975decadf4 100644
--- a/src/vm/gcenv.ee.static.cpp
+++ b/src/vm/gcenv.ee.static.cpp
@@ -6,6 +6,7 @@
#include "gcenv.h"
#include "../gc/env/gcenv.ee.h"
#include "threadsuspend.h"
+#include "nativeoverlapped.h"
#ifdef FEATURE_COMINTEROP
#include "runtimecallablewrapper.h"
@@ -22,4 +23,4 @@ extern MethodTable* pWeakReferenceOfTCanonMT;
// Finalizes a weak reference directly.
extern void FinalizeWeakReference(Object* obj);
-#include "gcenv.ee.cpp" \ No newline at end of file
+#include "gcenv.ee.cpp"