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