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

Side by Side Diff: src/v8threads.cc

Issue 6903154: Revert "This implements per-isolate locking and unlocking, including tests" (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 7 months 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/top.cc ('k') | test/cctest/SConscript » ('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 25 matching lines...) Expand all
36 36
37 namespace v8 { 37 namespace v8 {
38 38
39 39
40 // Track whether this V8 instance has ever called v8::Locker. This allows the 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. 41 // API code to verify that the lock is always held when V8 is being entered.
42 bool Locker::active_ = false; 42 bool Locker::active_ = false;
43 43
44 44
45 // Constructor for the Locker object. Once the Locker is constructed the 45 // Constructor for the Locker object. Once the Locker is constructed the
46 // current thread will be guaranteed to have the lock for a given isolate. 46 // current thread will be guaranteed to have the big V8 lock.
47 Locker::Locker(v8::Isolate* isolate) 47 Locker::Locker() : has_lock_(false), top_level_(true) {
48 : has_lock_(false), 48 // TODO(isolates): When Locker has Isolate parameter and it is provided, grab
49 top_level_(false), 49 // that one instead of using the current one.
50 isolate_(reinterpret_cast<i::Isolate*>(isolate)) { 50 // We pull default isolate for Locker constructor w/o p[arameter.
51 if (isolate_ == NULL) { 51 // A thread should not enter an isolate before acquiring a lock,
52 isolate_ = i::Isolate::GetDefaultIsolateForLocking(); 52 // in cases which mandate using Lockers.
53 } 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
54 // Record that the Locker has been used at least once. 59 // Record that the Locker has been used at least once.
55 active_ = true; 60 active_ = true;
56 // Get the big lock if necessary. 61 // Get the big lock if necessary.
57 if (!isolate_->thread_manager()->IsLockedByCurrentThread()) { 62 if (!isolate->thread_manager()->IsLockedByCurrentThread()) {
58 isolate_->thread_manager()->Lock(); 63 isolate->thread_manager()->Lock();
59 has_lock_ = true; 64 has_lock_ = true;
60 65
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
61 // Make sure that V8 is initialized. Archiving of threads interferes 74 // Make sure that V8 is initialized. Archiving of threads interferes
62 // with deserialization by adding additional root pointers, so we must 75 // with deserialization by adding additional root pointers, so we must
63 // initialize here, before anyone can call ~Locker() or Unlocker(). 76 // initialize here, before anyone can call ~Locker() or Unlocker().
64 if (isolate_->IsDefaultIsolate()) { 77 if (!isolate->IsInitialized()) {
65 // This only enters if not yet entered.
66 internal::Isolate::EnterDefaultIsolate();
67 } else if (!isolate_->IsInitialized()) {
68 isolate_->Enter();
69 V8::Initialize(); 78 V8::Initialize();
70 isolate_->Exit();
71 } 79 }
72
73 // This may be a locker within an unlocker in which case we have to 80 // This may be a locker within an unlocker in which case we have to
74 // get the saved state for this thread and restore it. 81 // get the saved state for this thread and restore it.
75 if (isolate_->thread_manager()->RestoreThread()) { 82 if (isolate->thread_manager()->RestoreThread()) {
76 top_level_ = false; 83 top_level_ = false;
77 } else { 84 } else {
78 internal::ExecutionAccess access(isolate_); 85 internal::ExecutionAccess access(isolate);
79 isolate_->stack_guard()->ClearThread(access); 86 isolate->stack_guard()->ClearThread(access);
80 isolate_->stack_guard()->InitThread(access); 87 isolate->stack_guard()->InitThread(access);
81 } 88 }
82 } 89 }
83 ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread()); 90 ASSERT(isolate->thread_manager()->IsLockedByCurrentThread());
84 } 91 }
85 92
86 93
87 bool Locker::IsLocked(v8::Isolate* isolate) { 94 bool Locker::IsLocked() {
88 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); 95 return internal::Isolate::Current()->thread_manager()->
89 if (internal_isolate == NULL) { 96 IsLockedByCurrentThread();
90 internal_isolate = i::Isolate::GetDefaultIsolateForLocking();
91 }
92 return internal_isolate->thread_manager()->IsLockedByCurrentThread();
93 } 97 }
94 98
95 99
96 Locker::~Locker() { 100 Locker::~Locker() {
97 ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread()); 101 // 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());
98 if (has_lock_) { 105 if (has_lock_) {
99 if (top_level_) { 106 if (top_level_) {
100 isolate_->thread_manager()->FreeThreadResources(); 107 isolate->thread_manager()->FreeThreadResources();
101 } else { 108 } else {
102 isolate_->thread_manager()->ArchiveThread(); 109 isolate->thread_manager()->ArchiveThread();
103 } 110 }
104 isolate_->thread_manager()->Unlock(); 111 isolate->thread_manager()->Unlock();
105 } 112 }
106 } 113 }
107 114
108 115
109 Unlocker::Unlocker(v8::Isolate* isolate) 116 Unlocker::Unlocker() {
110 : isolate_(reinterpret_cast<i::Isolate*>(isolate)) { 117 internal::Isolate* isolate = internal::Isolate::Current();
111 if (isolate_ == NULL) { 118 ASSERT(isolate->thread_manager()->IsLockedByCurrentThread());
112 isolate_ = i::Isolate::GetDefaultIsolateForLocking(); 119 isolate->thread_manager()->ArchiveThread();
113 } 120 isolate->thread_manager()->Unlock();
114
115 ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
116 isolate_->thread_manager()->ArchiveThread();
117 isolate_->thread_manager()->Unlock();
118 } 121 }
119 122
120 123
121 Unlocker::~Unlocker() { 124 Unlocker::~Unlocker() {
122 ASSERT(!isolate_->thread_manager()->IsLockedByCurrentThread()); 125 // TODO(isolates): check it's the isolate we unlocked.
123 isolate_->thread_manager()->Lock(); 126 internal::Isolate* isolate = internal::Isolate::Current();
124 isolate_->thread_manager()->RestoreThread(); 127 ASSERT(!isolate->thread_manager()->IsLockedByCurrentThread());
128 isolate->thread_manager()->Lock();
129 isolate->thread_manager()->RestoreThread();
125 } 130 }
126 131
127 132
128 void Locker::StartPreemption(int every_n_ms) { 133 void Locker::StartPreemption(int every_n_ms) {
129 v8::internal::ContextSwitcher::StartPreemption(every_n_ms); 134 v8::internal::ContextSwitcher::StartPreemption(every_n_ms);
130 } 135 }
131 136
132 137
133 void Locker::StopPreemption() { 138 void Locker::StopPreemption() {
134 v8::internal::ContextSwitcher::StopPreemption(); 139 v8::internal::ContextSwitcher::StopPreemption();
135 } 140 }
136 141
137 142
138 namespace internal { 143 namespace internal {
139 144
140 145
141 bool ThreadManager::RestoreThread() { 146 bool ThreadManager::RestoreThread() {
142 ASSERT(IsLockedByCurrentThread());
143 // First check whether the current thread has been 'lazily archived', ie 147 // First check whether the current thread has been 'lazily archived', ie
144 // not archived at all. If that is the case we put the state storage we 148 // not archived at all. If that is the case we put the state storage we
145 // had prepared back in the free list, since we didn't need it after all. 149 // had prepared back in the free list, since we didn't need it after all.
146 if (lazily_archived_thread_.Equals(ThreadId::Current())) { 150 if (lazily_archived_thread_.Equals(ThreadId::Current())) {
147 lazily_archived_thread_ = ThreadId::Invalid(); 151 lazily_archived_thread_ = ThreadId::Invalid();
148 Isolate::PerIsolateThreadData* per_thread = 152 ASSERT(Isolate::CurrentPerIsolateThreadData()->thread_state() ==
149 isolate_->FindPerThreadDataForThisThread(); 153 lazily_archived_thread_state_);
150 ASSERT(per_thread != NULL);
151 ASSERT(per_thread->thread_state() == lazily_archived_thread_state_);
152 lazily_archived_thread_state_->set_id(ThreadId::Invalid()); 154 lazily_archived_thread_state_->set_id(ThreadId::Invalid());
153 lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST); 155 lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST);
154 lazily_archived_thread_state_ = NULL; 156 lazily_archived_thread_state_ = NULL;
155 per_thread->set_thread_state(NULL); 157 Isolate::CurrentPerIsolateThreadData()->set_thread_state(NULL);
156 return true; 158 return true;
157 } 159 }
158 160
159 // Make sure that the preemption thread cannot modify the thread state while 161 // Make sure that the preemption thread cannot modify the thread state while
160 // it is being archived or restored. 162 // it is being archived or restored.
161 ExecutionAccess access(isolate_); 163 ExecutionAccess access(isolate_);
162 164
163 // If there is another thread that was lazily archived then we have to really 165 // If there is another thread that was lazily archived then we have to really
164 // archive it now. 166 // archive it now.
165 if (lazily_archived_thread_.IsValid()) { 167 if (lazily_archived_thread_.IsValid()) {
166 EagerlyArchiveThread(); 168 EagerlyArchiveThread();
167 } 169 }
168 Isolate::PerIsolateThreadData* per_thread = 170 Isolate::PerIsolateThreadData* per_thread =
169 isolate_->FindPerThreadDataForThisThread(); 171 Isolate::CurrentPerIsolateThreadData();
170 if (per_thread == NULL || per_thread->thread_state() == NULL) { 172 if (per_thread == NULL || per_thread->thread_state() == NULL) {
171 // This is a new thread. 173 // This is a new thread.
172 isolate_->stack_guard()->InitThread(access); 174 isolate_->stack_guard()->InitThread(access);
173 return false; 175 return false;
174 } 176 }
175 ThreadState* state = per_thread->thread_state(); 177 ThreadState* state = per_thread->thread_state();
176 char* from = state->data(); 178 char* from = state->data();
177 from = isolate_->handle_scope_implementer()->RestoreThread(from); 179 from = isolate_->handle_scope_implementer()->RestoreThread(from);
178 from = isolate_->RestoreThread(from); 180 from = isolate_->RestoreThread(from);
179 from = Relocatable::RestoreState(isolate_, from); 181 from = Relocatable::RestoreState(from);
180 #ifdef ENABLE_DEBUGGER_SUPPORT 182 #ifdef ENABLE_DEBUGGER_SUPPORT
181 from = isolate_->debug()->RestoreDebug(from); 183 from = isolate_->debug()->RestoreDebug(from);
182 #endif 184 #endif
183 from = isolate_->stack_guard()->RestoreStackGuard(from); 185 from = isolate_->stack_guard()->RestoreStackGuard(from);
184 from = isolate_->regexp_stack()->RestoreStack(from); 186 from = isolate_->regexp_stack()->RestoreStack(from);
185 from = isolate_->bootstrapper()->RestoreState(from); 187 from = isolate_->bootstrapper()->RestoreState(from);
186 per_thread->set_thread_state(NULL); 188 per_thread->set_thread_state(NULL);
187 if (state->terminate_on_restore()) { 189 if (state->terminate_on_restore()) {
188 isolate_->stack_guard()->TerminateExecution(); 190 isolate_->stack_guard()->TerminateExecution();
189 state->set_terminate_on_restore(false); 191 state->set_terminate_on_restore(false);
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 293
292 294
293 ThreadManager::~ThreadManager() { 295 ThreadManager::~ThreadManager() {
294 // TODO(isolates): Destroy mutexes. 296 // TODO(isolates): Destroy mutexes.
295 } 297 }
296 298
297 299
298 void ThreadManager::ArchiveThread() { 300 void ThreadManager::ArchiveThread() {
299 ASSERT(lazily_archived_thread_.Equals(ThreadId::Invalid())); 301 ASSERT(lazily_archived_thread_.Equals(ThreadId::Invalid()));
300 ASSERT(!IsArchived()); 302 ASSERT(!IsArchived());
301 ASSERT(IsLockedByCurrentThread());
302 ThreadState* state = GetFreeThreadState(); 303 ThreadState* state = GetFreeThreadState();
303 state->Unlink(); 304 state->Unlink();
304 Isolate::PerIsolateThreadData* per_thread = 305 Isolate::CurrentPerIsolateThreadData()->set_thread_state(state);
305 isolate_->FindOrAllocatePerThreadDataForThisThread();
306 per_thread->set_thread_state(state);
307 lazily_archived_thread_ = ThreadId::Current(); 306 lazily_archived_thread_ = ThreadId::Current();
308 lazily_archived_thread_state_ = state; 307 lazily_archived_thread_state_ = state;
309 ASSERT(state->id().Equals(ThreadId::Invalid())); 308 ASSERT(state->id().Equals(ThreadId::Invalid()));
310 state->set_id(CurrentId()); 309 state->set_id(CurrentId());
311 ASSERT(!state->id().Equals(ThreadId::Invalid())); 310 ASSERT(!state->id().Equals(ThreadId::Invalid()));
312 } 311 }
313 312
314 313
315 void ThreadManager::EagerlyArchiveThread() { 314 void ThreadManager::EagerlyArchiveThread() {
316 ASSERT(IsLockedByCurrentThread());
317 ThreadState* state = lazily_archived_thread_state_; 315 ThreadState* state = lazily_archived_thread_state_;
318 state->LinkInto(ThreadState::IN_USE_LIST); 316 state->LinkInto(ThreadState::IN_USE_LIST);
319 char* to = state->data(); 317 char* to = state->data();
320 // Ensure that data containing GC roots are archived first, and handle them 318 // Ensure that data containing GC roots are archived first, and handle them
321 // in ThreadManager::Iterate(ObjectVisitor*). 319 // in ThreadManager::Iterate(ObjectVisitor*).
322 to = isolate_->handle_scope_implementer()->ArchiveThread(to); 320 to = isolate_->handle_scope_implementer()->ArchiveThread(to);
323 to = isolate_->ArchiveThread(to); 321 to = isolate_->ArchiveThread(to);
324 to = Relocatable::ArchiveState(isolate_, to); 322 to = Relocatable::ArchiveState(to);
325 #ifdef ENABLE_DEBUGGER_SUPPORT 323 #ifdef ENABLE_DEBUGGER_SUPPORT
326 to = isolate_->debug()->ArchiveDebug(to); 324 to = isolate_->debug()->ArchiveDebug(to);
327 #endif 325 #endif
328 to = isolate_->stack_guard()->ArchiveStackGuard(to); 326 to = isolate_->stack_guard()->ArchiveStackGuard(to);
329 to = isolate_->regexp_stack()->ArchiveStack(to); 327 to = isolate_->regexp_stack()->ArchiveStack(to);
330 to = isolate_->bootstrapper()->ArchiveState(to); 328 to = isolate_->bootstrapper()->ArchiveState(to);
331 lazily_archived_thread_ = ThreadId::Invalid(); 329 lazily_archived_thread_ = ThreadId::Invalid();
332 lazily_archived_thread_state_ = NULL; 330 lazily_archived_thread_state_ = NULL;
333 } 331 }
334 332
335 333
336 void ThreadManager::FreeThreadResources() { 334 void ThreadManager::FreeThreadResources() {
337 isolate_->handle_scope_implementer()->FreeThreadResources(); 335 isolate_->handle_scope_implementer()->FreeThreadResources();
338 isolate_->FreeThreadResources(); 336 isolate_->FreeThreadResources();
339 #ifdef ENABLE_DEBUGGER_SUPPORT 337 #ifdef ENABLE_DEBUGGER_SUPPORT
340 isolate_->debug()->FreeThreadResources(); 338 isolate_->debug()->FreeThreadResources();
341 #endif 339 #endif
342 isolate_->stack_guard()->FreeThreadResources(); 340 isolate_->stack_guard()->FreeThreadResources();
343 isolate_->regexp_stack()->FreeThreadResources(); 341 isolate_->regexp_stack()->FreeThreadResources();
344 isolate_->bootstrapper()->FreeThreadResources(); 342 isolate_->bootstrapper()->FreeThreadResources();
345 } 343 }
346 344
347 345
348 bool ThreadManager::IsArchived() { 346 bool ThreadManager::IsArchived() {
349 Isolate::PerIsolateThreadData* data = 347 Isolate::PerIsolateThreadData* data = Isolate::CurrentPerIsolateThreadData();
350 isolate_->FindPerThreadDataForThisThread();
351 return data != NULL && data->thread_state() != NULL; 348 return data != NULL && data->thread_state() != NULL;
352 } 349 }
353 350
351
354 void ThreadManager::Iterate(ObjectVisitor* v) { 352 void ThreadManager::Iterate(ObjectVisitor* v) {
355 // Expecting no threads during serialization/deserialization 353 // Expecting no threads during serialization/deserialization
356 for (ThreadState* state = FirstThreadStateInUse(); 354 for (ThreadState* state = FirstThreadStateInUse();
357 state != NULL; 355 state != NULL;
358 state = state->Next()) { 356 state = state->Next()) {
359 char* data = state->data(); 357 char* data = state->data();
360 data = HandleScopeImplementer::Iterate(v, data); 358 data = HandleScopeImplementer::Iterate(v, data);
361 data = isolate_->Iterate(v, data); 359 data = isolate_->Iterate(v, data);
362 data = Relocatable::Iterate(v, data); 360 data = Relocatable::Iterate(v, data);
363 } 361 }
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 // Acknowledge the preemption by the receiving thread. 444 // Acknowledge the preemption by the receiving thread.
447 void ContextSwitcher::PreemptionReceived() { 445 void ContextSwitcher::PreemptionReceived() {
448 ASSERT(Locker::IsLocked()); 446 ASSERT(Locker::IsLocked());
449 // There is currently no accounting being done for this. But could be in the 447 // There is currently no accounting being done for this. But could be in the
450 // future, which is why we leave this in. 448 // future, which is why we leave this in.
451 } 449 }
452 450
453 451
454 } // namespace internal 452 } // namespace internal
455 } // namespace v8 453 } // namespace v8
OLDNEW
« no previous file with comments | « src/top.cc ('k') | test/cctest/SConscript » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698