blob: 26169b50be6c51c590737d003d3a924a14642d2d [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// 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#include "v8.h"
29
30#include "api.h"
31#include "bootstrapper.h"
32#include "debug.h"
33#include "execution.h"
34#include "v8threads.h"
35#include "regexp-stack.h"
36
37namespace v8 {
38
Steve Blocka7e24c12009-10-30 11:49:00 +000039
40// Track whether this V8 instance has ever called v8::Locker. This allows the
41// API code to verify that the lock is always held when V8 is being entered.
42bool Locker::active_ = false;
43
44
45// Constructor for the Locker object. Once the Locker is constructed the
Ben Murdoch257744e2011-11-30 15:57:28 +000046// current thread will be guaranteed to have the lock for a given isolate.
47Locker::Locker(v8::Isolate* isolate)
48 : has_lock_(false),
49 top_level_(false),
50 isolate_(reinterpret_cast<i::Isolate*>(isolate)) {
51 if (isolate_ == NULL) {
52 isolate_ = i::Isolate::GetDefaultIsolateForLocking();
53 }
Steve Blocka7e24c12009-10-30 11:49:00 +000054 // Record that the Locker has been used at least once.
55 active_ = true;
56 // Get the big lock if necessary.
Ben Murdoch257744e2011-11-30 15:57:28 +000057 if (!isolate_->thread_manager()->IsLockedByCurrentThread()) {
58 isolate_->thread_manager()->Lock();
Steve Blocka7e24c12009-10-30 11:49:00 +000059 has_lock_ = true;
Steve Block44f0eee2011-05-26 01:26:41 +010060
Steve Blocka7e24c12009-10-30 11:49:00 +000061 // Make sure that V8 is initialized. Archiving of threads interferes
62 // with deserialization by adding additional root pointers, so we must
63 // initialize here, before anyone can call ~Locker() or Unlocker().
Ben Murdoch257744e2011-11-30 15:57:28 +000064 if (!isolate_->IsInitialized()) {
65 isolate_->Enter();
Steve Blocka7e24c12009-10-30 11:49:00 +000066 V8::Initialize();
Ben Murdoch257744e2011-11-30 15:57:28 +000067 isolate_->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000068 }
Ben Murdoch257744e2011-11-30 15:57:28 +000069
Steve Blocka7e24c12009-10-30 11:49:00 +000070 // This may be a locker within an unlocker in which case we have to
71 // get the saved state for this thread and restore it.
Ben Murdoch257744e2011-11-30 15:57:28 +000072 if (isolate_->thread_manager()->RestoreThread()) {
Steve Blocka7e24c12009-10-30 11:49:00 +000073 top_level_ = false;
74 } else {
Ben Murdoch257744e2011-11-30 15:57:28 +000075 internal::ExecutionAccess access(isolate_);
76 isolate_->stack_guard()->ClearThread(access);
77 isolate_->stack_guard()->InitThread(access);
78 }
79 if (isolate_->IsDefaultIsolate()) {
80 // This only enters if not yet entered.
81 internal::Isolate::EnterDefaultIsolate();
Steve Blocka7e24c12009-10-30 11:49:00 +000082 }
83 }
Ben Murdoch257744e2011-11-30 15:57:28 +000084 ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
Steve Blocka7e24c12009-10-30 11:49:00 +000085}
86
87
Ben Murdoch257744e2011-11-30 15:57:28 +000088bool Locker::IsLocked(v8::Isolate* isolate) {
89 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
90 if (internal_isolate == NULL) {
91 internal_isolate = i::Isolate::GetDefaultIsolateForLocking();
92 }
93 return internal_isolate->thread_manager()->IsLockedByCurrentThread();
Steve Blocka7e24c12009-10-30 11:49:00 +000094}
95
96
97Locker::~Locker() {
Ben Murdoch257744e2011-11-30 15:57:28 +000098 ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
Steve Blocka7e24c12009-10-30 11:49:00 +000099 if (has_lock_) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000100 if (isolate_->IsDefaultIsolate()) {
101 isolate_->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +0000102 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000103 if (top_level_) {
104 isolate_->thread_manager()->FreeThreadResources();
105 } else {
106 isolate_->thread_manager()->ArchiveThread();
107 }
108 isolate_->thread_manager()->Unlock();
Steve Blocka7e24c12009-10-30 11:49:00 +0000109 }
110}
111
112
Ben Murdoch257744e2011-11-30 15:57:28 +0000113Unlocker::Unlocker(v8::Isolate* isolate)
114 : isolate_(reinterpret_cast<i::Isolate*>(isolate)) {
115 if (isolate_ == NULL) {
116 isolate_ = i::Isolate::GetDefaultIsolateForLocking();
117 }
118 ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
119 if (isolate_->IsDefaultIsolate()) {
120 isolate_->Exit();
121 }
122 isolate_->thread_manager()->ArchiveThread();
123 isolate_->thread_manager()->Unlock();
Steve Blocka7e24c12009-10-30 11:49:00 +0000124}
125
126
127Unlocker::~Unlocker() {
Ben Murdoch257744e2011-11-30 15:57:28 +0000128 ASSERT(!isolate_->thread_manager()->IsLockedByCurrentThread());
129 isolate_->thread_manager()->Lock();
130 isolate_->thread_manager()->RestoreThread();
131 if (isolate_->IsDefaultIsolate()) {
132 isolate_->Enter();
133 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000134}
135
136
137void Locker::StartPreemption(int every_n_ms) {
138 v8::internal::ContextSwitcher::StartPreemption(every_n_ms);
139}
140
141
142void Locker::StopPreemption() {
143 v8::internal::ContextSwitcher::StopPreemption();
144}
145
146
147namespace internal {
148
149
150bool ThreadManager::RestoreThread() {
Ben Murdoch257744e2011-11-30 15:57:28 +0000151 ASSERT(IsLockedByCurrentThread());
Steve Blocka7e24c12009-10-30 11:49:00 +0000152 // First check whether the current thread has been 'lazily archived', ie
153 // not archived at all. If that is the case we put the state storage we
154 // had prepared back in the free list, since we didn't need it after all.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100155 if (lazily_archived_thread_.Equals(ThreadId::Current())) {
156 lazily_archived_thread_ = ThreadId::Invalid();
Ben Murdoch257744e2011-11-30 15:57:28 +0000157 Isolate::PerIsolateThreadData* per_thread =
158 isolate_->FindPerThreadDataForThisThread();
159 ASSERT(per_thread != NULL);
160 ASSERT(per_thread->thread_state() == lazily_archived_thread_state_);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100161 lazily_archived_thread_state_->set_id(ThreadId::Invalid());
Steve Blocka7e24c12009-10-30 11:49:00 +0000162 lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST);
163 lazily_archived_thread_state_ = NULL;
Ben Murdoch257744e2011-11-30 15:57:28 +0000164 per_thread->set_thread_state(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000165 return true;
166 }
167
168 // Make sure that the preemption thread cannot modify the thread state while
169 // it is being archived or restored.
Steve Block44f0eee2011-05-26 01:26:41 +0100170 ExecutionAccess access(isolate_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000171
172 // If there is another thread that was lazily archived then we have to really
173 // archive it now.
174 if (lazily_archived_thread_.IsValid()) {
175 EagerlyArchiveThread();
176 }
Steve Block44f0eee2011-05-26 01:26:41 +0100177 Isolate::PerIsolateThreadData* per_thread =
Ben Murdoch257744e2011-11-30 15:57:28 +0000178 isolate_->FindPerThreadDataForThisThread();
Steve Block44f0eee2011-05-26 01:26:41 +0100179 if (per_thread == NULL || per_thread->thread_state() == NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000180 // This is a new thread.
Steve Block44f0eee2011-05-26 01:26:41 +0100181 isolate_->stack_guard()->InitThread(access);
Steve Blocka7e24c12009-10-30 11:49:00 +0000182 return false;
183 }
Steve Block44f0eee2011-05-26 01:26:41 +0100184 ThreadState* state = per_thread->thread_state();
Steve Blocka7e24c12009-10-30 11:49:00 +0000185 char* from = state->data();
Steve Block44f0eee2011-05-26 01:26:41 +0100186 from = isolate_->handle_scope_implementer()->RestoreThread(from);
187 from = isolate_->RestoreThread(from);
Ben Murdoch257744e2011-11-30 15:57:28 +0000188 from = Relocatable::RestoreState(isolate_, from);
Steve Blocka7e24c12009-10-30 11:49:00 +0000189#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Block44f0eee2011-05-26 01:26:41 +0100190 from = isolate_->debug()->RestoreDebug(from);
Steve Blocka7e24c12009-10-30 11:49:00 +0000191#endif
Steve Block44f0eee2011-05-26 01:26:41 +0100192 from = isolate_->stack_guard()->RestoreStackGuard(from);
193 from = isolate_->regexp_stack()->RestoreStack(from);
194 from = isolate_->bootstrapper()->RestoreState(from);
195 per_thread->set_thread_state(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000196 if (state->terminate_on_restore()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100197 isolate_->stack_guard()->TerminateExecution();
Steve Blocka7e24c12009-10-30 11:49:00 +0000198 state->set_terminate_on_restore(false);
199 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100200 state->set_id(ThreadId::Invalid());
Steve Blocka7e24c12009-10-30 11:49:00 +0000201 state->Unlink();
202 state->LinkInto(ThreadState::FREE_LIST);
203 return true;
204}
205
206
207void ThreadManager::Lock() {
208 mutex_->Lock();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100209 mutex_owner_ = ThreadId::Current();
Steve Blocka7e24c12009-10-30 11:49:00 +0000210 ASSERT(IsLockedByCurrentThread());
211}
212
213
214void ThreadManager::Unlock() {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100215 mutex_owner_ = ThreadId::Invalid();
Steve Blocka7e24c12009-10-30 11:49:00 +0000216 mutex_->Unlock();
217}
218
219
220static int ArchiveSpacePerThread() {
221 return HandleScopeImplementer::ArchiveSpacePerThread() +
Steve Block44f0eee2011-05-26 01:26:41 +0100222 Isolate::ArchiveSpacePerThread() +
Steve Blocka7e24c12009-10-30 11:49:00 +0000223#ifdef ENABLE_DEBUGGER_SUPPORT
224 Debug::ArchiveSpacePerThread() +
225#endif
226 StackGuard::ArchiveSpacePerThread() +
227 RegExpStack::ArchiveSpacePerThread() +
228 Bootstrapper::ArchiveSpacePerThread() +
229 Relocatable::ArchiveSpacePerThread();
230}
231
232
Steve Block44f0eee2011-05-26 01:26:41 +0100233ThreadState::ThreadState(ThreadManager* thread_manager)
Ben Murdoch8b112d22011-06-08 16:22:53 +0100234 : id_(ThreadId::Invalid()),
Steve Block44f0eee2011-05-26 01:26:41 +0100235 terminate_on_restore_(false),
236 next_(this),
237 previous_(this),
238 thread_manager_(thread_manager) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000239}
240
241
242void ThreadState::AllocateSpace() {
243 data_ = NewArray<char>(ArchiveSpacePerThread());
244}
245
246
247void ThreadState::Unlink() {
248 next_->previous_ = previous_;
249 previous_->next_ = next_;
250}
251
252
253void ThreadState::LinkInto(List list) {
254 ThreadState* flying_anchor =
Steve Block44f0eee2011-05-26 01:26:41 +0100255 list == FREE_LIST ? thread_manager_->free_anchor_
256 : thread_manager_->in_use_anchor_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000257 next_ = flying_anchor->next_;
258 previous_ = flying_anchor;
259 flying_anchor->next_ = this;
260 next_->previous_ = this;
261}
262
263
Steve Block44f0eee2011-05-26 01:26:41 +0100264ThreadState* ThreadManager::GetFreeThreadState() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000265 ThreadState* gotten = free_anchor_->next_;
266 if (gotten == free_anchor_) {
Steve Block44f0eee2011-05-26 01:26:41 +0100267 ThreadState* new_thread_state = new ThreadState(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000268 new_thread_state->AllocateSpace();
269 return new_thread_state;
270 }
271 return gotten;
272}
273
274
275// Gets the first in the list of archived threads.
Steve Block44f0eee2011-05-26 01:26:41 +0100276ThreadState* ThreadManager::FirstThreadStateInUse() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000277 return in_use_anchor_->Next();
278}
279
280
281ThreadState* ThreadState::Next() {
Steve Block44f0eee2011-05-26 01:26:41 +0100282 if (next_ == thread_manager_->in_use_anchor_) return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000283 return next_;
284}
285
286
287// Thread ids must start with 1, because in TLS having thread id 0 can't
288// be distinguished from not having a thread id at all (since NULL is
289// defined as 0.)
Steve Block44f0eee2011-05-26 01:26:41 +0100290ThreadManager::ThreadManager()
291 : mutex_(OS::CreateMutex()),
Ben Murdoch8b112d22011-06-08 16:22:53 +0100292 mutex_owner_(ThreadId::Invalid()),
293 lazily_archived_thread_(ThreadId::Invalid()),
Steve Block44f0eee2011-05-26 01:26:41 +0100294 lazily_archived_thread_state_(NULL),
295 free_anchor_(NULL),
296 in_use_anchor_(NULL) {
297 free_anchor_ = new ThreadState(this);
298 in_use_anchor_ = new ThreadState(this);
299}
300
301
302ThreadManager::~ThreadManager() {
303 // TODO(isolates): Destroy mutexes.
304}
Steve Blocka7e24c12009-10-30 11:49:00 +0000305
306
307void ThreadManager::ArchiveThread() {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100308 ASSERT(lazily_archived_thread_.Equals(ThreadId::Invalid()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000309 ASSERT(!IsArchived());
Ben Murdoch257744e2011-11-30 15:57:28 +0000310 ASSERT(IsLockedByCurrentThread());
Steve Block44f0eee2011-05-26 01:26:41 +0100311 ThreadState* state = GetFreeThreadState();
Steve Blocka7e24c12009-10-30 11:49:00 +0000312 state->Unlink();
Ben Murdoch257744e2011-11-30 15:57:28 +0000313 Isolate::PerIsolateThreadData* per_thread =
314 isolate_->FindOrAllocatePerThreadDataForThisThread();
315 per_thread->set_thread_state(state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100316 lazily_archived_thread_ = ThreadId::Current();
Steve Blocka7e24c12009-10-30 11:49:00 +0000317 lazily_archived_thread_state_ = state;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100318 ASSERT(state->id().Equals(ThreadId::Invalid()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000319 state->set_id(CurrentId());
Ben Murdoch8b112d22011-06-08 16:22:53 +0100320 ASSERT(!state->id().Equals(ThreadId::Invalid()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000321}
322
323
324void ThreadManager::EagerlyArchiveThread() {
Ben Murdoch257744e2011-11-30 15:57:28 +0000325 ASSERT(IsLockedByCurrentThread());
Steve Blocka7e24c12009-10-30 11:49:00 +0000326 ThreadState* state = lazily_archived_thread_state_;
327 state->LinkInto(ThreadState::IN_USE_LIST);
328 char* to = state->data();
329 // Ensure that data containing GC roots are archived first, and handle them
330 // in ThreadManager::Iterate(ObjectVisitor*).
Steve Block44f0eee2011-05-26 01:26:41 +0100331 to = isolate_->handle_scope_implementer()->ArchiveThread(to);
332 to = isolate_->ArchiveThread(to);
Ben Murdoch257744e2011-11-30 15:57:28 +0000333 to = Relocatable::ArchiveState(isolate_, to);
Steve Blocka7e24c12009-10-30 11:49:00 +0000334#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Block44f0eee2011-05-26 01:26:41 +0100335 to = isolate_->debug()->ArchiveDebug(to);
Steve Blocka7e24c12009-10-30 11:49:00 +0000336#endif
Steve Block44f0eee2011-05-26 01:26:41 +0100337 to = isolate_->stack_guard()->ArchiveStackGuard(to);
338 to = isolate_->regexp_stack()->ArchiveStack(to);
339 to = isolate_->bootstrapper()->ArchiveState(to);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100340 lazily_archived_thread_ = ThreadId::Invalid();
Steve Blocka7e24c12009-10-30 11:49:00 +0000341 lazily_archived_thread_state_ = NULL;
342}
343
344
345void ThreadManager::FreeThreadResources() {
Steve Block44f0eee2011-05-26 01:26:41 +0100346 isolate_->handle_scope_implementer()->FreeThreadResources();
347 isolate_->FreeThreadResources();
Steve Blocka7e24c12009-10-30 11:49:00 +0000348#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Block44f0eee2011-05-26 01:26:41 +0100349 isolate_->debug()->FreeThreadResources();
Steve Blocka7e24c12009-10-30 11:49:00 +0000350#endif
Steve Block44f0eee2011-05-26 01:26:41 +0100351 isolate_->stack_guard()->FreeThreadResources();
352 isolate_->regexp_stack()->FreeThreadResources();
353 isolate_->bootstrapper()->FreeThreadResources();
Steve Blocka7e24c12009-10-30 11:49:00 +0000354}
355
356
357bool ThreadManager::IsArchived() {
Ben Murdoch257744e2011-11-30 15:57:28 +0000358 Isolate::PerIsolateThreadData* data =
359 isolate_->FindPerThreadDataForThisThread();
Steve Block44f0eee2011-05-26 01:26:41 +0100360 return data != NULL && data->thread_state() != NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000361}
362
Steve Blocka7e24c12009-10-30 11:49:00 +0000363void ThreadManager::Iterate(ObjectVisitor* v) {
364 // Expecting no threads during serialization/deserialization
Steve Block44f0eee2011-05-26 01:26:41 +0100365 for (ThreadState* state = FirstThreadStateInUse();
Steve Blocka7e24c12009-10-30 11:49:00 +0000366 state != NULL;
367 state = state->Next()) {
368 char* data = state->data();
369 data = HandleScopeImplementer::Iterate(v, data);
Steve Block44f0eee2011-05-26 01:26:41 +0100370 data = isolate_->Iterate(v, data);
Steve Blocka7e24c12009-10-30 11:49:00 +0000371 data = Relocatable::Iterate(v, data);
372 }
373}
374
375
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100376void ThreadManager::IterateArchivedThreads(ThreadVisitor* v) {
Steve Block44f0eee2011-05-26 01:26:41 +0100377 for (ThreadState* state = FirstThreadStateInUse();
Steve Block6ded16b2010-05-10 14:33:55 +0100378 state != NULL;
379 state = state->Next()) {
380 char* data = state->data();
381 data += HandleScopeImplementer::ArchiveSpacePerThread();
Steve Block44f0eee2011-05-26 01:26:41 +0100382 isolate_->IterateThread(v, data);
Steve Block6ded16b2010-05-10 14:33:55 +0100383 }
384}
385
386
Ben Murdoch8b112d22011-06-08 16:22:53 +0100387ThreadId ThreadManager::CurrentId() {
388 return ThreadId::Current();
Steve Blocka7e24c12009-10-30 11:49:00 +0000389}
390
391
Ben Murdoch8b112d22011-06-08 16:22:53 +0100392void ThreadManager::TerminateExecution(ThreadId thread_id) {
Steve Block44f0eee2011-05-26 01:26:41 +0100393 for (ThreadState* state = FirstThreadStateInUse();
Steve Blocka7e24c12009-10-30 11:49:00 +0000394 state != NULL;
395 state = state->Next()) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100396 if (thread_id.Equals(state->id())) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000397 state->set_terminate_on_restore(true);
398 }
399 }
400}
401
402
Steve Block44f0eee2011-05-26 01:26:41 +0100403ContextSwitcher::ContextSwitcher(Isolate* isolate, int every_n_ms)
404 : Thread(isolate, "v8:CtxtSwitcher"),
Steve Block9fac8402011-05-12 15:51:54 +0100405 keep_going_(true),
Steve Blocka7e24c12009-10-30 11:49:00 +0000406 sleep_ms_(every_n_ms) {
407}
408
409
410// Set the scheduling interval of V8 threads. This function starts the
411// ContextSwitcher thread if needed.
412void ContextSwitcher::StartPreemption(int every_n_ms) {
Steve Block44f0eee2011-05-26 01:26:41 +0100413 Isolate* isolate = Isolate::Current();
Steve Blocka7e24c12009-10-30 11:49:00 +0000414 ASSERT(Locker::IsLocked());
Steve Block44f0eee2011-05-26 01:26:41 +0100415 if (isolate->context_switcher() == NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000416 // If the ContextSwitcher thread is not running at the moment start it now.
Steve Block44f0eee2011-05-26 01:26:41 +0100417 isolate->set_context_switcher(new ContextSwitcher(isolate, every_n_ms));
418 isolate->context_switcher()->Start();
Steve Blocka7e24c12009-10-30 11:49:00 +0000419 } else {
420 // ContextSwitcher thread is already running, so we just change the
421 // scheduling interval.
Steve Block44f0eee2011-05-26 01:26:41 +0100422 isolate->context_switcher()->sleep_ms_ = every_n_ms;
Steve Blocka7e24c12009-10-30 11:49:00 +0000423 }
424}
425
426
427// Disable preemption of V8 threads. If multiple threads want to use V8 they
428// must cooperatively schedule amongst them from this point on.
429void ContextSwitcher::StopPreemption() {
Steve Block44f0eee2011-05-26 01:26:41 +0100430 Isolate* isolate = Isolate::Current();
Steve Blocka7e24c12009-10-30 11:49:00 +0000431 ASSERT(Locker::IsLocked());
Steve Block44f0eee2011-05-26 01:26:41 +0100432 if (isolate->context_switcher() != NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000433 // The ContextSwitcher thread is running. We need to stop it and release
434 // its resources.
Steve Block44f0eee2011-05-26 01:26:41 +0100435 isolate->context_switcher()->keep_going_ = false;
436 // Wait for the ContextSwitcher thread to exit.
437 isolate->context_switcher()->Join();
Steve Blocka7e24c12009-10-30 11:49:00 +0000438 // Thread has exited, now we can delete it.
Steve Block44f0eee2011-05-26 01:26:41 +0100439 delete(isolate->context_switcher());
440 isolate->set_context_switcher(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000441 }
442}
443
444
445// Main loop of the ContextSwitcher thread: Preempt the currently running V8
446// thread at regular intervals.
447void ContextSwitcher::Run() {
448 while (keep_going_) {
449 OS::Sleep(sleep_ms_);
Steve Block44f0eee2011-05-26 01:26:41 +0100450 isolate()->stack_guard()->Preempt();
Steve Blocka7e24c12009-10-30 11:49:00 +0000451 }
452}
453
454
455// Acknowledge the preemption by the receiving thread.
456void ContextSwitcher::PreemptionReceived() {
457 ASSERT(Locker::IsLocked());
458 // There is currently no accounting being done for this. But could be in the
459 // future, which is why we leave this in.
460}
461
462
463} // namespace internal
464} // namespace v8