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

Side by Side Diff: src/v8threads.cc

Issue 48009: Add thread information to the debugger (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 9 months 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 | Annotate | Revision Log
« src/runtime.cc ('K') | « 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 20 matching lines...) Expand all
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
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
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
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
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
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
OLDNEW
« src/runtime.cc ('K') | « src/v8threads.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698