Support building most targets on mac

Rationale: takes very little efforts, increases unittest-ability and
avoid having to think/#ifdef when using the watchdog.

Bug: 76169489
Change-Id: Ife14e2ec77d21b17fa48a48f0629c4026a60bf2c
diff --git a/Android.bp b/Android.bp
index 44ab92c..55775e7 100644
--- a/Android.bp
+++ b/Android.bp
@@ -39,7 +39,7 @@
     "src/base/temp_file.cc",
     "src/base/thread_checker.cc",
     "src/base/unix_task_runner.cc",
-    "src/base/watchdog.cc",
+    "src/base/watchdog_posix.cc",
     "src/ftrace_reader/atrace_wrapper.cc",
     "src/ftrace_reader/cpu_reader.cc",
     "src/ftrace_reader/event_info.cc",
@@ -154,7 +154,7 @@
     "src/base/temp_file.cc",
     "src/base/thread_checker.cc",
     "src/base/unix_task_runner.cc",
-    "src/base/watchdog.cc",
+    "src/base/watchdog_posix.cc",
     "src/ipc/buffered_frame_deserializer.cc",
     "src/ipc/client_impl.cc",
     "src/ipc/deferred.cc",
@@ -278,7 +278,7 @@
     "src/base/test/vm_test_utils.cc",
     "src/base/thread_checker.cc",
     "src/base/unix_task_runner.cc",
-    "src/base/watchdog.cc",
+    "src/base/watchdog_posix.cc",
     "src/ftrace_reader/atrace_wrapper.cc",
     "src/ftrace_reader/cpu_reader.cc",
     "src/ftrace_reader/end_to_end_integrationtest.cc",
@@ -3138,7 +3138,7 @@
     "src/base/temp_file.cc",
     "src/base/thread_checker.cc",
     "src/base/unix_task_runner.cc",
-    "src/base/watchdog.cc",
+    "src/base/watchdog_posix.cc",
     "src/ipc/buffered_frame_deserializer.cc",
     "src/ipc/client_impl.cc",
     "src/ipc/deferred.cc",
@@ -3315,7 +3315,7 @@
     "src/base/time_unittest.cc",
     "src/base/unix_task_runner.cc",
     "src/base/utils_unittest.cc",
-    "src/base/watchdog.cc",
+    "src/base/watchdog_posix.cc",
     "src/base/watchdog_unittest.cc",
     "src/base/weak_ptr_unittest.cc",
     "src/ftrace_reader/atrace_wrapper.cc",
diff --git a/BUILD.gn b/BUILD.gn
index 1207331..7e3dcc0 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -30,25 +30,23 @@
   ]
   if (!build_with_chromium) {
     deps += [
+      ":perfetto",
+      ":perfetto_benchmarks",
+      ":perfetto_integrationtests",
+      ":traced",
+      ":traced_probes",
       "protos/perfetto/config:merged_config",  # For syntax-checking the proto.
       "src/ipc/protoc_plugin:ipc_plugin($host_toolchain)",
       "test/configs",
       "tools:protoc_helper",
+      "tools/ftrace_proto_gen:ftrace_proto_gen",
       "tools/proto_to_cpp",
     ]
     if (!build_with_android) {
       deps += [ "tools/trace_to_text" ]
     }
     if (is_linux || is_android) {
-      deps += [
-        ":perfetto",
-        ":perfetto_benchmarks",
-        ":perfetto_integrationtests",
-        ":traced",
-        ":traced_probes",
-        "tools/ftrace_proto_gen:ftrace_proto_gen",
-        "tools/skippy",
-      ]
+      deps += [ "tools/skippy" ]
     }
   }
 }
@@ -63,24 +61,19 @@
     "src/tracing:unittests",
   ]
   if (!build_with_chromium) {
-    if (is_linux || is_android) {
-      deps += [
-        "src/ftrace_reader:unittests",
-        "src/traced/probes:unittests",
-        "tools/ftrace_proto_gen:unittests",
-      ]
-    }
-
     deps += [
+      "src/ftrace_reader:unittests",
       "src/ipc:unittests",
       "src/perfetto_cmd:unittests",
+      "src/traced/probes:unittests",
       "src/traced/probes/filesystem:unittests",
+      "tools/ftrace_proto_gen:unittests",
       "tools/sanitizers_unittests",
     ]
   }
 }
 
-if (!build_with_chromium && (is_linux || is_android)) {
+if (!build_with_chromium) {
   executable("perfetto_benchmarks") {
     testonly = true
     deps = [
@@ -175,15 +168,15 @@
         "tools/trace_to_text:lib",
       ]
     }
-  }
 
-  # This target exports perfetto trace protos in the Android build system,
-  # allowing both host and device targets to implement custom parsers based on
-  # our protos.
-  static_library("perfetto_trace_protos") {
-    deps = [
-      "protos/perfetto/trace:lite",
-    ]
+    # This target exports perfetto trace protos in the Android build system,
+    # allowing both host and device targets to implement custom parsers based on
+    # our protos.
+    static_library("perfetto_trace_protos") {
+      deps = [
+        "protos/perfetto/trace:lite",
+      ]
+    }
   }
 }
 
diff --git a/include/perfetto/base/BUILD.gn b/include/perfetto/base/BUILD.gn
index 03d24eb..9d29811 100644
--- a/include/perfetto/base/BUILD.gn
+++ b/include/perfetto/base/BUILD.gn
@@ -27,6 +27,8 @@
     "unix_task_runner.h",
     "utils.h",
     "watchdog.h",
+    "watchdog_noop.h",
+    "watchdog_posix.h",
     "weak_ptr.h",
   ]
   if (is_android) {
diff --git a/include/perfetto/base/task_runner.h b/include/perfetto/base/task_runner.h
index bde4980..77fb572 100644
--- a/include/perfetto/base/task_runner.h
+++ b/include/perfetto/base/task_runner.h
@@ -21,11 +21,7 @@
 
 #include "perfetto/base/build_config.h"
 #include "perfetto/base/utils.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
 #include "perfetto/base/watchdog.h"
-#endif
 
 namespace perfetto {
 namespace base {
@@ -72,12 +68,8 @@
 
  protected:
   static void RunTask(const std::function<void()>& task) {
-#if !PERFETTO_BUILDFLAG(PERFETTO_CHROMIUM_BUILD) && \
-    (PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||       \
-     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID))
     Watchdog::Timer handle =
         base::Watchdog::GetInstance()->CreateFatalTimer(kWatchdogMillis);
-#endif
     task();
   }
 };
diff --git a/include/perfetto/base/time.h b/include/perfetto/base/time.h
index eb20fe5..d90d378 100644
--- a/include/perfetto/base/time.h
+++ b/include/perfetto/base/time.h
@@ -25,7 +25,10 @@
 #include "perfetto/base/logging.h"
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
+#include <mach/mach_init.h>
+#include <mach/mach_port.h>
 #include <mach/mach_time.h>
+#include <mach/thread_act.h>
 #endif
 
 namespace perfetto {
@@ -70,6 +73,25 @@
   return TimeNanos(mach_absolute_time() * monotonic_timebase_factor);
 }
 
+inline TimeNanos GetThreadCPUTimeNs() {
+  mach_port_t this_thread = mach_thread_self();
+  mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
+  thread_basic_info_data_t info{};
+  kern_return_t kr =
+      thread_info(this_thread, THREAD_BASIC_INFO,
+                  reinterpret_cast<thread_info_t>(&info), &count);
+  mach_port_deallocate(mach_task_self(), this_thread);
+
+  if (kr != KERN_SUCCESS) {
+    PERFETTO_DCHECK(false);
+    return TimeNanos(0);
+  }
+  return TimeNanos(info.user_time.seconds * 1000000000LL +
+                   info.user_time.microseconds * 1000LL +
+                   info.system_time.seconds * 1000000000LL +
+                   info.system_time.microseconds * 1000LL);
+}
+
 #endif  // !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
 
 inline TimeMillis GetWallTimeMs() {
diff --git a/include/perfetto/base/watchdog.h b/include/perfetto/base/watchdog.h
index 8bfb4df..77f021a 100644
--- a/include/perfetto/base/watchdog.h
+++ b/include/perfetto/base/watchdog.h
@@ -17,137 +17,14 @@
 #ifndef INCLUDE_PERFETTO_BASE_WATCHDOG_H_
 #define INCLUDE_PERFETTO_BASE_WATCHDOG_H_
 
-#include "perfetto/base/thread_checker.h"
+#include "perfetto/base/build_config.h"
 
-#include <condition_variable>
-#include <mutex>
-#include <thread>
+#if (PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||    \
+     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)) && \
+    !PERFETTO_BUILDFLAG(PERFETTO_CHROMIUM_BUILD)
+#include "perfetto/base/watchdog_posix.h"
+#else
+#include "perfetto/base/watchdog_noop.h"
+#endif
 
-namespace perfetto {
-namespace base {
-
-// Ensures that the calling program does not exceed certain hard limits on
-// resource usage e.g. time, memory and CPU. If exceeded, the program is
-// crashed.
-class Watchdog {
- public:
-  // Handle to the timer set to crash the program. If the handle is dropped,
-  // the timer is removed so the program does not crash.
-  class Timer {
-   public:
-    ~Timer();
-    Timer(Timer&&) noexcept;
-
-   private:
-    friend class Watchdog;
-
-    explicit Timer(uint32_t ms);
-    Timer(const Timer&) = delete;
-    Timer& operator=(const Timer&) = delete;
-
-    timer_t timerid_ = nullptr;
-  };
-  virtual ~Watchdog();
-
-  static Watchdog* GetInstance();
-
-  // Sets a timer which will crash the program in |ms| milliseconds if the
-  // returned handle is not destroyed before this point.
-  Timer CreateFatalTimer(uint32_t ms);
-
-  // Starts the watchdog thread which monitors the memory and CPU usage
-  // of the program.
-  void Start();
-
-  // Sets a limit on the memory (defined as the RSS) used by the program
-  // averaged over the last |window_ms| milliseconds. If |kb| is 0, any
-  // existing limit is removed.
-  // Note: |window_ms| has to be a multiple of |polling_interval_ms_|.
-  void SetMemoryLimit(uint32_t bytes, uint32_t window_ms);
-
-  // Sets a limit on the CPU usage used by the program averaged over the last
-  // |window_ms| milliseconds. If |percentage| is 0, any existing limit is
-  // removed.
-  // Note: |window_ms| has to be a multiple of |polling_interval_ms_|.
-  void SetCpuLimit(uint32_t percentage, uint32_t window_ms);
-
- protected:
-  // Protected for testing.
-  Watchdog(uint32_t polling_interval_ms);
-
- private:
-  // Represents a ring buffer in which integer values can be stored.
-  class WindowedInterval {
-   public:
-    // Pushes a new value into a ring buffer wrapping if necessary and returns
-    // whether the ring buffer is full.
-    bool Push(uint64_t sample);
-
-    // Returns the mean of the values in the buffer.
-    double Mean() const;
-
-    // Clears the ring buffer while keeping the existing size.
-    void Clear();
-
-    // Resets the size of the buffer as well as clearing it.
-    void Reset(size_t new_size);
-
-    // Gets the oldest value inserted in the buffer. The buffer must be full
-    // (i.e. Push returned true) before this method can be called.
-    uint64_t OldestWhenFull() const {
-      PERFETTO_CHECK(filled_);
-      return buffer_[position_];
-    }
-
-    // Gets the newest value inserted in the buffer. The buffer must be full
-    // (i.e. Push returned true) before this method can be called.
-    uint64_t NewestWhenFull() const {
-      PERFETTO_CHECK(filled_);
-      return buffer_[(position_ + size_ - 1) % size_];
-    }
-
-    // Returns the size of the ring buffer.
-    size_t size() const { return size_; }
-
-   private:
-    bool filled_ = false;
-    size_t position_ = 0;
-    size_t size_ = 0;
-    std::unique_ptr<uint64_t[]> buffer_;
-  };
-
-  explicit Watchdog(const Watchdog&) = delete;
-  Watchdog& operator=(const Watchdog&) = delete;
-
-  // Main method for the watchdog thread.
-  void ThreadMain();
-
-  // Check each type of resource every |polling_interval_ms_| miillis.
-  void CheckMemory(uint64_t rss_bytes);
-  void CheckCpu(uint64_t cpu_time);
-
-  // Computes the time interval spanned by a given ring buffer with respect
-  // to |polling_interval_ms_|.
-  uint32_t WindowTimeForRingBuffer(const WindowedInterval& window);
-
-  const uint32_t polling_interval_ms_;
-  std::thread thread_;
-  std::condition_variable exit_signal_;
-
-  // --- Begin lock-protected members ---
-
-  std::mutex mutex_;
-  bool quit_ = true;
-
-  uint32_t memory_limit_bytes_ = 0;
-  WindowedInterval memory_window_bytes_;
-
-  uint32_t cpu_limit_percentage_ = 0;
-  WindowedInterval cpu_window_time_ticks_;
-
-  // --- End lock-protected members ---
-};
-
-}  // namespace base
-}  // namespace perfetto
 #endif  // INCLUDE_PERFETTO_BASE_WATCHDOG_H_
diff --git a/include/perfetto/base/watchdog_noop.h b/include/perfetto/base/watchdog_noop.h
new file mode 100644
index 0000000..5a97b70
--- /dev/null
+++ b/include/perfetto/base/watchdog_noop.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_WATCHDOG_NOOP_H_
+#define INCLUDE_PERFETTO_BASE_WATCHDOG_NOOP_H_
+
+#include <stdint.h>
+
+namespace perfetto {
+namespace base {
+
+class Watchdog {
+ public:
+  class Timer {
+   public:
+    // Define an empty dtor to avoid "unused variable" errors on the call site.
+    Timer() {}
+    Timer(const Timer&) {}
+    ~Timer() {}
+  };
+  static Watchdog* GetInstance();
+  Timer CreateFatalTimer(uint32_t ms) { return Timer(); }
+  void Start() {}
+  void SetMemoryLimit(uint32_t bytes, uint32_t window_ms) {}
+  void SetCpuLimit(uint32_t percentage, uint32_t window_ms) {}
+};
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_WATCHDOG_NOOP_H_
diff --git a/include/perfetto/base/watchdog_posix.h b/include/perfetto/base/watchdog_posix.h
new file mode 100644
index 0000000..d0683a0
--- /dev/null
+++ b/include/perfetto/base/watchdog_posix.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_WATCHDOG_POSIX_H_
+#define INCLUDE_PERFETTO_BASE_WATCHDOG_POSIX_H_
+
+#include "perfetto/base/thread_checker.h"
+
+#include <condition_variable>
+#include <mutex>
+#include <thread>
+
+namespace perfetto {
+namespace base {
+
+// Ensures that the calling program does not exceed certain hard limits on
+// resource usage e.g. time, memory and CPU. If exceeded, the program is
+// crashed.
+class Watchdog {
+ public:
+  // Handle to the timer set to crash the program. If the handle is dropped,
+  // the timer is removed so the program does not crash.
+  class Timer {
+   public:
+    ~Timer();
+    Timer(Timer&&) noexcept;
+
+   private:
+    friend class Watchdog;
+
+    explicit Timer(uint32_t ms);
+    Timer(const Timer&) = delete;
+    Timer& operator=(const Timer&) = delete;
+
+    timer_t timerid_ = nullptr;
+  };
+  virtual ~Watchdog();
+
+  static Watchdog* GetInstance();
+
+  // Sets a timer which will crash the program in |ms| milliseconds if the
+  // returned handle is not destroyed before this point.
+  Timer CreateFatalTimer(uint32_t ms);
+
+  // Starts the watchdog thread which monitors the memory and CPU usage
+  // of the program.
+  void Start();
+
+  // Sets a limit on the memory (defined as the RSS) used by the program
+  // averaged over the last |window_ms| milliseconds. If |kb| is 0, any
+  // existing limit is removed.
+  // Note: |window_ms| has to be a multiple of |polling_interval_ms_|.
+  void SetMemoryLimit(uint32_t bytes, uint32_t window_ms);
+
+  // Sets a limit on the CPU usage used by the program averaged over the last
+  // |window_ms| milliseconds. If |percentage| is 0, any existing limit is
+  // removed.
+  // Note: |window_ms| has to be a multiple of |polling_interval_ms_|.
+  void SetCpuLimit(uint32_t percentage, uint32_t window_ms);
+
+ protected:
+  // Protected for testing.
+  Watchdog(uint32_t polling_interval_ms);
+
+ private:
+  // Represents a ring buffer in which integer values can be stored.
+  class WindowedInterval {
+   public:
+    // Pushes a new value into a ring buffer wrapping if necessary and returns
+    // whether the ring buffer is full.
+    bool Push(uint64_t sample);
+
+    // Returns the mean of the values in the buffer.
+    double Mean() const;
+
+    // Clears the ring buffer while keeping the existing size.
+    void Clear();
+
+    // Resets the size of the buffer as well as clearing it.
+    void Reset(size_t new_size);
+
+    // Gets the oldest value inserted in the buffer. The buffer must be full
+    // (i.e. Push returned true) before this method can be called.
+    uint64_t OldestWhenFull() const {
+      PERFETTO_CHECK(filled_);
+      return buffer_[position_];
+    }
+
+    // Gets the newest value inserted in the buffer. The buffer must be full
+    // (i.e. Push returned true) before this method can be called.
+    uint64_t NewestWhenFull() const {
+      PERFETTO_CHECK(filled_);
+      return buffer_[(position_ + size_ - 1) % size_];
+    }
+
+    // Returns the size of the ring buffer.
+    size_t size() const { return size_; }
+
+   private:
+    bool filled_ = false;
+    size_t position_ = 0;
+    size_t size_ = 0;
+    std::unique_ptr<uint64_t[]> buffer_;
+  };
+
+  explicit Watchdog(const Watchdog&) = delete;
+  Watchdog& operator=(const Watchdog&) = delete;
+
+  // Main method for the watchdog thread.
+  void ThreadMain();
+
+  // Check each type of resource every |polling_interval_ms_| miillis.
+  void CheckMemory(uint64_t rss_bytes);
+  void CheckCpu(uint64_t cpu_time);
+
+  // Computes the time interval spanned by a given ring buffer with respect
+  // to |polling_interval_ms_|.
+  uint32_t WindowTimeForRingBuffer(const WindowedInterval& window);
+
+  const uint32_t polling_interval_ms_;
+  std::thread thread_;
+  std::condition_variable exit_signal_;
+
+  // --- Begin lock-protected members ---
+
+  std::mutex mutex_;
+  bool quit_ = true;
+
+  uint32_t memory_limit_bytes_ = 0;
+  WindowedInterval memory_window_bytes_;
+
+  uint32_t cpu_limit_percentage_ = 0;
+  WindowedInterval cpu_window_time_ticks_;
+
+  // --- End lock-protected members ---
+};
+
+}  // namespace base
+}  // namespace perfetto
+#endif  // INCLUDE_PERFETTO_BASE_WATCHDOG_POSIX_H_
diff --git a/src/base/BUILD.gn b/src/base/BUILD.gn
index 41c47d0..9d01949 100644
--- a/src/base/BUILD.gn
+++ b/src/base/BUILD.gn
@@ -30,7 +30,9 @@
     "unix_task_runner.cc",
   ]
   if (!build_with_chromium && (is_linux || is_android)) {
-    sources += [ "watchdog.cc" ]
+    sources += [ "watchdog_posix.cc" ]
+  } else {
+    sources += [ "watchdog_noop.cc" ]
   }
   if (is_debug) {
     deps += [ ":debug_crash_stack_trace" ]
diff --git a/src/base/watchdog_noop.cc b/src/base/watchdog_noop.cc
new file mode 100644
index 0000000..97f0777
--- /dev/null
+++ b/src/base/watchdog_noop.cc
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "perfetto/base/watchdog_noop.h"
+
+namespace perfetto {
+namespace base {
+
+Watchdog* Watchdog::GetInstance() {
+  static Watchdog* watchdog = new Watchdog();
+  return watchdog;
+}
+
+}  // namespace base
+}  // namespace perfetto
diff --git a/src/base/watchdog.cc b/src/base/watchdog_posix.cc
similarity index 97%
rename from src/base/watchdog.cc
rename to src/base/watchdog_posix.cc
index 904e7df..f757d77 100644
--- a/src/base/watchdog.cc
+++ b/src/base/watchdog_posix.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "perfetto/base/watchdog.h"
+#include "perfetto/base/watchdog_posix.h"
 
 #include "perfetto/base/logging.h"
 #include "perfetto/base/scoped_file.h"
@@ -26,6 +26,10 @@
 #include <fstream>
 #include <thread>
 
+#if PERFETTO_BUILDFLAG(PERFETTO_CHROMIUM_BUILD)
+#error perfetto::base::Watchdog should not be used in Chromium
+#endif
+
 namespace perfetto {
 namespace base {
 
@@ -66,11 +70,6 @@
 }
 
 Watchdog* Watchdog::GetInstance() {
-#if PERFETTO_BUILDFLAG(PERFETTO_CHROMIUM_BUILD)
-  // Ensure that it is impossible to use watchdog on a Chromium build.
-  PERFETTO_FATAL("perfetto::base::Watchdog should not be used in Chromium");
-#endif
-
   static Watchdog* watchdog = new Watchdog(kDefaultPollingInterval);
   return watchdog;
 }
diff --git a/src/ftrace_reader/cpu_reader.cc b/src/ftrace_reader/cpu_reader.cc
index 34f04e2..ecb949c 100644
--- a/src/ftrace_reader/cpu_reader.cc
+++ b/src/ftrace_reader/cpu_reader.cc
@@ -24,6 +24,7 @@
 #include <string>
 #include <utility>
 
+#include "perfetto/base/build_config.h"
 #include "perfetto/base/logging.h"
 #include "perfetto/base/utils.h"
 #include "proto_translation_table.h"
@@ -162,6 +163,8 @@
     int trace_fd,
     int staging_write_fd,
     const std::function<void()>& on_data_available) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
   // This thread is responsible for moving data from the trace pipe into the
   // staging pipe at least one page at a time. This is done using the splice(2)
   // system call, which unlike poll/select makes it possible to block until at
@@ -207,6 +210,9 @@
     // This callback will block until we are allowed to read more data.
     on_data_available();
   }
+#else
+  PERFETTO_ELOG("Supported only on Linux/Android");
+#endif
 }
 
 // static
diff --git a/src/ftrace_reader/cpu_reader.h b/src/ftrace_reader/cpu_reader.h
index 049165b..e320ac6 100644
--- a/src/ftrace_reader/cpu_reader.h
+++ b/src/ftrace_reader/cpu_reader.h
@@ -20,13 +20,13 @@
 #include <stdint.h>
 #include <string.h>
 
-#include <sys/sysmacros.h>
 #include <array>
 #include <memory>
 #include <set>
 #include <thread>
 
 #include "gtest/gtest_prod.h"
+#include "perfetto/base/build_config.h"
 #include "perfetto/base/scoped_file.h"
 #include "perfetto/base/thread_checker.h"
 #include "perfetto/ftrace_reader/ftrace_controller.h"
@@ -161,7 +161,9 @@
     unsigned int maj = static_cast<unsigned int>((kernel_dev) >> 20);
     unsigned int min =
         static_cast<unsigned int>((kernel_dev) & ((1U << 20) - 1));
-    return static_cast<BlockDeviceID>(makedev(maj, min));
+    return static_cast<BlockDeviceID>(  // From makedev()
+        (((maj)&0xfffff000ULL) << 32) | (((maj)&0xfffULL) << 8) |
+        (((min)&0xffffff00ULL) << 12) | (((min)&0xffULL)));
   }
 
   // Iterate through every file in the current directory and check if the inode
diff --git a/src/ftrace_reader/cpu_reader_unittest.cc b/src/ftrace_reader/cpu_reader_unittest.cc
index b4a12c1..1aef25c 100644
--- a/src/ftrace_reader/cpu_reader_unittest.cc
+++ b/src/ftrace_reader/cpu_reader_unittest.cc
@@ -23,6 +23,7 @@
 #include "proto_translation_table.h"
 #include "src/ftrace_reader/event_info.h"
 
+#include "perfetto/base/build_config.h"
 #include "perfetto/base/utils.h"
 #include "perfetto/protozero/scattered_stream_writer.h"
 #include "src/ftrace_reader/test/scattered_stream_delegate_for_testing.h"
@@ -867,7 +868,10 @@
   EXPECT_EQ(event->all_fields().field_pid(), 97);
   EXPECT_EQ(event->all_fields().field_dev_32(), kUserspaceBlockDeviceId);
   EXPECT_EQ(event->all_fields().field_inode_32(), 98u);
+// TODO(primiano): for some reason this fails on mac.
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
   EXPECT_EQ(event->all_fields().field_dev_64(), k64BitUserspaceBlockDeviceId);
+#endif
   EXPECT_EQ(event->all_fields().field_inode_64(), 99u);
   EXPECT_EQ(event->all_fields().field_char_16(), "Hello");
   EXPECT_EQ(event->all_fields().field_char(), "Goodbye");
diff --git a/src/ftrace_reader/ftrace_controller.cc b/src/ftrace_reader/ftrace_controller.cc
index ee322ec..5db4f6e 100644
--- a/src/ftrace_reader/ftrace_controller.cc
+++ b/src/ftrace_reader/ftrace_controller.cc
@@ -20,7 +20,6 @@
 #include <stdint.h>
 #include <string.h>
 #include <sys/stat.h>
-#include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
diff --git a/src/ftrace_reader/ftrace_controller_unittest.cc b/src/ftrace_reader/ftrace_controller_unittest.cc
index 7893123..a071bee 100644
--- a/src/ftrace_reader/ftrace_controller_unittest.cc
+++ b/src/ftrace_reader/ftrace_controller_unittest.cc
@@ -610,16 +610,16 @@
   metadata.Clear();
   EXPECT_THAT(metadata.inode_and_device, IsEmpty());
   EXPECT_THAT(metadata.pids, IsEmpty());
-  EXPECT_EQ(metadata.overwrite_count, 0u);
-  EXPECT_EQ(metadata.last_seen_device_id, 0u);
+  EXPECT_EQ(0u, metadata.overwrite_count);
+  EXPECT_EQ(BlockDeviceID(0), metadata.last_seen_device_id);
 }
 
 TEST(FtraceMetadataTest, AddDevice) {
   FtraceMetadata metadata;
   metadata.AddDevice(1);
-  EXPECT_EQ(metadata.last_seen_device_id, 1u);
+  EXPECT_EQ(BlockDeviceID(1), metadata.last_seen_device_id);
   metadata.AddDevice(3);
-  EXPECT_EQ(metadata.last_seen_device_id, 3u);
+  EXPECT_EQ(BlockDeviceID(3), metadata.last_seen_device_id);
 }
 
 TEST(FtraceMetadataTest, AddInode) {
diff --git a/src/traced/probes/probes_producer.h b/src/traced/probes/probes_producer.h
index a320c5a..c788ed5 100644
--- a/src/traced/probes/probes_producer.h
+++ b/src/traced/probes/probes_producer.h
@@ -22,6 +22,7 @@
 #include <utility>
 
 #include "perfetto/base/task_runner.h"
+#include "perfetto/base/watchdog.h"
 #include "perfetto/ftrace_reader/ftrace_controller.h"
 #include "perfetto/tracing/core/producer.h"
 #include "perfetto/tracing/core/trace_writer.h"
diff --git a/test/task_runner_thread.cc b/test/task_runner_thread.cc
index c7dc985..990fcaa 100644
--- a/test/task_runner_thread.cc
+++ b/test/task_runner_thread.cc
@@ -78,7 +78,11 @@
 }
 
 void TaskRunnerThread::Run(std::unique_ptr<ThreadDelegate> delegate) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
+  pthread_setname_np(name_);
+#else
   pthread_setname_np(pthread_self(), name_);
+#endif
 
   // Create the task runner and execute the specicalised code.
   base::PlatformTaskRunner task_runner;