15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2009 Google Inc. All rights reserved. 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met: 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer. 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer in the 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * documentation and/or other materials provided with the distribution. 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 281e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/ThreadTimers.h" 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 301e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/PlatformThreadData.h" 31197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "platform/SharedTimer.h" 321e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/Timer.h" 331e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/TraceEvent.h" 34197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "platform/scheduler/Scheduler.h" 357757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/CurrentTime.h" 367757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/MainThread.h" 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 38c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Fire timers for this length of time, and then quit to let the run loop process user input events. 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 100ms is about a perceptable delay in UI, so use a half of that as a threshold. 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This is to prevent UI freeze when there are too many timers or machine performance is low. 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const double maxDurationOfFiringTimers = 0.050; 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Timers are created, started and fired on the same thread, and each thread has its own ThreadTimers 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// copy to keep the heap and a set of currently firing timers. 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static MainThreadSharedTimer* mainThreadSharedTimer() 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static MainThreadSharedTimer* timer = new MainThreadSharedTimer; 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return timer; 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ThreadTimers::ThreadTimers() 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : m_sharedTimer(0) 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_firingTimers(false) 57926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) , m_pendingSharedTimerFireTime(0) 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isMainThread()) 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setSharedTimer(mainThreadSharedTimer()); 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// A worker thread may initialize SharedTimer after some timers are created. 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Also, SharedTimer can be replaced with 0 before all timers are destroyed. 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ThreadTimers::setSharedTimer(SharedTimer* sharedTimer) 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_sharedTimer) { 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_sharedTimer->setFiredFunction(0); 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_sharedTimer->stop(); 70926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) m_pendingSharedTimerFireTime = 0; 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 7202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_sharedTimer = sharedTimer; 7402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (sharedTimer) { 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_sharedTimer->setFiredFunction(ThreadTimers::sharedTimerFired); 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) updateSharedTimer(); 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ThreadTimers::updateSharedTimer() 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_sharedTimer) 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 8502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 86926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (m_firingTimers || m_timerHeap.isEmpty()) { 87926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) m_pendingSharedTimerFireTime = 0; 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_sharedTimer->stop(); 89926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else { 90926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) double nextFireTime = m_timerHeap.first()->m_nextFireTime; 91926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) double currentMonotonicTime = monotonicallyIncreasingTime(); 92926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (m_pendingSharedTimerFireTime) { 93926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // No need to restart the timer if both the pending fire time and the new fire time are in the past. 94926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (m_pendingSharedTimerFireTime <= currentMonotonicTime && nextFireTime <= currentMonotonicTime) 95926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return; 9602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch } 97926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) m_pendingSharedTimerFireTime = nextFireTime; 987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_sharedTimer->setFireInterval(std::max(nextFireTime - currentMonotonicTime, 0.0)); 99926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ThreadTimers::sharedTimerFired() 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 104197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch TRACE_EVENT_SET_SAMPLING_STATE("blink", "BlinkInternal"); 105591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Redirect to non-static method. 1071e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) PlatformThreadData::current().threadTimers().sharedTimerFiredInternal(); 108591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 109197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch TRACE_EVENT_SET_SAMPLING_STATE("blink", "Sleeping"); 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ThreadTimers::sharedTimerFiredInternal() 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Do a re-entrancy check. 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_firingTimers) 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_firingTimers = true; 118926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) m_pendingSharedTimerFireTime = 0; 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) double fireTime = monotonicallyIncreasingTime(); 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) double timeToQuit = fireTime + maxDurationOfFiringTimers; 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (!m_timerHeap.isEmpty() && m_timerHeap.first()->m_nextFireTime <= fireTime) { 124d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) TimerBase& timer = *m_timerHeap.first(); 125d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) timer.m_nextFireTime = 0; 126d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) timer.m_unalignedNextFireTime = 0; 127d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) timer.heapDeleteMin(); 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 129d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) double interval = timer.repeatInterval(); 130d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) timer.setNextFireTime(interval ? fireTime + interval : 0); 131d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 132d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) TRACE_EVENT2("blink", "ThreadTimers::sharedTimerFiredInternal", 133d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) "src_file", timer.location().fileName(), 134d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) "src_func", timer.location().functionName()); 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Once the timer has been fired, it may be deleted, so do nothing else with it after this point. 137d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) timer.fired(); 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Catch the case where the timer asked timers to fire in a nested event loop, or we are over time limit. 140197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch if (!m_firingTimers || timeToQuit < monotonicallyIncreasingTime() || (isMainThread() && Scheduler::shared()->shouldYieldForHighPriorityWork())) 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_firingTimers = false; 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) updateSharedTimer(); 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ThreadTimers::fireTimersInNestedEventLoop() 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Reset the reentrancy guard so the timers can fire again. 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_firingTimers = false; 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) updateSharedTimer(); 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 156c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 158