ager@chromium.org | 9258b6b | 2008-09-11 09:11:10 +0000 | [diff] [blame] | 1 | // Copyright 2008 the V8 project authors. All rights reserved. |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 2 | // Redistribution and use in source and binary forms, with or without |
| 3 | // modification, are permitted provided that the following conditions are |
| 4 | // met: |
| 5 | // |
| 6 | // * Redistributions of source code must retain the above copyright |
| 7 | // notice, this list of conditions and the following disclaimer. |
| 8 | // * Redistributions in binary form must reproduce the above |
| 9 | // copyright notice, this list of conditions and the following |
| 10 | // disclaimer in the documentation and/or other materials provided |
| 11 | // with the distribution. |
| 12 | // * Neither the name of Google Inc. nor the names of its |
| 13 | // contributors may be used to endorse or promote products derived |
| 14 | // from this software without specific prior written permission. |
| 15 | // |
| 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | |
| 28 | #include "v8.h" |
| 29 | |
| 30 | #include "api.h" |
ager@chromium.org | ddb913d | 2009-01-27 10:01:48 +0000 | [diff] [blame] | 31 | #include "bootstrapper.h" |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 32 | #include "debug.h" |
| 33 | #include "execution.h" |
| 34 | #include "v8threads.h" |
ager@chromium.org | 3291210 | 2009-01-16 10:38:43 +0000 | [diff] [blame] | 35 | #include "regexp-stack.h" |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 36 | |
| 37 | namespace v8 { |
| 38 | |
| 39 | static internal::Thread::LocalStorageKey thread_state_key = |
| 40 | internal::Thread::CreateThreadLocalKey(); |
ager@chromium.org | bb29dc9 | 2009-03-24 13:25:23 +0000 | [diff] [blame] | 41 | static internal::Thread::LocalStorageKey thread_id_key = |
| 42 | internal::Thread::CreateThreadLocalKey(); |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 43 | |
ager@chromium.org | ddb913d | 2009-01-27 10:01:48 +0000 | [diff] [blame] | 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 | |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 50 | // Constructor for the Locker object. Once the Locker is constructed the |
| 51 | // current thread will be guaranteed to have the big V8 lock. |
| 52 | Locker::Locker() : has_lock_(false), top_level_(true) { |
ager@chromium.org | ddb913d | 2009-01-27 10:01:48 +0000 | [diff] [blame] | 53 | // Record that the Locker has been used at least once. |
| 54 | active_ = true; |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 55 | // Get the big lock if necessary. |
| 56 | if (!internal::ThreadManager::IsLockedByCurrentThread()) { |
| 57 | internal::ThreadManager::Lock(); |
| 58 | has_lock_ = true; |
| 59 | // This may be a locker within an unlocker in which case we have to |
| 60 | // get the saved state for this thread and restore it. |
| 61 | if (internal::ThreadManager::RestoreThread()) { |
| 62 | top_level_ = false; |
| 63 | } |
| 64 | } |
| 65 | ASSERT(internal::ThreadManager::IsLockedByCurrentThread()); |
ager@chromium.org | bb29dc9 | 2009-03-24 13:25:23 +0000 | [diff] [blame] | 66 | |
| 67 | // Make sure this thread is assigned a thread id. |
| 68 | internal::ThreadManager::AssignId(); |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 69 | } |
| 70 | |
| 71 | |
ager@chromium.org | 9258b6b | 2008-09-11 09:11:10 +0000 | [diff] [blame] | 72 | bool Locker::IsLocked() { |
| 73 | return internal::ThreadManager::IsLockedByCurrentThread(); |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 74 | } |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 75 | |
| 76 | |
| 77 | Locker::~Locker() { |
| 78 | ASSERT(internal::ThreadManager::IsLockedByCurrentThread()); |
| 79 | if (has_lock_) { |
| 80 | if (!top_level_) { |
| 81 | internal::ThreadManager::ArchiveThread(); |
| 82 | } |
| 83 | internal::ThreadManager::Unlock(); |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | |
| 88 | Unlocker::Unlocker() { |
| 89 | ASSERT(internal::ThreadManager::IsLockedByCurrentThread()); |
| 90 | internal::ThreadManager::ArchiveThread(); |
| 91 | internal::ThreadManager::Unlock(); |
| 92 | } |
| 93 | |
| 94 | |
| 95 | Unlocker::~Unlocker() { |
| 96 | ASSERT(!internal::ThreadManager::IsLockedByCurrentThread()); |
| 97 | internal::ThreadManager::Lock(); |
| 98 | internal::ThreadManager::RestoreThread(); |
| 99 | } |
| 100 | |
| 101 | |
| 102 | void Locker::StartPreemption(int every_n_ms) { |
| 103 | v8::internal::ContextSwitcher::StartPreemption(every_n_ms); |
| 104 | } |
| 105 | |
| 106 | |
| 107 | void Locker::StopPreemption() { |
| 108 | v8::internal::ContextSwitcher::StopPreemption(); |
| 109 | } |
| 110 | |
| 111 | |
| 112 | namespace internal { |
| 113 | |
| 114 | |
| 115 | bool ThreadManager::RestoreThread() { |
| 116 | // First check whether the current thread has been 'lazily archived', ie |
| 117 | // not archived at all. If that is the case we put the state storage we |
| 118 | // had prepared back in the free list, since we didn't need it after all. |
| 119 | if (lazily_archived_thread_.IsSelf()) { |
| 120 | lazily_archived_thread_.Initialize(ThreadHandle::INVALID); |
| 121 | ASSERT(Thread::GetThreadLocal(thread_state_key) == |
| 122 | lazily_archived_thread_state_); |
ager@chromium.org | bb29dc9 | 2009-03-24 13:25:23 +0000 | [diff] [blame] | 123 | lazily_archived_thread_state_->set_id(kInvalidId); |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 124 | lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST); |
| 125 | lazily_archived_thread_state_ = NULL; |
| 126 | Thread::SetThreadLocal(thread_state_key, NULL); |
| 127 | return true; |
| 128 | } |
ager@chromium.org | ddb913d | 2009-01-27 10:01:48 +0000 | [diff] [blame] | 129 | |
| 130 | // Make sure that the preemption thread cannot modify the thread state while |
| 131 | // it is being archived or restored. |
| 132 | ExecutionAccess access; |
| 133 | |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 134 | // If there is another thread that was lazily archived then we have to really |
| 135 | // archive it now. |
| 136 | if (lazily_archived_thread_.IsValid()) { |
| 137 | EagerlyArchiveThread(); |
| 138 | } |
| 139 | ThreadState* state = |
| 140 | reinterpret_cast<ThreadState*>(Thread::GetThreadLocal(thread_state_key)); |
| 141 | if (state == NULL) { |
| 142 | return false; |
| 143 | } |
| 144 | char* from = state->data(); |
| 145 | from = HandleScopeImplementer::RestoreThread(from); |
| 146 | from = Top::RestoreThread(from); |
ager@chromium.org | 65dad4b | 2009-04-23 08:48:43 +0000 | [diff] [blame^] | 147 | #ifdef ENABLE_DEBUGGER_SUPPORT |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 148 | from = Debug::RestoreDebug(from); |
ager@chromium.org | 65dad4b | 2009-04-23 08:48:43 +0000 | [diff] [blame^] | 149 | #endif |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 150 | from = StackGuard::RestoreStackGuard(from); |
ager@chromium.org | 3291210 | 2009-01-16 10:38:43 +0000 | [diff] [blame] | 151 | from = RegExpStack::RestoreStack(from); |
ager@chromium.org | ddb913d | 2009-01-27 10:01:48 +0000 | [diff] [blame] | 152 | from = Bootstrapper::RestoreState(from); |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 153 | Thread::SetThreadLocal(thread_state_key, NULL); |
ager@chromium.org | bb29dc9 | 2009-03-24 13:25:23 +0000 | [diff] [blame] | 154 | state->set_id(kInvalidId); |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 155 | state->Unlink(); |
| 156 | state->LinkInto(ThreadState::FREE_LIST); |
| 157 | return true; |
| 158 | } |
| 159 | |
| 160 | |
| 161 | void ThreadManager::Lock() { |
| 162 | mutex_->Lock(); |
| 163 | mutex_owner_.Initialize(ThreadHandle::SELF); |
| 164 | ASSERT(IsLockedByCurrentThread()); |
| 165 | } |
| 166 | |
| 167 | |
| 168 | void ThreadManager::Unlock() { |
| 169 | mutex_owner_.Initialize(ThreadHandle::INVALID); |
| 170 | mutex_->Unlock(); |
| 171 | } |
| 172 | |
| 173 | |
| 174 | static int ArchiveSpacePerThread() { |
| 175 | return HandleScopeImplementer::ArchiveSpacePerThread() + |
| 176 | Top::ArchiveSpacePerThread() + |
ager@chromium.org | 65dad4b | 2009-04-23 08:48:43 +0000 | [diff] [blame^] | 177 | #ifdef ENABLE_DEBUGGER_SUPPORT |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 178 | Debug::ArchiveSpacePerThread() + |
ager@chromium.org | 65dad4b | 2009-04-23 08:48:43 +0000 | [diff] [blame^] | 179 | #endif |
ager@chromium.org | 3291210 | 2009-01-16 10:38:43 +0000 | [diff] [blame] | 180 | StackGuard::ArchiveSpacePerThread() + |
ager@chromium.org | ddb913d | 2009-01-27 10:01:48 +0000 | [diff] [blame] | 181 | RegExpStack::ArchiveSpacePerThread() + |
| 182 | Bootstrapper::ArchiveSpacePerThread(); |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 183 | } |
| 184 | |
| 185 | |
| 186 | ThreadState* ThreadState::free_anchor_ = new ThreadState(); |
| 187 | ThreadState* ThreadState::in_use_anchor_ = new ThreadState(); |
| 188 | |
| 189 | |
ager@chromium.org | bb29dc9 | 2009-03-24 13:25:23 +0000 | [diff] [blame] | 190 | ThreadState::ThreadState() : id_(ThreadManager::kInvalidId), |
| 191 | next_(this), previous_(this) { |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 192 | } |
| 193 | |
| 194 | |
| 195 | void ThreadState::AllocateSpace() { |
| 196 | data_ = NewArray<char>(ArchiveSpacePerThread()); |
| 197 | } |
| 198 | |
| 199 | |
| 200 | void ThreadState::Unlink() { |
| 201 | next_->previous_ = previous_; |
| 202 | previous_->next_ = next_; |
| 203 | } |
| 204 | |
| 205 | |
| 206 | void ThreadState::LinkInto(List list) { |
| 207 | ThreadState* flying_anchor = |
| 208 | list == FREE_LIST ? free_anchor_ : in_use_anchor_; |
| 209 | next_ = flying_anchor->next_; |
| 210 | previous_ = flying_anchor; |
| 211 | flying_anchor->next_ = this; |
| 212 | next_->previous_ = this; |
| 213 | } |
| 214 | |
| 215 | |
| 216 | ThreadState* ThreadState::GetFree() { |
| 217 | ThreadState* gotten = free_anchor_->next_; |
| 218 | if (gotten == free_anchor_) { |
| 219 | ThreadState* new_thread_state = new ThreadState(); |
| 220 | new_thread_state->AllocateSpace(); |
| 221 | return new_thread_state; |
| 222 | } |
| 223 | return gotten; |
| 224 | } |
| 225 | |
| 226 | |
| 227 | // Gets the first in the list of archived threads. |
| 228 | ThreadState* ThreadState::FirstInUse() { |
| 229 | return in_use_anchor_->Next(); |
| 230 | } |
| 231 | |
| 232 | |
| 233 | ThreadState* ThreadState::Next() { |
| 234 | if (next_ == in_use_anchor_) return NULL; |
| 235 | return next_; |
| 236 | } |
| 237 | |
| 238 | |
ager@chromium.org | bb29dc9 | 2009-03-24 13:25:23 +0000 | [diff] [blame] | 239 | int ThreadManager::next_id_ = 0; |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 240 | Mutex* ThreadManager::mutex_ = OS::CreateMutex(); |
| 241 | ThreadHandle ThreadManager::mutex_owner_(ThreadHandle::INVALID); |
| 242 | ThreadHandle ThreadManager::lazily_archived_thread_(ThreadHandle::INVALID); |
| 243 | ThreadState* ThreadManager::lazily_archived_thread_state_ = NULL; |
| 244 | |
| 245 | |
| 246 | void ThreadManager::ArchiveThread() { |
| 247 | ASSERT(!lazily_archived_thread_.IsValid()); |
| 248 | ASSERT(Thread::GetThreadLocal(thread_state_key) == NULL); |
| 249 | ThreadState* state = ThreadState::GetFree(); |
| 250 | state->Unlink(); |
| 251 | Thread::SetThreadLocal(thread_state_key, reinterpret_cast<void*>(state)); |
| 252 | lazily_archived_thread_.Initialize(ThreadHandle::SELF); |
| 253 | lazily_archived_thread_state_ = state; |
ager@chromium.org | bb29dc9 | 2009-03-24 13:25:23 +0000 | [diff] [blame] | 254 | ASSERT(state->id() == kInvalidId); |
| 255 | state->set_id(CurrentId()); |
| 256 | ASSERT(state->id() != kInvalidId); |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 257 | } |
| 258 | |
| 259 | |
| 260 | void ThreadManager::EagerlyArchiveThread() { |
| 261 | ThreadState* state = lazily_archived_thread_state_; |
| 262 | state->LinkInto(ThreadState::IN_USE_LIST); |
| 263 | char* to = state->data(); |
| 264 | to = HandleScopeImplementer::ArchiveThread(to); |
| 265 | to = Top::ArchiveThread(to); |
ager@chromium.org | 65dad4b | 2009-04-23 08:48:43 +0000 | [diff] [blame^] | 266 | #ifdef ENABLE_DEBUGGER_SUPPORT |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 267 | to = Debug::ArchiveDebug(to); |
ager@chromium.org | 65dad4b | 2009-04-23 08:48:43 +0000 | [diff] [blame^] | 268 | #endif |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 269 | to = StackGuard::ArchiveStackGuard(to); |
ager@chromium.org | 3291210 | 2009-01-16 10:38:43 +0000 | [diff] [blame] | 270 | to = RegExpStack::ArchiveStack(to); |
ager@chromium.org | ddb913d | 2009-01-27 10:01:48 +0000 | [diff] [blame] | 271 | to = Bootstrapper::ArchiveState(to); |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 272 | lazily_archived_thread_.Initialize(ThreadHandle::INVALID); |
| 273 | lazily_archived_thread_state_ = NULL; |
| 274 | } |
| 275 | |
| 276 | |
| 277 | void ThreadManager::Iterate(ObjectVisitor* v) { |
| 278 | // Expecting no threads during serialization/deserialization |
| 279 | for (ThreadState* state = ThreadState::FirstInUse(); |
| 280 | state != NULL; |
| 281 | state = state->Next()) { |
| 282 | char* data = state->data(); |
| 283 | data = HandleScopeImplementer::Iterate(v, data); |
| 284 | data = Top::Iterate(v, data); |
| 285 | } |
| 286 | } |
| 287 | |
| 288 | |
kasperl@chromium.org | 061ef74 | 2009-02-27 12:16:20 +0000 | [diff] [blame] | 289 | void ThreadManager::MarkCompactPrologue(bool is_compacting) { |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 290 | for (ThreadState* state = ThreadState::FirstInUse(); |
| 291 | state != NULL; |
| 292 | state = state->Next()) { |
| 293 | char* data = state->data(); |
| 294 | data += HandleScopeImplementer::ArchiveSpacePerThread(); |
kasperl@chromium.org | 061ef74 | 2009-02-27 12:16:20 +0000 | [diff] [blame] | 295 | Top::MarkCompactPrologue(is_compacting, data); |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 296 | } |
| 297 | } |
| 298 | |
| 299 | |
kasperl@chromium.org | 061ef74 | 2009-02-27 12:16:20 +0000 | [diff] [blame] | 300 | void ThreadManager::MarkCompactEpilogue(bool is_compacting) { |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 301 | for (ThreadState* state = ThreadState::FirstInUse(); |
| 302 | state != NULL; |
| 303 | state = state->Next()) { |
| 304 | char* data = state->data(); |
| 305 | data += HandleScopeImplementer::ArchiveSpacePerThread(); |
kasperl@chromium.org | 061ef74 | 2009-02-27 12:16:20 +0000 | [diff] [blame] | 306 | Top::MarkCompactEpilogue(is_compacting, data); |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 307 | } |
| 308 | } |
| 309 | |
| 310 | |
ager@chromium.org | bb29dc9 | 2009-03-24 13:25:23 +0000 | [diff] [blame] | 311 | int ThreadManager::CurrentId() { |
| 312 | return bit_cast<int, void*>(Thread::GetThreadLocal(thread_id_key)); |
| 313 | } |
| 314 | |
| 315 | |
| 316 | void ThreadManager::AssignId() { |
| 317 | if (Thread::GetThreadLocal(thread_id_key) == NULL) { |
| 318 | Thread::SetThreadLocal(thread_id_key, bit_cast<void*, int>(next_id_++)); |
| 319 | } |
| 320 | } |
| 321 | |
| 322 | |
christian.plesner.hansen@gmail.com | 37abdec | 2009-01-06 14:43:28 +0000 | [diff] [blame] | 323 | // This is the ContextSwitcher singleton. There is at most a single thread |
| 324 | // running which delivers preemption events to V8 threads. |
| 325 | ContextSwitcher* ContextSwitcher::singleton_ = NULL; |
| 326 | |
| 327 | |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 328 | ContextSwitcher::ContextSwitcher(int every_n_ms) |
christian.plesner.hansen@gmail.com | 37abdec | 2009-01-06 14:43:28 +0000 | [diff] [blame] | 329 | : keep_going_(true), |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 330 | sleep_ms_(every_n_ms) { |
| 331 | } |
| 332 | |
| 333 | |
christian.plesner.hansen@gmail.com | 37abdec | 2009-01-06 14:43:28 +0000 | [diff] [blame] | 334 | // Set the scheduling interval of V8 threads. This function starts the |
| 335 | // ContextSwitcher thread if needed. |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 336 | void ContextSwitcher::StartPreemption(int every_n_ms) { |
ager@chromium.org | 9258b6b | 2008-09-11 09:11:10 +0000 | [diff] [blame] | 337 | ASSERT(Locker::IsLocked()); |
christian.plesner.hansen@gmail.com | 37abdec | 2009-01-06 14:43:28 +0000 | [diff] [blame] | 338 | if (singleton_ == NULL) { |
| 339 | // If the ContextSwitcher thread is not running at the moment start it now. |
| 340 | singleton_ = new ContextSwitcher(every_n_ms); |
| 341 | singleton_->Start(); |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 342 | } else { |
christian.plesner.hansen@gmail.com | 37abdec | 2009-01-06 14:43:28 +0000 | [diff] [blame] | 343 | // ContextSwitcher thread is already running, so we just change the |
| 344 | // scheduling interval. |
| 345 | singleton_->sleep_ms_ = every_n_ms; |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 346 | } |
| 347 | } |
| 348 | |
| 349 | |
christian.plesner.hansen@gmail.com | 37abdec | 2009-01-06 14:43:28 +0000 | [diff] [blame] | 350 | // Disable preemption of V8 threads. If multiple threads want to use V8 they |
| 351 | // must cooperatively schedule amongst them from this point on. |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 352 | void ContextSwitcher::StopPreemption() { |
ager@chromium.org | 9258b6b | 2008-09-11 09:11:10 +0000 | [diff] [blame] | 353 | ASSERT(Locker::IsLocked()); |
christian.plesner.hansen@gmail.com | 37abdec | 2009-01-06 14:43:28 +0000 | [diff] [blame] | 354 | if (singleton_ != NULL) { |
| 355 | // The ContextSwitcher thread is running. We need to stop it and release |
| 356 | // its resources. |
| 357 | singleton_->keep_going_ = false; |
| 358 | singleton_->Join(); // Wait for the ContextSwitcher thread to exit. |
| 359 | // Thread has exited, now we can delete it. |
| 360 | delete(singleton_); |
| 361 | singleton_ = NULL; |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 362 | } |
| 363 | } |
| 364 | |
| 365 | |
christian.plesner.hansen@gmail.com | 37abdec | 2009-01-06 14:43:28 +0000 | [diff] [blame] | 366 | // Main loop of the ContextSwitcher thread: Preempt the currently running V8 |
| 367 | // thread at regular intervals. |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 368 | void ContextSwitcher::Run() { |
| 369 | while (keep_going_) { |
| 370 | OS::Sleep(sleep_ms_); |
| 371 | StackGuard::Preempt(); |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 372 | } |
| 373 | } |
| 374 | |
| 375 | |
christian.plesner.hansen@gmail.com | 37abdec | 2009-01-06 14:43:28 +0000 | [diff] [blame] | 376 | // Acknowledge the preemption by the receiving thread. |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 377 | void ContextSwitcher::PreemptionReceived() { |
ager@chromium.org | 9258b6b | 2008-09-11 09:11:10 +0000 | [diff] [blame] | 378 | ASSERT(Locker::IsLocked()); |
christian.plesner.hansen@gmail.com | 37abdec | 2009-01-06 14:43:28 +0000 | [diff] [blame] | 379 | // There is currently no accounting being done for this. But could be in the |
| 380 | // future, which is why we leave this in. |
christian.plesner.hansen | 43d26ec | 2008-07-03 15:10:15 +0000 | [diff] [blame] | 381 | } |
| 382 | |
| 383 | |
| 384 | } // namespace internal |
| 385 | } // namespace v8 |