@@ -13,6 +13,7 @@ using v8::Isolate;
13
13
using v8::Object;
14
14
using v8::Platform;
15
15
using v8::Task;
16
+ using v8::TaskPriority;
16
17
17
18
namespace {
18
19
@@ -22,8 +23,31 @@ struct PlatformWorkerData {
22
23
ConditionVariable* platform_workers_ready;
23
24
int * pending_platform_workers;
24
25
int id;
26
+ PlatformDebugLogLevel debug_log_level;
25
27
};
26
28
29
+ const char * GetTaskPriorityName (TaskPriority priority) {
30
+ switch (priority) {
31
+ case TaskPriority::kUserBlocking :
32
+ return " UserBlocking" ;
33
+ case TaskPriority::kUserVisible :
34
+ return " UserVisible" ;
35
+ case TaskPriority::kBestEffort :
36
+ return " BestEffort" ;
37
+ default :
38
+ return " Unknown" ;
39
+ }
40
+ }
41
+
42
+ static void PrintSourceLocation (const v8::SourceLocation& location) {
43
+ auto loc = location.ToString ();
44
+ if (!loc.empty ()) {
45
+ fprintf (stderr, " %s\n " , loc.c_str ());
46
+ } else {
47
+ fprintf (stderr, " <no location>\n " );
48
+ }
49
+ }
50
+
27
51
static void PlatformWorkerThread (void * data) {
28
52
uv_thread_setname (" V8Worker" );
29
53
std::unique_ptr<PlatformWorkerData>
@@ -40,8 +64,18 @@ static void PlatformWorkerThread(void* data) {
40
64
worker_data->platform_workers_ready ->Signal (lock);
41
65
}
42
66
67
+ bool debug_log_enabled =
68
+ worker_data->debug_log_level != PlatformDebugLogLevel::kNone ;
69
+ int id = worker_data->id ;
43
70
while (std::unique_ptr<Task> task =
44
71
pending_worker_tasks->Lock ().BlockingPop ()) {
72
+ if (debug_log_enabled) {
73
+ fprintf (stderr,
74
+ " \n PlatformWorkerThread %d running task %p\n " ,
75
+ id,
76
+ task.get ());
77
+ fflush (stderr);
78
+ }
45
79
task->Run ();
46
80
pending_worker_tasks->Lock ().NotifyOfCompletion ();
47
81
}
@@ -75,6 +109,12 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler {
75
109
76
110
void PostDelayedTask (std::unique_ptr<Task> task, double delay_in_seconds) {
77
111
auto locked = tasks_.Lock ();
112
+
113
+ // The delayed task scheuler is on is own thread with its own loop that
114
+ // runs the timers for the scheduled tasks to pop the original task back
115
+ // into the the worker task queue. This first pushes the tasks that
116
+ // schedules the timers into the local task queue that will be flushed
117
+ // by the local event loop.
78
118
locked.Push (std::make_unique<ScheduleTask>(
79
119
this , std::move (task), delay_in_seconds));
80
120
uv_async_send (&flush_tasks_);
@@ -109,6 +149,9 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler {
109
149
while (!tasks_to_run.empty ()) {
110
150
std::unique_ptr<Task> task = std::move (tasks_to_run.front ());
111
151
tasks_to_run.pop ();
152
+ // This runs either the ScheduleTasks that scheduels the timers to
153
+ // pop the tasks back into the worker task runner queue, or the
154
+ // or the StopTasks to stop the timers and drop all the pending tasks.
112
155
task->Run ();
113
156
}
114
157
}
@@ -136,9 +179,9 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler {
136
179
ScheduleTask (DelayedTaskScheduler* scheduler,
137
180
std::unique_ptr<Task> task,
138
181
double delay_in_seconds)
139
- : scheduler_(scheduler),
140
- task_ (std::move(task)),
141
- delay_in_seconds_(delay_in_seconds) {}
182
+ : scheduler_(scheduler),
183
+ task_ (std::move(task)),
184
+ delay_in_seconds_(delay_in_seconds) {}
142
185
143
186
void Run () override {
144
187
uint64_t delay_millis = llround (delay_in_seconds_ * 1000 );
@@ -173,15 +216,21 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler {
173
216
}
174
217
175
218
uv_sem_t ready_;
219
+ // Task queue in the worker thread task runner, we push the delayed task back
220
+ // to it when the timer expires.
176
221
TaskQueue<Task>* pending_worker_tasks_;
177
222
223
+ // Locally scheduled tasks to be poped into the worker task runner queue.
224
+ // It is flushed whenever the next closest timer expires.
178
225
TaskQueue<Task> tasks_;
179
226
uv_loop_t loop_;
180
227
uv_async_t flush_tasks_;
181
228
std::unordered_set<uv_timer_t *> timers_;
182
229
};
183
230
184
- WorkerThreadsTaskRunner::WorkerThreadsTaskRunner (int thread_pool_size) {
231
+ WorkerThreadsTaskRunner::WorkerThreadsTaskRunner (
232
+ int thread_pool_size, PlatformDebugLogLevel debug_log_level)
233
+ : debug_log_level_(debug_log_level) {
185
234
Mutex platform_workers_mutex;
186
235
ConditionVariable platform_workers_ready;
187
236
@@ -193,10 +242,13 @@ WorkerThreadsTaskRunner::WorkerThreadsTaskRunner(int thread_pool_size) {
193
242
threads_.push_back (delayed_task_scheduler_->Start ());
194
243
195
244
for (int i = 0 ; i < thread_pool_size; i++) {
196
- PlatformWorkerData* worker_data = new PlatformWorkerData{
197
- &pending_worker_tasks_, &platform_workers_mutex,
198
- &platform_workers_ready, &pending_platform_workers, i
199
- };
245
+ PlatformWorkerData* worker_data =
246
+ new PlatformWorkerData{&pending_worker_tasks_,
247
+ &platform_workers_mutex,
248
+ &platform_workers_ready,
249
+ &pending_platform_workers,
250
+ i,
251
+ debug_log_level_};
200
252
std::unique_ptr<uv_thread_t > t { new uv_thread_t () };
201
253
if (uv_thread_create (t.get (), PlatformWorkerThread,
202
254
worker_data) != 0 ) {
@@ -238,8 +290,8 @@ int WorkerThreadsTaskRunner::NumberOfWorkerThreads() const {
238
290
}
239
291
240
292
PerIsolatePlatformData::PerIsolatePlatformData (
241
- Isolate* isolate, uv_loop_t * loop)
242
- : isolate_(isolate), loop_(loop) {
293
+ Isolate* isolate, uv_loop_t * loop, PlatformDebugLogLevel debug_log_level )
294
+ : isolate_(isolate), loop_(loop), debug_log_level_(debug_log_level ) {
243
295
flush_tasks_ = new uv_async_t ();
244
296
CHECK_EQ (0 , uv_async_init (loop, flush_tasks_, FlushTasks));
245
297
flush_tasks_->data = static_cast <void *>(this );
@@ -267,6 +319,15 @@ void PerIsolatePlatformData::PostTaskImpl(std::unique_ptr<Task> task,
267
319
// the foreground task runner is being cleaned up by Shutdown(). In that
268
320
// case, make sure we wait until the shutdown is completed (which leads
269
321
// to flush_tasks_ == nullptr, and the task will be discarded).
322
+ if (debug_log_level_ != PlatformDebugLogLevel::kNone ) {
323
+ fprintf (stderr, " \n PerIsolatePlatformData::PostTaskImpl %p" , task.get ());
324
+ PrintSourceLocation (location);
325
+ if (debug_log_level_ == PlatformDebugLogLevel::kVerbose ) {
326
+ DumpNativeBacktrace (stderr);
327
+ }
328
+ fflush (stderr);
329
+ }
330
+
270
331
auto locked = foreground_tasks_.Lock ();
271
332
if (flush_tasks_ == nullptr ) return ;
272
333
locked.Push (std::move (task));
@@ -277,6 +338,18 @@ void PerIsolatePlatformData::PostDelayedTaskImpl(
277
338
std::unique_ptr<Task> task,
278
339
double delay_in_seconds,
279
340
const v8::SourceLocation& location) {
341
+ if (debug_log_level_ != PlatformDebugLogLevel::kNone ) {
342
+ fprintf (stderr,
343
+ " \n PerIsolatePlatformData::PostDelayedTaskImpl %p %f" ,
344
+ task.get (),
345
+ delay_in_seconds);
346
+ PrintSourceLocation (location);
347
+ if (debug_log_level_ == PlatformDebugLogLevel::kVerbose ) {
348
+ DumpNativeBacktrace (stderr);
349
+ }
350
+ fflush (stderr);
351
+ }
352
+
280
353
auto locked = foreground_delayed_tasks_.Lock ();
281
354
if (flush_tasks_ == nullptr ) return ;
282
355
std::unique_ptr<DelayedTask> delayed (new DelayedTask ());
@@ -346,6 +419,16 @@ void PerIsolatePlatformData::DecreaseHandleCount() {
346
419
NodePlatform::NodePlatform (int thread_pool_size,
347
420
v8::TracingController* tracing_controller,
348
421
v8::PageAllocator* page_allocator) {
422
+ if (per_process::enabled_debug_list.enabled (
423
+ DebugCategory::PLATFORM_VERBOSE)) {
424
+ debug_log_level_ = PlatformDebugLogLevel::kVerbose ;
425
+ } else if (per_process::enabled_debug_list.enabled (
426
+ DebugCategory::PLATFORM_MINIMAL)) {
427
+ debug_log_level_ = PlatformDebugLogLevel::kMinimal ;
428
+ } else {
429
+ debug_log_level_ = PlatformDebugLogLevel::kNone ;
430
+ }
431
+
349
432
if (tracing_controller != nullptr ) {
350
433
tracing_controller_ = tracing_controller;
351
434
} else {
@@ -362,8 +445,8 @@ NodePlatform::NodePlatform(int thread_pool_size,
362
445
DCHECK_EQ (GetTracingController (), tracing_controller_);
363
446
364
447
thread_pool_size = GetActualThreadPoolSize (thread_pool_size);
365
- worker_thread_task_runner_ =
366
- std::make_shared<WorkerThreadsTaskRunner>( thread_pool_size);
448
+ worker_thread_task_runner_ = std::make_shared<WorkerThreadsTaskRunner>(
449
+ thread_pool_size, debug_log_level_ );
367
450
}
368
451
369
452
NodePlatform::~NodePlatform () {
@@ -372,7 +455,8 @@ NodePlatform::~NodePlatform() {
372
455
373
456
void NodePlatform::RegisterIsolate (Isolate* isolate, uv_loop_t * loop) {
374
457
Mutex::ScopedLock lock (per_isolate_mutex_);
375
- auto delegate = std::make_shared<PerIsolatePlatformData>(isolate, loop);
458
+ auto delegate =
459
+ std::make_shared<PerIsolatePlatformData>(isolate, loop, debug_log_level_);
376
460
IsolatePlatformDelegate* ptr = delegate.get ();
377
461
auto insertion = per_isolate_.emplace (
378
462
isolate,
@@ -527,6 +611,17 @@ void NodePlatform::PostTaskOnWorkerThreadImpl(
527
611
v8::TaskPriority priority,
528
612
std::unique_ptr<v8::Task> task,
529
613
const v8::SourceLocation& location) {
614
+ if (debug_log_level_ != PlatformDebugLogLevel::kNone ) {
615
+ fprintf (stderr,
616
+ " \n NodePlatform::PostTaskOnWorkerThreadImpl %s %p" ,
617
+ GetTaskPriorityName (priority),
618
+ task.get ());
619
+ PrintSourceLocation (location);
620
+ if (debug_log_level_ == PlatformDebugLogLevel::kVerbose ) {
621
+ DumpNativeBacktrace (stderr);
622
+ }
623
+ fflush (stderr);
624
+ }
530
625
worker_thread_task_runner_->PostTask (std::move (task));
531
626
}
532
627
@@ -535,6 +630,18 @@ void NodePlatform::PostDelayedTaskOnWorkerThreadImpl(
535
630
std::unique_ptr<v8::Task> task,
536
631
double delay_in_seconds,
537
632
const v8::SourceLocation& location) {
633
+ if (debug_log_level_ != PlatformDebugLogLevel::kNone ) {
634
+ fprintf (stderr,
635
+ " \n NodePlatform::PostDelayedTaskOnWorkerThreadImpl %s %p %f" ,
636
+ GetTaskPriorityName (priority),
637
+ task.get (),
638
+ delay_in_seconds);
639
+ PrintSourceLocation (location);
640
+ if (debug_log_level_ == PlatformDebugLogLevel::kVerbose ) {
641
+ DumpNativeBacktrace (stderr);
642
+ }
643
+ fflush (stderr);
644
+ }
538
645
worker_thread_task_runner_->PostDelayedTask (std::move (task),
539
646
delay_in_seconds);
540
647
}
@@ -564,6 +671,17 @@ std::unique_ptr<v8::JobHandle> NodePlatform::CreateJobImpl(
564
671
v8::TaskPriority priority,
565
672
std::unique_ptr<v8::JobTask> job_task,
566
673
const v8::SourceLocation& location) {
674
+ if (debug_log_level_ != PlatformDebugLogLevel::kNone ) {
675
+ fprintf (stderr,
676
+ " \n NodePlatform::CreateJobImpl %s %p" ,
677
+ GetTaskPriorityName (priority),
678
+ job_task.get ());
679
+ PrintSourceLocation (location);
680
+ if (debug_log_level_ == PlatformDebugLogLevel::kVerbose ) {
681
+ DumpNativeBacktrace (stderr);
682
+ }
683
+ fflush (stderr);
684
+ }
567
685
return v8::platform::NewDefaultJobHandle (
568
686
this , priority, std::move (job_task), NumberOfWorkerThreads ());
569
687
}
0 commit comments