@@ -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
std::unique_ptr<PlatformWorkerData>
29
53
worker_data (static_cast <PlatformWorkerData*>(data));
@@ -39,8 +63,18 @@ static void PlatformWorkerThread(void* data) {
39
63
worker_data->platform_workers_ready ->Signal (lock);
40
64
}
41
65
66
+ bool debug_log_enabled =
67
+ worker_data->debug_log_level != PlatformDebugLogLevel::kNone ;
68
+ int id = worker_data->id ;
42
69
while (std::unique_ptr<Task> task =
43
70
pending_worker_tasks->Lock ().BlockingPop ()) {
71
+ if (debug_log_enabled) {
72
+ fprintf (stderr,
73
+ " \n PlatformWorkerThread %d running task %p\n " ,
74
+ id,
75
+ task.get ());
76
+ fflush (stderr);
77
+ }
44
78
task->Run ();
45
79
pending_worker_tasks->Lock ().NotifyOfCompletion ();
46
80
}
@@ -74,6 +108,12 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler {
74
108
75
109
void PostDelayedTask (std::unique_ptr<Task> task, double delay_in_seconds) {
76
110
auto locked = tasks_.Lock ();
111
+
112
+ // The delayed task scheuler is on is own thread with its own loop that
113
+ // runs the timers for the scheduled tasks to pop the original task back
114
+ // into the the worker task queue. This first pushes the tasks that
115
+ // schedules the timers into the local task queue that will be flushed
116
+ // by the local event loop.
77
117
locked.Push (std::make_unique<ScheduleTask>(
78
118
this , std::move (task), delay_in_seconds));
79
119
uv_async_send (&flush_tasks_);
@@ -108,6 +148,9 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler {
108
148
while (!tasks_to_run.empty ()) {
109
149
std::unique_ptr<Task> task = std::move (tasks_to_run.front ());
110
150
tasks_to_run.pop ();
151
+ // This runs either the ScheduleTasks that scheduels the timers to
152
+ // pop the tasks back into the worker task runner queue, or the
153
+ // or the StopTasks to stop the timers and drop all the pending tasks.
111
154
task->Run ();
112
155
}
113
156
}
@@ -135,9 +178,9 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler {
135
178
ScheduleTask (DelayedTaskScheduler* scheduler,
136
179
std::unique_ptr<Task> task,
137
180
double delay_in_seconds)
138
- : scheduler_(scheduler),
139
- task_ (std::move(task)),
140
- delay_in_seconds_(delay_in_seconds) {}
181
+ : scheduler_(scheduler),
182
+ task_ (std::move(task)),
183
+ delay_in_seconds_(delay_in_seconds) {}
141
184
142
185
void Run () override {
143
186
uint64_t delay_millis = llround (delay_in_seconds_ * 1000 );
@@ -172,15 +215,21 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler {
172
215
}
173
216
174
217
uv_sem_t ready_;
218
+ // Task queue in the worker thread task runner, we push the delayed task back
219
+ // to it when the timer expires.
175
220
TaskQueue<Task>* pending_worker_tasks_;
176
221
222
+ // Locally scheduled tasks to be poped into the worker task runner queue.
223
+ // It is flushed whenever the next closest timer expires.
177
224
TaskQueue<Task> tasks_;
178
225
uv_loop_t loop_;
179
226
uv_async_t flush_tasks_;
180
227
std::unordered_set<uv_timer_t *> timers_;
181
228
};
182
229
183
- WorkerThreadsTaskRunner::WorkerThreadsTaskRunner (int thread_pool_size) {
230
+ WorkerThreadsTaskRunner::WorkerThreadsTaskRunner (
231
+ int thread_pool_size, PlatformDebugLogLevel debug_log_level)
232
+ : debug_log_level_(debug_log_level) {
184
233
Mutex platform_workers_mutex;
185
234
ConditionVariable platform_workers_ready;
186
235
@@ -192,10 +241,13 @@ WorkerThreadsTaskRunner::WorkerThreadsTaskRunner(int thread_pool_size) {
192
241
threads_.push_back (delayed_task_scheduler_->Start ());
193
242
194
243
for (int i = 0 ; i < thread_pool_size; i++) {
195
- PlatformWorkerData* worker_data = new PlatformWorkerData{
196
- &pending_worker_tasks_, &platform_workers_mutex,
197
- &platform_workers_ready, &pending_platform_workers, i
198
- };
244
+ PlatformWorkerData* worker_data =
245
+ new PlatformWorkerData{&pending_worker_tasks_,
246
+ &platform_workers_mutex,
247
+ &platform_workers_ready,
248
+ &pending_platform_workers,
249
+ i,
250
+ debug_log_level_};
199
251
std::unique_ptr<uv_thread_t > t { new uv_thread_t () };
200
252
if (uv_thread_create (t.get (), PlatformWorkerThread,
201
253
worker_data) != 0 ) {
@@ -237,8 +289,8 @@ int WorkerThreadsTaskRunner::NumberOfWorkerThreads() const {
237
289
}
238
290
239
291
PerIsolatePlatformData::PerIsolatePlatformData (
240
- Isolate* isolate, uv_loop_t * loop)
241
- : isolate_(isolate), loop_(loop) {
292
+ Isolate* isolate, uv_loop_t * loop, PlatformDebugLogLevel debug_log_level )
293
+ : isolate_(isolate), loop_(loop), debug_log_level_(debug_log_level ) {
242
294
flush_tasks_ = new uv_async_t ();
243
295
CHECK_EQ (0 , uv_async_init (loop, flush_tasks_, FlushTasks));
244
296
flush_tasks_->data = static_cast <void *>(this );
@@ -264,6 +316,14 @@ void PerIsolatePlatformData::PostTask(std::unique_ptr<Task> task) {
264
316
// the foreground task runner is being cleaned up by Shutdown(). In that
265
317
// case, make sure we wait until the shutdown is completed (which leads
266
318
// to flush_tasks_ == nullptr, and the task will be discarded).
319
+ if (debug_log_level_ != PlatformDebugLogLevel::kNone ) {
320
+ fprintf (stderr, " \n PerIsolatePlatformData::PostTaskImpl %p" , task.get ());
321
+ if (debug_log_level_ == PlatformDebugLogLevel::kVerbose ) {
322
+ DumpNativeBacktrace (stderr);
323
+ }
324
+ fflush (stderr);
325
+ }
326
+
267
327
auto locked = foreground_tasks_.Lock ();
268
328
if (flush_tasks_ == nullptr ) return ;
269
329
locked.Push (std::move (task));
@@ -272,6 +332,17 @@ void PerIsolatePlatformData::PostTask(std::unique_ptr<Task> task) {
272
332
273
333
void PerIsolatePlatformData::PostDelayedTask (
274
334
std::unique_ptr<Task> task, double delay_in_seconds) {
335
+ if (debug_log_level_ != PlatformDebugLogLevel::kNone ) {
336
+ fprintf (stderr,
337
+ " \n PerIsolatePlatformData::PostDelayedTaskImpl %p %f" ,
338
+ task.get (),
339
+ delay_in_seconds);
340
+ if (debug_log_level_ == PlatformDebugLogLevel::kVerbose ) {
341
+ DumpNativeBacktrace (stderr);
342
+ }
343
+ fflush (stderr);
344
+ }
345
+
275
346
auto locked = foreground_delayed_tasks_.Lock ();
276
347
if (flush_tasks_ == nullptr ) return ;
277
348
std::unique_ptr<DelayedTask> delayed (new DelayedTask ());
@@ -339,6 +410,16 @@ void PerIsolatePlatformData::DecreaseHandleCount() {
339
410
NodePlatform::NodePlatform (int thread_pool_size,
340
411
v8::TracingController* tracing_controller,
341
412
v8::PageAllocator* page_allocator) {
413
+ if (per_process::enabled_debug_list.enabled (
414
+ DebugCategory::PLATFORM_VERBOSE)) {
415
+ debug_log_level_ = PlatformDebugLogLevel::kVerbose ;
416
+ } else if (per_process::enabled_debug_list.enabled (
417
+ DebugCategory::PLATFORM_MINIMAL)) {
418
+ debug_log_level_ = PlatformDebugLogLevel::kMinimal ;
419
+ } else {
420
+ debug_log_level_ = PlatformDebugLogLevel::kNone ;
421
+ }
422
+
342
423
if (tracing_controller != nullptr ) {
343
424
tracing_controller_ = tracing_controller;
344
425
} else {
@@ -355,8 +436,8 @@ NodePlatform::NodePlatform(int thread_pool_size,
355
436
DCHECK_EQ (GetTracingController (), tracing_controller_);
356
437
357
438
thread_pool_size = GetActualThreadPoolSize (thread_pool_size);
358
- worker_thread_task_runner_ =
359
- std::make_shared<WorkerThreadsTaskRunner>( thread_pool_size);
439
+ worker_thread_task_runner_ = std::make_shared<WorkerThreadsTaskRunner>(
440
+ thread_pool_size, debug_log_level_ );
360
441
}
361
442
362
443
NodePlatform::~NodePlatform () {
@@ -365,7 +446,8 @@ NodePlatform::~NodePlatform() {
365
446
366
447
void NodePlatform::RegisterIsolate (Isolate* isolate, uv_loop_t * loop) {
367
448
Mutex::ScopedLock lock (per_isolate_mutex_);
368
- auto delegate = std::make_shared<PerIsolatePlatformData>(isolate, loop);
449
+ auto delegate =
450
+ std::make_shared<PerIsolatePlatformData>(isolate, loop, debug_log_level_);
369
451
IsolatePlatformDelegate* ptr = delegate.get ();
370
452
auto insertion = per_isolate_.emplace (
371
453
isolate,
@@ -520,6 +602,17 @@ void NodePlatform::PostTaskOnWorkerThreadImpl(
520
602
v8::TaskPriority priority,
521
603
std::unique_ptr<v8::Task> task,
522
604
const v8::SourceLocation& location) {
605
+ if (debug_log_level_ != PlatformDebugLogLevel::kNone ) {
606
+ fprintf (stderr,
607
+ " \n NodePlatform::PostTaskOnWorkerThreadImpl %s %p" ,
608
+ GetTaskPriorityName (priority),
609
+ task.get ());
610
+ PrintSourceLocation (location);
611
+ if (debug_log_level_ == PlatformDebugLogLevel::kVerbose ) {
612
+ DumpNativeBacktrace (stderr);
613
+ }
614
+ fflush (stderr);
615
+ }
523
616
worker_thread_task_runner_->PostTask (std::move (task));
524
617
}
525
618
@@ -528,6 +621,18 @@ void NodePlatform::PostDelayedTaskOnWorkerThreadImpl(
528
621
std::unique_ptr<v8::Task> task,
529
622
double delay_in_seconds,
530
623
const v8::SourceLocation& location) {
624
+ if (debug_log_level_ != PlatformDebugLogLevel::kNone ) {
625
+ fprintf (stderr,
626
+ " \n NodePlatform::PostDelayedTaskOnWorkerThreadImpl %s %p %f" ,
627
+ GetTaskPriorityName (priority),
628
+ task.get (),
629
+ delay_in_seconds);
630
+ PrintSourceLocation (location);
631
+ if (debug_log_level_ == PlatformDebugLogLevel::kVerbose ) {
632
+ DumpNativeBacktrace (stderr);
633
+ }
634
+ fflush (stderr);
635
+ }
531
636
worker_thread_task_runner_->PostDelayedTask (std::move (task),
532
637
delay_in_seconds);
533
638
}
@@ -557,6 +662,17 @@ std::unique_ptr<v8::JobHandle> NodePlatform::CreateJobImpl(
557
662
v8::TaskPriority priority,
558
663
std::unique_ptr<v8::JobTask> job_task,
559
664
const v8::SourceLocation& location) {
665
+ if (debug_log_level_ != PlatformDebugLogLevel::kNone ) {
666
+ fprintf (stderr,
667
+ " \n NodePlatform::CreateJobImpl %s %p" ,
668
+ GetTaskPriorityName (priority),
669
+ job_task.get ());
670
+ PrintSourceLocation (location);
671
+ if (debug_log_level_ == PlatformDebugLogLevel::kVerbose ) {
672
+ DumpNativeBacktrace (stderr);
673
+ }
674
+ fflush (stderr);
675
+ }
560
676
return v8::platform::NewDefaultJobHandle (
561
677
this , priority, std::move (job_task), NumberOfWorkerThreads ());
562
678
}
0 commit comments