From 2a256c82ecb7cd4c797d834d49051bc2bf79986c Mon Sep 17 00:00:00 2001 From: Markus Handell Date: Mon, 27 Feb 2023 12:41:39 +0100 Subject: [PATCH] Implement support for Chrome task origin tracing. #2/4 This prepares TaskQueueBase sub classes to be able to migrate to the location and traits-based API. It re-introduces a Location class into the webrtc namespace, which is meant to be overridden by Chromium. Bug: chromium:1416199 Change-Id: I712c7806a71b3b99b2a2bf95e555b357c21c15ae Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/294381 Reviewed-by: Mirko Bonadei Commit-Queue: Markus Handell Reviewed-by: Danil Chapovalov Reviewed-by: Harald Alvestrand Cr-Commit-Position: refs/heads/main@{#39400} --- api/BUILD.gn | 11 +++++++ api/location.h | 31 +++++++++++++++++++ api/task_queue/BUILD.gn | 1 + api/task_queue/task_queue_base.h | 51 ++++++++++++++++++++++++++++++-- rtc_base/BUILD.gn | 2 ++ rtc_base/task_queue_gcd.cc | 31 ++++++++++--------- rtc_base/task_queue_libevent.cc | 30 ++++++++++--------- rtc_base/task_queue_stdlib.cc | 30 ++++++++++--------- rtc_base/task_queue_win.cc | 30 ++++++++++--------- rtc_base/thread.cc | 19 ++++++------ rtc_base/thread.h | 24 +++++++++++---- 11 files changed, 185 insertions(+), 75 deletions(-) create mode 100644 api/location.h diff --git a/api/BUILD.gn b/api/BUILD.gn index d1b2c23491..c336bee27a 100644 --- a/api/BUILD.gn +++ b/api/BUILD.gn @@ -65,6 +65,17 @@ if (!build_with_chromium) { } } +rtc_library("location") { + visibility = [ "*" ] + deps = [ "../rtc_base/system:rtc_export" ] + if (build_with_chromium) { + sources = [ "../../webrtc_overrides/api/location.h" ] + deps += [ "//base" ] + } else { + sources = [ "location.h" ] + } +} + rtc_library("rtp_headers") { visibility = [ "*" ] sources = [ diff --git a/api/location.h b/api/location.h new file mode 100644 index 0000000000..81e9a15dcc --- /dev/null +++ b/api/location.h @@ -0,0 +1,31 @@ +/* + * Copyright 2023 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef API_LOCATION_H_ +#define API_LOCATION_H_ + +#include "rtc_base/system/rtc_export.h" + +namespace webrtc { + +// Location provides basic info where of an object was constructed, or was +// significantly brought to life. This is a stripped down version of +// https://source.chromium.org/chromium/chromium/src/+/main:base/location.h +// that only specifies an interface compatible to how base::Location is +// supposed to be used. +// The declaration is overriden inside the Chromium build. +class RTC_EXPORT Location { + public: + static Location Current() { return Location(); } +}; + +} // namespace webrtc + +#endif // API_LOCATION_H_ diff --git a/api/task_queue/BUILD.gn b/api/task_queue/BUILD.gn index 69393b80ff..65bb1ae21b 100644 --- a/api/task_queue/BUILD.gn +++ b/api/task_queue/BUILD.gn @@ -17,6 +17,7 @@ rtc_library("task_queue") { sources = [ "task_queue_base.cc" ] deps = [ + "..:location", "../../rtc_base:checks", "../../rtc_base:macromagic", "../../rtc_base/system:rtc_export", diff --git a/api/task_queue/task_queue_base.h b/api/task_queue/task_queue_base.h index f78600de60..9c4fdd79c1 100644 --- a/api/task_queue/task_queue_base.h +++ b/api/task_queue/task_queue_base.h @@ -14,6 +14,7 @@ #include #include "absl/functional/any_invocable.h" +#include "api/location.h" #include "api/units/time_delta.h" #include "rtc_base/system/rtc_export.h" #include "rtc_base/thread_annotations.h" @@ -62,7 +63,11 @@ class RTC_LOCKABLE RTC_EXPORT TaskQueueBase { // Note that this guarantee does not apply to delayed tasks. // // May be called on any thread or task queue, including this task queue. - virtual void PostTask(absl::AnyInvocable task) = 0; + // TODO(crbug.com/1416199): Remove virtual and pass location of the caller + // once subclasses migrated. + virtual void PostTask(absl::AnyInvocable task) { + PostTaskImpl(std::move(task), PostTaskTraits{}, Location::Current()); + } // Prefer PostDelayedTask() over PostDelayedHighPrecisionTask() whenever // possible. @@ -87,8 +92,14 @@ class RTC_LOCKABLE RTC_EXPORT TaskQueueBase { // https://crbug.com/webrtc/13583 for more information. // // May be called on any thread or task queue, including this task queue. + // TODO(crbug.com/1416199): Remove virtual and pass location of the caller + // once subclasses migrated. virtual void PostDelayedTask(absl::AnyInvocable task, - TimeDelta delay) = 0; + TimeDelta delay) { + PostDelayedTaskImpl(std::move(task), delay, + PostDelayedTaskTraits{.high_precision = false}, + Location::Current()); + } // Prefer PostDelayedTask() over PostDelayedHighPrecisionTask() whenever // possible. @@ -106,8 +117,14 @@ class RTC_LOCKABLE RTC_EXPORT TaskQueueBase { // battery, when the timer precision can be as poor as 15 ms. // // May be called on any thread or task queue, including this task queue. + // TODO(crbug.com/1416199): Remove virtual and pass location of the caller + // once subclasses migrated. virtual void PostDelayedHighPrecisionTask(absl::AnyInvocable task, - TimeDelta delay) = 0; + TimeDelta delay) { + PostDelayedTaskImpl(std::move(task), delay, + PostDelayedTaskTraits{.high_precision = true}, + Location::Current()); + } // As specified by `precision`, calls either PostDelayedTask() or // PostDelayedHighPrecisionTask(). @@ -131,6 +148,18 @@ class RTC_LOCKABLE RTC_EXPORT TaskQueueBase { bool IsCurrent() const { return Current() == this; } protected: + // This is currently only present here to simplify introduction of future + // planned task queue changes. + struct PostTaskTraits {}; + + struct PostDelayedTaskTraits { + // If `high_precision` is false, tasks may execute within up to a 17 ms + // leeway in addition to OS timer precision. Otherwise the task should be + // limited to OS timer precision. See PostDelayedTask() and + // PostDelayedHighPrecisionTask() for more information. + bool high_precision = false; + }; + class RTC_EXPORT CurrentTaskQueueSetter { public: explicit CurrentTaskQueueSetter(TaskQueueBase* task_queue); @@ -142,6 +171,22 @@ class RTC_LOCKABLE RTC_EXPORT TaskQueueBase { TaskQueueBase* const previous_; }; + // Subclasses should implement this method to support the behavior defined in + // the PostTask and PostTaskTraits docs above. + // TODO(crbug.com/1416199): make pure virtual once subclasses migrate. + virtual void PostTaskImpl(absl::AnyInvocable task, + const PostTaskTraits& traits, + const Location& location) {} + + // Subclasses should implement this method to support the behavior defined in + // the PostDelayedTask/PostHighPrecisionDelayedTask and PostDelayedTaskTraits + // docs above. + // TODO(crbug.com/1416199): make pure virtual once subclasses migrate. + virtual void PostDelayedTaskImpl(absl::AnyInvocable task, + TimeDelta delay, + const PostDelayedTaskTraits& traits, + const Location& location) {} + // Users of the TaskQueue should call Delete instead of directly deleting // this object. virtual ~TaskQueueBase() = default; diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn index 0d8bd4f759..fc92b0183b 100644 --- a/rtc_base/BUILD.gn +++ b/rtc_base/BUILD.gn @@ -671,6 +671,7 @@ if (is_mac || is_ios) { deps = [ ":checks", ":logging", + "../api:location", "../api/task_queue", "../api/units:time_delta", "synchronization:mutex", @@ -976,6 +977,7 @@ rtc_library("threading") { ":socket_server", ":timeutils", "../api:function_view", + "../api:location", "../api:refcountedbase", "../api:scoped_refptr", "../api:sequence_checker", diff --git a/rtc_base/task_queue_gcd.cc b/rtc_base/task_queue_gcd.cc index 6612b45f49..fb870e7637 100644 --- a/rtc_base/task_queue_gcd.cc +++ b/rtc_base/task_queue_gcd.cc @@ -21,6 +21,7 @@ #include "absl/functional/any_invocable.h" #include "absl/strings/string_view.h" +#include "api/location.h" #include "api/task_queue/task_queue_base.h" #include "api/units/time_delta.h" #include "rtc_base/checks.h" @@ -46,11 +47,15 @@ class TaskQueueGcd final : public TaskQueueBase { TaskQueueGcd(absl::string_view queue_name, int gcd_priority); void Delete() override; - void PostTask(absl::AnyInvocable task) override; - void PostDelayedTask(absl::AnyInvocable task, - TimeDelta delay) override; - void PostDelayedHighPrecisionTask(absl::AnyInvocable task, - TimeDelta delay) override; + + protected: + void PostTaskImpl(absl::AnyInvocable task, + const PostTaskTraits& traits, + const Location& location) override; + void PostDelayedTaskImpl(absl::AnyInvocable task, + TimeDelta delay, + const PostDelayedTaskTraits& traits, + const Location& location) override; private: struct TaskContext { @@ -100,24 +105,22 @@ void TaskQueueGcd::Delete() { dispatch_release(queue_); } -void TaskQueueGcd::PostTask(absl::AnyInvocable task) { +void TaskQueueGcd::PostTaskImpl(absl::AnyInvocable task, + const PostTaskTraits& traits, + const Location& location) { auto* context = new TaskContext(this, std::move(task)); dispatch_async_f(queue_, context, &RunTask); } -void TaskQueueGcd::PostDelayedTask(absl::AnyInvocable task, - TimeDelta delay) { +void TaskQueueGcd::PostDelayedTaskImpl(absl::AnyInvocable task, + TimeDelta delay, + const PostDelayedTaskTraits& traits, + const Location& location) { auto* context = new TaskContext(this, std::move(task)); dispatch_after_f(dispatch_time(DISPATCH_TIME_NOW, delay.us() * NSEC_PER_USEC), queue_, context, &RunTask); } -void TaskQueueGcd::PostDelayedHighPrecisionTask( - absl::AnyInvocable task, - TimeDelta delay) { - PostDelayedTask(std::move(task), delay); -} - // static void TaskQueueGcd::RunTask(void* task_context) { std::unique_ptr tc(static_cast(task_context)); diff --git a/rtc_base/task_queue_libevent.cc b/rtc_base/task_queue_libevent.cc index 63633b5198..e27c6eff9f 100644 --- a/rtc_base/task_queue_libevent.cc +++ b/rtc_base/task_queue_libevent.cc @@ -107,11 +107,15 @@ class TaskQueueLibevent final : public TaskQueueBase { TaskQueueLibevent(absl::string_view queue_name, rtc::ThreadPriority priority); void Delete() override; - void PostTask(absl::AnyInvocable task) override; - void PostDelayedTask(absl::AnyInvocable task, - TimeDelta delay) override; - void PostDelayedHighPrecisionTask(absl::AnyInvocable task, - TimeDelta delay) override; + + protected: + void PostTaskImpl(absl::AnyInvocable task, + const PostTaskTraits& traits, + const Location& location) override; + void PostDelayedTaskImpl(absl::AnyInvocable task, + TimeDelta delay, + const PostDelayedTaskTraits& traits, + const Location& location) override; private: struct TimerEvent; @@ -211,7 +215,9 @@ void TaskQueueLibevent::Delete() { delete this; } -void TaskQueueLibevent::PostTask(absl::AnyInvocable task) { +void TaskQueueLibevent::PostTaskImpl(absl::AnyInvocable task, + const PostTaskTraits& traits, + const Location& location) { { MutexLock lock(&pending_lock_); bool had_pending_tasks = !pending_.empty(); @@ -250,8 +256,10 @@ void TaskQueueLibevent::PostDelayedTaskOnTaskQueue( event_add(&timer->ev, &tv); } -void TaskQueueLibevent::PostDelayedTask(absl::AnyInvocable task, - TimeDelta delay) { +void TaskQueueLibevent::PostDelayedTaskImpl(absl::AnyInvocable task, + TimeDelta delay, + const PostDelayedTaskTraits& traits, + const Location& location) { if (IsCurrent()) { PostDelayedTaskOnTaskQueue(std::move(task), delay); } else { @@ -265,12 +273,6 @@ void TaskQueueLibevent::PostDelayedTask(absl::AnyInvocable task, } } -void TaskQueueLibevent::PostDelayedHighPrecisionTask( - absl::AnyInvocable task, - TimeDelta delay) { - PostDelayedTask(std::move(task), delay); -} - // static void TaskQueueLibevent::OnWakeup(int socket, short flags, // NOLINT diff --git a/rtc_base/task_queue_stdlib.cc b/rtc_base/task_queue_stdlib.cc index 300873ac15..1ac01e1830 100644 --- a/rtc_base/task_queue_stdlib.cc +++ b/rtc_base/task_queue_stdlib.cc @@ -52,11 +52,15 @@ class TaskQueueStdlib final : public TaskQueueBase { ~TaskQueueStdlib() override = default; void Delete() override; - void PostTask(absl::AnyInvocable task) override; - void PostDelayedTask(absl::AnyInvocable task, - TimeDelta delay) override; - void PostDelayedHighPrecisionTask(absl::AnyInvocable task, - TimeDelta delay) override; + + protected: + void PostTaskImpl(absl::AnyInvocable task, + const PostTaskTraits& traits, + const Location& location) override; + void PostDelayedTaskImpl(absl::AnyInvocable task, + TimeDelta delay, + const PostDelayedTaskTraits& traits, + const Location& location) override; private: using OrderId = uint64_t; @@ -156,7 +160,9 @@ void TaskQueueStdlib::Delete() { delete this; } -void TaskQueueStdlib::PostTask(absl::AnyInvocable task) { +void TaskQueueStdlib::PostTaskImpl(absl::AnyInvocable task, + const PostTaskTraits& traits, + const Location& location) { { MutexLock lock(&pending_lock_); pending_queue_.push( @@ -166,8 +172,10 @@ void TaskQueueStdlib::PostTask(absl::AnyInvocable task) { NotifyWake(); } -void TaskQueueStdlib::PostDelayedTask(absl::AnyInvocable task, - TimeDelta delay) { +void TaskQueueStdlib::PostDelayedTaskImpl(absl::AnyInvocable task, + TimeDelta delay, + const PostDelayedTaskTraits& traits, + const Location& location) { DelayedEntryTimeout delayed_entry; delayed_entry.next_fire_at_us = rtc::TimeMicros() + delay.us(); @@ -180,12 +188,6 @@ void TaskQueueStdlib::PostDelayedTask(absl::AnyInvocable task, NotifyWake(); } -void TaskQueueStdlib::PostDelayedHighPrecisionTask( - absl::AnyInvocable task, - TimeDelta delay) { - PostDelayedTask(std::move(task), delay); -} - TaskQueueStdlib::NextTask TaskQueueStdlib::GetNextTask() { NextTask result; diff --git a/rtc_base/task_queue_win.cc b/rtc_base/task_queue_win.cc index 9ea7fc60ae..7e46d58e27 100644 --- a/rtc_base/task_queue_win.cc +++ b/rtc_base/task_queue_win.cc @@ -160,11 +160,15 @@ class TaskQueueWin : public TaskQueueBase { ~TaskQueueWin() override = default; void Delete() override; - void PostTask(absl::AnyInvocable task) override; - void PostDelayedTask(absl::AnyInvocable task, - TimeDelta delay) override; - void PostDelayedHighPrecisionTask(absl::AnyInvocable task, - TimeDelta delay) override; + + protected: + void PostTaskImpl(absl::AnyInvocable task, + const PostTaskTraits& traits, + const Location& location) override; + void PostDelayedTaskImpl(absl::AnyInvocable task, + TimeDelta delay, + const PostDelayedTaskTraits& traits, + const Location& location) override; void RunPendingTasks(); private: @@ -217,14 +221,18 @@ void TaskQueueWin::Delete() { delete this; } -void TaskQueueWin::PostTask(absl::AnyInvocable task) { +void TaskQueueWin::PostTaskImpl(absl::AnyInvocable task, + const PostTaskTraits& traits, + const Location& location) { MutexLock lock(&pending_lock_); pending_.push(std::move(task)); ::SetEvent(in_queue_); } -void TaskQueueWin::PostDelayedTask(absl::AnyInvocable task, - TimeDelta delay) { +void TaskQueueWin::PostDelayedTaskImpl(absl::AnyInvocable task, + TimeDelta delay, + const PostDelayedTaskTraits& traits, + const Location& location) { if (delay <= TimeDelta::Zero()) { PostTask(std::move(task)); return; @@ -239,12 +247,6 @@ void TaskQueueWin::PostDelayedTask(absl::AnyInvocable task, } } -void TaskQueueWin::PostDelayedHighPrecisionTask( - absl::AnyInvocable task, - TimeDelta delay) { - PostDelayedTask(std::move(task), delay); -} - void TaskQueueWin::RunPendingTasks() { while (true) { absl::AnyInvocable task; diff --git a/rtc_base/thread.cc b/rtc_base/thread.cc index 4790a6f1d7..6f101ac8f4 100644 --- a/rtc_base/thread.cc +++ b/rtc_base/thread.cc @@ -455,7 +455,9 @@ absl::AnyInvocable Thread::Get(int cmsWait) { return nullptr; } -void Thread::PostTask(absl::AnyInvocable task) { +void Thread::PostTaskImpl(absl::AnyInvocable task, + const PostTaskTraits& traits, + const webrtc::Location& location) { if (IsQuitting()) { return; } @@ -471,8 +473,10 @@ void Thread::PostTask(absl::AnyInvocable task) { WakeUpSocketServer(); } -void Thread::PostDelayedHighPrecisionTask(absl::AnyInvocable task, - webrtc::TimeDelta delay) { +void Thread::PostDelayedTaskImpl(absl::AnyInvocable task, + webrtc::TimeDelta delay, + const PostDelayedTaskTraits& traits, + const webrtc::Location& location) { if (IsQuitting()) { return; } @@ -719,7 +723,8 @@ void Thread::Stop() { Join(); } -void Thread::BlockingCall(rtc::FunctionView functor) { +void Thread::BlockingCallImpl(rtc::FunctionView functor, + const webrtc::Location& location) { TRACE_EVENT0("webrtc", "Thread::BlockingCall"); RTC_DCHECK(!IsQuitting()); @@ -823,12 +828,6 @@ void Thread::Delete() { delete this; } -void Thread::PostDelayedTask(absl::AnyInvocable task, - webrtc::TimeDelta delay) { - // This implementation does not support low precision yet. - PostDelayedHighPrecisionTask(std::move(task), delay); -} - bool Thread::IsProcessingMessagesForTesting() { return (owned_ || IsCurrent()) && !IsQuitting(); } diff --git a/rtc_base/thread.h b/rtc_base/thread.h index 276a2e71af..b3c824ccf8 100644 --- a/rtc_base/thread.h +++ b/rtc_base/thread.h @@ -31,6 +31,7 @@ #include "absl/base/attributes.h" #include "absl/functional/any_invocable.h" #include "api/function_view.h" +#include "api/location.h" #include "api/task_queue/task_queue_base.h" #include "api/units/time_delta.h" #include "rtc_base/checks.h" @@ -308,7 +309,11 @@ class RTC_LOCKABLE RTC_EXPORT Thread : public webrtc::TaskQueueBase { // See ScopedDisallowBlockingCalls for details. // NOTE: Blocking calls are DISCOURAGED, consider if what you're doing can // be achieved with PostTask() and callbacks instead. - virtual void BlockingCall(FunctionView functor); + // TODO(crbug.com/1416199): Remove virtual and pass location of the caller + // once subclasses migrated. + virtual void BlockingCall(FunctionView functor) { + BlockingCallImpl(std::move(functor), webrtc::Location::Current()); + } template , @@ -336,11 +341,6 @@ class RTC_LOCKABLE RTC_EXPORT Thread : public webrtc::TaskQueueBase { // From TaskQueueBase void Delete() override; - void PostTask(absl::AnyInvocable task) override; - void PostDelayedTask(absl::AnyInvocable task, - webrtc::TimeDelta delay) override; - void PostDelayedHighPrecisionTask(absl::AnyInvocable task, - webrtc::TimeDelta delay) override; // ProcessMessages will process I/O and dispatch messages until: // 1) cms milliseconds have elapsed (returns true) @@ -412,6 +412,18 @@ class RTC_LOCKABLE RTC_EXPORT Thread : public webrtc::TaskQueueBase { mutable absl::AnyInvocable functor; }; + // TaskQueueBase implementation. + void PostTaskImpl(absl::AnyInvocable task, + const PostTaskTraits& traits, + const webrtc::Location& location) override; + void PostDelayedTaskImpl(absl::AnyInvocable task, + webrtc::TimeDelta delay, + const PostDelayedTaskTraits& traits, + const webrtc::Location& location) override; + + virtual void BlockingCallImpl(FunctionView functor, + const webrtc::Location& location); + // Perform initialization, subclasses must call this from their constructor // if false was passed as init_queue to the Thread constructor. void DoInit();