summaryrefslogtreecommitdiff
path: root/src/vm/rcwwalker.h
diff options
context:
space:
mode:
authordotnet-bot <dotnet-bot@microsoft.com>2015-01-30 14:14:42 -0800
committerdotnet-bot <dotnet-bot@microsoft.com>2015-01-30 14:14:42 -0800
commitef1e2ab328087c61a6878c1e84f4fc5d710aebce (patch)
treedee1bbb89e9d722e16b0d1485e3cdd1b6c8e2cfa /src/vm/rcwwalker.h
downloadcoreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.tar.gz
coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.tar.bz2
coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.zip
Initial commit to populate CoreCLR repo
[tfs-changeset: 1407945]
Diffstat (limited to 'src/vm/rcwwalker.h')
-rw-r--r--src/vm/rcwwalker.h151
1 files changed, 151 insertions, 0 deletions
diff --git a/src/vm/rcwwalker.h b/src/vm/rcwwalker.h
new file mode 100644
index 0000000000..a2272eafbb
--- /dev/null
+++ b/src/vm/rcwwalker.h
@@ -0,0 +1,151 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+//
+
+//
+
+/*============================================================
+**
+** Header: RCWWalker.h
+**
+**
+** Purpose: Solve native/manage cyclic reference issue by
+** walking RCW objects
+**
+==============================================================*/
+
+#ifndef _H_RCWWALKER_
+#define _H_RCWWALKER_
+
+#ifdef FEATURE_COMINTEROP
+
+#include "internalunknownimpl.h"
+#include "utilcode.h"
+#include "runtimecallablewrapper.h"
+
+
+//
+// RCW Walker
+// Walks jupiter RCW objects and create references from RCW to referenced CCW (in native side)
+//
+class RCWWalker
+{
+private :
+ static VolatilePtr<IJupiterGCManager> s_pGCManager; // The one and only GCManager instance
+ static BOOL s_bGCStarted; // Has GC started?
+ SVAL_DECL(BOOL, s_bIsGlobalPeggingOn); // Do we need to peg every CCW?
+
+public :
+#ifndef DACCESS_COMPILE
+ static void OnJupiterRCWCreated(RCW *pRCW, IJupiterObject *pJupiterObject);
+ static void AfterJupiterRCWCreated(RCW *pRCW);
+ static void BeforeJupiterRCWDestroyed(RCW *pRCW);
+ static void OnEEShutdown();
+
+ //
+ // Send out a AfterAddRef callback to notify Jupiter we've done a AddRef
+ // We should do this *after* we made a AddRef because we should never
+ // be in a state where reported refs > actual refs
+ //
+ FORCEINLINE static void AfterInterfaceAddRef(RCW *pRCW)
+ {
+
+ CONTRACTL {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ IJupiterObject *pJupiterObject = pRCW->GetJupiterObject();
+ if (pJupiterObject)
+ {
+ STRESS_LOG2(LF_INTEROP, LL_INFO100, "[RCW Walker] Calling IJupiterObject::AfterAddRef (IJupiterObject = 0x%p, RCW = 0x%p)\n", pJupiterObject, pRCW);
+ pJupiterObject->AfterAddRef();
+ }
+ }
+
+ //
+ // Send out BeforeRelease callback for every cached interface pointer
+ // This needs to be made before call Release because we should never be in a
+ // state that reported refs > actual refs
+ //
+ FORCEINLINE static void BeforeInterfaceRelease(RCW *pRCW)
+ {
+ CONTRACTL {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ IJupiterObject *pJupiterObject = pRCW->GetJupiterObject();
+ if (pJupiterObject)
+ {
+ STRESS_LOG2(LF_INTEROP, LL_INFO100, "[RCW Walker] Calling IJupiterObject::BeforeRelease before Release (IJupiterObject = 0x%p, RCW = 0x%p)\n", pJupiterObject, pRCW);
+ pJupiterObject->BeforeRelease();
+ }
+ }
+
+
+#endif // !DACCESS_COMPILE
+
+
+public :
+ //
+ // Called in ComCallableWrapper::IsWrapperActive
+ // Used to override the individual pegging flag on CCWs and force pegging every jupiter referenced CCW
+ // See IsWrapperActive for more details
+ //
+ static FORCEINLINE BOOL IsGlobalPeggingOn()
+ {
+ // We need this weird cast because s_bIsGlobalPeggingOn is used in DAC and defined as
+ // __GlobalVal in DAC build
+ // C++'s operator magic didn't work if two levels of operator overloading are involved...
+ return VolatileLoad((BOOL *)&s_bIsGlobalPeggingOn);
+ }
+
+#ifndef DACCESS_COMPILE
+ //
+ // Tells GC whether walking all the Jupiter RCW is necessary, which only should happen
+ // if we have seen jupiter RCWs
+ //
+ static FORCEINLINE BOOL NeedToWalkRCWs()
+ {
+ LIMITED_METHOD_CONTRACT;
+
+ return (((IJupiterGCManager *)s_pGCManager) != NULL);
+ }
+
+ //
+ // Whether a GC has been started and we need to RCW walk
+ //
+ static FORCEINLINE BOOL HasGCStarted()
+ {
+ return s_bGCStarted;
+ }
+
+ //
+ // Called when GC started
+ // We do most of our work here
+ //
+ static void OnGCStarted(int nCondemnedGeneration);
+
+ //
+ // Called when GC finished
+ //
+ static void OnGCFinished(int nCondemnedGeneration);
+
+private :
+ static void OnGCStartedWorker();
+ static void OnGCFinishedWorker();
+ static void WalkRCWs();
+ static HRESULT WalkOneRCW(RCW *pRCW, RCWRefCache *pRCWRefCache);
+#endif // DACCESS_COMPILE
+};
+
+#endif // FEATURE_COMINTEROP
+
+#endif // _H_RCWWALKER_