v8threads.h revision 3fb3ca8c7ca439d408449a395897395c0faae8d1
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_; } 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 5844f0eee88ff00398ff7f715fab053374d808c90dSteve Block explicit ThreadState(ThreadManager* thread_manager); 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void AllocateSpace(); 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ThreadId id_; 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool terminate_on_restore_; 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char* data_; 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ThreadState* next_; 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ThreadState* previous_; 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ThreadManager* thread_manager_; 6944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 7044f0eee88ff00398ff7f715fab053374d808c90dSteve Block friend class ThreadManager; 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Defined in top.h 756ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass ThreadLocalTop; 766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 786ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass ThreadVisitor { 796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public: 806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ThreadLocalTop may be only available during this call. 818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch virtual void VisitThread(Isolate* isolate, ThreadLocalTop* top) = 0; 826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block protected: 846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block virtual ~ThreadVisitor() {} 856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}; 866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass ThreadManager { 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 9044f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Lock(); 9144f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Unlock(); 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9344f0eee88ff00398ff7f715fab053374d808c90dSteve Block void ArchiveThread(); 9444f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool RestoreThread(); 9544f0eee88ff00398ff7f715fab053374d808c90dSteve Block void FreeThreadResources(); 9644f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool IsArchived(); 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9844f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Iterate(ObjectVisitor* v); 9944f0eee88ff00398ff7f715fab053374d808c90dSteve Block void IterateArchivedThreads(ThreadVisitor* v); 1008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch bool IsLockedByCurrentThread() { 1018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return mutex_owner_.Equals(ThreadId::Current()); 1028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ThreadId CurrentId(); 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch void TerminateExecution(ThreadId thread_id); 10744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 10844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Iterate over in-use states. 10944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ThreadState* FirstThreadStateInUse(); 11044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ThreadState* GetFreeThreadState(); 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 11344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ThreadManager(); 11444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ~ThreadManager(); 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void EagerlyArchiveThread(); 11744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 11844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Mutex* mutex_; 1198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ThreadId mutex_owner_; 1208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ThreadId lazily_archived_thread_; 12144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ThreadState* lazily_archived_thread_state_; 12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 12344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // In the following two lists there is always at least one object on the list. 12444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // The first object is a flying anchor that is only there to simplify linking 12544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // and unlinking. 12644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Head of linked list of free states. 12744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ThreadState* free_anchor_; 12844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Head of linked list of states in use. 12944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ThreadState* in_use_anchor_; 13044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 13144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate_; 13244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 13344f0eee88ff00398ff7f715fab053374d808c90dSteve Block friend class Isolate; 13444f0eee88ff00398ff7f715fab053374d808c90dSteve Block friend class ThreadState; 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The ContextSwitcher thread is used to schedule regular preemptions to 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// multiple running V8 threads. Generally it is necessary to call 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// StartPreemption if there is more than one thread running. If not, a single 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// JavaScript can take full control of V8 and not allow other threads to run. 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ContextSwitcher: public Thread { 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the preemption interval for the ContextSwitcher thread. 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static void StartPreemption(int every_n_ms); 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stop sending preemption requests to threads. 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static void StopPreemption(); 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Preempted thread needs to call back to the ContextSwitcher to acknowledge 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the handling of a preemption request. 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static void PreemptionReceived(); 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 1553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ContextSwitcher(Isolate* isolate, int every_n_ms); 1563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Isolate* isolate() const { return isolate_; } 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Run(); 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool keep_going_; 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int sleep_ms_; 1633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Isolate* isolate_; 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // V8_V8THREADS_H_ 169