perfetto: change watchdog to monitor guardrails when explicitly started

Bug: 73051936
Change-Id: I7e9c2a07225dbe382556b8669e249a1f6012e8f6
diff --git a/src/base/watchdog.cc b/src/base/watchdog.cc
index df6ebd1..97ece02 100644
--- a/src/base/watchdog.cc
+++ b/src/base/watchdog.cc
@@ -50,10 +50,26 @@
     : polling_interval_ms_(polling_interval_ms) {}
 
 Watchdog::~Watchdog() {
-  QuitThreadUnlocked();
+  if (!thread_.joinable()) {
+    PERFETTO_DCHECK(quit_);
+    return;
+  }
+
+  {
+    std::lock_guard<std::mutex> guard(mutex_);
+    PERFETTO_DCHECK(!quit_);
+    quit_ = true;
+  }
+  exit_signal_.notify_one();
+  thread_.join();
 }
 
 Watchdog* Watchdog::GetInstance() {
+#if PERFETTO_BUILDFLAG(PERFETTO_CHROMIUM_BUILD)
+  // Ensure that it is impossible to use watchdog on a Chromium build.
+  PERFETTO_CHECK(false);
+#endif
+
   static Watchdog* watchdog = new Watchdog(kDefaultPollingInterval);
   return watchdog;
 }
@@ -62,33 +78,43 @@
   return Watchdog::Timer(ms);
 }
 
-void Watchdog::SetMemoryLimit(uint32_t bytes, uint32_t window_ms) {
-  {
-    // Update the fields under the lock.
-    std::lock_guard<std::mutex> guard(mutex_);
+void Watchdog::Start() {
+  std::lock_guard<std::mutex> guard(mutex_);
+  if (thread_.joinable()) {
+    PERFETTO_DCHECK(!quit_);
+  } else {
+    PERFETTO_DCHECK(quit_);
 
-    PERFETTO_CHECK(IsMultipleOf(window_ms, polling_interval_ms_) || bytes == 0);
-
-    size_t size = bytes == 0 ? 0 : window_ms / polling_interval_ms_ + 1;
-    memory_window_bytes_.Reset(size);
-    memory_limit_bytes_ = bytes;
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+    // Kick the thread to start running but only on Android or Linux.
+    quit_ = false;
+    thread_ = std::thread(&Watchdog::ThreadMain, this);
+#endif
   }
-  UpdateThreadStateUnlocked();
+}
+
+void Watchdog::SetMemoryLimit(uint32_t bytes, uint32_t window_ms) {
+  // Update the fields under the lock.
+  std::lock_guard<std::mutex> guard(mutex_);
+
+  PERFETTO_CHECK(IsMultipleOf(window_ms, polling_interval_ms_) || bytes == 0);
+
+  size_t size = bytes == 0 ? 0 : window_ms / polling_interval_ms_ + 1;
+  memory_window_bytes_.Reset(size);
+  memory_limit_bytes_ = bytes;
 }
 
 void Watchdog::SetCpuLimit(uint32_t percentage, uint32_t window_ms) {
-  {
-    std::lock_guard<std::mutex> guard(mutex_);
+  std::lock_guard<std::mutex> guard(mutex_);
 
-    PERFETTO_CHECK(percentage <= 100);
-    PERFETTO_CHECK(IsMultipleOf(window_ms, polling_interval_ms_) ||
-                   percentage == 0);
+  PERFETTO_CHECK(percentage <= 100);
+  PERFETTO_CHECK(IsMultipleOf(window_ms, polling_interval_ms_) ||
+                 percentage == 0);
 
-    size_t size = percentage == 0 ? 0 : window_ms / polling_interval_ms_ + 1;
-    cpu_window_time_ticks_.Reset(size);
-    cpu_limit_percentage_ = percentage;
-  }
-  UpdateThreadStateUnlocked();
+  size_t size = percentage == 0 ? 0 : window_ms / polling_interval_ms_ + 1;
+  cpu_window_time_ticks_.Reset(size);
+  cpu_limit_percentage_ = percentage;
 }
 
 void Watchdog::ThreadMain() {
@@ -166,48 +192,6 @@
   }
 }
 
-void Watchdog::UpdateThreadStateUnlocked() {
-  if (cpu_limit_percentage_ > 0 || memory_limit_bytes_ > 0) {
-    StartThreadUnlocked();
-  } else if (cpu_limit_percentage_ == 0 && memory_limit_bytes_ == 0) {
-    QuitThreadUnlocked();
-  }
-}
-
-void Watchdog::StartThreadUnlocked() {
-  if (thread_.joinable()) {
-#if PERFETTO_DCHECK_IS_ON()
-    std::lock_guard<std::mutex> guard(mutex_);
-    PERFETTO_DCHECK(!quit_);
-#endif
-  } else {
-    // Don't need to lock because thread is not running.
-    PERFETTO_DCHECK(quit_);
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-    // Kick the thread to start running but only on Android or Linux.
-    quit_ = false;
-    thread_ = std::thread(&Watchdog::ThreadMain, this);
-#endif
-  }
-}
-
-void Watchdog::QuitThreadUnlocked() {
-  if (thread_.joinable()) {
-    {
-      std::lock_guard<std::mutex> guard(mutex_);
-      PERFETTO_DCHECK(!quit_);
-      quit_ = true;
-    }
-    exit_signal_.notify_one();
-    thread_.join();
-    thread_ = std::thread();
-  } else {
-    PERFETTO_DCHECK(quit_);
-  }
-}
-
 uint32_t Watchdog::WindowTimeForRingBuffer(const WindowedInterval& window) {
   return static_cast<uint32_t>(window.size() - 1) * polling_interval_ms_;
 }