| 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 20 matching lines...) Expand all Loading... |
| 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 = | 39 static internal::Thread::LocalStorageKey thread_state_key = |
| 40 internal::Thread::CreateThreadLocalKey(); | 40 internal::Thread::CreateThreadLocalKey(); |
| 41 static internal::Thread::LocalStorageKey thread_id_key = |
| 42 internal::Thread::CreateThreadLocalKey(); |
| 41 | 43 |
| 42 | 44 |
| 43 // 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 |
| 44 // 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. |
| 45 bool Locker::active_ = false; | 47 bool Locker::active_ = false; |
| 46 | 48 |
| 47 | 49 |
| 48 // Constructor for the Locker object. Once the Locker is constructed the | 50 // Constructor for the Locker object. Once the Locker is constructed the |
| 49 // current thread will be guaranteed to have the big V8 lock. | 51 // current thread will be guaranteed to have the big V8 lock. |
| 50 Locker::Locker() : has_lock_(false), top_level_(true) { | 52 Locker::Locker() : has_lock_(false), top_level_(true) { |
| 51 // Record that the Locker has been used at least once. | 53 // Record that the Locker has been used at least once. |
| 52 active_ = true; | 54 active_ = true; |
| 53 // Get the big lock if necessary. | 55 // Get the big lock if necessary. |
| 54 if (!internal::ThreadManager::IsLockedByCurrentThread()) { | 56 if (!internal::ThreadManager::IsLockedByCurrentThread()) { |
| 55 internal::ThreadManager::Lock(); | 57 internal::ThreadManager::Lock(); |
| 56 has_lock_ = true; | 58 has_lock_ = true; |
| 57 // This may be a locker within an unlocker in which case we have to | 59 // This may be a locker within an unlocker in which case we have to |
| 58 // get the saved state for this thread and restore it. | 60 // get the saved state for this thread and restore it. |
| 59 if (internal::ThreadManager::RestoreThread()) { | 61 if (internal::ThreadManager::RestoreThread()) { |
| 60 top_level_ = false; | 62 top_level_ = false; |
| 61 } | 63 } |
| 62 } | 64 } |
| 63 ASSERT(internal::ThreadManager::IsLockedByCurrentThread()); | 65 ASSERT(internal::ThreadManager::IsLockedByCurrentThread()); |
| 66 |
| 67 // Make sure this thread is assigned a thread id. |
| 68 internal::ThreadManager::AssignId(); |
| 64 } | 69 } |
| 65 | 70 |
| 66 | 71 |
| 67 bool Locker::IsLocked() { | 72 bool Locker::IsLocked() { |
| 68 return internal::ThreadManager::IsLockedByCurrentThread(); | 73 return internal::ThreadManager::IsLockedByCurrentThread(); |
| 69 } | 74 } |
| 70 | 75 |
| 71 | 76 |
| 72 Locker::~Locker() { | 77 Locker::~Locker() { |
| 73 ASSERT(internal::ThreadManager::IsLockedByCurrentThread()); | 78 ASSERT(internal::ThreadManager::IsLockedByCurrentThread()); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 | 113 |
| 109 | 114 |
| 110 bool ThreadManager::RestoreThread() { | 115 bool ThreadManager::RestoreThread() { |
| 111 // First check whether the current thread has been 'lazily archived', ie | 116 // First check whether the current thread has been 'lazily archived', ie |
| 112 // not archived at all. If that is the case we put the state storage we | 117 // not archived at all. If that is the case we put the state storage we |
| 113 // had prepared back in the free list, since we didn't need it after all. | 118 // had prepared back in the free list, since we didn't need it after all. |
| 114 if (lazily_archived_thread_.IsSelf()) { | 119 if (lazily_archived_thread_.IsSelf()) { |
| 115 lazily_archived_thread_.Initialize(ThreadHandle::INVALID); | 120 lazily_archived_thread_.Initialize(ThreadHandle::INVALID); |
| 116 ASSERT(Thread::GetThreadLocal(thread_state_key) == | 121 ASSERT(Thread::GetThreadLocal(thread_state_key) == |
| 117 lazily_archived_thread_state_); | 122 lazily_archived_thread_state_); |
| 123 lazily_archived_thread_state_->set_id(kInvalidId); |
| 118 lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST); | 124 lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST); |
| 119 lazily_archived_thread_state_ = NULL; | 125 lazily_archived_thread_state_ = NULL; |
| 120 Thread::SetThreadLocal(thread_state_key, NULL); | 126 Thread::SetThreadLocal(thread_state_key, NULL); |
| 121 return true; | 127 return true; |
| 122 } | 128 } |
| 123 | 129 |
| 124 // Make sure that the preemption thread cannot modify the thread state while | 130 // Make sure that the preemption thread cannot modify the thread state while |
| 125 // it is being archived or restored. | 131 // it is being archived or restored. |
| 126 ExecutionAccess access; | 132 ExecutionAccess access; |
| 127 | 133 |
| 128 // If there is another thread that was lazily archived then we have to really | 134 // If there is another thread that was lazily archived then we have to really |
| 129 // archive it now. | 135 // archive it now. |
| 130 if (lazily_archived_thread_.IsValid()) { | 136 if (lazily_archived_thread_.IsValid()) { |
| 131 EagerlyArchiveThread(); | 137 EagerlyArchiveThread(); |
| 132 } | 138 } |
| 133 ThreadState* state = | 139 ThreadState* state = |
| 134 reinterpret_cast<ThreadState*>(Thread::GetThreadLocal(thread_state_key)); | 140 reinterpret_cast<ThreadState*>(Thread::GetThreadLocal(thread_state_key)); |
| 135 if (state == NULL) { | 141 if (state == NULL) { |
| 136 return false; | 142 return false; |
| 137 } | 143 } |
| 138 char* from = state->data(); | 144 char* from = state->data(); |
| 139 from = HandleScopeImplementer::RestoreThread(from); | 145 from = HandleScopeImplementer::RestoreThread(from); |
| 140 from = Top::RestoreThread(from); | 146 from = Top::RestoreThread(from); |
| 141 from = Debug::RestoreDebug(from); | 147 from = Debug::RestoreDebug(from); |
| 142 from = StackGuard::RestoreStackGuard(from); | 148 from = StackGuard::RestoreStackGuard(from); |
| 143 from = RegExpStack::RestoreStack(from); | 149 from = RegExpStack::RestoreStack(from); |
| 144 from = Bootstrapper::RestoreState(from); | 150 from = Bootstrapper::RestoreState(from); |
| 145 Thread::SetThreadLocal(thread_state_key, NULL); | 151 Thread::SetThreadLocal(thread_state_key, NULL); |
| 152 state->set_id(kInvalidId); |
| 146 state->Unlink(); | 153 state->Unlink(); |
| 147 state->LinkInto(ThreadState::FREE_LIST); | 154 state->LinkInto(ThreadState::FREE_LIST); |
| 148 return true; | 155 return true; |
| 149 } | 156 } |
| 150 | 157 |
| 151 | 158 |
| 152 void ThreadManager::Lock() { | 159 void ThreadManager::Lock() { |
| 153 mutex_->Lock(); | 160 mutex_->Lock(); |
| 154 mutex_owner_.Initialize(ThreadHandle::SELF); | 161 mutex_owner_.Initialize(ThreadHandle::SELF); |
| 155 ASSERT(IsLockedByCurrentThread()); | 162 ASSERT(IsLockedByCurrentThread()); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 169 StackGuard::ArchiveSpacePerThread() + | 176 StackGuard::ArchiveSpacePerThread() + |
| 170 RegExpStack::ArchiveSpacePerThread() + | 177 RegExpStack::ArchiveSpacePerThread() + |
| 171 Bootstrapper::ArchiveSpacePerThread(); | 178 Bootstrapper::ArchiveSpacePerThread(); |
| 172 } | 179 } |
| 173 | 180 |
| 174 | 181 |
| 175 ThreadState* ThreadState::free_anchor_ = new ThreadState(); | 182 ThreadState* ThreadState::free_anchor_ = new ThreadState(); |
| 176 ThreadState* ThreadState::in_use_anchor_ = new ThreadState(); | 183 ThreadState* ThreadState::in_use_anchor_ = new ThreadState(); |
| 177 | 184 |
| 178 | 185 |
| 179 ThreadState::ThreadState() : next_(this), previous_(this) { | 186 ThreadState::ThreadState() : id_(ThreadManager::kInvalidId), |
| 187 next_(this), previous_(this) { |
| 180 } | 188 } |
| 181 | 189 |
| 182 | 190 |
| 183 void ThreadState::AllocateSpace() { | 191 void ThreadState::AllocateSpace() { |
| 184 data_ = NewArray<char>(ArchiveSpacePerThread()); | 192 data_ = NewArray<char>(ArchiveSpacePerThread()); |
| 185 } | 193 } |
| 186 | 194 |
| 187 | 195 |
| 188 void ThreadState::Unlink() { | 196 void ThreadState::Unlink() { |
| 189 next_->previous_ = previous_; | 197 next_->previous_ = previous_; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 217 return in_use_anchor_->Next(); | 225 return in_use_anchor_->Next(); |
| 218 } | 226 } |
| 219 | 227 |
| 220 | 228 |
| 221 ThreadState* ThreadState::Next() { | 229 ThreadState* ThreadState::Next() { |
| 222 if (next_ == in_use_anchor_) return NULL; | 230 if (next_ == in_use_anchor_) return NULL; |
| 223 return next_; | 231 return next_; |
| 224 } | 232 } |
| 225 | 233 |
| 226 | 234 |
| 235 int ThreadManager::next_id_ = 0; |
| 227 Mutex* ThreadManager::mutex_ = OS::CreateMutex(); | 236 Mutex* ThreadManager::mutex_ = OS::CreateMutex(); |
| 228 ThreadHandle ThreadManager::mutex_owner_(ThreadHandle::INVALID); | 237 ThreadHandle ThreadManager::mutex_owner_(ThreadHandle::INVALID); |
| 229 ThreadHandle ThreadManager::lazily_archived_thread_(ThreadHandle::INVALID); | 238 ThreadHandle ThreadManager::lazily_archived_thread_(ThreadHandle::INVALID); |
| 230 ThreadState* ThreadManager::lazily_archived_thread_state_ = NULL; | 239 ThreadState* ThreadManager::lazily_archived_thread_state_ = NULL; |
| 231 | 240 |
| 232 | 241 |
| 233 void ThreadManager::ArchiveThread() { | 242 void ThreadManager::ArchiveThread() { |
| 234 ASSERT(!lazily_archived_thread_.IsValid()); | 243 ASSERT(!lazily_archived_thread_.IsValid()); |
| 235 ASSERT(Thread::GetThreadLocal(thread_state_key) == NULL); | 244 ASSERT(Thread::GetThreadLocal(thread_state_key) == NULL); |
| 236 ThreadState* state = ThreadState::GetFree(); | 245 ThreadState* state = ThreadState::GetFree(); |
| 237 state->Unlink(); | 246 state->Unlink(); |
| 238 Thread::SetThreadLocal(thread_state_key, reinterpret_cast<void*>(state)); | 247 Thread::SetThreadLocal(thread_state_key, reinterpret_cast<void*>(state)); |
| 239 lazily_archived_thread_.Initialize(ThreadHandle::SELF); | 248 lazily_archived_thread_.Initialize(ThreadHandle::SELF); |
| 240 lazily_archived_thread_state_ = state; | 249 lazily_archived_thread_state_ = state; |
| 250 ASSERT(state->id() == kInvalidId); |
| 251 state->set_id(CurrentId()); |
| 252 ASSERT(state->id() != kInvalidId); |
| 241 } | 253 } |
| 242 | 254 |
| 243 | 255 |
| 244 void ThreadManager::EagerlyArchiveThread() { | 256 void ThreadManager::EagerlyArchiveThread() { |
| 245 ThreadState* state = lazily_archived_thread_state_; | 257 ThreadState* state = lazily_archived_thread_state_; |
| 246 state->LinkInto(ThreadState::IN_USE_LIST); | 258 state->LinkInto(ThreadState::IN_USE_LIST); |
| 247 char* to = state->data(); | 259 char* to = state->data(); |
| 248 to = HandleScopeImplementer::ArchiveThread(to); | 260 to = HandleScopeImplementer::ArchiveThread(to); |
| 249 to = Top::ArchiveThread(to); | 261 to = Top::ArchiveThread(to); |
| 250 to = Debug::ArchiveDebug(to); | 262 to = Debug::ArchiveDebug(to); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 for (ThreadState* state = ThreadState::FirstInUse(); | 295 for (ThreadState* state = ThreadState::FirstInUse(); |
| 284 state != NULL; | 296 state != NULL; |
| 285 state = state->Next()) { | 297 state = state->Next()) { |
| 286 char* data = state->data(); | 298 char* data = state->data(); |
| 287 data += HandleScopeImplementer::ArchiveSpacePerThread(); | 299 data += HandleScopeImplementer::ArchiveSpacePerThread(); |
| 288 Top::MarkCompactEpilogue(is_compacting, data); | 300 Top::MarkCompactEpilogue(is_compacting, data); |
| 289 } | 301 } |
| 290 } | 302 } |
| 291 | 303 |
| 292 | 304 |
| 305 int ThreadManager::CurrentId() { |
| 306 return bit_cast<int, void*>(Thread::GetThreadLocal(thread_id_key)); |
| 307 } |
| 308 |
| 309 |
| 310 void ThreadManager::AssignId() { |
| 311 if (Thread::GetThreadLocal(thread_id_key) == NULL) { |
| 312 Thread::SetThreadLocal(thread_id_key, bit_cast<void*, int>(next_id_++)); |
| 313 } |
| 314 } |
| 315 |
| 316 |
| 293 // This is the ContextSwitcher singleton. There is at most a single thread | 317 // This is the ContextSwitcher singleton. There is at most a single thread |
| 294 // running which delivers preemption events to V8 threads. | 318 // running which delivers preemption events to V8 threads. |
| 295 ContextSwitcher* ContextSwitcher::singleton_ = NULL; | 319 ContextSwitcher* ContextSwitcher::singleton_ = NULL; |
| 296 | 320 |
| 297 | 321 |
| 298 ContextSwitcher::ContextSwitcher(int every_n_ms) | 322 ContextSwitcher::ContextSwitcher(int every_n_ms) |
| 299 : keep_going_(true), | 323 : keep_going_(true), |
| 300 sleep_ms_(every_n_ms) { | 324 sleep_ms_(every_n_ms) { |
| 301 } | 325 } |
| 302 | 326 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 346 // Acknowledge the preemption by the receiving thread. | 370 // Acknowledge the preemption by the receiving thread. |
| 347 void ContextSwitcher::PreemptionReceived() { | 371 void ContextSwitcher::PreemptionReceived() { |
| 348 ASSERT(Locker::IsLocked()); | 372 ASSERT(Locker::IsLocked()); |
| 349 // There is currently no accounting being done for this. But could be in the | 373 // There is currently no accounting being done for this. But could be in the |
| 350 // future, which is why we leave this in. | 374 // future, which is why we leave this in. |
| 351 } | 375 } |
| 352 | 376 |
| 353 | 377 |
| 354 } // namespace internal | 378 } // namespace internal |
| 355 } // namespace v8 | 379 } // namespace v8 |
| OLD | NEW |