15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2008 Apple Inc. All Rights Reserved. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met: 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer. 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer in the 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * documentation and/or other materials provided with the distribution. 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/workers/WorkerThread.h" 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 31197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ScriptSourceCode.h" 32e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#include "core/dom/Microtask.h" 3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/inspector/InspectorInstrumentation.h" 34c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "core/inspector/WorkerInspectorController.h" 35591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "core/workers/DedicatedWorkerGlobalScope.h" 367757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "core/workers/WorkerClients.h" 3709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/workers/WorkerReportingProxy.h" 387757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "core/workers/WorkerThreadStartupData.h" 391e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/PlatformThreadData.h" 40c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "platform/Task.h" 41c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "platform/ThreadTimers.h" 42a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include "platform/heap/ThreadState.h" 4351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "platform/weborigin/KURL.h" 445267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "public/platform/Platform.h" 45c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "public/platform/WebThread.h" 4609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "public/platform/WebWaitableEvent.h" 475267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "public/platform/WebWorkerRunLoop.h" 48521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "wtf/Noncopyable.h" 49521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "wtf/text/WTFString.h" 50521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 51521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include <utility> 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 53c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 54c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 55c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace { 56c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)const int64 kShortIdleHandlerDelayMs = 1000; 57c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)const int64 kLongIdleHandlerDelayMs = 10*1000; 58e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) 59e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)class MicrotaskRunner : public WebThread::TaskObserver { 60e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)public: 61e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) virtual void willProcessTask() OVERRIDE { } 62e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) virtual void didProcessTask() OVERRIDE 63e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) { 64e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) Microtask::performCheckpoint(); 65e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) } 66e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)}; 67e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) 68e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)} // namespace 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 70926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)static Mutex& threadSetMutex() 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return mutex; 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 76926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)static HashSet<WorkerThread*>& workerThreads() 77926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){ 78926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) DEFINE_STATIC_LOCAL(HashSet<WorkerThread*>, threads, ()); 79926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return threads; 80926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)} 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)unsigned WorkerThread::workerThreadCount() 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 84926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) MutexLocker lock(threadSetMutex()); 85926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return workerThreads().size(); 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 88c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)class WorkerSharedTimer : public SharedTimer { 89c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)public: 90c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) explicit WorkerSharedTimer(WorkerThread* workerThread) 91c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) : m_workerThread(workerThread) 92c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) , m_nextFireTime(0.0) 93c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) , m_running(false) 94c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) { } 95c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 96c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) typedef void (*SharedTimerFunction)(); 97c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) virtual void setFiredFunction(SharedTimerFunction func) 98c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) { 99c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_sharedTimerFunction = func; 100c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (!m_sharedTimerFunction) 101c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_nextFireTime = 0.0; 102c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 103c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 104c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) virtual void setFireInterval(double interval) 105c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) { 106c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) ASSERT(m_sharedTimerFunction); 107c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 108c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // See BlinkPlatformImpl::setSharedTimerFireInterval for explanation of 109c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // why ceil is used in the interval calculation. 110c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) int64 delay = static_cast<int64>(ceil(interval * 1000)); 111c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 112c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (delay < 0) { 113c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) delay = 0; 114c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_nextFireTime = 0.0; 115c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 116c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 117c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_running = true; 118c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_nextFireTime = currentTime() + interval; 119c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_workerThread->postDelayedTask(createSameThreadTask(&WorkerSharedTimer::OnTimeout, this), delay); 120c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 121c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 122c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) virtual void stop() 123c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) { 124c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_running = false; 125c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 126c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 127c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) double nextFireTime() { return m_nextFireTime; } 128c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 129c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)private: 130c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) void OnTimeout() 131c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) { 132c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) ASSERT(m_workerThread->workerGlobalScope()); 133c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (m_sharedTimerFunction && m_running && !m_workerThread->workerGlobalScope()->isClosing()) 134c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_sharedTimerFunction(); 135c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 136c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 137c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) WorkerThread* m_workerThread; 138c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) SharedTimerFunction m_sharedTimerFunction; 139c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) double m_nextFireTime; 140c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) bool m_running; 141c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}; 142c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 143c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)class WorkerThreadTask : public blink::WebThread::Task { 144c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) WTF_MAKE_NONCOPYABLE(WorkerThreadTask); WTF_MAKE_FAST_ALLOCATED; 145c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)public: 146c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) static PassOwnPtr<WorkerThreadTask> create(const WorkerThread& workerThread, PassOwnPtr<ExecutionContextTask> task, bool isInstrumented) 147c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) { 148c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return adoptPtr(new WorkerThreadTask(workerThread, task, isInstrumented)); 149c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 150c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 151c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) virtual ~WorkerThreadTask() { } 152c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 153c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) virtual void run() OVERRIDE 154c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) { 155c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) WorkerGlobalScope* workerGlobalScope = m_workerThread.workerGlobalScope(); 156c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // Tasks could be put on the message loop after the cleanup task, 157c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // ensure none of those are ran. 158c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (!workerGlobalScope) 159c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return; 160c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 161c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (m_isInstrumented) 162c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) InspectorInstrumentation::willPerformExecutionContextTask(workerGlobalScope, m_task.get()); 163c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if ((!workerGlobalScope->isClosing() && !m_workerThread.terminated()) || m_task->isCleanupTask()) 164c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_task->performTask(workerGlobalScope); 165c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (m_isInstrumented) 166c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) InspectorInstrumentation::didPerformExecutionContextTask(workerGlobalScope); 167c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 168c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 169c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)private: 170c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) WorkerThreadTask(const WorkerThread& workerThread, PassOwnPtr<ExecutionContextTask> task, bool isInstrumented) 171c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) : m_workerThread(workerThread) 172c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) , m_task(task) 173c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) , m_isInstrumented(isInstrumented) 174c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) { 175c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (m_isInstrumented) 176c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_isInstrumented = !m_task->taskNameForInstrumentation().isEmpty(); 177c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (m_isInstrumented) 178c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) InspectorInstrumentation::didPostExecutionContextTask(m_workerThread.workerGlobalScope(), m_task.get()); 179c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 180c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 181c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) const WorkerThread& m_workerThread; 182c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) OwnPtr<ExecutionContextTask> m_task; 183c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) bool m_isInstrumented; 184c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}; 185c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 186c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)class RunDebuggerQueueTask FINAL : public ExecutionContextTask { 187c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)public: 188c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) static PassOwnPtr<RunDebuggerQueueTask> create(WorkerThread* thread) 189c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) { 190c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return adoptPtr(new RunDebuggerQueueTask(thread)); 191c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 192c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) virtual void performTask(ExecutionContext* context) OVERRIDE 193c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) { 194c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) ASSERT(context->isWorkerGlobalScope()); 195c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_thread->runDebuggerTask(WorkerThread::DontWaitForMessage); 196c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 197c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 198c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)private: 199c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) explicit RunDebuggerQueueTask(WorkerThread* thread) : m_thread(thread) { } 200c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 201c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) WorkerThread* m_thread; 202c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}; 203c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 204d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)WorkerThread::WorkerThread(WorkerLoaderProxy& workerLoaderProxy, WorkerReportingProxy& workerReportingProxy, PassOwnPtrWillBeRawPtr<WorkerThreadStartupData> startupData) 205c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) : m_terminated(false) 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_workerLoaderProxy(workerLoaderProxy) 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_workerReportingProxy(workerReportingProxy) 2087757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch , m_startupData(startupData) 20909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) , m_shutdownEvent(adoptPtr(blink::Platform::current()->createWaitableEvent())) 2107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci , m_terminationEvent(adoptPtr(blink::Platform::current()->createWaitableEvent())) 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 212926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) MutexLocker lock(threadSetMutex()); 213926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) workerThreads().add(this); 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WorkerThread::~WorkerThread() 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 218926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) MutexLocker lock(threadSetMutex()); 219926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) ASSERT(workerThreads().contains(this)); 220926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) workerThreads().remove(this); 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 223c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThread::start() 2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 225c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (m_thread) 226c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return; 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_thread = WebThreadSupportingGC::create("WebCore: Worker"); 229c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_thread->postTask(new Task(WTF::bind(&WorkerThread::initialize, this))); 2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 232c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThread::interruptAndDispatchInspectorCommands() 2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 234c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) MutexLocker locker(m_workerInspectorControllerMutex); 235c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (m_workerInspectorController) 236c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_workerInspectorController->interruptAndDispatchInspectorCommands(); 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2397242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciPlatformThreadId WorkerThread::platformThreadId() const 2407242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{ 2417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci if (!m_thread) 2427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci return 0; 2437242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci return m_thread->platformThread().threadId(); 2447242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci} 2457242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 246c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThread::initialize() 2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2487757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch KURL scriptURL = m_startupData->m_scriptURL; 2497757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch String sourceCode = m_startupData->m_sourceCode; 2507757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch WorkerThreadStartMode startMode = m_startupData->m_startMode; 2517757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) MutexLocker lock(m_threadCreationMutex); 254c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 255e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) // The worker was terminated before the thread had a chance to run. 256e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) if (m_terminated) { 257e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) // Notify the proxy that the WorkerGlobalScope has been disposed of. 258e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) // This can free this thread object, hence it must not be touched afterwards. 259e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) m_workerReportingProxy.workerThreadTerminated(); 260e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) return; 261e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) } 262e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) 263e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) m_microtaskRunner = adoptPtr(new MicrotaskRunner); 264e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) m_thread->addTaskObserver(m_microtaskRunner.get()); 2657242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_thread->attachGC(); 2667757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch m_workerGlobalScope = createWorkerGlobalScope(m_startupData.release()); 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 268c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_sharedTimer = adoptPtr(new WorkerSharedTimer(this)); 269c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) PlatformThreadData::current().threadTimers().setSharedTimer(m_sharedTimer.get()); 2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 271c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The corresponding call to didStopWorkerRunLoop is in 2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // ~WorkerScriptController. 274c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) blink::Platform::current()->didStartWorkerRunLoop(blink::WebWorkerRunLoop(this)); 2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 27609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // Notify proxy that a new WorkerGlobalScope has been created and started. 27709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get()); 27809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 279591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch WorkerScriptController* script = m_workerGlobalScope->script(); 280d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) if (!script->isExecutionForbidden()) 281d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) script->initializeContextIfNeeded(); 2827757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch InspectorInstrumentation::willEvaluateWorkerScript(workerGlobalScope(), startMode); 2837757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch script->evaluate(ScriptSourceCode(sourceCode, scriptURL)); 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 285c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) postInitialize(); 286c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 287c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) postDelayedTask(createSameThreadTask(&WorkerThread::idleHandler, this), kShortIdleHandlerDelayMs); 288c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} 289c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 290c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThread::cleanup() 291c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){ 2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 29310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch // This should be called before we start the shutdown procedure. 29410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch workerReportingProxy().willDestroyWorkerGlobalScope(); 29510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The below assignment will destroy the context, which will in turn notify messaging proxy. 2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We cannot let any objects survive past thread exit, because no other thread will run GC or otherwise destroy them. 298d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // If Oilpan is enabled, we detach of the context/global scope, with the final heap cleanup below sweeping it out. 29910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch#if !ENABLE(OILPAN) 300d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ASSERT(m_workerGlobalScope->hasOneRef()); 301d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#endif 30210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch m_workerGlobalScope->dispose(); 303d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_workerGlobalScope = nullptr; 3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3057242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_thread->detachGC(); 30609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 307e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) m_thread->removeTaskObserver(m_microtaskRunner.get()); 308e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) m_microtaskRunner = nullptr; 309c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 31043e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) // Notify the proxy that the WorkerGlobalScope has been disposed of. 31143e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) // This can free this thread object, hence it must not be touched afterwards. 312e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) workerReportingProxy().workerThreadTerminated(); 31343e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) 3147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_terminationEvent->signal(); 3157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 3161e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) // Clean up PlatformThreadData before WTF::WTFThreadData goes away! 3171e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) PlatformThreadData::current().destroy(); 3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3201e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)class WorkerThreadShutdownFinishTask : public ExecutionContextTask { 3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public: 3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static PassOwnPtr<WorkerThreadShutdownFinishTask> create() 3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return adoptPtr(new WorkerThreadShutdownFinishTask()); 3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3271e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) virtual void performTask(ExecutionContext *context) 3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 329591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context); 330591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch workerGlobalScope->clearInspector(); 3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // It's not safe to call clearScript until all the cleanup tasks posted by functions initiated by WorkerThreadShutdownStartTask have completed. 332591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch workerGlobalScope->clearScript(); 333c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) workerGlobalScope->thread()->m_thread->postTask(new Task(WTF::bind(&WorkerThread::cleanup, workerGlobalScope->thread()))); 3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) virtual bool isCleanupTask() const { return true; } 3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}; 3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3391e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)class WorkerThreadShutdownStartTask : public ExecutionContextTask { 3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public: 3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static PassOwnPtr<WorkerThreadShutdownStartTask> create() 3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return adoptPtr(new WorkerThreadShutdownStartTask()); 3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3461e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) virtual void performTask(ExecutionContext *context) 3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 348591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context); 3495d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) workerGlobalScope->stopFetch(); 350591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch workerGlobalScope->stopActiveDOMObjects(); 351c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) PlatformThreadData::current().threadTimers().setSharedTimer(nullptr); 3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Event listeners would keep DOMWrapperWorld objects alive for too long. Also, they have references to JS objects, 3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // which become dangling once Heap is destroyed. 355591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch workerGlobalScope->removeAllEventListeners(); 3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Stick a shutdown command at the end of the queue, so that we deal 3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // with all the cleanup tasks the databases post first. 359591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch workerGlobalScope->postTask(WorkerThreadShutdownFinishTask::create()); 3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) virtual bool isCleanupTask() const { return true; } 3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}; 3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void WorkerThread::stop() 3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 36709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // Prevent the deadlock between GC and an attempt to stop a thread. 36809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ThreadState::SafePointScope safePointScope(ThreadState::HeapPointersOnStack); 3697242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci stopInternal(); 3707242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci} 37109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 3727242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid WorkerThread::stopInShutdownSequence() 3737242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{ 3747242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci stopInternal(); 3757242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci} 3767242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 3777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid WorkerThread::stopInternal() 3787242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{ 379c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // Protect against this method and initialize() racing each other. 3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) MutexLocker lock(m_threadCreationMutex); 3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 382c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // If stop has already been called, just return. 383c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (m_terminated) 384c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return; 385e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) m_terminated = true; 386c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 38709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // Signal the thread to notify that the thread's stopping. 38809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (m_shutdownEvent) 38909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_shutdownEvent->signal(); 39009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 391c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (!m_workerGlobalScope) 392926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) return; 393c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 394c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // Ensure that tasks are being handled by thread event loop. If script execution weren't forbidden, a while(1) loop in JS could keep the thread alive forever. 395c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_workerGlobalScope->script()->scheduleExecutionTermination(); 396c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) InspectorInstrumentation::didKillAllExecutionContextTasks(m_workerGlobalScope.get()); 397c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_debuggerMessageQueue.kill(); 398c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) postTask(WorkerThreadShutdownStartTask::create()); 3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid WorkerThread::terminateAndWaitForAllWorkers() 4027242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{ 4037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Keep this lock to prevent WorkerThread instances from being destroyed. 4047242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci MutexLocker lock(threadSetMutex()); 4057242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci HashSet<WorkerThread*> threads = workerThreads(); 4067242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci for (HashSet<WorkerThread*>::iterator itr = threads.begin(); itr != threads.end(); ++itr) 4077242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci (*itr)->stopInShutdownSequence(); 4087242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 4097242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci for (HashSet<WorkerThread*>::iterator itr = threads.begin(); itr != threads.end(); ++itr) 4107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci (*itr)->terminationEvent()->wait(); 4117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci} 4127242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 41393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)bool WorkerThread::isCurrentThread() const 41493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){ 415c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return m_thread && m_thread->isCurrentThread(); 416c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} 417c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 418c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThread::idleHandler() 419c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){ 420c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) ASSERT(m_workerGlobalScope.get()); 421c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) int64 delay = kLongIdleHandlerDelayMs; 422c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 423c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // Do a script engine idle notification if the next event is distant enough. 424c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) const double kMinIdleTimespan = 0.3; 425c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (m_sharedTimer->nextFireTime() == 0.0 || m_sharedTimer->nextFireTime() > currentTime() + kMinIdleTimespan) { 426c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) bool hasMoreWork = !m_workerGlobalScope->idleNotification(); 427c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (hasMoreWork) 428c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) delay = kShortIdleHandlerDelayMs; 429c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 430c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 431c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) postDelayedTask(createSameThreadTask(&WorkerThread::idleHandler, this), delay); 432c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} 433c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 434c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThread::postTask(PassOwnPtr<ExecutionContextTask> task) 435c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){ 436c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_thread->postTask(WorkerThreadTask::create(*this, task, true).leakPtr()); 437c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} 438c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 439c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThread::postDelayedTask(PassOwnPtr<ExecutionContextTask> task, long long delayMs) 440c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){ 441c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_thread->postDelayedTask(WorkerThreadTask::create(*this, task, true).leakPtr(), delayMs); 442c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} 443c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 444c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThread::postDebuggerTask(PassOwnPtr<ExecutionContextTask> task) 445c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){ 446c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_debuggerMessageQueue.append(WorkerThreadTask::create(*this, task, false)); 447c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) postTask(RunDebuggerQueueTask::create(this)); 448c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} 449c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 450c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)MessageQueueWaitResult WorkerThread::runDebuggerTask(WaitMode waitMode) 451c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){ 452c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) ASSERT(isCurrentThread()); 453c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) MessageQueueWaitResult result; 454c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) double absoluteTime = MessageQueue<blink::WebThread::Task>::infiniteTime(); 455c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) OwnPtr<blink::WebThread::Task> task; 456c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) { 457c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (waitMode == DontWaitForMessage) 458c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) absoluteTime = 0.0; 459c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) ThreadState::SafePointScope safePointScope(ThreadState::NoHeapPointersOnStack); 460c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) task = m_debuggerMessageQueue.waitForMessageWithTimeout(result, absoluteTime); 461c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 462c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 463c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (result == MessageQueueMessageReceived) { 464c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) InspectorInstrumentation::willProcessTask(workerGlobalScope()); 465c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) task->run(); 466c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) InspectorInstrumentation::didProcessTask(workerGlobalScope()); 467c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 468c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 469c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return result; 470c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} 471c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 472c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThread::willEnterNestedLoop() 473c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){ 474c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) InspectorInstrumentation::willEnterNestedRunLoop(m_workerGlobalScope.get()); 475c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} 476c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 477c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThread::didLeaveNestedLoop() 478c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){ 479c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); 480c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} 481c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 482c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThread::setWorkerInspectorController(WorkerInspectorController* workerInspectorController) 483c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){ 484c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) MutexLocker locker(m_workerInspectorControllerMutex); 485c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_workerInspectorController = workerInspectorController; 48693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)} 48793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 488c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink 489