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)
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "bindings/v8/ScriptSourceCode.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/inspector/InspectorInstrumentation.h"
33591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "core/workers/DedicatedWorkerGlobalScope.h"
347757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "core/workers/WorkerClients.h"
357757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "core/workers/WorkerThreadStartupData.h"
3653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webdatabase/DatabaseManager.h"
3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webdatabase/DatabaseTask.h"
381e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/PlatformThreadData.h"
3951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "platform/weborigin/KURL.h"
405267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "public/platform/Platform.h"
415267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "public/platform/WebWorkerRunLoop.h"
42521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "wtf/Noncopyable.h"
43521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "wtf/text/WTFString.h"
44521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
45521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include <utility>
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
49926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)static Mutex& threadSetMutex()
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return mutex;
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
55926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)static HashSet<WorkerThread*>& workerThreads()
56926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
57926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    DEFINE_STATIC_LOCAL(HashSet<WorkerThread*>, threads, ());
58926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return threads;
59926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)unsigned WorkerThread::workerThreadCount()
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
63926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    MutexLocker lock(threadSetMutex());
64926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return workerThreads().size();
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
677757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochWorkerThread::WorkerThread(WorkerLoaderProxy& workerLoaderProxy, WorkerReportingProxy& workerReportingProxy, PassOwnPtr<WorkerThreadStartupData> startupData)
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_threadID(0)
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_workerLoaderProxy(workerLoaderProxy)
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_workerReportingProxy(workerReportingProxy)
717757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    , m_startupData(startupData)
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_notificationClient(0)
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
74926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    MutexLocker lock(threadSetMutex());
75926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    workerThreads().add(this);
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WorkerThread::~WorkerThread()
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
80926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    MutexLocker lock(threadSetMutex());
81926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(workerThreads().contains(this));
82926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    workerThreads().remove(this);
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool WorkerThread::start()
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Mutex protection is necessary to ensure that m_threadID is initialized when the thread starts.
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    MutexLocker lock(m_threadCreationMutex);
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_threadID)
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_threadID = createThread(WorkerThread::workerThreadStart, this, "WebCore: Worker");
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_threadID;
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void WorkerThread::workerThreadStart(void* thread)
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static_cast<WorkerThread*>(thread)->workerThread();
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void WorkerThread::workerThread()
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1057757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    KURL scriptURL = m_startupData->m_scriptURL;
1067757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    String sourceCode = m_startupData->m_sourceCode;
1077757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    WorkerThreadStartMode startMode = m_startupData->m_startMode;
1087757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        MutexLocker lock(m_threadCreationMutex);
1117757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
1127757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        m_workerGlobalScope = createWorkerGlobalScope(m_startupData.release());
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_runLoop.terminated()) {
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // The worker was terminated before the thread had a chance to run. Since the context didn't exist yet,
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // forbidExecution() couldn't be called from stop().
117591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            m_workerGlobalScope->script()->forbidExecution();
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The corresponding call to didStopWorkerRunLoop is in
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // ~WorkerScriptController.
12251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    blink::Platform::current()->didStartWorkerRunLoop(blink::WebWorkerRunLoop(&m_runLoop));
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
124591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    WorkerScriptController* script = m_workerGlobalScope->script();
1257757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    InspectorInstrumentation::willEvaluateWorkerScript(workerGlobalScope(), startMode);
1267757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    script->evaluate(ScriptSourceCode(sourceCode, scriptURL));
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    runEventLoop();
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ThreadIdentifier threadID = m_threadID;
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
132591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT(m_workerGlobalScope->hasOneRef());
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The below assignment will destroy the context, which will in turn notify messaging proxy.
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We cannot let any objects survive past thread exit, because no other thread will run GC or otherwise destroy them.
136591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    m_workerGlobalScope = 0;
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1381e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // Clean up PlatformThreadData before WTF::WTFThreadData goes away!
1391e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    PlatformThreadData::current().destroy();
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The thread object may be already destroyed from notification now, don't try to access "this".
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    detachThread(threadID);
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void WorkerThread::runEventLoop()
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Does not return until terminated.
148591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    m_runLoop.run(m_workerGlobalScope.get());
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1511e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)class WorkerThreadShutdownFinishTask : public ExecutionContextTask {
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static PassOwnPtr<WorkerThreadShutdownFinishTask> create()
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return adoptPtr(new WorkerThreadShutdownFinishTask());
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1581e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    virtual void performTask(ExecutionContext *context)
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
160591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context);
161591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        workerGlobalScope->clearInspector();
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // It's not safe to call clearScript until all the cleanup tasks posted by functions initiated by WorkerThreadShutdownStartTask have completed.
163591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        workerGlobalScope->clearScript();
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    virtual bool isCleanupTask() const { return true; }
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1691e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)class WorkerThreadShutdownStartTask : public ExecutionContextTask {
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static PassOwnPtr<WorkerThreadShutdownStartTask> create()
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return adoptPtr(new WorkerThreadShutdownStartTask());
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1761e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    virtual void performTask(ExecutionContext *context)
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
178591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context);
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: Should we stop the databases as part of stopActiveDOMObjects() below?
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        DatabaseTaskSynchronizer cleanupSync;
182591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        DatabaseManager::manager().stopDatabases(workerGlobalScope, &cleanupSync);
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
184591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        workerGlobalScope->stopActiveDOMObjects();
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
186591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        workerGlobalScope->notifyObserversOfStop();
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Event listeners would keep DOMWrapperWorld objects alive for too long. Also, they have references to JS objects,
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // which become dangling once Heap is destroyed.
190591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        workerGlobalScope->removeAllEventListeners();
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // We wait for the database thread to clean up all its stuff so that we
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // can do more stringent leak checks as we exit.
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        cleanupSync.waitForTaskCompletion();
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Stick a shutdown command at the end of the queue, so that we deal
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // with all the cleanup tasks the databases post first.
198591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        workerGlobalScope->postTask(WorkerThreadShutdownFinishTask::create());
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    virtual bool isCleanupTask() const { return true; }
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void WorkerThread::stop()
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Mutex protection is necessary because stop() can be called before the context is fully created.
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    MutexLocker lock(m_threadCreationMutex);
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (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.
210591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (m_workerGlobalScope) {
211591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        m_workerGlobalScope->script()->scheduleExecutionTermination();
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
213591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        DatabaseManager::manager().interruptAllDatabasesForContext(m_workerGlobalScope.get());
214926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        m_runLoop.postTaskAndTerminate(WorkerThreadShutdownStartTask::create());
215926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_runLoop.terminate();
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
22093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)bool WorkerThread::isCurrentThread() const
22193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
22293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    return m_threadID == currentThread();
22393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}
22493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
2251e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)class ReleaseFastMallocFreeMemoryTask : public ExecutionContextTask {
2261e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    virtual void performTask(ExecutionContext*) OVERRIDE { WTF::releaseFastMallocFreeMemory(); }
227926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
228926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
229926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void WorkerThread::releaseFastMallocFreeMemoryInAllThreads()
230926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
231926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    MutexLocker lock(threadSetMutex());
232926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    HashSet<WorkerThread*>& threads = workerThreads();
233926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    HashSet<WorkerThread*>::iterator end = threads.end();
234926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    for (HashSet<WorkerThread*>::iterator it = threads.begin(); it != end; ++it)
235926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        (*it)->runLoop().postTask(adoptPtr(new ReleaseFastMallocFreeMemoryTask));
236926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
237926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore
239