OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. | 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 13 matching lines...) Expand all Loading... |
24 * | 24 * |
25 */ | 25 */ |
26 | 26 |
27 #include "core/workers/WorkerThread.h" | 27 #include "core/workers/WorkerThread.h" |
28 | 28 |
29 #include <limits.h> | 29 #include <limits.h> |
30 #include <memory> | 30 #include <memory> |
31 #include "bindings/core/v8/Microtask.h" | 31 #include "bindings/core/v8/Microtask.h" |
32 #include "bindings/core/v8/ScriptSourceCode.h" | 32 #include "bindings/core/v8/ScriptSourceCode.h" |
33 #include "bindings/core/v8/WorkerOrWorkletScriptController.h" | 33 #include "bindings/core/v8/WorkerOrWorkletScriptController.h" |
34 #include "core/dom/TaskRunnerHelper.h" | |
35 #include "core/inspector/ConsoleMessageStorage.h" | 34 #include "core/inspector/ConsoleMessageStorage.h" |
36 #include "core/inspector/InspectorTaskRunner.h" | 35 #include "core/inspector/InspectorTaskRunner.h" |
37 #include "core/inspector/WorkerInspectorController.h" | 36 #include "core/inspector/WorkerInspectorController.h" |
38 #include "core/inspector/WorkerThreadDebugger.h" | 37 #include "core/inspector/WorkerThreadDebugger.h" |
39 #include "core/origin_trials/OriginTrialContext.h" | 38 #include "core/origin_trials/OriginTrialContext.h" |
40 #include "core/probe/CoreProbes.h" | 39 #include "core/probe/CoreProbes.h" |
41 #include "core/workers/ThreadedWorkletGlobalScope.h" | 40 #include "core/workers/ThreadedWorkletGlobalScope.h" |
42 #include "core/workers/WorkerBackingThread.h" | 41 #include "core/workers/WorkerBackingThread.h" |
43 #include "core/workers/WorkerClients.h" | 42 #include "core/workers/WorkerClients.h" |
44 #include "core/workers/WorkerGlobalScope.h" | 43 #include "core/workers/WorkerGlobalScope.h" |
45 #include "core/workers/WorkerReportingProxy.h" | 44 #include "core/workers/WorkerReportingProxy.h" |
46 #include "core/workers/WorkerThreadStartupData.h" | 45 #include "core/workers/WorkerThreadStartupData.h" |
47 #include "platform/CrossThreadFunctional.h" | 46 #include "platform/CrossThreadFunctional.h" |
48 #include "platform/Histogram.h" | 47 #include "platform/Histogram.h" |
49 #include "platform/WaitableEvent.h" | 48 #include "platform/WaitableEvent.h" |
50 #include "platform/WebThreadSupportingGC.h" | 49 #include "platform/WebThreadSupportingGC.h" |
51 #include "platform/heap/SafePoint.h" | 50 #include "platform/heap/SafePoint.h" |
52 #include "platform/heap/ThreadState.h" | 51 #include "platform/heap/ThreadState.h" |
53 #include "platform/scheduler/child/webthread_impl_for_worker_scheduler.h" | |
54 #include "platform/scheduler/child/worker_global_scope_scheduler.h" | |
55 #include "platform/weborigin/KURL.h" | 52 #include "platform/weborigin/KURL.h" |
56 #include "platform/wtf/Functional.h" | 53 #include "platform/wtf/Functional.h" |
57 #include "platform/wtf/Noncopyable.h" | 54 #include "platform/wtf/Noncopyable.h" |
58 #include "platform/wtf/PtrUtil.h" | 55 #include "platform/wtf/PtrUtil.h" |
59 #include "platform/wtf/Threading.h" | 56 #include "platform/wtf/Threading.h" |
60 #include "platform/wtf/text/WTFString.h" | 57 #include "platform/wtf/text/WTFString.h" |
61 | 58 |
62 namespace blink { | 59 namespace blink { |
63 | 60 |
64 using ExitCode = WorkerThread::ExitCode; | 61 using ExitCode = WorkerThread::ExitCode; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 DEFINE_THREAD_SAFE_STATIC_LOCAL( | 100 DEFINE_THREAD_SAFE_STATIC_LOCAL( |
104 EnumerationHistogram, exit_code_histogram, | 101 EnumerationHistogram, exit_code_histogram, |
105 new EnumerationHistogram("WorkerThread.ExitCode", | 102 new EnumerationHistogram("WorkerThread.ExitCode", |
106 static_cast<int>(ExitCode::kLastEnum))); | 103 static_cast<int>(ExitCode::kLastEnum))); |
107 exit_code_histogram.Count(static_cast<int>(exit_code_)); | 104 exit_code_histogram.Count(static_cast<int>(exit_code_)); |
108 } | 105 } |
109 | 106 |
110 void WorkerThread::Start(std::unique_ptr<WorkerThreadStartupData> startup_data, | 107 void WorkerThread::Start(std::unique_ptr<WorkerThreadStartupData> startup_data, |
111 ParentFrameTaskRunners* parent_frame_task_runners) { | 108 ParentFrameTaskRunners* parent_frame_task_runners) { |
112 DCHECK(IsMainThread()); | 109 DCHECK(IsMainThread()); |
| 110 |
113 if (requested_to_start_) | 111 if (requested_to_start_) |
114 return; | 112 return; |
115 | 113 |
116 requested_to_start_ = true; | 114 requested_to_start_ = true; |
117 parent_frame_task_runners_ = parent_frame_task_runners; | 115 parent_frame_task_runners_ = parent_frame_task_runners; |
118 | |
119 // Synchronously initialize the per-global-scope scheduler to prevent someone | |
120 // from posting a task to the thread before the scheduler is ready. | |
121 WaitableEvent waitable_event; | |
122 GetWorkerBackingThread().BackingThread().PostTask( | |
123 BLINK_FROM_HERE, | |
124 CrossThreadBind(&WorkerThread::InitializeSchedulerOnWorkerThread, | |
125 CrossThreadUnretained(this), | |
126 CrossThreadUnretained(&waitable_event))); | |
127 waitable_event.Wait(); | |
128 | |
129 GetWorkerBackingThread().BackingThread().PostTask( | 116 GetWorkerBackingThread().BackingThread().PostTask( |
130 BLINK_FROM_HERE, CrossThreadBind(&WorkerThread::InitializeOnWorkerThread, | 117 BLINK_FROM_HERE, CrossThreadBind(&WorkerThread::InitializeOnWorkerThread, |
131 CrossThreadUnretained(this), | 118 CrossThreadUnretained(this), |
132 WTF::Passed(std::move(startup_data)))); | 119 WTF::Passed(std::move(startup_data)))); |
133 } | 120 } |
134 | 121 |
135 void WorkerThread::Terminate() { | 122 void WorkerThread::Terminate() { |
136 DCHECK(IsMainThread()); | 123 DCHECK(IsMainThread()); |
137 TerminateInternal(TerminationMode::kGraceful); | 124 TerminateInternal(TerminationMode::kGraceful); |
138 } | 125 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 } | 183 } |
197 | 184 |
198 v8::Isolate* WorkerThread::GetIsolate() { | 185 v8::Isolate* WorkerThread::GetIsolate() { |
199 return GetWorkerBackingThread().GetIsolate(); | 186 return GetWorkerBackingThread().GetIsolate(); |
200 } | 187 } |
201 | 188 |
202 bool WorkerThread::IsCurrentThread() { | 189 bool WorkerThread::IsCurrentThread() { |
203 return GetWorkerBackingThread().BackingThread().IsCurrentThread(); | 190 return GetWorkerBackingThread().BackingThread().IsCurrentThread(); |
204 } | 191 } |
205 | 192 |
| 193 void WorkerThread::PostTask(const WebTraceLocation& location, |
| 194 std::unique_ptr<WTF::Closure> task) { |
| 195 DCHECK(IsCurrentThread()); |
| 196 if (IsInShutdown()) |
| 197 return; |
| 198 GetWorkerBackingThread().BackingThread().PostTask( |
| 199 location, |
| 200 WTF::Bind( |
| 201 &WorkerThread::PerformTaskOnWorkerThread<WTF::kSameThreadAffinity>, |
| 202 WTF::Unretained(this), WTF::Passed(std::move(task)))); |
| 203 } |
| 204 |
| 205 void WorkerThread::PostTask(const WebTraceLocation& location, |
| 206 std::unique_ptr<WTF::CrossThreadClosure> task) { |
| 207 if (IsInShutdown()) |
| 208 return; |
| 209 GetWorkerBackingThread().BackingThread().PostTask( |
| 210 location, |
| 211 CrossThreadBind( |
| 212 &WorkerThread::PerformTaskOnWorkerThread<WTF::kCrossThreadAffinity>, |
| 213 CrossThreadUnretained(this), WTF::Passed(std::move(task)))); |
| 214 } |
| 215 |
206 void WorkerThread::AppendDebuggerTask( | 216 void WorkerThread::AppendDebuggerTask( |
207 std::unique_ptr<CrossThreadClosure> task) { | 217 std::unique_ptr<CrossThreadClosure> task) { |
208 DCHECK(IsMainThread()); | 218 DCHECK(IsMainThread()); |
209 if (requested_to_terminate_) | 219 if (IsInShutdown()) |
210 return; | 220 return; |
211 inspector_task_runner_->AppendTask(CrossThreadBind( | 221 inspector_task_runner_->AppendTask(CrossThreadBind( |
212 &WorkerThread::PerformDebuggerTaskOnWorkerThread, | 222 &WorkerThread::PerformDebuggerTaskOnWorkerThread, |
213 CrossThreadUnretained(this), WTF::Passed(std::move(task)))); | 223 CrossThreadUnretained(this), WTF::Passed(std::move(task)))); |
214 { | 224 { |
215 MutexLocker lock(thread_state_mutex_); | 225 MutexLocker lock(thread_state_mutex_); |
216 if (GetIsolate() && thread_state_ != ThreadState::kReadyToShutdown) | 226 if (GetIsolate() && thread_state_ != ThreadState::kReadyToShutdown) |
217 inspector_task_runner_->InterruptAndRunAllTasksDontWait(GetIsolate()); | 227 inspector_task_runner_->InterruptAndRunAllTasksDontWait(GetIsolate()); |
218 } | 228 } |
219 TaskRunnerHelper::Get(TaskType::kUnthrottled, this) | 229 GetWorkerBackingThread().BackingThread().PostTask( |
220 ->PostTask(BLINK_FROM_HERE, | 230 BLINK_FROM_HERE, |
221 CrossThreadBind( | 231 CrossThreadBind(&WorkerThread::PerformDebuggerTaskDontWaitOnWorkerThread, |
222 &WorkerThread::PerformDebuggerTaskDontWaitOnWorkerThread, | 232 CrossThreadUnretained(this))); |
223 CrossThreadUnretained(this))); | |
224 } | 233 } |
225 | 234 |
226 void WorkerThread::StartRunningDebuggerTasksOnPauseOnWorkerThread() { | 235 void WorkerThread::StartRunningDebuggerTasksOnPauseOnWorkerThread() { |
227 DCHECK(IsCurrentThread()); | 236 DCHECK(IsCurrentThread()); |
228 if (worker_inspector_controller_) | 237 if (worker_inspector_controller_) |
229 worker_inspector_controller_->FlushProtocolNotifications(); | 238 worker_inspector_controller_->FlushProtocolNotifications(); |
230 paused_in_debugger_ = true; | 239 paused_in_debugger_ = true; |
231 ThreadDebugger::IdleStarted(GetIsolate()); | 240 ThreadDebugger::IdleStarted(GetIsolate()); |
232 std::unique_ptr<CrossThreadClosure> task; | 241 std::unique_ptr<CrossThreadClosure> task; |
233 do { | 242 do { |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 DCHECK(IsThreadStateMutexLocked(lock)); | 423 DCHECK(IsThreadStateMutexLocked(lock)); |
415 | 424 |
416 DCHECK(exit_code == ExitCode::kSyncForciblyTerminated || | 425 DCHECK(exit_code == ExitCode::kSyncForciblyTerminated || |
417 exit_code == ExitCode::kAsyncForciblyTerminated); | 426 exit_code == ExitCode::kAsyncForciblyTerminated); |
418 SetExitCode(lock, exit_code); | 427 SetExitCode(lock, exit_code); |
419 | 428 |
420 GetIsolate()->TerminateExecution(); | 429 GetIsolate()->TerminateExecution(); |
421 forcible_termination_task_handle_.Cancel(); | 430 forcible_termination_task_handle_.Cancel(); |
422 } | 431 } |
423 | 432 |
424 void WorkerThread::InitializeSchedulerOnWorkerThread( | 433 bool WorkerThread::IsInShutdown() { |
425 WaitableEvent* waitable_event) { | 434 // Check if we've started termination or shutdown sequence. Avoid acquiring |
426 DCHECK(IsCurrentThread()); | 435 // a lock here to avoid introducing a risk of deadlock. Note that accessing |
427 DCHECK(!global_scope_scheduler_); | 436 // |m_requestedToTerminate| on the main thread or |m_threadState| on the |
428 scheduler::WebThreadImplForWorkerScheduler& web_thread_for_worker = | 437 // worker thread is safe as the flag is set only on the thread. |
429 static_cast<scheduler::WebThreadImplForWorkerScheduler&>( | 438 if (IsMainThread() && requested_to_terminate_) |
430 GetWorkerBackingThread().BackingThread().PlatformThread()); | 439 return true; |
431 global_scope_scheduler_ = | 440 if (IsCurrentThread() && thread_state_ == ThreadState::kReadyToShutdown) |
432 WTF::MakeUnique<scheduler::WorkerGlobalScopeScheduler>( | 441 return true; |
433 web_thread_for_worker.GetWorkerScheduler()); | 442 return false; |
434 waitable_event->Signal(); | |
435 } | 443 } |
436 | 444 |
437 void WorkerThread::InitializeOnWorkerThread( | 445 void WorkerThread::InitializeOnWorkerThread( |
438 std::unique_ptr<WorkerThreadStartupData> startup_data) { | 446 std::unique_ptr<WorkerThreadStartupData> startup_data) { |
439 DCHECK(IsCurrentThread()); | 447 DCHECK(IsCurrentThread()); |
440 DCHECK_EQ(ThreadState::kNotStarted, thread_state_); | 448 DCHECK_EQ(ThreadState::kNotStarted, thread_state_); |
441 | 449 |
442 KURL script_url = startup_data->script_url_; | 450 KURL script_url = startup_data->script_url_; |
443 String source_code = startup_data->source_code_; | 451 String source_code = startup_data->source_code_; |
444 WorkerThreadStartMode start_mode = startup_data->start_mode_; | 452 WorkerThreadStartMode start_mode = startup_data->start_mode_; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
521 inspector_task_runner_->Kill(); | 529 inspector_task_runner_->Kill(); |
522 GetWorkerReportingProxy().WillDestroyWorkerGlobalScope(); | 530 GetWorkerReportingProxy().WillDestroyWorkerGlobalScope(); |
523 probe::AllAsyncTasksCanceled(GlobalScope()); | 531 probe::AllAsyncTasksCanceled(GlobalScope()); |
524 | 532 |
525 GlobalScope()->NotifyContextDestroyed(); | 533 GlobalScope()->NotifyContextDestroyed(); |
526 if (worker_inspector_controller_) { | 534 if (worker_inspector_controller_) { |
527 worker_inspector_controller_->Dispose(); | 535 worker_inspector_controller_->Dispose(); |
528 worker_inspector_controller_.Clear(); | 536 worker_inspector_controller_.Clear(); |
529 } | 537 } |
530 GlobalScope()->Dispose(); | 538 GlobalScope()->Dispose(); |
531 global_scope_scheduler_->Dispose(); | |
532 console_message_storage_.Clear(); | 539 console_message_storage_.Clear(); |
533 GetWorkerBackingThread().BackingThread().RemoveTaskObserver(this); | 540 GetWorkerBackingThread().BackingThread().RemoveTaskObserver(this); |
534 } | 541 } |
535 | 542 |
536 void WorkerThread::PerformShutdownOnWorkerThread() { | 543 void WorkerThread::PerformShutdownOnWorkerThread() { |
537 DCHECK(IsCurrentThread()); | 544 DCHECK(IsCurrentThread()); |
538 DCHECK(CheckRequestedToTerminateOnWorkerThread()); | 545 DCHECK(CheckRequestedToTerminateOnWorkerThread()); |
539 DCHECK_EQ(ThreadState::kReadyToShutdown, thread_state_); | 546 DCHECK_EQ(ThreadState::kReadyToShutdown, thread_state_); |
540 | 547 |
541 // The below assignment will destroy the context, which will in turn notify | 548 // The below assignment will destroy the context, which will in turn notify |
542 // messaging proxy. We cannot let any objects survive past thread exit, | 549 // messaging proxy. We cannot let any objects survive past thread exit, |
543 // because no other thread will run GC or otherwise destroy them. If Oilpan | 550 // because no other thread will run GC or otherwise destroy them. If Oilpan |
544 // is enabled, we detach of the context/global scope, with the final heap | 551 // is enabled, we detach of the context/global scope, with the final heap |
545 // cleanup below sweeping it out. | 552 // cleanup below sweeping it out. |
546 global_scope_ = nullptr; | 553 global_scope_ = nullptr; |
547 | 554 |
548 if (IsOwningBackingThread()) | 555 if (IsOwningBackingThread()) |
549 GetWorkerBackingThread().Shutdown(); | 556 GetWorkerBackingThread().Shutdown(); |
550 // We must not touch workerBackingThread() from now on. | 557 // We must not touch workerBackingThread() from now on. |
551 | 558 |
552 // Notify the proxy that the WorkerOrWorkletGlobalScope has been disposed | 559 // Notify the proxy that the WorkerOrWorkletGlobalScope has been disposed |
553 // of. This can free this thread object, hence it must not be touched | 560 // of. This can free this thread object, hence it must not be touched |
554 // afterwards. | 561 // afterwards. |
555 GetWorkerReportingProxy().DidTerminateWorkerThread(); | 562 GetWorkerReportingProxy().DidTerminateWorkerThread(); |
556 | 563 |
557 shutdown_event_->Signal(); | 564 shutdown_event_->Signal(); |
558 } | 565 } |
559 | 566 |
| 567 template <WTF::FunctionThreadAffinity threadAffinity> |
| 568 void WorkerThread::PerformTaskOnWorkerThread( |
| 569 std::unique_ptr<Function<void(), threadAffinity>> task) { |
| 570 DCHECK(IsCurrentThread()); |
| 571 if (thread_state_ != ThreadState::kRunning) |
| 572 return; |
| 573 |
| 574 { |
| 575 DEFINE_THREAD_SAFE_STATIC_LOCAL( |
| 576 CustomCountHistogram, scoped_us_counter, |
| 577 new CustomCountHistogram("WorkerThread.Task.Time", 0, 10000000, 50)); |
| 578 ScopedUsHistogramTimer timer(scoped_us_counter); |
| 579 (*task)(); |
| 580 } |
| 581 } |
| 582 |
560 void WorkerThread::PerformDebuggerTaskOnWorkerThread( | 583 void WorkerThread::PerformDebuggerTaskOnWorkerThread( |
561 std::unique_ptr<CrossThreadClosure> task) { | 584 std::unique_ptr<CrossThreadClosure> task) { |
562 DCHECK(IsCurrentThread()); | 585 DCHECK(IsCurrentThread()); |
563 InspectorTaskRunner::IgnoreInterruptsScope scope( | 586 InspectorTaskRunner::IgnoreInterruptsScope scope( |
564 inspector_task_runner_.get()); | 587 inspector_task_runner_.get()); |
565 { | 588 { |
566 MutexLocker lock(thread_state_mutex_); | 589 MutexLocker lock(thread_state_mutex_); |
567 DCHECK_EQ(ThreadState::kRunning, thread_state_); | 590 DCHECK_EQ(ThreadState::kRunning, thread_state_); |
568 running_debugger_task_ = true; | 591 running_debugger_task_ = true; |
569 } | 592 } |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
636 MutexLocker lock(thread_state_mutex_); | 659 MutexLocker lock(thread_state_mutex_); |
637 return requested_to_terminate_; | 660 return requested_to_terminate_; |
638 } | 661 } |
639 | 662 |
640 ExitCode WorkerThread::GetExitCodeForTesting() { | 663 ExitCode WorkerThread::GetExitCodeForTesting() { |
641 MutexLocker lock(thread_state_mutex_); | 664 MutexLocker lock(thread_state_mutex_); |
642 return exit_code_; | 665 return exit_code_; |
643 } | 666 } |
644 | 667 |
645 } // namespace blink | 668 } // namespace blink |
OLD | NEW |