void BlockAllocator::blockFreeingThreadMain() { size_t currentNumberOfEmptyRegions; while (!m_blockFreeingThreadShouldQuit) { // Generally wait for one second before scavenging free blocks. This // may return early, particularly when we're being asked to quit. waitForRelativeTime(1.0); if (m_blockFreeingThreadShouldQuit) break; if (m_isCurrentlyAllocating) { m_isCurrentlyAllocating = false; continue; } // Sleep until there is actually work to do rather than waking up every second to check. { MutexLocker locker(m_emptyRegionConditionLock); SpinLockHolder regionLocker(&m_regionLock); while (!m_numberOfEmptyRegions && !m_blockFreeingThreadShouldQuit) { m_regionLock.Unlock(); m_emptyRegionCondition.wait(m_emptyRegionConditionLock); m_regionLock.Lock(); } currentNumberOfEmptyRegions = m_numberOfEmptyRegions; } size_t desiredNumberOfEmptyRegions = currentNumberOfEmptyRegions / 2; while (!m_blockFreeingThreadShouldQuit) { Region* region; { SpinLockHolder locker(&m_regionLock); if (m_numberOfEmptyRegions <= desiredNumberOfEmptyRegions) region = 0; else { region = m_emptyRegions.removeHead(); RELEASE_ASSERT(region); m_numberOfEmptyRegions--; } } if (!region) break; delete region; } } }
void BlockAllocator::blockFreeingThreadMain() { while (!m_blockFreeingThreadShouldQuit) { // Generally wait for one second before scavenging free blocks. This // may return early, particularly when we're being asked to quit. waitForRelativeTime(1.0); if (m_blockFreeingThreadShouldQuit) break; if (m_isCurrentlyAllocating) { m_isCurrentlyAllocating = false; continue; } // Now process the list of free blocks. Keep freeing until half of the // blocks that are currently on the list are gone. Assume that a size_t // field can be accessed atomically. size_t currentNumberOfFreeBlocks = m_numberOfFreeBlocks; if (!currentNumberOfFreeBlocks) continue; size_t desiredNumberOfFreeBlocks = currentNumberOfFreeBlocks / 2; while (!m_blockFreeingThreadShouldQuit) { MarkedBlock* block; { MutexLocker locker(m_freeBlockLock); if (m_numberOfFreeBlocks <= desiredNumberOfFreeBlocks) block = 0; else { // FIXME: How do we know this is a MarkedBlock? It could be a CopiedBlock. block = static_cast<MarkedBlock*>(m_freeBlocks.removeHead()); ASSERT(block); m_numberOfFreeBlocks--; } } if (!block) break; MarkedBlock::destroy(block); } } }