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

Side by Side Diff: third_party/WebKit/Source/core/workers/WorkerThread.cpp

Issue 2806623004: Worker: Introduce per-global-scope task scheduler (Closed)
Patch Set: address review comments Created 3 years, 8 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
OLDNEW
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
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"
34 #include "core/inspector/ConsoleMessageStorage.h" 35 #include "core/inspector/ConsoleMessageStorage.h"
35 #include "core/inspector/InspectorTaskRunner.h" 36 #include "core/inspector/InspectorTaskRunner.h"
36 #include "core/inspector/WorkerInspectorController.h" 37 #include "core/inspector/WorkerInspectorController.h"
37 #include "core/inspector/WorkerThreadDebugger.h" 38 #include "core/inspector/WorkerThreadDebugger.h"
38 #include "core/origin_trials/OriginTrialContext.h" 39 #include "core/origin_trials/OriginTrialContext.h"
39 #include "core/probe/CoreProbes.h" 40 #include "core/probe/CoreProbes.h"
40 #include "core/workers/ThreadedWorkletGlobalScope.h" 41 #include "core/workers/ThreadedWorkletGlobalScope.h"
41 #include "core/workers/WorkerBackingThread.h" 42 #include "core/workers/WorkerBackingThread.h"
42 #include "core/workers/WorkerClients.h" 43 #include "core/workers/WorkerClients.h"
43 #include "core/workers/WorkerGlobalScope.h" 44 #include "core/workers/WorkerGlobalScope.h"
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 DEFINE_THREAD_SAFE_STATIC_LOCAL( 101 DEFINE_THREAD_SAFE_STATIC_LOCAL(
101 EnumerationHistogram, exit_code_histogram, 102 EnumerationHistogram, exit_code_histogram,
102 new EnumerationHistogram("WorkerThread.ExitCode", 103 new EnumerationHistogram("WorkerThread.ExitCode",
103 static_cast<int>(ExitCode::kLastEnum))); 104 static_cast<int>(ExitCode::kLastEnum)));
104 exit_code_histogram.Count(static_cast<int>(exit_code_)); 105 exit_code_histogram.Count(static_cast<int>(exit_code_));
105 } 106 }
106 107
107 void WorkerThread::Start(std::unique_ptr<WorkerThreadStartupData> startup_data, 108 void WorkerThread::Start(std::unique_ptr<WorkerThreadStartupData> startup_data,
108 ParentFrameTaskRunners* parent_frame_task_runners) { 109 ParentFrameTaskRunners* parent_frame_task_runners) {
109 DCHECK(IsMainThread()); 110 DCHECK(IsMainThread());
110
111 if (requested_to_start_) 111 if (requested_to_start_)
112 return; 112 return;
113 113
114 requested_to_start_ = true; 114 requested_to_start_ = true;
115 parent_frame_task_runners_ = parent_frame_task_runners; 115 parent_frame_task_runners_ = parent_frame_task_runners;
116
117 // Synchronously initialize the per-global-scope scheduler to prevent someone
118 // from posting a task to the thread before the scheduler is ready.
119 WaitableEvent waitable_event;
120 GetWorkerBackingThread().BackingThread().PostTask(
121 BLINK_FROM_HERE,
122 CrossThreadBind(&WorkerThread::InitializeSchedulerOnWorkerThread,
123 CrossThreadUnretained(this),
124 CrossThreadUnretained(&waitable_event)));
125 waitable_event.Wait();
126
116 GetWorkerBackingThread().BackingThread().PostTask( 127 GetWorkerBackingThread().BackingThread().PostTask(
117 BLINK_FROM_HERE, CrossThreadBind(&WorkerThread::InitializeOnWorkerThread, 128 BLINK_FROM_HERE, CrossThreadBind(&WorkerThread::InitializeOnWorkerThread,
118 CrossThreadUnretained(this), 129 CrossThreadUnretained(this),
119 WTF::Passed(std::move(startup_data)))); 130 WTF::Passed(std::move(startup_data))));
120 } 131 }
121 132
122 void WorkerThread::Terminate() { 133 void WorkerThread::Terminate() {
123 DCHECK(IsMainThread()); 134 DCHECK(IsMainThread());
124 TerminateInternal(TerminationMode::kGraceful); 135 TerminateInternal(TerminationMode::kGraceful);
125 } 136 }
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 } 194 }
184 195
185 v8::Isolate* WorkerThread::GetIsolate() { 196 v8::Isolate* WorkerThread::GetIsolate() {
186 return GetWorkerBackingThread().GetIsolate(); 197 return GetWorkerBackingThread().GetIsolate();
187 } 198 }
188 199
189 bool WorkerThread::IsCurrentThread() { 200 bool WorkerThread::IsCurrentThread() {
190 return GetWorkerBackingThread().BackingThread().IsCurrentThread(); 201 return GetWorkerBackingThread().BackingThread().IsCurrentThread();
191 } 202 }
192 203
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
216 void WorkerThread::AppendDebuggerTask( 204 void WorkerThread::AppendDebuggerTask(
217 std::unique_ptr<CrossThreadClosure> task) { 205 std::unique_ptr<CrossThreadClosure> task) {
218 DCHECK(IsMainThread()); 206 DCHECK(IsMainThread());
219 if (IsInShutdown()) 207 if (requested_to_terminate_)
220 return; 208 return;
221 inspector_task_runner_->AppendTask(CrossThreadBind( 209 inspector_task_runner_->AppendTask(CrossThreadBind(
222 &WorkerThread::PerformDebuggerTaskOnWorkerThread, 210 &WorkerThread::PerformDebuggerTaskOnWorkerThread,
223 CrossThreadUnretained(this), WTF::Passed(std::move(task)))); 211 CrossThreadUnretained(this), WTF::Passed(std::move(task))));
224 { 212 {
225 MutexLocker lock(thread_state_mutex_); 213 MutexLocker lock(thread_state_mutex_);
226 if (GetIsolate() && thread_state_ != ThreadState::kReadyToShutdown) 214 if (GetIsolate() && thread_state_ != ThreadState::kReadyToShutdown)
227 inspector_task_runner_->InterruptAndRunAllTasksDontWait(GetIsolate()); 215 inspector_task_runner_->InterruptAndRunAllTasksDontWait(GetIsolate());
228 } 216 }
229 GetWorkerBackingThread().BackingThread().PostTask( 217 TaskRunnerHelper::Get(TaskType::kUnthrottled, this)
230 BLINK_FROM_HERE, 218 ->PostTask(BLINK_FROM_HERE,
231 CrossThreadBind(&WorkerThread::PerformDebuggerTaskDontWaitOnWorkerThread, 219 CrossThreadBind(
232 CrossThreadUnretained(this))); 220 &WorkerThread::PerformDebuggerTaskDontWaitOnWorkerThread,
221 CrossThreadUnretained(this)));
233 } 222 }
234 223
235 void WorkerThread::StartRunningDebuggerTasksOnPauseOnWorkerThread() { 224 void WorkerThread::StartRunningDebuggerTasksOnPauseOnWorkerThread() {
236 DCHECK(IsCurrentThread()); 225 DCHECK(IsCurrentThread());
237 if (worker_inspector_controller_) 226 if (worker_inspector_controller_)
238 worker_inspector_controller_->FlushProtocolNotifications(); 227 worker_inspector_controller_->FlushProtocolNotifications();
239 paused_in_debugger_ = true; 228 paused_in_debugger_ = true;
240 ThreadDebugger::IdleStarted(GetIsolate()); 229 ThreadDebugger::IdleStarted(GetIsolate());
241 std::unique_ptr<CrossThreadClosure> task; 230 std::unique_ptr<CrossThreadClosure> task;
242 do { 231 do {
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 DCHECK(IsThreadStateMutexLocked(lock)); 412 DCHECK(IsThreadStateMutexLocked(lock));
424 413
425 DCHECK(exit_code == ExitCode::kSyncForciblyTerminated || 414 DCHECK(exit_code == ExitCode::kSyncForciblyTerminated ||
426 exit_code == ExitCode::kAsyncForciblyTerminated); 415 exit_code == ExitCode::kAsyncForciblyTerminated);
427 SetExitCode(lock, exit_code); 416 SetExitCode(lock, exit_code);
428 417
429 GetIsolate()->TerminateExecution(); 418 GetIsolate()->TerminateExecution();
430 forcible_termination_task_handle_.Cancel(); 419 forcible_termination_task_handle_.Cancel();
431 } 420 }
432 421
433 bool WorkerThread::IsInShutdown() { 422 void WorkerThread::InitializeSchedulerOnWorkerThread(
434 // Check if we've started termination or shutdown sequence. Avoid acquiring 423 WaitableEvent* waitable_event) {
435 // a lock here to avoid introducing a risk of deadlock. Note that accessing 424 DCHECK(IsCurrentThread());
kinuko 2017/04/17 05:01:11 nit: DCHECK(!global_scope_scheduler_)
nhiroki 2017/04/17 11:03:46 Done.
436 // |m_requestedToTerminate| on the main thread or |m_threadState| on the 425 global_scope_scheduler_ =
437 // worker thread is safe as the flag is set only on the thread. 426 GetWorkerBackingThread().CreateGlobalScopeScheduler();
438 if (IsMainThread() && requested_to_terminate_) 427 waitable_event->Signal();
439 return true;
440 if (IsCurrentThread() && thread_state_ == ThreadState::kReadyToShutdown)
441 return true;
442 return false;
443 } 428 }
444 429
445 void WorkerThread::InitializeOnWorkerThread( 430 void WorkerThread::InitializeOnWorkerThread(
446 std::unique_ptr<WorkerThreadStartupData> startup_data) { 431 std::unique_ptr<WorkerThreadStartupData> startup_data) {
447 DCHECK(IsCurrentThread()); 432 DCHECK(IsCurrentThread());
448 DCHECK_EQ(ThreadState::kNotStarted, thread_state_); 433 DCHECK_EQ(ThreadState::kNotStarted, thread_state_);
449 434
450 KURL script_url = startup_data->script_url_; 435 KURL script_url = startup_data->script_url_;
451 String source_code = startup_data->source_code_; 436 String source_code = startup_data->source_code_;
452 WorkerThreadStartMode start_mode = startup_data->start_mode_; 437 WorkerThreadStartMode start_mode = startup_data->start_mode_;
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 inspector_task_runner_->Kill(); 514 inspector_task_runner_->Kill();
530 GetWorkerReportingProxy().WillDestroyWorkerGlobalScope(); 515 GetWorkerReportingProxy().WillDestroyWorkerGlobalScope();
531 probe::AllAsyncTasksCanceled(GlobalScope()); 516 probe::AllAsyncTasksCanceled(GlobalScope());
532 517
533 GlobalScope()->NotifyContextDestroyed(); 518 GlobalScope()->NotifyContextDestroyed();
534 if (worker_inspector_controller_) { 519 if (worker_inspector_controller_) {
535 worker_inspector_controller_->Dispose(); 520 worker_inspector_controller_->Dispose();
536 worker_inspector_controller_.Clear(); 521 worker_inspector_controller_.Clear();
537 } 522 }
538 GlobalScope()->Dispose(); 523 GlobalScope()->Dispose();
524 global_scope_scheduler_->Dispose();
539 console_message_storage_.Clear(); 525 console_message_storage_.Clear();
540 GetWorkerBackingThread().BackingThread().RemoveTaskObserver(this); 526 GetWorkerBackingThread().BackingThread().RemoveTaskObserver(this);
541 } 527 }
542 528
543 void WorkerThread::PerformShutdownOnWorkerThread() { 529 void WorkerThread::PerformShutdownOnWorkerThread() {
544 DCHECK(IsCurrentThread()); 530 DCHECK(IsCurrentThread());
545 DCHECK(CheckRequestedToTerminateOnWorkerThread()); 531 DCHECK(CheckRequestedToTerminateOnWorkerThread());
546 DCHECK_EQ(ThreadState::kReadyToShutdown, thread_state_); 532 DCHECK_EQ(ThreadState::kReadyToShutdown, thread_state_);
547 533
548 // The below assignment will destroy the context, which will in turn notify 534 // The below assignment will destroy the context, which will in turn notify
549 // messaging proxy. We cannot let any objects survive past thread exit, 535 // messaging proxy. We cannot let any objects survive past thread exit,
550 // because no other thread will run GC or otherwise destroy them. If Oilpan 536 // because no other thread will run GC or otherwise destroy them. If Oilpan
551 // is enabled, we detach of the context/global scope, with the final heap 537 // is enabled, we detach of the context/global scope, with the final heap
552 // cleanup below sweeping it out. 538 // cleanup below sweeping it out.
553 global_scope_ = nullptr; 539 global_scope_ = nullptr;
554 540
555 if (IsOwningBackingThread()) 541 if (IsOwningBackingThread())
556 GetWorkerBackingThread().Shutdown(); 542 GetWorkerBackingThread().Shutdown();
557 // We must not touch workerBackingThread() from now on. 543 // We must not touch workerBackingThread() from now on.
558 544
559 // Notify the proxy that the WorkerOrWorkletGlobalScope has been disposed 545 // Notify the proxy that the WorkerOrWorkletGlobalScope has been disposed
560 // of. This can free this thread object, hence it must not be touched 546 // of. This can free this thread object, hence it must not be touched
561 // afterwards. 547 // afterwards.
562 GetWorkerReportingProxy().DidTerminateWorkerThread(); 548 GetWorkerReportingProxy().DidTerminateWorkerThread();
563 549
564 shutdown_event_->Signal(); 550 shutdown_event_->Signal();
565 } 551 }
566 552
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));
kinuko 2017/04/17 05:01:11 Are we deprecating this histogram?
nhiroki 2017/04/17 11:03:46 Oh, good catch. I moved this into WorkerScheduler
578 ScopedUsHistogramTimer timer(scoped_us_counter);
579 (*task)();
580 }
581 }
582
583 void WorkerThread::PerformDebuggerTaskOnWorkerThread( 553 void WorkerThread::PerformDebuggerTaskOnWorkerThread(
584 std::unique_ptr<CrossThreadClosure> task) { 554 std::unique_ptr<CrossThreadClosure> task) {
585 DCHECK(IsCurrentThread()); 555 DCHECK(IsCurrentThread());
586 InspectorTaskRunner::IgnoreInterruptsScope scope( 556 InspectorTaskRunner::IgnoreInterruptsScope scope(
587 inspector_task_runner_.get()); 557 inspector_task_runner_.get());
588 { 558 {
589 MutexLocker lock(thread_state_mutex_); 559 MutexLocker lock(thread_state_mutex_);
590 DCHECK_EQ(ThreadState::kRunning, thread_state_); 560 DCHECK_EQ(ThreadState::kRunning, thread_state_);
591 running_debugger_task_ = true; 561 running_debugger_task_ = true;
592 } 562 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
659 MutexLocker lock(thread_state_mutex_); 629 MutexLocker lock(thread_state_mutex_);
660 return requested_to_terminate_; 630 return requested_to_terminate_;
661 } 631 }
662 632
663 ExitCode WorkerThread::GetExitCodeForTesting() { 633 ExitCode WorkerThread::GetExitCodeForTesting() {
664 MutexLocker lock(thread_state_mutex_); 634 MutexLocker lock(thread_state_mutex_);
665 return exit_code_; 635 return exit_code_;
666 } 636 }
667 637
668 } // namespace blink 638 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698