1// Copyright 2008 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_V8THREADS_H_
29#define V8_V8THREADS_H_
30
31namespace v8 {
32namespace internal {
33
34
35class ThreadState {
36 public:
37  // Returns NULL after the last one.
38  ThreadState* Next();
39
40  enum List {FREE_LIST, IN_USE_LIST};
41
42  void LinkInto(List list);
43  void Unlink();
44
45  // Id of thread.
46  void set_id(ThreadId id) { id_ = id; }
47  ThreadId id() { return id_; }
48
49  // Should the thread be terminated when it is restored?
50  bool terminate_on_restore() { return terminate_on_restore_; }
51  void set_terminate_on_restore(bool terminate_on_restore) {
52    terminate_on_restore_ = terminate_on_restore;
53  }
54
55  // Get data area for archiving a thread.
56  char* data() { return data_; }
57 private:
58  explicit ThreadState(ThreadManager* thread_manager);
59
60  void AllocateSpace();
61
62  ThreadId id_;
63  bool terminate_on_restore_;
64  char* data_;
65  ThreadState* next_;
66  ThreadState* previous_;
67
68  ThreadManager* thread_manager_;
69
70  friend class ThreadManager;
71};
72
73
74// Defined in top.h
75class ThreadLocalTop;
76
77
78class ThreadVisitor {
79 public:
80  // ThreadLocalTop may be only available during this call.
81  virtual void VisitThread(Isolate* isolate, ThreadLocalTop* top) = 0;
82
83 protected:
84  virtual ~ThreadVisitor() {}
85};
86
87
88class ThreadManager {
89 public:
90  void Lock();
91  void Unlock();
92
93  void ArchiveThread();
94  bool RestoreThread();
95  void FreeThreadResources();
96  bool IsArchived();
97
98  void Iterate(ObjectVisitor* v);
99  void IterateArchivedThreads(ThreadVisitor* v);
100  bool IsLockedByCurrentThread() {
101    return mutex_owner_.Equals(ThreadId::Current());
102  }
103
104  ThreadId CurrentId();
105
106  void TerminateExecution(ThreadId thread_id);
107
108  // Iterate over in-use states.
109  ThreadState* FirstThreadStateInUse();
110  ThreadState* GetFreeThreadState();
111
112 private:
113  ThreadManager();
114  ~ThreadManager();
115
116  void EagerlyArchiveThread();
117
118  Mutex* mutex_;
119  ThreadId mutex_owner_;
120  ThreadId lazily_archived_thread_;
121  ThreadState* lazily_archived_thread_state_;
122
123  // In the following two lists there is always at least one object on the list.
124  // The first object is a flying anchor that is only there to simplify linking
125  // and unlinking.
126  // Head of linked list of free states.
127  ThreadState* free_anchor_;
128  // Head of linked list of states in use.
129  ThreadState* in_use_anchor_;
130
131  Isolate* isolate_;
132
133  friend class Isolate;
134  friend class ThreadState;
135};
136
137
138// The ContextSwitcher thread is used to schedule regular preemptions to
139// multiple running V8 threads. Generally it is necessary to call
140// StartPreemption if there is more than one thread running. If not, a single
141// JavaScript can take full control of V8 and not allow other threads to run.
142class ContextSwitcher: public Thread {
143 public:
144  // Set the preemption interval for the ContextSwitcher thread.
145  static void StartPreemption(int every_n_ms);
146
147  // Stop sending preemption requests to threads.
148  static void StopPreemption();
149
150  // Preempted thread needs to call back to the ContextSwitcher to acknowledge
151  // the handling of a preemption request.
152  static void PreemptionReceived();
153
154 private:
155  explicit ContextSwitcher(Isolate* isolate, int every_n_ms);
156
157  void Run();
158
159  bool keep_going_;
160  int sleep_ms_;
161};
162
163} }  // namespace v8::internal
164
165#endif  // V8_V8THREADS_H_
166