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

Side by Side Diff: src/v8threads.cc

Issue 503022: Add locker support to DebugMessageDispatchHandler (Closed)
Patch Set: make compilable with debugger support off 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
« no previous file with comments | « src/v8threads.h ('k') | no next file » | 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 28 matching lines...) Expand all
39 static internal::Thread::LocalStorageKey thread_state_key = 39 static internal::Thread::LocalStorageKey thread_state_key =
40 internal::Thread::CreateThreadLocalKey(); 40 internal::Thread::CreateThreadLocalKey();
41 static internal::Thread::LocalStorageKey thread_id_key = 41 static internal::Thread::LocalStorageKey thread_id_key =
42 internal::Thread::CreateThreadLocalKey(); 42 internal::Thread::CreateThreadLocalKey();
43 43
44 44
45 // Track whether this V8 instance has ever called v8::Locker. This allows the 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. 46 // API code to verify that the lock is always held when V8 is being entered.
47 bool Locker::active_ = false; 47 bool Locker::active_ = false;
48 48
49
50 // Constructor for the Locker object. Once the Locker is constructed the 49 // Constructor for the Locker object. Once the Locker is constructed the
51 // current thread will be guaranteed to have the big V8 lock. 50 // current thread will be guaranteed to have the big V8 lock.
52 Locker::Locker() : has_lock_(false), top_level_(true) { 51 Locker::Locker(LockParameters* lock_parameters) : has_lock_(false), top_level_(t rue) {
53 // Record that the Locker has been used at least once. 52 // Record that the Locker has been used at least once.
54 active_ = true; 53 active_ = true;
54 effective_ = false;
55 // Get the big lock if necessary. 55 // Get the big lock if necessary.
56 if (!internal::ThreadManager::IsLockedByCurrentThread()) { 56 if (!internal::ThreadManager::IsLockedByCurrentThread()) {
57
58 #ifdef ENABLE_DEBUGGER_SUPPORT
59 if (lock_parameters == NULL) {
60 internal::ThreadManager::Lock();
61 } else {
62 bool res = internal::ThreadManager::LockOrAsk(&internal::Promises::promise _to_process_debug_commands);
63 if (!res) {
64 lock_parameters->successfully_relaied = true;
65 return;
66 }
67 }
68 #else
57 internal::ThreadManager::Lock(); 69 internal::ThreadManager::Lock();
70 #endif
58 has_lock_ = true; 71 has_lock_ = true;
59 // Make sure that V8 is initialized. Archiving of threads interferes 72 // Make sure that V8 is initialized. Archiving of threads interferes
60 // with deserialization by adding additional root pointers, so we must 73 // with deserialization by adding additional root pointers, so we must
61 // initialize here, before anyone can call ~Locker() or Unlocker(). 74 // initialize here, before anyone can call ~Locker() or Unlocker().
62 if (!internal::V8::IsRunning()) { 75 if (!internal::V8::IsRunning()) {
63 V8::Initialize(); 76 V8::Initialize();
64 } 77 }
65 // This may be a locker within an unlocker in which case we have to 78 // 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. 79 // get the saved state for this thread and restore it.
67 if (internal::ThreadManager::RestoreThread()) { 80 if (internal::ThreadManager::RestoreThread()) {
68 top_level_ = false; 81 top_level_ = false;
69 } else { 82 } else {
70 internal::ExecutionAccess access; 83 internal::ExecutionAccess access;
71 internal::StackGuard::ClearThread(access); 84 internal::StackGuard::ClearThread(access);
72 internal::StackGuard::InitThread(access); 85 internal::StackGuard::InitThread(access);
73 } 86 }
74 } 87 }
75 ASSERT(internal::ThreadManager::IsLockedByCurrentThread()); 88 ASSERT(internal::ThreadManager::IsLockedByCurrentThread());
76 89
77 // Make sure this thread is assigned a thread id. 90 // Make sure this thread is assigned a thread id.
78 internal::ThreadManager::AssignId(); 91 internal::ThreadManager::AssignId();
92 effective_ = true;
79 } 93 }
80 94
81 95
82 bool Locker::IsLocked() { 96 bool Locker::IsLocked() {
83 return internal::ThreadManager::IsLockedByCurrentThread(); 97 return internal::ThreadManager::IsLockedByCurrentThread();
84 } 98 }
85 99
86 100
87 Locker::~Locker() { 101 Locker::~Locker() {
102 if (!effective_) {
103 return;
104 }
88 ASSERT(internal::ThreadManager::IsLockedByCurrentThread()); 105 ASSERT(internal::ThreadManager::IsLockedByCurrentThread());
89 if (has_lock_) { 106 if (has_lock_) {
90 if (top_level_) { 107 if (top_level_) {
91 internal::ThreadManager::FreeThreadResources(); 108 internal::ThreadManager::FreeThreadResources();
92 } else { 109 } else {
93 internal::ThreadManager::ArchiveThread(); 110 internal::ThreadManager::ArchiveThread();
94 } 111 }
95 internal::ThreadManager::Unlock(); 112 internal::ThreadManager::Unlock();
96 } 113 }
97 } 114 }
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 if (state->terminate_on_restore()) { 186 if (state->terminate_on_restore()) {
170 StackGuard::TerminateExecution(); 187 StackGuard::TerminateExecution();
171 state->set_terminate_on_restore(false); 188 state->set_terminate_on_restore(false);
172 } 189 }
173 state->set_id(kInvalidId); 190 state->set_id(kInvalidId);
174 state->Unlink(); 191 state->Unlink();
175 state->LinkInto(ThreadState::FREE_LIST); 192 state->LinkInto(ThreadState::FREE_LIST);
176 return true; 193 return true;
177 } 194 }
178 195
196 #ifdef ENABLE_DEBUGGER_SUPPORT
197
198 class PromisesHandler {
199 public:
200 static bool CanUnlock(Promises* promises) {
201 return !promises->promise_to_process_debug_commands;
202 }
203 static void KeepPromises(const Promises* promises) {
204 v8::Debug::ProcessDebuggerCommands();
205 }
206 };
207
208
209 MutexWithResponsibilities::MutexWithResponsibilities()
210 : flag_mutex_(OS::CreateMutex()),
211 sem_(OS::CreateSemaphore(1)), // Am I accurate with semaphore?
212 locked_(false)
213 {
214 }
215
216 MutexWithResponsibilities::~MutexWithResponsibilities() {
217 delete sem_;
218 delete flag_mutex_;
219 }
220
221
222 void MutexWithResponsibilities::Lock() {
223 while (true) {
224 {
225 ScopedLock lock(flag_mutex_);
226 if (!locked_) {
227 locked_ = true;
228 has_promises_ = true;
229 return;
230 }
231 }
232 sem_->Wait();
233 }
234 }
235
236 bool MutexWithResponsibilities::LockOrAsk(bool Promises::* promise) {
237 ScopedLock lock(flag_mutex_);
238 if (locked_) {
239 ASSERT(has_promises_);
240 promises_.*promise = true;
241 return false;
242 } else {
243 locked_ = true;
244 has_promises_ = false;
245 return true;
246 }
247 }
248
249 void MutexWithResponsibilities::Unlock() {
250 while (true) {
251 Promises promises_copy;
252 {
253 ScopedLock lock(flag_mutex_);
254 ASSERT(locked_);
255 bool has_to_do = has_promises_ && PromisesHandler::CanUnlock(&promises_);
256 if (!has_to_do) {
257 locked_ = false;
258 break;
259 }
260 promises_copy = promises_;
261 promises_.Reset();
262 }
263 PromisesHandler::KeepPromises(&promises_copy);
264 }
265 sem_->Signal();
266 }
267
268 #endif
269
270
179 271
180 void ThreadManager::Lock() { 272 void ThreadManager::Lock() {
181 mutex_->Lock(); 273 mutex_->Lock();
182 mutex_owner_.Initialize(ThreadHandle::SELF); 274 mutex_owner_.Initialize(ThreadHandle::SELF);
183 ASSERT(IsLockedByCurrentThread()); 275 ASSERT(IsLockedByCurrentThread());
184 } 276 }
185 277
186 278
187 void ThreadManager::Unlock() { 279 void ThreadManager::Unlock() {
188 mutex_owner_.Initialize(ThreadHandle::INVALID); 280 mutex_owner_.Initialize(ThreadHandle::INVALID);
189 mutex_->Unlock(); 281 mutex_->Unlock();
190 } 282 }
191 283
284 #ifdef ENABLE_DEBUGGER_SUPPORT
285 bool ThreadManager::LockOrAsk(bool Promises::* promise) {
286 bool res = mutex_->LockOrAsk(promise);
287 if (res) {
288 mutex_owner_.Initialize(ThreadHandle::SELF);
289 ASSERT(IsLockedByCurrentThread());
290 }
291 return res;
292 }
293 #endif
294
192 295
193 static int ArchiveSpacePerThread() { 296 static int ArchiveSpacePerThread() {
194 return HandleScopeImplementer::ArchiveSpacePerThread() + 297 return HandleScopeImplementer::ArchiveSpacePerThread() +
195 Top::ArchiveSpacePerThread() + 298 Top::ArchiveSpacePerThread() +
196 #ifdef ENABLE_DEBUGGER_SUPPORT 299 #ifdef ENABLE_DEBUGGER_SUPPORT
197 Debug::ArchiveSpacePerThread() + 300 Debug::ArchiveSpacePerThread() +
198 #endif 301 #endif
199 StackGuard::ArchiveSpacePerThread() + 302 StackGuard::ArchiveSpacePerThread() +
200 RegExpStack::ArchiveSpacePerThread() + 303 RegExpStack::ArchiveSpacePerThread() +
201 Bootstrapper::ArchiveSpacePerThread() + 304 Bootstrapper::ArchiveSpacePerThread() +
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 ThreadState* ThreadState::Next() { 357 ThreadState* ThreadState::Next() {
255 if (next_ == in_use_anchor_) return NULL; 358 if (next_ == in_use_anchor_) return NULL;
256 return next_; 359 return next_;
257 } 360 }
258 361
259 362
260 // Thread ids must start with 1, because in TLS having thread id 0 can't 363 // 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 364 // be distinguished from not having a thread id at all (since NULL is
262 // defined as 0.) 365 // defined as 0.)
263 int ThreadManager::last_id_ = 0; 366 int ThreadManager::last_id_ = 0;
367 #ifdef ENABLE_DEBUGGER_SUPPORT
368 MutexWithResponsibilities* ThreadManager::mutex_ = new MutexWithResponsibilities ;
369 #else
264 Mutex* ThreadManager::mutex_ = OS::CreateMutex(); 370 Mutex* ThreadManager::mutex_ = OS::CreateMutex();
371 #endif
265 ThreadHandle ThreadManager::mutex_owner_(ThreadHandle::INVALID); 372 ThreadHandle ThreadManager::mutex_owner_(ThreadHandle::INVALID);
266 ThreadHandle ThreadManager::lazily_archived_thread_(ThreadHandle::INVALID); 373 ThreadHandle ThreadManager::lazily_archived_thread_(ThreadHandle::INVALID);
267 ThreadState* ThreadManager::lazily_archived_thread_state_ = NULL; 374 ThreadState* ThreadManager::lazily_archived_thread_state_ = NULL;
268 375
269 376
270 void ThreadManager::ArchiveThread() { 377 void ThreadManager::ArchiveThread() {
271 ASSERT(!lazily_archived_thread_.IsValid()); 378 ASSERT(!lazily_archived_thread_.IsValid());
272 ASSERT(!IsArchived()); 379 ASSERT(!IsArchived());
273 ThreadState* state = ThreadState::GetFree(); 380 ThreadState* state = ThreadState::GetFree();
274 state->Unlink(); 381 state->Unlink();
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 // Acknowledge the preemption by the receiving thread. 548 // Acknowledge the preemption by the receiving thread.
442 void ContextSwitcher::PreemptionReceived() { 549 void ContextSwitcher::PreemptionReceived() {
443 ASSERT(Locker::IsLocked()); 550 ASSERT(Locker::IsLocked());
444 // There is currently no accounting being done for this. But could be in the 551 // There is currently no accounting being done for this. But could be in the
445 // future, which is why we leave this in. 552 // future, which is why we leave this in.
446 } 553 }
447 554
448 555
449 } // namespace internal 556 } // namespace internal
450 } // namespace v8 557 } // namespace v8
OLDNEW
« no previous file with comments | « src/v8threads.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698