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