blob: 34d26ece7f12d087c640b46b85f47e4909c52941 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005#include "src/v8threads.h"
Steve Blocka7e24c12009-10-30 11:49:00 +00006
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007#include "src/api.h"
8#include "src/bootstrapper.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009#include "src/debug/debug.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/execution.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011#include "src/isolate-inl.h"
12#include "src/regexp/regexp-stack.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000013
14namespace v8 {
15
Steve Blocka7e24c12009-10-30 11:49:00 +000016
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017namespace {
18
Steve Blocka7e24c12009-10-30 11:49:00 +000019// Track whether this V8 instance has ever called v8::Locker. This allows the
20// API code to verify that the lock is always held when V8 is being entered.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021base::Atomic32 g_locker_was_ever_used_ = 0;
22
23} // namespace
Steve Blocka7e24c12009-10-30 11:49:00 +000024
25
Ben Murdochb8a8cc12014-11-26 15:28:44 +000026// Once the Locker is initialized, the current thread will be guaranteed to have
27// the lock for a given isolate.
28void Locker::Initialize(v8::Isolate* isolate) {
29 DCHECK(isolate != NULL);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040030 has_lock_ = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000031 top_level_ = true;
32 isolate_ = reinterpret_cast<i::Isolate*>(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000033 // Record that the Locker has been used at least once.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040034 base::NoBarrier_Store(&g_locker_was_ever_used_, 1);
Steve Blocka7e24c12009-10-30 11:49:00 +000035 // Get the big lock if necessary.
Ben Murdoch257744e2011-11-30 15:57:28 +000036 if (!isolate_->thread_manager()->IsLockedByCurrentThread()) {
37 isolate_->thread_manager()->Lock();
Steve Blocka7e24c12009-10-30 11:49:00 +000038 has_lock_ = true;
Steve Block44f0eee2011-05-26 01:26:41 +010039
Steve Blocka7e24c12009-10-30 11:49:00 +000040 // This may be a locker within an unlocker in which case we have to
41 // get the saved state for this thread and restore it.
Ben Murdoch257744e2011-11-30 15:57:28 +000042 if (isolate_->thread_manager()->RestoreThread()) {
Steve Blocka7e24c12009-10-30 11:49:00 +000043 top_level_ = false;
44 } else {
Ben Murdoch257744e2011-11-30 15:57:28 +000045 internal::ExecutionAccess access(isolate_);
46 isolate_->stack_guard()->ClearThread(access);
47 isolate_->stack_guard()->InitThread(access);
48 }
Steve Blocka7e24c12009-10-30 11:49:00 +000049 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000050 DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread());
Steve Blocka7e24c12009-10-30 11:49:00 +000051}
52
53
Ben Murdoch257744e2011-11-30 15:57:28 +000054bool Locker::IsLocked(v8::Isolate* isolate) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000055 DCHECK(isolate != NULL);
Ben Murdoch257744e2011-11-30 15:57:28 +000056 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000057 return internal_isolate->thread_manager()->IsLockedByCurrentThread();
Steve Blocka7e24c12009-10-30 11:49:00 +000058}
59
60
Ben Murdoch69a99ed2011-11-30 16:03:39 +000061bool Locker::IsActive() {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040062 return !!base::NoBarrier_Load(&g_locker_was_ever_used_);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000063}
64
65
Steve Blocka7e24c12009-10-30 11:49:00 +000066Locker::~Locker() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000067 DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread());
Steve Blocka7e24c12009-10-30 11:49:00 +000068 if (has_lock_) {
Ben Murdoch257744e2011-11-30 15:57:28 +000069 if (top_level_) {
70 isolate_->thread_manager()->FreeThreadResources();
71 } else {
72 isolate_->thread_manager()->ArchiveThread();
73 }
74 isolate_->thread_manager()->Unlock();
Steve Blocka7e24c12009-10-30 11:49:00 +000075 }
76}
77
78
Ben Murdochb8a8cc12014-11-26 15:28:44 +000079void Unlocker::Initialize(v8::Isolate* isolate) {
80 DCHECK(isolate != NULL);
81 isolate_ = reinterpret_cast<i::Isolate*>(isolate);
82 DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread());
Ben Murdoch257744e2011-11-30 15:57:28 +000083 isolate_->thread_manager()->ArchiveThread();
84 isolate_->thread_manager()->Unlock();
Steve Blocka7e24c12009-10-30 11:49:00 +000085}
86
87
88Unlocker::~Unlocker() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000089 DCHECK(!isolate_->thread_manager()->IsLockedByCurrentThread());
Ben Murdoch257744e2011-11-30 15:57:28 +000090 isolate_->thread_manager()->Lock();
91 isolate_->thread_manager()->RestoreThread();
Steve Blocka7e24c12009-10-30 11:49:00 +000092}
93
94
95namespace internal {
96
97
98bool ThreadManager::RestoreThread() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000099 DCHECK(IsLockedByCurrentThread());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100100 // First check whether the current thread has been 'lazily archived', i.e.
Steve Blocka7e24c12009-10-30 11:49:00 +0000101 // not archived at all. If that is the case we put the state storage we
102 // had prepared back in the free list, since we didn't need it after all.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100103 if (lazily_archived_thread_.Equals(ThreadId::Current())) {
104 lazily_archived_thread_ = ThreadId::Invalid();
Ben Murdoch257744e2011-11-30 15:57:28 +0000105 Isolate::PerIsolateThreadData* per_thread =
106 isolate_->FindPerThreadDataForThisThread();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000107 DCHECK(per_thread != NULL);
108 DCHECK(per_thread->thread_state() == lazily_archived_thread_state_);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100109 lazily_archived_thread_state_->set_id(ThreadId::Invalid());
Steve Blocka7e24c12009-10-30 11:49:00 +0000110 lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST);
111 lazily_archived_thread_state_ = NULL;
Ben Murdoch257744e2011-11-30 15:57:28 +0000112 per_thread->set_thread_state(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000113 return true;
114 }
115
116 // Make sure that the preemption thread cannot modify the thread state while
117 // it is being archived or restored.
Steve Block44f0eee2011-05-26 01:26:41 +0100118 ExecutionAccess access(isolate_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000119
120 // If there is another thread that was lazily archived then we have to really
121 // archive it now.
122 if (lazily_archived_thread_.IsValid()) {
123 EagerlyArchiveThread();
124 }
Steve Block44f0eee2011-05-26 01:26:41 +0100125 Isolate::PerIsolateThreadData* per_thread =
Ben Murdoch257744e2011-11-30 15:57:28 +0000126 isolate_->FindPerThreadDataForThisThread();
Steve Block44f0eee2011-05-26 01:26:41 +0100127 if (per_thread == NULL || per_thread->thread_state() == NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000128 // This is a new thread.
Steve Block44f0eee2011-05-26 01:26:41 +0100129 isolate_->stack_guard()->InitThread(access);
Steve Blocka7e24c12009-10-30 11:49:00 +0000130 return false;
131 }
Steve Block44f0eee2011-05-26 01:26:41 +0100132 ThreadState* state = per_thread->thread_state();
Steve Blocka7e24c12009-10-30 11:49:00 +0000133 char* from = state->data();
Steve Block44f0eee2011-05-26 01:26:41 +0100134 from = isolate_->handle_scope_implementer()->RestoreThread(from);
135 from = isolate_->RestoreThread(from);
Ben Murdoch257744e2011-11-30 15:57:28 +0000136 from = Relocatable::RestoreState(isolate_, from);
Steve Block44f0eee2011-05-26 01:26:41 +0100137 from = isolate_->debug()->RestoreDebug(from);
Steve Block44f0eee2011-05-26 01:26:41 +0100138 from = isolate_->stack_guard()->RestoreStackGuard(from);
139 from = isolate_->regexp_stack()->RestoreStack(from);
140 from = isolate_->bootstrapper()->RestoreState(from);
141 per_thread->set_thread_state(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000142 if (state->terminate_on_restore()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000143 isolate_->stack_guard()->RequestTerminateExecution();
Steve Blocka7e24c12009-10-30 11:49:00 +0000144 state->set_terminate_on_restore(false);
145 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100146 state->set_id(ThreadId::Invalid());
Steve Blocka7e24c12009-10-30 11:49:00 +0000147 state->Unlink();
148 state->LinkInto(ThreadState::FREE_LIST);
149 return true;
150}
151
152
153void ThreadManager::Lock() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000154 mutex_.Lock();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100155 mutex_owner_ = ThreadId::Current();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000156 DCHECK(IsLockedByCurrentThread());
Steve Blocka7e24c12009-10-30 11:49:00 +0000157}
158
159
160void ThreadManager::Unlock() {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100161 mutex_owner_ = ThreadId::Invalid();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000162 mutex_.Unlock();
Steve Blocka7e24c12009-10-30 11:49:00 +0000163}
164
165
166static int ArchiveSpacePerThread() {
167 return HandleScopeImplementer::ArchiveSpacePerThread() +
Steve Block44f0eee2011-05-26 01:26:41 +0100168 Isolate::ArchiveSpacePerThread() +
Steve Blocka7e24c12009-10-30 11:49:00 +0000169 Debug::ArchiveSpacePerThread() +
Steve Blocka7e24c12009-10-30 11:49:00 +0000170 StackGuard::ArchiveSpacePerThread() +
171 RegExpStack::ArchiveSpacePerThread() +
172 Bootstrapper::ArchiveSpacePerThread() +
173 Relocatable::ArchiveSpacePerThread();
174}
175
176
Steve Block44f0eee2011-05-26 01:26:41 +0100177ThreadState::ThreadState(ThreadManager* thread_manager)
Ben Murdoch8b112d22011-06-08 16:22:53 +0100178 : id_(ThreadId::Invalid()),
Steve Block44f0eee2011-05-26 01:26:41 +0100179 terminate_on_restore_(false),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000180 data_(NULL),
Steve Block44f0eee2011-05-26 01:26:41 +0100181 next_(this),
182 previous_(this),
183 thread_manager_(thread_manager) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000184}
185
186
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000187ThreadState::~ThreadState() {
188 DeleteArray<char>(data_);
189}
190
191
Steve Blocka7e24c12009-10-30 11:49:00 +0000192void ThreadState::AllocateSpace() {
193 data_ = NewArray<char>(ArchiveSpacePerThread());
194}
195
196
197void ThreadState::Unlink() {
198 next_->previous_ = previous_;
199 previous_->next_ = next_;
200}
201
202
203void ThreadState::LinkInto(List list) {
204 ThreadState* flying_anchor =
Steve Block44f0eee2011-05-26 01:26:41 +0100205 list == FREE_LIST ? thread_manager_->free_anchor_
206 : thread_manager_->in_use_anchor_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000207 next_ = flying_anchor->next_;
208 previous_ = flying_anchor;
209 flying_anchor->next_ = this;
210 next_->previous_ = this;
211}
212
213
Steve Block44f0eee2011-05-26 01:26:41 +0100214ThreadState* ThreadManager::GetFreeThreadState() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000215 ThreadState* gotten = free_anchor_->next_;
216 if (gotten == free_anchor_) {
Steve Block44f0eee2011-05-26 01:26:41 +0100217 ThreadState* new_thread_state = new ThreadState(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000218 new_thread_state->AllocateSpace();
219 return new_thread_state;
220 }
221 return gotten;
222}
223
224
225// Gets the first in the list of archived threads.
Steve Block44f0eee2011-05-26 01:26:41 +0100226ThreadState* ThreadManager::FirstThreadStateInUse() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000227 return in_use_anchor_->Next();
228}
229
230
231ThreadState* ThreadState::Next() {
Steve Block44f0eee2011-05-26 01:26:41 +0100232 if (next_ == thread_manager_->in_use_anchor_) return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000233 return next_;
234}
235
236
237// Thread ids must start with 1, because in TLS having thread id 0 can't
238// be distinguished from not having a thread id at all (since NULL is
239// defined as 0.)
Steve Block44f0eee2011-05-26 01:26:41 +0100240ThreadManager::ThreadManager()
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000241 : mutex_owner_(ThreadId::Invalid()),
Ben Murdoch8b112d22011-06-08 16:22:53 +0100242 lazily_archived_thread_(ThreadId::Invalid()),
Steve Block44f0eee2011-05-26 01:26:41 +0100243 lazily_archived_thread_state_(NULL),
244 free_anchor_(NULL),
245 in_use_anchor_(NULL) {
246 free_anchor_ = new ThreadState(this);
247 in_use_anchor_ = new ThreadState(this);
248}
249
250
251ThreadManager::~ThreadManager() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000252 DeleteThreadStateList(free_anchor_);
253 DeleteThreadStateList(in_use_anchor_);
254}
255
256
257void ThreadManager::DeleteThreadStateList(ThreadState* anchor) {
258 // The list starts and ends with the anchor.
259 for (ThreadState* current = anchor->next_; current != anchor;) {
260 ThreadState* next = current->next_;
261 delete current;
262 current = next;
263 }
264 delete anchor;
Steve Block44f0eee2011-05-26 01:26:41 +0100265}
Steve Blocka7e24c12009-10-30 11:49:00 +0000266
267
268void ThreadManager::ArchiveThread() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000269 DCHECK(lazily_archived_thread_.Equals(ThreadId::Invalid()));
270 DCHECK(!IsArchived());
271 DCHECK(IsLockedByCurrentThread());
Steve Block44f0eee2011-05-26 01:26:41 +0100272 ThreadState* state = GetFreeThreadState();
Steve Blocka7e24c12009-10-30 11:49:00 +0000273 state->Unlink();
Ben Murdoch257744e2011-11-30 15:57:28 +0000274 Isolate::PerIsolateThreadData* per_thread =
275 isolate_->FindOrAllocatePerThreadDataForThisThread();
276 per_thread->set_thread_state(state);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100277 lazily_archived_thread_ = ThreadId::Current();
Steve Blocka7e24c12009-10-30 11:49:00 +0000278 lazily_archived_thread_state_ = state;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000279 DCHECK(state->id().Equals(ThreadId::Invalid()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000280 state->set_id(CurrentId());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000281 DCHECK(!state->id().Equals(ThreadId::Invalid()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000282}
283
284
285void ThreadManager::EagerlyArchiveThread() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000286 DCHECK(IsLockedByCurrentThread());
Steve Blocka7e24c12009-10-30 11:49:00 +0000287 ThreadState* state = lazily_archived_thread_state_;
288 state->LinkInto(ThreadState::IN_USE_LIST);
289 char* to = state->data();
290 // Ensure that data containing GC roots are archived first, and handle them
291 // in ThreadManager::Iterate(ObjectVisitor*).
Steve Block44f0eee2011-05-26 01:26:41 +0100292 to = isolate_->handle_scope_implementer()->ArchiveThread(to);
293 to = isolate_->ArchiveThread(to);
Ben Murdoch257744e2011-11-30 15:57:28 +0000294 to = Relocatable::ArchiveState(isolate_, to);
Steve Block44f0eee2011-05-26 01:26:41 +0100295 to = isolate_->debug()->ArchiveDebug(to);
Steve Block44f0eee2011-05-26 01:26:41 +0100296 to = isolate_->stack_guard()->ArchiveStackGuard(to);
297 to = isolate_->regexp_stack()->ArchiveStack(to);
298 to = isolate_->bootstrapper()->ArchiveState(to);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100299 lazily_archived_thread_ = ThreadId::Invalid();
Steve Blocka7e24c12009-10-30 11:49:00 +0000300 lazily_archived_thread_state_ = NULL;
301}
302
303
304void ThreadManager::FreeThreadResources() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000305 DCHECK(!isolate_->has_pending_exception());
306 DCHECK(!isolate_->external_caught_exception());
307 DCHECK(isolate_->try_catch_handler() == NULL);
Steve Block44f0eee2011-05-26 01:26:41 +0100308 isolate_->handle_scope_implementer()->FreeThreadResources();
309 isolate_->FreeThreadResources();
Steve Block44f0eee2011-05-26 01:26:41 +0100310 isolate_->debug()->FreeThreadResources();
Steve Block44f0eee2011-05-26 01:26:41 +0100311 isolate_->stack_guard()->FreeThreadResources();
312 isolate_->regexp_stack()->FreeThreadResources();
313 isolate_->bootstrapper()->FreeThreadResources();
Steve Blocka7e24c12009-10-30 11:49:00 +0000314}
315
316
317bool ThreadManager::IsArchived() {
Ben Murdoch257744e2011-11-30 15:57:28 +0000318 Isolate::PerIsolateThreadData* data =
319 isolate_->FindPerThreadDataForThisThread();
Steve Block44f0eee2011-05-26 01:26:41 +0100320 return data != NULL && data->thread_state() != NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000321}
322
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000323
Steve Blocka7e24c12009-10-30 11:49:00 +0000324void ThreadManager::Iterate(ObjectVisitor* v) {
325 // Expecting no threads during serialization/deserialization
Steve Block44f0eee2011-05-26 01:26:41 +0100326 for (ThreadState* state = FirstThreadStateInUse();
Steve Blocka7e24c12009-10-30 11:49:00 +0000327 state != NULL;
328 state = state->Next()) {
329 char* data = state->data();
330 data = HandleScopeImplementer::Iterate(v, data);
Steve Block44f0eee2011-05-26 01:26:41 +0100331 data = isolate_->Iterate(v, data);
Steve Blocka7e24c12009-10-30 11:49:00 +0000332 data = Relocatable::Iterate(v, data);
333 }
334}
335
336
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100337void ThreadManager::IterateArchivedThreads(ThreadVisitor* v) {
Steve Block44f0eee2011-05-26 01:26:41 +0100338 for (ThreadState* state = FirstThreadStateInUse();
Steve Block6ded16b2010-05-10 14:33:55 +0100339 state != NULL;
340 state = state->Next()) {
341 char* data = state->data();
342 data += HandleScopeImplementer::ArchiveSpacePerThread();
Steve Block44f0eee2011-05-26 01:26:41 +0100343 isolate_->IterateThread(v, data);
Steve Block6ded16b2010-05-10 14:33:55 +0100344 }
345}
346
347
Ben Murdoch8b112d22011-06-08 16:22:53 +0100348ThreadId ThreadManager::CurrentId() {
349 return ThreadId::Current();
Steve Blocka7e24c12009-10-30 11:49:00 +0000350}
351
352
Ben Murdoch8b112d22011-06-08 16:22:53 +0100353void ThreadManager::TerminateExecution(ThreadId thread_id) {
Steve Block44f0eee2011-05-26 01:26:41 +0100354 for (ThreadState* state = FirstThreadStateInUse();
Steve Blocka7e24c12009-10-30 11:49:00 +0000355 state != NULL;
356 state = state->Next()) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100357 if (thread_id.Equals(state->id())) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000358 state->set_terminate_on_restore(true);
359 }
360 }
361}
362
363
Steve Blocka7e24c12009-10-30 11:49:00 +0000364} // namespace internal
365} // namespace v8