diff options
author | dotnet-bot <dotnet-bot@microsoft.com> | 2015-01-30 14:14:42 -0800 |
---|---|---|
committer | dotnet-bot <dotnet-bot@microsoft.com> | 2015-01-30 14:14:42 -0800 |
commit | ef1e2ab328087c61a6878c1e84f4fc5d710aebce (patch) | |
tree | dee1bbb89e9d722e16b0d1485e3cdd1b6c8e2cfa /src/vm/rcwwalker.h | |
download | coreclr-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.h | 151 |
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_ |