Beispiel #1
0
void StressLog::Terminate(BOOL fProcessDetach) {
    STATIC_CONTRACT_NOTHROW;
    STATIC_CONTRACT_FORBID_FAULT;
    
    if (theLog.TLSslot != (unsigned int)TLS_OUT_OF_INDEXES) {
        theLog.facilitiesToLog = 0;

        StressLogLockHolder lockh(theLog.lock, FALSE);
        if (!fProcessDetach) {
            lockh.Acquire(); lockh.Release();       // The Enter() Leave() forces a memory barrier on weak memory model systems
                                    // we want all the other threads to notice that facilitiesToLog is now zero

                    // This is not strictly threadsafe, since there is no way of insuring when all the
                    // threads are out of logMsg.  In practice, since they can no longer enter logMsg
                    // and there are no blocking operations in logMsg, simply sleeping will insure
                    // that everyone gets out. 
            ClrSleepEx(2, FALSE);
            lockh.Acquire();    
        }

        // Free the log memory
        ThreadStressLog* ptr = theLog.logs;
        theLog.logs = 0;
        while(ptr != 0) {
            ThreadStressLog* tmp = ptr;
            ptr = ptr->next;
            delete tmp;
        }

        theLog.TLSslot = TLS_OUT_OF_INDEXES;
        if (!fProcessDetach) {
            lockh.Release();
        }
    }
#if !defined (STRESS_LOG_READONLY)    
    if (StressLogChunk::s_LogChunkHeap != NULL && StressLogChunk::s_LogChunkHeap != ClrGetProcessHeap ())
    {
        ClrHeapDestroy (StressLogChunk::s_LogChunkHeap);
    }
#endif //!STRESS_LOG_READONLY
}
// Called to initialise the allocation subsystem (the first time it's used).
void DbgAllocInit()
{
    STATIC_CONTRACT_NOTHROW;

 retry:

    // Try to get the exclusive right to initialize.
    if (InterlockedExchange(&g_HeapInitializing, 1) == 0) {

        // We're now in a critical section. Check whether the subsystem was
        // initialized in the meantime.
        if (g_HeapInitialized) {
            g_HeapInitializing = 0;
            return;
        }

        // Nobody beat us to it. Initialize the subsystem now (other potential
        // initializors are spinning on g_HeapInitializing).

        // Create the mutex used to synchronize all heap debugging operations.
        UnsafeInitializeCriticalSection(&g_AllocMutex);

        // Reset statistics.
        CDA_STATS_CLEAR();

        // Reset allocation size distribution buckets.
        memset (&g_AllocBuckets, 0, sizeof(g_AllocBuckets));
        g_LargeAllocs = 0;

        // Initialize the global serial number count. This is stamped into newly
        // allocated packet headers and then incremented as a way of uniquely
        // identifying allocations.
        g_NextSN = 1;

        // Initialize the pointers to the first and last packets in a chain of
        // live allocations (used to track all leaked packets at the end of a
        // run).
        g_AllocListFirst = NULL;
        g_AllocListLast = NULL;


        // See if we should be logging locking stuff
        g_DisplayLockInfo = DbgAllocReadRegistry("DisplayLockInfo") != 0;

        // Get setup from registry.
        g_DbgEnabled = DbgAllocReadRegistry("AllocDebug") != 0;
        if (g_DbgEnabled) {
            g_ConstantRecheck = DbgAllocReadRegistry("AllocRecheck") != 0;
            g_AllocGuard = DbgAllocReadRegistry("AllocGuard") != 0;
            g_PoisonPackets = DbgAllocReadRegistry("AllocPoison") != 0;
            g_FreeQueueSize = DbgAllocReadRegistry("AllocFreeQueueSize") != 0;
            g_LogDist = DbgAllocReadRegistry("AllocDist") != 0;
            g_LogStats = DbgAllocReadRegistry("AllocStats") != 0;
            g_DetectLeaks = DbgAllocReadRegistry("AllocLeakDetect") != 0;
            g_AssertOnLeaks = 0;
            g_BreakOnAlloc = DbgAllocReadRegistry("AllocBreakOnAllocEnable") != 0;
            g_BreakOnAllocNumber = DbgAllocReadRegistry("AllocBreakOnAllocNumber");
            g_UsePrivateHeap = DbgAllocReadRegistry("AllocUsePrivateHeap") != 0;
            g_ValidateHeap = DbgAllocReadRegistry("AllocValidateHeap") != 0;
            g_PagePerAlloc = DbgAllocReadRegistry("AllocPagePerAlloc") != 0;
            g_UsageByAllocator = DbgAllocReadRegistry("UsageByAllocator") != 0;

        }


        // Page per alloc mode isn't compatible with some heap functions and
        // guard bytes don't make any sense.
        if (g_PagePerAlloc) {
            g_UsePrivateHeap = false;
            g_ValidateHeap = false;
            g_AllocGuard = false;
        }

            g_HeapHandle = ClrGetProcessHeap();

        // Get the system page size.
        SYSTEM_INFO sysinfo;
        GetSystemInfo(&sysinfo);
        g_PageSize = sysinfo.dwPageSize;

        // If we have been asked to record the top allocators, initialize the
        // table to its empty state.
        if (g_UsageByAllocator) {
            g_TopAllocators = NULL;
            g_TopAllocatorsSlots = 0;
        }

        if (g_PoisonPackets) {
            if (g_FreeQueueSize == 0)
                g_FreeQueueSize = 8192;     // keep the last 8K free packets around
            g_AllocFreeQueueCur = 0;

            _ASSERTE( !"This is broken because ClrHeapAlloc allocates and this function is not reentrant" );
            g_AllocFreeQueue = (DbgAllocHeader ** )
                ClrHeapAlloc(g_HeapHandle, HEAP_ZERO_MEMORY, sizeof(DbgAllocHeader*)*g_FreeQueueSize);
            _ASSERTE(g_AllocFreeQueue);
        }

        // Initialization complete. Once we reset g_HeapInitializing to 0, any
        // other potential initializors can get in and see they have no work to
        // do.
        g_HeapInitialized = true;
        g_HeapInitializing = 0;
    } else {
        // Someone else is initializing, wait until they finish.
        ClrSleepEx(0, FALSE);
        goto retry;
    }
}