Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: src/v8threads.cc

Issue 435003: Patch for allowing several V8 instances in process:... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/v8threads.h ('k') | src/x64/assembler-x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2008 the V8 project authors. All rights reserved. 1 // Copyright 2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 18 matching lines...) Expand all
29 29
30 #include "api.h" 30 #include "api.h"
31 #include "bootstrapper.h" 31 #include "bootstrapper.h"
32 #include "debug.h" 32 #include "debug.h"
33 #include "execution.h" 33 #include "execution.h"
34 #include "v8threads.h" 34 #include "v8threads.h"
35 #include "regexp-stack.h" 35 #include "regexp-stack.h"
36 36
37 namespace v8 { 37 namespace v8 {
38 38
39 static internal::Thread::LocalStorageKey thread_state_key =
40 internal::Thread::CreateThreadLocalKey();
41 static internal::Thread::LocalStorageKey thread_id_key =
42 internal::Thread::CreateThreadLocalKey();
43
44
45 // Track whether this V8 instance has ever called v8::Locker. This allows the
46 // API code to verify that the lock is always held when V8 is being entered.
47 bool Locker::active_ = false;
48
49
50 // Constructor for the Locker object. Once the Locker is constructed the 39 // Constructor for the Locker object. Once the Locker is constructed the
51 // current thread will be guaranteed to have the big V8 lock. 40 // current thread will be guaranteed to have the big V8 lock.
52 Locker::Locker() : has_lock_(false), top_level_(true) { 41 Locker::Locker() : has_lock_(false), top_level_(true) {
42 internal::V8Context* const v8context = v8_context();
43
53 // Record that the Locker has been used at least once. 44 // Record that the Locker has been used at least once.
54 active_ = true; 45 v8context->v8_data_.active_ = true;
55 // Get the big lock if necessary. 46 // Get the big lock if necessary.
56 if (!internal::ThreadManager::IsLockedByCurrentThread()) { 47 if (!internal::ThreadManager::IsLockedByCurrentThread()) {
57 internal::ThreadManager::Lock(); 48 internal::ThreadManager::Lock();
58 has_lock_ = true; 49 has_lock_ = true;
59 // Make sure that V8 is initialized. Archiving of threads interferes 50 // Make sure that V8 is initialized. Archiving of threads interferes
60 // with deserialization by adding additional root pointers, so we must 51 // with deserialization by adding additional root pointers, so we must
61 // initialize here, before anyone can call ~Locker() or Unlocker(). 52 // initialize here, before anyone can call ~Locker() or Unlocker().
62 if (!internal::V8::IsRunning()) { 53 if (!internal::V8::IsRunning()) {
63 V8::Initialize(); 54 V8::Initialize();
64 } 55 }
65 // This may be a locker within an unlocker in which case we have to 56 // This may be a locker within an unlocker in which case we have to
66 // get the saved state for this thread and restore it. 57 // get the saved state for this thread and restore it.
67 if (internal::ThreadManager::RestoreThread()) { 58 if (internal::ThreadManager::RestoreThread()) {
68 top_level_ = false; 59 top_level_ = false;
69 } else { 60 } else {
70 internal::ExecutionAccess access; 61 internal::ExecutionAccess access;
71 internal::StackGuard::ClearThread(access); 62 internal::StackGuard::ClearThread(access);
72 internal::StackGuard::InitThread(access); 63 internal::StackGuard::InitThread(access);
73 } 64 }
74 } 65 }
75 ASSERT(internal::ThreadManager::IsLockedByCurrentThread()); 66 ASSERT(internal::ThreadManager::IsLockedByCurrentThread());
76 67
77 // Make sure this thread is assigned a thread id. 68 // Make sure this thread is assigned a thread id.
78 internal::ThreadManager::AssignId(); 69 internal::ThreadManager::AssignId();
79 } 70 }
80 71
72 bool Locker::IsActive() {
73 return v8_context()->v8_data_.active_;
74 }
81 75
82 bool Locker::IsLocked() { 76 bool Locker::IsLocked() {
83 return internal::ThreadManager::IsLockedByCurrentThread(); 77 return internal::ThreadManager::IsLockedByCurrentThread();
84 } 78 }
85 79
86 80
87 Locker::~Locker() { 81 Locker::~Locker() {
88 ASSERT(internal::ThreadManager::IsLockedByCurrentThread()); 82 ASSERT(internal::ThreadManager::IsLockedByCurrentThread());
89 if (has_lock_) { 83 if (has_lock_) {
90 if (top_level_) { 84 if (top_level_) {
(...skipping 27 matching lines...) Expand all
118 112
119 void Locker::StopPreemption() { 113 void Locker::StopPreemption() {
120 v8::internal::ContextSwitcher::StopPreemption(); 114 v8::internal::ContextSwitcher::StopPreemption();
121 } 115 }
122 116
123 117
124 namespace internal { 118 namespace internal {
125 119
126 120
127 bool ThreadManager::RestoreThread() { 121 bool ThreadManager::RestoreThread() {
122 ThreadManagerData& thread_manager_data = v8_context()->thread_manager_data_;
128 // First check whether the current thread has been 'lazily archived', ie 123 // First check whether the current thread has been 'lazily archived', ie
129 // not archived at all. If that is the case we put the state storage we 124 // not archived at all. If that is the case we put the state storage we
130 // had prepared back in the free list, since we didn't need it after all. 125 // had prepared back in the free list, since we didn't need it after all.
131 if (lazily_archived_thread_.IsSelf()) { 126 if (thread_manager_data.lazily_archived_thread_.IsSelf()) {
132 lazily_archived_thread_.Initialize(ThreadHandle::INVALID); 127 thread_manager_data.lazily_archived_thread_.Initialize(
133 ASSERT(Thread::GetThreadLocal(thread_state_key) == 128 ThreadHandle::INVALID);
134 lazily_archived_thread_state_); 129 ASSERT(Thread::GetThreadLocal(thread_manager_data.thread_state_key_) ==
135 lazily_archived_thread_state_->set_id(kInvalidId); 130 thread_manager_data.lazily_archived_thread_state_);
136 lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST); 131 thread_manager_data.lazily_archived_thread_state_->set_id(kInvalidId);
137 lazily_archived_thread_state_ = NULL; 132 thread_manager_data.lazily_archived_thread_state_->LinkInto(
138 Thread::SetThreadLocal(thread_state_key, NULL); 133 ThreadState::FREE_LIST);
134
135 thread_manager_data.lazily_archived_thread_state_ = NULL;
136 Thread::SetThreadLocal(thread_manager_data.thread_state_key_, NULL);
139 return true; 137 return true;
140 } 138 }
141 139
142 // Make sure that the preemption thread cannot modify the thread state while 140 // Make sure that the preemption thread cannot modify the thread state while
143 // it is being archived or restored. 141 // it is being archived or restored.
144 ExecutionAccess access; 142 ExecutionAccess access;
145 143
146 // If there is another thread that was lazily archived then we have to really 144 // If there is another thread that was lazily archived then we have to really
147 // archive it now. 145 // archive it now.
148 if (lazily_archived_thread_.IsValid()) { 146 if (thread_manager_data.lazily_archived_thread_.IsValid()) {
149 EagerlyArchiveThread(); 147 EagerlyArchiveThread();
150 } 148 }
151 ThreadState* state = 149 ThreadState* state = reinterpret_cast<ThreadState*>(
152 reinterpret_cast<ThreadState*>(Thread::GetThreadLocal(thread_state_key)); 150 Thread::GetThreadLocal(thread_manager_data.thread_state_key_));
153 if (state == NULL) { 151 if (state == NULL) {
154 // This is a new thread. 152 // This is a new thread.
155 StackGuard::InitThread(access); 153 StackGuard::InitThread(access);
156 return false; 154 return false;
157 } 155 }
158 char* from = state->data(); 156 char* from = state->data();
159 from = HandleScopeImplementer::RestoreThread(from); 157 from = HandleScopeImplementer::RestoreThread(from);
160 from = Top::RestoreThread(from); 158 from = Top::RestoreThread(from);
161 from = Relocatable::RestoreState(from); 159 from = Relocatable::RestoreState(from);
162 #ifdef ENABLE_DEBUGGER_SUPPORT 160 #ifdef ENABLE_DEBUGGER_SUPPORT
163 from = Debug::RestoreDebug(from); 161 from = Debug::RestoreDebug(from);
164 #endif 162 #endif
165 from = StackGuard::RestoreStackGuard(from); 163 from = StackGuard::RestoreStackGuard(from);
166 from = RegExpStack::RestoreStack(from); 164 from = RegExpStack::RestoreStack(from);
167 from = Bootstrapper::RestoreState(from); 165 from = Bootstrapper::RestoreState(from);
168 Thread::SetThreadLocal(thread_state_key, NULL); 166 Thread::SetThreadLocal(thread_manager_data.thread_state_key_, NULL);
169 if (state->terminate_on_restore()) { 167 if (state->terminate_on_restore()) {
170 StackGuard::TerminateExecution(); 168 StackGuard::TerminateExecution();
171 state->set_terminate_on_restore(false); 169 state->set_terminate_on_restore(false);
172 } 170 }
173 state->set_id(kInvalidId); 171 state->set_id(kInvalidId);
174 state->Unlink(); 172 state->Unlink();
175 state->LinkInto(ThreadState::FREE_LIST); 173 state->LinkInto(ThreadState::FREE_LIST);
176 return true; 174 return true;
177 } 175 }
178 176
179 177
180 void ThreadManager::Lock() { 178 void ThreadManager::Lock() {
181 mutex_->Lock(); 179 v8_context()->thread_manager_data_.mutex_->Lock();
182 mutex_owner_.Initialize(ThreadHandle::SELF); 180 v8_context()->thread_manager_data_.mutex_owner_.Initialize(
181 ThreadHandle::SELF);
183 ASSERT(IsLockedByCurrentThread()); 182 ASSERT(IsLockedByCurrentThread());
184 } 183 }
185 184
186 185
187 void ThreadManager::Unlock() { 186 void ThreadManager::Unlock() {
188 mutex_owner_.Initialize(ThreadHandle::INVALID); 187 v8_context()->thread_manager_data_.mutex_owner_.Initialize(
189 mutex_->Unlock(); 188 ThreadHandle::INVALID);
189 v8_context()->thread_manager_data_.mutex_->Unlock();
190 } 190 }
191 191
192 192
193 static int ArchiveSpacePerThread() { 193 static int ArchiveSpacePerThread() {
194 return HandleScopeImplementer::ArchiveSpacePerThread() + 194 return HandleScopeImplementer::ArchiveSpacePerThread() +
195 Top::ArchiveSpacePerThread() + 195 Top::ArchiveSpacePerThread() +
196 #ifdef ENABLE_DEBUGGER_SUPPORT 196 #ifdef ENABLE_DEBUGGER_SUPPORT
197 Debug::ArchiveSpacePerThread() + 197 Debug::ArchiveSpacePerThread() +
198 #endif 198 #endif
199 StackGuard::ArchiveSpacePerThread() + 199 StackGuard::ArchiveSpacePerThread() +
200 RegExpStack::ArchiveSpacePerThread() + 200 RegExpStack::ArchiveSpacePerThread() +
201 Bootstrapper::ArchiveSpacePerThread() + 201 Bootstrapper::ArchiveSpacePerThread() +
202 Relocatable::ArchiveSpacePerThread(); 202 Relocatable::ArchiveSpacePerThread();
203 } 203 }
204 204
205 205
206 ThreadState* ThreadState::free_anchor_ = new ThreadState();
207 ThreadState* ThreadState::in_use_anchor_ = new ThreadState();
208 206
209 207
210 ThreadState::ThreadState() : id_(ThreadManager::kInvalidId), 208 ThreadState::ThreadState() : id_(ThreadManager::kInvalidId),
211 terminate_on_restore_(false), 209 terminate_on_restore_(false),
212 next_(this), previous_(this) { 210 next_(this), previous_(this) {
213 } 211 }
214 212
215 213
216 void ThreadState::AllocateSpace() { 214 void ThreadState::AllocateSpace() {
217 data_ = NewArray<char>(ArchiveSpacePerThread()); 215 data_ = NewArray<char>(ArchiveSpacePerThread());
218 } 216 }
219 217
220 218
221 void ThreadState::Unlink() { 219 void ThreadState::Unlink() {
222 next_->previous_ = previous_; 220 next_->previous_ = previous_;
223 previous_->next_ = next_; 221 previous_->next_ = next_;
224 } 222 }
225 223
226 224
227 void ThreadState::LinkInto(List list) { 225 void ThreadState::LinkInto(List list) {
228 ThreadState* flying_anchor = 226 ThreadState* flying_anchor = list == FREE_LIST ?
229 list == FREE_LIST ? free_anchor_ : in_use_anchor_; 227 v8_context()->thread_manager_data_.free_anchor_
228 : v8_context()->thread_manager_data_.in_use_anchor_;
230 next_ = flying_anchor->next_; 229 next_ = flying_anchor->next_;
231 previous_ = flying_anchor; 230 previous_ = flying_anchor;
232 flying_anchor->next_ = this; 231 flying_anchor->next_ = this;
233 next_->previous_ = this; 232 next_->previous_ = this;
234 } 233 }
235 234
236 235
237 ThreadState* ThreadState::GetFree() { 236 ThreadState* ThreadState::GetFree() {
238 ThreadState* gotten = free_anchor_->next_; 237 ThreadState* gotten = v8_context()->thread_manager_data_.free_anchor_->next_;
239 if (gotten == free_anchor_) { 238 if (gotten == v8_context()->thread_manager_data_.free_anchor_) {
240 ThreadState* new_thread_state = new ThreadState(); 239 ThreadState* new_thread_state = new ThreadState();
241 new_thread_state->AllocateSpace(); 240 new_thread_state->AllocateSpace();
242 return new_thread_state; 241 return new_thread_state;
243 } 242 }
244 return gotten; 243 return gotten;
245 } 244 }
246 245
247 246
248 // Gets the first in the list of archived threads. 247 // Gets the first in the list of archived threads.
249 ThreadState* ThreadState::FirstInUse() { 248 ThreadState* ThreadState::FirstInUse() {
250 return in_use_anchor_->Next(); 249 return v8_context()->thread_manager_data_.in_use_anchor_->Next();
251 } 250 }
252 251
253 252
254 ThreadState* ThreadState::Next() { 253 ThreadState* ThreadState::Next() {
255 if (next_ == in_use_anchor_) return NULL; 254 if (next_ == v8_context()->thread_manager_data_.in_use_anchor_) return NULL;
256 return next_; 255 return next_;
257 } 256 }
258 257
259 258
259 ThreadManagerData::ThreadManagerData()
260 // Thread ids must start with 1, because in TLS having thread id 0 can't 260 // Thread ids must start with 1, because in TLS having thread id 0 can't
261 // be distinguished from not having a thread id at all (since NULL is 261 // be distinguished from not having a thread id at all (since NULL is
262 // defined as 0.) 262 // defined as 0.)
263 int ThreadManager::last_id_ = 0; 263 :last_id_(0),
264 Mutex* ThreadManager::mutex_ = OS::CreateMutex(); 264 mutex_(OS::CreateMutex()),
265 ThreadHandle ThreadManager::mutex_owner_(ThreadHandle::INVALID); 265 mutex_owner_(ThreadHandle::INVALID),
266 ThreadHandle ThreadManager::lazily_archived_thread_(ThreadHandle::INVALID); 266 lazily_archived_thread_(ThreadHandle::INVALID),
267 ThreadState* ThreadManager::lazily_archived_thread_state_ = NULL; 267 lazily_archived_thread_state_(NULL),
268 268 free_anchor_(new ThreadState()),
269 in_use_anchor_(new ThreadState()),
270 singleton_(NULL),
271 thread_state_key_(Thread::CreateThreadLocalKey()),
272 thread_id_key_(Thread::CreateThreadLocalKey()) {
273 }
269 274
270 void ThreadManager::ArchiveThread() { 275 void ThreadManager::ArchiveThread() {
271 ASSERT(!lazily_archived_thread_.IsValid()); 276 ThreadManagerData& thread_manager_data = v8_context()->thread_manager_data_;
277 ASSERT(!thread_manager_data.lazily_archived_thread_.IsValid());
272 ASSERT(!IsArchived()); 278 ASSERT(!IsArchived());
273 ThreadState* state = ThreadState::GetFree(); 279 ThreadState* state = ThreadState::GetFree();
274 state->Unlink(); 280 state->Unlink();
275 Thread::SetThreadLocal(thread_state_key, reinterpret_cast<void*>(state)); 281 Thread::SetThreadLocal(thread_manager_data .thread_state_key_,
276 lazily_archived_thread_.Initialize(ThreadHandle::SELF); 282 reinterpret_cast<void*>(state));
277 lazily_archived_thread_state_ = state; 283
284 thread_manager_data.lazily_archived_thread_.Initialize(ThreadHandle::SELF);
285 thread_manager_data.lazily_archived_thread_state_ = state;
278 ASSERT(state->id() == kInvalidId); 286 ASSERT(state->id() == kInvalidId);
279 state->set_id(CurrentId()); 287 state->set_id(CurrentId());
280 ASSERT(state->id() != kInvalidId); 288 ASSERT(state->id() != kInvalidId);
281 } 289 }
282 290
283 291
284 void ThreadManager::EagerlyArchiveThread() { 292 void ThreadManager::EagerlyArchiveThread() {
285 ThreadState* state = lazily_archived_thread_state_; 293 ThreadManagerData& thread_manager_data = v8_context()->thread_manager_data_;
294 ThreadState* state = thread_manager_data.lazily_archived_thread_state_;
286 state->LinkInto(ThreadState::IN_USE_LIST); 295 state->LinkInto(ThreadState::IN_USE_LIST);
287 char* to = state->data(); 296 char* to = state->data();
288 // Ensure that data containing GC roots are archived first, and handle them 297 // Ensure that data containing GC roots are archived first, and handle them
289 // in ThreadManager::Iterate(ObjectVisitor*). 298 // in ThreadManager::Iterate(ObjectVisitor*).
290 to = HandleScopeImplementer::ArchiveThread(to); 299 to = HandleScopeImplementer::ArchiveThread(to);
291 to = Top::ArchiveThread(to); 300 to = Top::ArchiveThread(to);
292 to = Relocatable::ArchiveState(to); 301 to = Relocatable::ArchiveState(to);
293 #ifdef ENABLE_DEBUGGER_SUPPORT 302 #ifdef ENABLE_DEBUGGER_SUPPORT
294 to = Debug::ArchiveDebug(to); 303 to = Debug::ArchiveDebug(to);
295 #endif 304 #endif
296 to = StackGuard::ArchiveStackGuard(to); 305 to = StackGuard::ArchiveStackGuard(to);
297 to = RegExpStack::ArchiveStack(to); 306 to = RegExpStack::ArchiveStack(to);
298 to = Bootstrapper::ArchiveState(to); 307 to = Bootstrapper::ArchiveState(to);
299 lazily_archived_thread_.Initialize(ThreadHandle::INVALID); 308 thread_manager_data.lazily_archived_thread_.Initialize(ThreadHandle::INVALID);
300 lazily_archived_thread_state_ = NULL; 309 thread_manager_data.lazily_archived_thread_state_ = NULL;
301 } 310 }
302 311
303 312
304 void ThreadManager::FreeThreadResources() { 313 void ThreadManager::FreeThreadResources() {
305 HandleScopeImplementer::FreeThreadResources(); 314 HandleScopeImplementer::FreeThreadResources();
306 Top::FreeThreadResources(); 315 Top::FreeThreadResources();
307 #ifdef ENABLE_DEBUGGER_SUPPORT 316 #ifdef ENABLE_DEBUGGER_SUPPORT
308 Debug::FreeThreadResources(); 317 Debug::FreeThreadResources();
309 #endif 318 #endif
310 StackGuard::FreeThreadResources(); 319 StackGuard::FreeThreadResources();
311 RegExpStack::FreeThreadResources(); 320 RegExpStack::FreeThreadResources();
312 Bootstrapper::FreeThreadResources(); 321 Bootstrapper::FreeThreadResources();
313 } 322 }
314 323
315 324
316 bool ThreadManager::IsArchived() { 325 bool ThreadManager::IsArchived() {
317 return Thread::HasThreadLocal(thread_state_key); 326 return Thread::HasThreadLocal(
327 v8_context()->thread_manager_data_.thread_state_key_);
318 } 328 }
319 329
320 330
321 void ThreadManager::Iterate(ObjectVisitor* v) { 331 void ThreadManager::Iterate(ObjectVisitor* v) {
322 // Expecting no threads during serialization/deserialization 332 // Expecting no threads during serialization/deserialization
323 for (ThreadState* state = ThreadState::FirstInUse(); 333 for (ThreadState* state = ThreadState::FirstInUse();
324 state != NULL; 334 state != NULL;
325 state = state->Next()) { 335 state = state->Next()) {
326 char* data = state->data(); 336 char* data = state->data();
327 data = HandleScopeImplementer::Iterate(v, data); 337 data = HandleScopeImplementer::Iterate(v, data);
(...skipping 19 matching lines...) Expand all
347 state != NULL; 357 state != NULL;
348 state = state->Next()) { 358 state = state->Next()) {
349 char* data = state->data(); 359 char* data = state->data();
350 data += HandleScopeImplementer::ArchiveSpacePerThread(); 360 data += HandleScopeImplementer::ArchiveSpacePerThread();
351 Top::MarkCompactEpilogue(is_compacting, data); 361 Top::MarkCompactEpilogue(is_compacting, data);
352 } 362 }
353 } 363 }
354 364
355 365
356 int ThreadManager::CurrentId() { 366 int ThreadManager::CurrentId() {
357 return Thread::GetThreadLocalInt(thread_id_key); 367 return Thread::GetThreadLocalInt(
368 v8_context()->thread_manager_data_.thread_id_key_);
358 } 369 }
359 370
360 371
361 void ThreadManager::AssignId() { 372 void ThreadManager::AssignId() {
362 if (!HasId()) { 373 if (!HasId()) {
363 ASSERT(Locker::IsLocked()); 374 ASSERT(Locker::IsLocked());
364 int thread_id = ++last_id_; 375 ThreadManagerData& thread_manager_data = v8_context()->thread_manager_data_;
376 int thread_id = ++thread_manager_data.last_id_;
365 ASSERT(thread_id > 0); // see the comment near last_id_ definition. 377 ASSERT(thread_id > 0); // see the comment near last_id_ definition.
366 Thread::SetThreadLocalInt(thread_id_key, thread_id); 378 Thread::SetThreadLocalInt(thread_manager_data.thread_id_key_, thread_id);
367 Top::set_thread_id(thread_id); 379 Top::set_thread_id(thread_id);
368 } 380 }
369 } 381 }
370 382
371 383
372 bool ThreadManager::HasId() { 384 bool ThreadManager::HasId() {
373 return Thread::HasThreadLocal(thread_id_key); 385 return Thread::HasThreadLocal(
386 v8_context()->thread_manager_data_.thread_id_key_);
374 } 387 }
375 388
376 389
377 void ThreadManager::TerminateExecution(int thread_id) { 390 void ThreadManager::TerminateExecution(int thread_id) {
378 for (ThreadState* state = ThreadState::FirstInUse(); 391 for (ThreadState* state = ThreadState::FirstInUse();
379 state != NULL; 392 state != NULL;
380 state = state->Next()) { 393 state = state->Next()) {
381 if (thread_id == state->id()) { 394 if (thread_id == state->id()) {
382 state->set_terminate_on_restore(true); 395 state->set_terminate_on_restore(true);
383 } 396 }
384 } 397 }
385 } 398 }
386 399
387
388 // This is the ContextSwitcher singleton. There is at most a single thread
389 // running which delivers preemption events to V8 threads.
390 ContextSwitcher* ContextSwitcher::singleton_ = NULL;
391
392
393 ContextSwitcher::ContextSwitcher(int every_n_ms) 400 ContextSwitcher::ContextSwitcher(int every_n_ms)
394 : keep_going_(true), 401 : keep_going_(true),
395 sleep_ms_(every_n_ms) { 402 sleep_ms_(every_n_ms) {
396 } 403 }
397 404
398 405
399 // Set the scheduling interval of V8 threads. This function starts the 406 // Set the scheduling interval of V8 threads. This function starts the
400 // ContextSwitcher thread if needed. 407 // ContextSwitcher thread if needed.
401 void ContextSwitcher::StartPreemption(int every_n_ms) { 408 void ContextSwitcher::StartPreemption(int every_n_ms) {
402 ASSERT(Locker::IsLocked()); 409 ASSERT(Locker::IsLocked());
403 if (singleton_ == NULL) { 410 ContextSwitcher* & singleton = v8_context()->thread_manager_data_.singleton_;
411 if (singleton == NULL) {
404 // If the ContextSwitcher thread is not running at the moment start it now. 412 // If the ContextSwitcher thread is not running at the moment start it now.
405 singleton_ = new ContextSwitcher(every_n_ms); 413 singleton = new ContextSwitcher(every_n_ms);
406 singleton_->Start(); 414 singleton->Start();
407 } else { 415 } else {
408 // ContextSwitcher thread is already running, so we just change the 416 // ContextSwitcher thread is already running, so we just change the
409 // scheduling interval. 417 // scheduling interval.
410 singleton_->sleep_ms_ = every_n_ms; 418 singleton->sleep_ms_ = every_n_ms;
411 } 419 }
412 } 420 }
413 421
414 422
415 // Disable preemption of V8 threads. If multiple threads want to use V8 they 423 // Disable preemption of V8 threads. If multiple threads want to use V8 they
416 // must cooperatively schedule amongst them from this point on. 424 // must cooperatively schedule amongst them from this point on.
417 void ContextSwitcher::StopPreemption() { 425 void ContextSwitcher::StopPreemption() {
418 ASSERT(Locker::IsLocked()); 426 ASSERT(Locker::IsLocked());
419 if (singleton_ != NULL) { 427 ContextSwitcher* & singleton = v8_context()->thread_manager_data_.singleton_;
428 if (singleton != NULL) {
420 // The ContextSwitcher thread is running. We need to stop it and release 429 // The ContextSwitcher thread is running. We need to stop it and release
421 // its resources. 430 // its resources.
422 singleton_->keep_going_ = false; 431 singleton->keep_going_ = false;
423 singleton_->Join(); // Wait for the ContextSwitcher thread to exit. 432 singleton->Join(); // Wait for the ContextSwitcher thread to exit.
424 // Thread has exited, now we can delete it. 433 // Thread has exited, now we can delete it.
425 delete(singleton_); 434 delete(singleton);
426 singleton_ = NULL; 435 singleton = NULL;
427 } 436 }
428 } 437 }
429 438
430 439
431 // Main loop of the ContextSwitcher thread: Preempt the currently running V8 440 // Main loop of the ContextSwitcher thread: Preempt the currently running V8
432 // thread at regular intervals. 441 // thread at regular intervals.
433 void ContextSwitcher::Run() { 442 void ContextSwitcher::Run() {
434 while (keep_going_) { 443 while (keep_going_) {
435 OS::Sleep(sleep_ms_); 444 OS::Sleep(sleep_ms_);
436 StackGuard::Preempt(); 445 StackGuard::Preempt();
437 } 446 }
438 } 447 }
439 448
440 449
441 // Acknowledge the preemption by the receiving thread. 450 // Acknowledge the preemption by the receiving thread.
442 void ContextSwitcher::PreemptionReceived() { 451 void ContextSwitcher::PreemptionReceived() {
443 ASSERT(Locker::IsLocked()); 452 ASSERT(Locker::IsLocked());
444 // There is currently no accounting being done for this. But could be in the 453 // There is currently no accounting being done for this. But could be in the
445 // future, which is why we leave this in. 454 // future, which is why we leave this in.
446 } 455 }
447 456
448 457
449 } // namespace internal 458 } // namespace internal
450 } // namespace v8 459 } // namespace v8
OLDNEW
« no previous file with comments | « src/v8threads.h ('k') | src/x64/assembler-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698