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 |