1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2008 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_V8THREADS_H_ 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_V8THREADS_H_ 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ThreadState { 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns NULL after the last one. 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ThreadState* Next(); 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block enum List {FREE_LIST, IN_USE_LIST}; 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void LinkInto(List list); 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Unlink(); 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Id of thread. 468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch void set_id(ThreadId id) { id_ = id; } 478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ThreadId id() { return id_; } 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Should the thread be terminated when it is restored? 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool terminate_on_restore() { return terminate_on_restore_; } 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void set_terminate_on_restore(bool terminate_on_restore) { 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block terminate_on_restore_ = terminate_on_restore; 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get data area for archiving a thread. 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char* data() { return data_; } 57589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 5944f0eee88ff00398ff7f715fab053374d808c90dSteve Block explicit ThreadState(ThreadManager* thread_manager); 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AllocateSpace(); 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ThreadId id_; 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool terminate_on_restore_; 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char* data_; 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ThreadState* next_; 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ThreadState* previous_; 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ThreadManager* thread_manager_; 7044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 7144f0eee88ff00398ff7f715fab053374d808c90dSteve Block friend class ThreadManager; 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 75692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch// Defined in isolate.h. 766ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass ThreadLocalTop; 776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 796ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass ThreadVisitor { 806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public: 816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ThreadLocalTop may be only available during this call. 828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch virtual void VisitThread(Isolate* isolate, ThreadLocalTop* top) = 0; 836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block protected: 856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block virtual ~ThreadVisitor() {} 866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}; 876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass ThreadManager { 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 9144f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Lock(); 9244f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Unlock(); 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9444f0eee88ff00398ff7f715fab053374d808c90dSteve Block void ArchiveThread(); 9544f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool RestoreThread(); 9644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void FreeThreadResources(); 9744f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool IsArchived(); 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9944f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Iterate(ObjectVisitor* v); 10044f0eee88ff00398ff7f715fab053374d808c90dSteve Block void IterateArchivedThreads(ThreadVisitor* v); 1018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch bool IsLockedByCurrentThread() { 1028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return mutex_owner_.Equals(ThreadId::Current()); 1038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ThreadId CurrentId(); 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch void TerminateExecution(ThreadId thread_id); 10844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 10944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Iterate over in-use states. 11044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ThreadState* FirstThreadStateInUse(); 11144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ThreadState* GetFreeThreadState(); 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 11444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ThreadManager(); 11544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ~ThreadManager(); 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11744f0eee88ff00398ff7f715fab053374d808c90dSteve Block void EagerlyArchiveThread(); 11844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 11944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Mutex* mutex_; 1208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ThreadId mutex_owner_; 1218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ThreadId lazily_archived_thread_; 12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ThreadState* lazily_archived_thread_state_; 12344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 12444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // In the following two lists there is always at least one object on the list. 12544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // The first object is a flying anchor that is only there to simplify linking 12644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // and unlinking. 12744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Head of linked list of free states. 12844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ThreadState* free_anchor_; 12944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Head of linked list of states in use. 13044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ThreadState* in_use_anchor_; 13144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 13244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate_; 13344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 13444f0eee88ff00398ff7f715fab053374d808c90dSteve Block friend class Isolate; 13544f0eee88ff00398ff7f715fab053374d808c90dSteve Block friend class ThreadState; 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The ContextSwitcher thread is used to schedule regular preemptions to 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// multiple running V8 threads. Generally it is necessary to call 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// StartPreemption if there is more than one thread running. If not, a single 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// JavaScript can take full control of V8 and not allow other threads to run. 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ContextSwitcher: public Thread { 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the preemption interval for the ContextSwitcher thread. 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static void StartPreemption(int every_n_ms); 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stop sending preemption requests to threads. 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static void StopPreemption(); 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Preempted thread needs to call back to the ContextSwitcher to acknowledge 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the handling of a preemption request. 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static void PreemptionReceived(); 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 1563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ContextSwitcher(Isolate* isolate, int every_n_ms); 1573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Isolate* isolate() const { return isolate_; } 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Run(); 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool keep_going_; 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int sleep_ms_; 1643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Isolate* isolate_; 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // V8_V8THREADS_H_ 170