Esempio n. 1
0
//=========================================================================
// Asserts if lock mode is PREEMPTIVE and thread in a GC_NOTRIGGER contract
//=========================================================================        
void SimpleRWLock::CheckGCNoTrigger()
{
    STATIC_CONTRACT_NOTHROW;

    // On PREEMPTIVE locks we'll toggle the GC mode, so we better not be in a GC_NOTRIGGERS region
    if (m_gcMode == PREEMPTIVE)
    {
        ClrDebugState *pClrDebugState = CheckClrDebugState();
        if (pClrDebugState)
        {
            if (pClrDebugState->GetGCNoTriggerCount())
            {
                // If we have no thread object, we won't be toggling the GC.  This is the case, 
                // for example, on the debugger helper thread which is always GC_NOTRIGGERS.
                if (GetThreadNULLOk() != NULL) 
                {
                    if (!( (GCViolation|BadDebugState) & pClrDebugState->ViolationMask()))
                    {
                        CONTRACT_ASSERT("You cannot enter a lock in a GC_NOTRIGGER region.",
                                        Contract::GC_NoTrigger,
                                        Contract::GC_Mask,
                                        __FUNCTION__,
                                        __FILE__,
                                        __LINE__);
                    }
                }
            }

            // The mode checks and enforcement of GC_NOTRIGGER during the lock are done in SimpleRWLock::PostEnter().
        }
    }
}
Esempio n. 2
0
//=============================================================================================
// Used to initialize the per-thread ClrDebugState. This is called once per thread (with
// possible exceptions for OOM scenarios.)
//
// No matter what, this function will not return NULL. If it can't do its job because of OOM reasons,
// it will return a pointer to &gBadClrDebugState which effectively disables contracts for
// this thread.
//=============================================================================================
ClrDebugState *CLRInitDebugState()
{
    // workaround!
    //
    // The existing Fls apis didn't provide the support we need and adding support cleanly is
    // messy because of the brittleness of IExecutionEngine.
    //
    // To understand this function, you need to know that the Fls routines have special semantics
    // for the TlsIdx_ClrDebugState slot:
    //
    //  - FlsSetValue will never throw. If it fails due to OOM on creation of the slot storage,
    //    it will silently bail. Thus, we must do a confirming FlsGetValue before we can conclude
    //    that the SetValue succeeded.
    //
    //  - FlsAssociateCallback will not complain about multiple sets of the callback.
    //
    //  - The mscorwks implemention of FlsAssociateCallback will ignore the passed in value
    //    and use the version of FreeClrDebugState compiled into mscorwks. This is needed to
    //    avoid dangling pointer races on shutdown.


    // This is our global "bad" debug state that thread use when they OOM on CLRInitDebugState.
    // We really only need to initialize it once but initializing each time is convenient
    // and has low perf impact.
    static ClrDebugState gBadClrDebugState;
    gBadClrDebugState.ViolationMaskSet( AllViolation );
    // SO_INFRASTRUCTURE_CODE() Macro to remove SO infrastructure code during build
    SO_INFRASTRUCTURE_CODE(gBadClrDebugState.BeginSOTolerant();)
Esempio n. 3
0
// Fls callback to deallocate ClrDebugState when our FLS block goes away.
void FreeClrDebugState(LPVOID pTlsData)
{
#ifdef _DEBUG
    ClrDebugState *pClrDebugState = (ClrDebugState*)pTlsData;

    // Make sure the ClrDebugState was initialized by a compatible version of
    // utilcode.lib. If it was initialized by an older version, we just let it leak.
    if (pClrDebugState && (pClrDebugState->ViolationMask() & CanFreeMe) && !(pClrDebugState->ViolationMask() & BadDebugState))
    {
#undef HeapFree
#undef GetProcessHeap
        
        // Since "!(pClrDebugState->m_violationmask & BadDebugState)", we know we have
        // a valid m_pLockData
        _ASSERTE(pClrDebugState->GetDbgStateLockData() != NULL);
        ::HeapFree (GetProcessHeap(), 0, pClrDebugState->GetDbgStateLockData());

        ::HeapFree (GetProcessHeap(), 0, pClrDebugState);
#define HeapFree(hHeap, dwFlags, lpMem) Dont_Use_HeapFree(hHeap, dwFlags, lpMem)
#define GetProcessHeap() Dont_Use_GetProcessHeap()
    }
#endif //_DEBUG
}
Esempio n. 4
0
//
// EnsureSOTolerant ASSERTS if we are not in an SO-tolerant mode
//
void EnsureSOTolerant()
{
    ClrDebugState *pClrDebugState = GetClrDebugState();
    _ASSERTE(! pClrDebugState || pClrDebugState->IsSOTolerant());
}