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; } }