blob: 4b033fcf0bd703cf12b5bdccfb116784b5a31d9a [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
46// current thread will be guaranteed to have the big V8 lock.
47Locker::Locker() : has_lock_(false), top_level_(true) {
Steve Block44f0eee2011-05-26 01:26:41 +010048 // TODO(isolates): When Locker has Isolate parameter and it is provided, grab
49 // that one instead of using the current one.
50 // We pull default isolate for Locker constructor w/o p[arameter.
51 // A thread should not enter an isolate before acquiring a lock,
52 // in cases which mandate using Lockers.
53 // So getting a lock is the first thing threads do in a scenario where
54 // multple threads share an isolate. Hence, we need to access
55 // 'locking isolate' before we can actually enter into default isolate.
56 internal::Isolate* isolate = internal::Isolate::GetDefaultIsolateForLocking();
57 ASSERT(isolate != NULL);
58
Steve Blocka7e24c12009-10-30 11:49:00 +000059 // Record that the Locker has been used at least once.
60 active_ = true;
61 // Get the big lock if necessary.
Steve Block44f0eee2011-05-26 01:26:41 +010062 if (!isolate->thread_manager()->IsLockedByCurrentThread()) {
63 isolate->thread_manager()->Lock();
Steve Blocka7e24c12009-10-30 11:49:00 +000064 has_lock_ = true;
Steve Block44f0eee2011-05-26 01:26:41 +010065
66 if (isolate->IsDefaultIsolate()) {
67 // This only enters if not yet entered.
68 internal::Isolate::EnterDefaultIsolate();
69 }
70
71 ASSERT(internal::Thread::HasThreadLocal(
72 internal::Isolate::thread_id_key()));
73
Steve Blocka7e24c12009-10-30 11:49:00 +000074 // Make sure that V8 is initialized. Archiving of threads interferes
75 // with deserialization by adding additional root pointers, so we must
76 // initialize here, before anyone can call ~Locker() or Unlocker().
Steve Block44f0eee2011-05-26 01:26:41 +010077 if (!isolate->IsInitialized()) {
Steve Blocka7e24c12009-10-30 11:49:00 +000078 V8::Initialize();
79 }
80 // This may be a locker within an unlocker in which case we have to
81 // get the saved state for this thread and restore it.
Steve Block44f0eee2011-05-26 01:26:41 +010082 if (isolate->thread_manager()->RestoreThread()) {
Steve Blocka7e24c12009-10-30 11:49:00 +000083 top_level_ = false;
84 } else {
Steve Block44f0eee2011-05-26 01:26:41 +010085 internal::ExecutionAccess access(isolate);
86 isolate->stack_guard()->ClearThread(access);
87 isolate->stack_guard()->InitThread(access);
Steve Blocka7e24c12009-10-30 11:49:00 +000088 }
89 }
Steve Block44f0eee2011-05-26 01:26:41 +010090 ASSERT(isolate->thread_manager()->IsLockedByCurrentThread());
Steve Blocka7e24c12009-10-30 11:49:00 +000091}
92
93
94bool Locker::IsLocked() {
Steve Block44f0eee2011-05-26 01:26:41 +010095 return internal::Isolate::Current()->thread_manager()->
96 IsLockedByCurrentThread();
Steve Blocka7e24c12009-10-30 11:49:00 +000097}
98
99
100Locker::~Locker() {
Steve Block44f0eee2011-05-26 01:26:41 +0100101 // TODO(isolate): this should use a field storing the isolate it
102 // locked instead.
103 internal::Isolate* isolate = internal::Isolate::Current();
104 ASSERT(isolate->thread_manager()->IsLockedByCurrentThread());
Steve Blocka7e24c12009-10-30 11:49:00 +0000105 if (has_lock_) {
106 if (top_level_) {
Steve Block44f0eee2011-05-26 01:26:41 +0100107 isolate->thread_manager()->FreeThreadResources();
Steve Blocka7e24c12009-10-30 11:49:00 +0000108 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100109 isolate->thread_manager()->ArchiveThread();
Steve Blocka7e24c12009-10-30 11:49:00 +0000110 }
Steve Block44f0eee2011-05-26 01:26:41 +0100111 isolate->thread_manager()->Unlock();
Steve Blocka7e24c12009-10-30 11:49:00 +0000112 }
113}
114
115
116Unlocker::Unlocker() {
Steve Block44f0eee2011-05-26 01:26:41 +0100117 internal::Isolate* isolate = internal::Isolate::Current();
118 ASSERT(isolate->thread_manager()->IsLockedByCurrentThread());
119 isolate->thread_manager()->ArchiveThread();
120 isolate->thread_manager()->Unlock();
Steve Blocka7e24c12009-10-30 11:49:00 +0000121}
122
123
124Unlocker::~Unlocker() {
Steve Block44f0eee2011-05-26 01:26:41 +0100125 // TODO(isolates): check it's the isolate we unlocked.
126 internal::Isolate* isolate = internal::Isolate::Current();
127 ASSERT(!isolate->thread_manager()->IsLockedByCurrentThread());
128 isolate->thread_manager()->Lock();
129 isolate->thread_manager()->RestoreThread();
Steve Blocka7e24c12009-10-30 11:49:00 +0000130}
131
132
133void Locker::StartPreemption(int every_n_ms) {
134 v8::internal::ContextSwitcher::StartPreemption(every_n_ms);
135}
136
137
138void Locker::StopPreemption() {
139 v8::internal::ContextSwitcher::StopPreemption();
140}
141
142
143namespace internal {
144
145
146bool ThreadManager::RestoreThread() {
147 // First check whether the current thread has been 'lazily archived', ie
148 // not archived at all. If that is the case we put the state storage we
149 // had prepared back in the free list, since we didn't need it after all.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100150 if (lazily_archived_thread_.Equals(ThreadId::Current())) {
151 lazily_archived_thread_ = ThreadId::Invalid();
Steve Block44f0eee2011-05-26 01:26:41 +0100152 ASSERT(Isolate::CurrentPerIsolateThreadData()->thread_state() ==
Steve Blocka7e24c12009-10-30 11:49:00 +0000153 lazily_archived_thread_state_);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100154 lazily_archived_thread_state_->set_id(ThreadId::Invalid());
Steve Blocka7e24c12009-10-30 11:49:00 +0000155 lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST);
156 lazily_archived_thread_state_ = NULL;
Steve Block44f0eee2011-05-26 01:26:41 +0100157 Isolate::CurrentPerIsolateThreadData()->set_thread_state(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000158 return true;
159 }
160
161 // Make sure that the preemption thread cannot modify the thread state while
162 // it is being archived or restored.
Steve Block44f0eee2011-05-26 01:26:41 +0100163 ExecutionAccess access(isolate_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000164
165 // If there is another thread that was lazily archived then we have to really
166 // archive it now.
167 if (lazily_archived_thread_.IsValid()) {
168 EagerlyArchiveThread();
169 }
Steve Block44f0eee2011-05-26 01:26:41 +0100170 Isolate::PerIsolateThreadData* per_thread =
171 Isolate::CurrentPerIsolateThreadData();
172 if (per_thread == NULL || per_thread->thread_state() == NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000173 // This is a new thread.
Steve Block44f0eee2011-05-26 01:26:41 +0100174 isolate_->stack_guard()->InitThread(access);
Steve Blocka7e24c12009-10-30 11:49:00 +0000175 return false;
176 }
Steve Block44f0eee2011-05-26 01:26:41 +0100177 ThreadState* state = per_thread->thread_state();
Steve Blocka7e24c12009-10-30 11:49:00 +0000178 char* from = state->data();
Steve Block44f0eee2011-05-26 01:26:41 +0100179 from = isolate_->handle_scope_implementer()->RestoreThread(from);
180 from = isolate_->RestoreThread(from);
Steve Blocka7e24c12009-10-30 11:49:00 +0000181 from = Relocatable::RestoreState(from);
182#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Block44f0eee2011-05-26 01:26:41 +0100183 from = isolate_->debug()->RestoreDebug(from);
Steve Blocka7e24c12009-10-30 11:49:00 +0000184#endif
Steve Block44f0eee2011-05-26 01:26:41 +0100185 from = isolate_->stack_guard()->RestoreStackGuard(from);
186 from = isolate_->regexp_stack()->RestoreStack(from);
187 from = isolate_->bootstrapper()->RestoreState(from);
188 per_thread->set_thread_state(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000189 if (state->terminate_on_restore()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100190 isolate_->stack_guard()->TerminateExecution();
Steve Blocka7e24c12009-10-30 11:49:00 +0000191 state->set_terminate_on_restore(false);
192 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100193 state->set_id(ThreadId::Invalid());
Steve Blocka7e24c12009-10-30 11:49:00 +0000194 state->Unlink();
195 state->LinkInto(ThreadState::FREE_LIST);
196 return true;
197}
198
199
200void ThreadManager::Lock() {
201 mutex_->Lock();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100202 mutex_owner_ = ThreadId::Current();
Steve Blocka7e24c12009-10-30 11:49:00 +0000203 ASSERT(IsLockedByCurrentThread());
204}
205
206
207void ThreadManager::Unlock() {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100208 mutex_owner_ = ThreadId::Invalid();
Steve Blocka7e24c12009-10-30 11:49:00 +0000209 mutex_->Unlock();
210}
211
212
213static int ArchiveSpacePerThread() {
214 return HandleScopeImplementer::ArchiveSpacePerThread() +
Steve Block44f0eee2011-05-26 01:26:41 +0100215 Isolate::ArchiveSpacePerThread() +
Steve Blocka7e24c12009-10-30 11:49:00 +0000216#ifdef ENABLE_DEBUGGER_SUPPORT
217 Debug::ArchiveSpacePerThread() +
218#endif
219 StackGuard::ArchiveSpacePerThread() +
220 RegExpStack::ArchiveSpacePerThread() +
221 Bootstrapper::ArchiveSpacePerThread() +
222 Relocatable::ArchiveSpacePerThread();
223}
224
225
Steve Block44f0eee2011-05-26 01:26:41 +0100226ThreadState::ThreadState(ThreadManager* thread_manager)
Ben Murdoch8b112d22011-06-08 16:22:53 +0100227 : id_(ThreadId::Invalid()),
Steve Block44f0eee2011-05-26 01:26:41 +0100228 terminate_on_restore_(false),
229 next_(this),
230 previous_(this),
231 thread_manager_(thread_manager) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000232}
233
234
235void ThreadState::AllocateSpace() {
236 data_ = NewArray<char>(ArchiveSpacePerThread());
237}
238
239
240void ThreadState::Unlink() {
241 next_->previous_ = previous_;
242 previous_->next_ = next_;
243}
244
245
246void ThreadState::LinkInto(List list) {
247 ThreadState* flying_anchor =
Steve Block44f0eee2011-05-26 01:26:41 +0100248 list == FREE_LIST ? thread_manager_->free_anchor_
249 : thread_manager_->in_use_anchor_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000250 next_ = flying_anchor->next_;
251 previous_ = flying_anchor;
252 flying_anchor->next_ = this;
253 next_->previous_ = this;
254}
255
256
Steve Block44f0eee2011-05-26 01:26:41 +0100257ThreadState* ThreadManager::GetFreeThreadState() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000258 ThreadState* gotten = free_anchor_->next_;
259 if (gotten == free_anchor_) {
Steve Block44f0eee2011-05-26 01:26:41 +0100260 ThreadState* new_thread_state = new ThreadState(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000261 new_thread_state->AllocateSpace();
262 return new_thread_state;
263 }
264 return gotten;
265}
266
267
268// Gets the first in the list of archived threads.
Steve Block44f0eee2011-05-26 01:26:41 +0100269ThreadState* ThreadManager::FirstThreadStateInUse() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000270 return in_use_anchor_->Next();
271}
272
273
274ThreadState* ThreadState::Next() {
Steve Block44f0eee2011-05-26 01:26:41 +0100275 if (next_ == thread_manager_->in_use_anchor_) return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000276 return next_;
277}
278
279
280// Thread ids must start with 1, because in TLS having thread id 0 can't
281// be distinguished from not having a thread id at all (since NULL is
282// defined as 0.)
Steve Block44f0eee2011-05-26 01:26:41 +0100283ThreadManager::ThreadManager()
284 : mutex_(OS::CreateMutex()),
Ben Murdoch8b112d22011-06-08 16:22:53 +0100285 mutex_owner_(ThreadId::Invalid()),
286 lazily_archived_thread_(ThreadId::Invalid()),
Steve Block44f0eee2011-05-26 01:26:41 +0100287 lazily_archived_thread_state_(NULL),
288 free_anchor_(NULL),
289 in_use_anchor_(NULL) {
290 free_anchor_ = new ThreadState(this);
291 in_use_anchor_ = new ThreadState(this);
292}
293
294
295ThreadManager::~ThreadManager() {
296 // TODO(isolates): Destroy mutexes.
297}
Steve Blocka7e24c12009-10-30 11:49:00 +0000298
299
300void ThreadManager::ArchiveThread() {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100301 ASSERT(lazily_archived_thread_.Equals(ThreadId::Invalid()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000302 ASSERT(!IsArchived());
Steve Block44f0eee2011-05-26 01:26:41 +0100303 ThreadState* state = GetFreeThreadState();
Steve Blocka7e24c12009-10-30 11:49:00 +0000304 state->Unlink();
Steve Block44f0eee2011-05-26 01:26:41 +0100305 Isolate::CurrentPerIsolateThreadData()->set_thread_state(state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100306 lazily_archived_thread_ = ThreadId::Current();
Steve Blocka7e24c12009-10-30 11:49:00 +0000307 lazily_archived_thread_state_ = state;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100308 ASSERT(state->id().Equals(ThreadId::Invalid()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000309 state->set_id(CurrentId());
Ben Murdoch8b112d22011-06-08 16:22:53 +0100310 ASSERT(!state->id().Equals(ThreadId::Invalid()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000311}
312
313
314void ThreadManager::EagerlyArchiveThread() {
315 ThreadState* state = lazily_archived_thread_state_;
316 state->LinkInto(ThreadState::IN_USE_LIST);
317 char* to = state->data();
318 // Ensure that data containing GC roots are archived first, and handle them
319 // in ThreadManager::Iterate(ObjectVisitor*).
Steve Block44f0eee2011-05-26 01:26:41 +0100320 to = isolate_->handle_scope_implementer()->ArchiveThread(to);
321 to = isolate_->ArchiveThread(to);
Steve Blocka7e24c12009-10-30 11:49:00 +0000322 to = Relocatable::ArchiveState(to);
323#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Block44f0eee2011-05-26 01:26:41 +0100324 to = isolate_->debug()->ArchiveDebug(to);
Steve Blocka7e24c12009-10-30 11:49:00 +0000325#endif
Steve Block44f0eee2011-05-26 01:26:41 +0100326 to = isolate_->stack_guard()->ArchiveStackGuard(to);
327 to = isolate_->regexp_stack()->ArchiveStack(to);
328 to = isolate_->bootstrapper()->ArchiveState(to);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100329 lazily_archived_thread_ = ThreadId::Invalid();
Steve Blocka7e24c12009-10-30 11:49:00 +0000330 lazily_archived_thread_state_ = NULL;
331}
332
333
334void ThreadManager::FreeThreadResources() {
Steve Block44f0eee2011-05-26 01:26:41 +0100335 isolate_->handle_scope_implementer()->FreeThreadResources();
336 isolate_->FreeThreadResources();
Steve Blocka7e24c12009-10-30 11:49:00 +0000337#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Block44f0eee2011-05-26 01:26:41 +0100338 isolate_->debug()->FreeThreadResources();
Steve Blocka7e24c12009-10-30 11:49:00 +0000339#endif
Steve Block44f0eee2011-05-26 01:26:41 +0100340 isolate_->stack_guard()->FreeThreadResources();
341 isolate_->regexp_stack()->FreeThreadResources();
342 isolate_->bootstrapper()->FreeThreadResources();
Steve Blocka7e24c12009-10-30 11:49:00 +0000343}
344
345
346bool ThreadManager::IsArchived() {
Steve Block44f0eee2011-05-26 01:26:41 +0100347 Isolate::PerIsolateThreadData* data = Isolate::CurrentPerIsolateThreadData();
348 return data != NULL && data->thread_state() != NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000349}
350
351
352void ThreadManager::Iterate(ObjectVisitor* v) {
353 // Expecting no threads during serialization/deserialization
Steve Block44f0eee2011-05-26 01:26:41 +0100354 for (ThreadState* state = FirstThreadStateInUse();
Steve Blocka7e24c12009-10-30 11:49:00 +0000355 state != NULL;
356 state = state->Next()) {
357 char* data = state->data();
358 data = HandleScopeImplementer::Iterate(v, data);
Steve Block44f0eee2011-05-26 01:26:41 +0100359 data = isolate_->Iterate(v, data);
Steve Blocka7e24c12009-10-30 11:49:00 +0000360 data = Relocatable::Iterate(v, data);
361 }
362}
363
364
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100365void ThreadManager::IterateArchivedThreads(ThreadVisitor* v) {
Steve Block44f0eee2011-05-26 01:26:41 +0100366 for (ThreadState* state = FirstThreadStateInUse();
Steve Block6ded16b2010-05-10 14:33:55 +0100367 state != NULL;
368 state = state->Next()) {
369 char* data = state->data();
370 data += HandleScopeImplementer::ArchiveSpacePerThread();
Steve Block44f0eee2011-05-26 01:26:41 +0100371 isolate_->IterateThread(v, data);
Steve Block6ded16b2010-05-10 14:33:55 +0100372 }
373}
374
375
Ben Murdoch8b112d22011-06-08 16:22:53 +0100376ThreadId ThreadManager::CurrentId() {
377 return ThreadId::Current();
Steve Blocka7e24c12009-10-30 11:49:00 +0000378}
379
380
Ben Murdoch8b112d22011-06-08 16:22:53 +0100381void ThreadManager::TerminateExecution(ThreadId thread_id) {
Steve Block44f0eee2011-05-26 01:26:41 +0100382 for (ThreadState* state = FirstThreadStateInUse();
Steve Blocka7e24c12009-10-30 11:49:00 +0000383 state != NULL;
384 state = state->Next()) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100385 if (thread_id.Equals(state->id())) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000386 state->set_terminate_on_restore(true);
387 }
388 }
389}
390
391
Steve Block44f0eee2011-05-26 01:26:41 +0100392ContextSwitcher::ContextSwitcher(Isolate* isolate, int every_n_ms)
393 : Thread(isolate, "v8:CtxtSwitcher"),
Steve Block9fac8402011-05-12 15:51:54 +0100394 keep_going_(true),
Steve Blocka7e24c12009-10-30 11:49:00 +0000395 sleep_ms_(every_n_ms) {
396}
397
398
399// Set the scheduling interval of V8 threads. This function starts the
400// ContextSwitcher thread if needed.
401void ContextSwitcher::StartPreemption(int every_n_ms) {
Steve Block44f0eee2011-05-26 01:26:41 +0100402 Isolate* isolate = Isolate::Current();
Steve Blocka7e24c12009-10-30 11:49:00 +0000403 ASSERT(Locker::IsLocked());
Steve Block44f0eee2011-05-26 01:26:41 +0100404 if (isolate->context_switcher() == NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000405 // If the ContextSwitcher thread is not running at the moment start it now.
Steve Block44f0eee2011-05-26 01:26:41 +0100406 isolate->set_context_switcher(new ContextSwitcher(isolate, every_n_ms));
407 isolate->context_switcher()->Start();
Steve Blocka7e24c12009-10-30 11:49:00 +0000408 } else {
409 // ContextSwitcher thread is already running, so we just change the
410 // scheduling interval.
Steve Block44f0eee2011-05-26 01:26:41 +0100411 isolate->context_switcher()->sleep_ms_ = every_n_ms;
Steve Blocka7e24c12009-10-30 11:49:00 +0000412 }
413}
414
415
416// Disable preemption of V8 threads. If multiple threads want to use V8 they
417// must cooperatively schedule amongst them from this point on.
418void ContextSwitcher::StopPreemption() {
Steve Block44f0eee2011-05-26 01:26:41 +0100419 Isolate* isolate = Isolate::Current();
Steve Blocka7e24c12009-10-30 11:49:00 +0000420 ASSERT(Locker::IsLocked());
Steve Block44f0eee2011-05-26 01:26:41 +0100421 if (isolate->context_switcher() != NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000422 // The ContextSwitcher thread is running. We need to stop it and release
423 // its resources.
Steve Block44f0eee2011-05-26 01:26:41 +0100424 isolate->context_switcher()->keep_going_ = false;
425 // Wait for the ContextSwitcher thread to exit.
426 isolate->context_switcher()->Join();
Steve Blocka7e24c12009-10-30 11:49:00 +0000427 // Thread has exited, now we can delete it.
Steve Block44f0eee2011-05-26 01:26:41 +0100428 delete(isolate->context_switcher());
429 isolate->set_context_switcher(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000430 }
431}
432
433
434// Main loop of the ContextSwitcher thread: Preempt the currently running V8
435// thread at regular intervals.
436void ContextSwitcher::Run() {
437 while (keep_going_) {
438 OS::Sleep(sleep_ms_);
Steve Block44f0eee2011-05-26 01:26:41 +0100439 isolate()->stack_guard()->Preempt();
Steve Blocka7e24c12009-10-30 11:49:00 +0000440 }
441}
442
443
444// Acknowledge the preemption by the receiving thread.
445void ContextSwitcher::PreemptionReceived() {
446 ASSERT(Locker::IsLocked());
447 // There is currently no accounting being done for this. But could be in the
448 // future, which is why we leave this in.
449}
450
451
452} // namespace internal
453} // namespace v8