2 * Copyright (C) 2012 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
29 #include "CopyVisitor.h"
30 #include "CopyVisitorInlines.h"
31 #include "GCThreadSharedData.h"
32 #include "SlotVisitor.h"
33 #include <wtf/MainThread.h>
34 #include <wtf/PassOwnPtr.h>
38 GCThread::GCThread(GCThreadSharedData
& shared
, SlotVisitor
* slotVisitor
, CopyVisitor
* copyVisitor
)
41 , m_slotVisitor(WTF::adoptPtr(slotVisitor
))
42 , m_copyVisitor(WTF::adoptPtr(copyVisitor
))
46 ThreadIdentifier
GCThread::threadID()
52 void GCThread::initializeThreadID(ThreadIdentifier threadID
)
55 m_threadID
= threadID
;
58 SlotVisitor
* GCThread::slotVisitor()
60 ASSERT(m_slotVisitor
);
61 return m_slotVisitor
.get();
64 CopyVisitor
* GCThread::copyVisitor()
66 ASSERT(m_copyVisitor
);
67 return m_copyVisitor
.get();
70 GCPhase
GCThread::waitForNextPhase()
72 MutexLocker
locker(m_shared
.m_phaseLock
);
73 while (m_shared
.m_gcThreadsShouldWait
)
74 m_shared
.m_phaseCondition
.wait(m_shared
.m_phaseLock
);
76 m_shared
.m_numberOfActiveGCThreads
--;
77 if (!m_shared
.m_numberOfActiveGCThreads
)
78 m_shared
.m_activityCondition
.signal();
80 while (m_shared
.m_currentPhase
== NoPhase
)
81 m_shared
.m_phaseCondition
.wait(m_shared
.m_phaseLock
);
82 m_shared
.m_numberOfActiveGCThreads
++;
83 return m_shared
.m_currentPhase
;
86 void GCThread::gcThreadMain()
89 #if ENABLE(PARALLEL_GC)
90 WTF::registerGCThread();
92 // Wait for the main thread to finish creating and initializing us. The main thread grabs this lock before
93 // creating this thread. We aren't guaranteed to have a valid threadID until the main thread releases this lock.
95 MutexLocker
locker(m_shared
.m_phaseLock
);
98 ParallelModeEnabler
enabler(*m_slotVisitor
);
99 while ((currentPhase
= waitForNextPhase()) != Exit
) {
100 // Note: Each phase is responsible for its own termination conditions. The comments below describe
101 // how each phase reaches termination.
102 switch (currentPhase
) {
104 m_slotVisitor
->drainFromShared(SlotVisitor::SlaveDrain
);
105 // GCThreads only return from drainFromShared() if the main thread sets the m_parallelMarkersShouldExit
106 // flag in the GCThreadSharedData. The only way the main thread sets that flag is if it realizes
107 // that all of the various subphases in Heap::markRoots() have been fully finished and there is
108 // no more marking work to do and all of the GCThreads are idle, meaning no more work can be generated.
111 // We don't have to call startCopying() because it's called for us on the main thread to avoid a
113 m_copyVisitor
->copyFromShared();
114 // We know we're done copying when we return from copyFromShared() because we would
115 // only do so if there were no more chunks of copying work left to do. When there is no
116 // more copying work to do, the main thread will wait in CopiedSpace::doneCopying() until
117 // all of the blocks that the GCThreads borrowed have been returned. doneCopying()
118 // returns our borrowed CopiedBlock, allowing the copying phase to finish.
119 m_copyVisitor
->doneCopying();
122 RELEASE_ASSERT_NOT_REACHED();
125 RELEASE_ASSERT_NOT_REACHED();
132 void GCThread::gcThreadStartFunc(void* data
)
134 GCThread
* thread
= static_cast<GCThread
*>(data
);
135 thread
->gcThreadMain();