OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |