base: add ability to override platform-level functionality in base
In Google3, we need the ability to annotate the regions around blocking
syscalls so the userspace scheduler is aware of them. Because of this,
add functionality to mark such regions by having an abstraction of a
"platform" at a build system level and allow Bazel to override it.
Moreover, annotate read, write and poll syscalls in base with these
new functions: the "default" functions are empty noops.
Change-Id: I18c8246d32bac512494c2bc2cd5b02d840b82ec6
diff --git a/src/base/BUILD.gn b/src/base/BUILD.gn
index b53b08a..6a58f0b 100644
--- a/src/base/BUILD.gn
+++ b/src/base/BUILD.gn
@@ -25,7 +25,10 @@
is_linux || is_chromeos || is_android || is_mac || is_win
perfetto_component("base") {
- deps = [ "../../gn:default_deps" ]
+ deps = [
+ "../../gn:base_platform",
+ "../../gn:default_deps",
+ ]
public_deps = [
"../../include/perfetto/base",
"../../include/perfetto/ext/base",
@@ -79,6 +82,16 @@
}
}
+# This target needs to be named as such because it's exposed directly in Bazel
+# and Android.bp.
+perfetto_component("perfetto_base_default_platform") {
+ deps = [
+ "../../gn:default_deps",
+ "../../include/perfetto/ext/base",
+ ]
+ sources = [ "default_platform.cc" ]
+}
+
perfetto_component("version") {
deps = [
":base",
diff --git a/src/base/default_platform.cc b/src/base/default_platform.cc
new file mode 100644
index 0000000..acc3cf3
--- /dev/null
+++ b/src/base/default_platform.cc
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 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/ext/base/platform.h"
+
+namespace perfetto {
+namespace base {
+namespace platform {
+
+// This is a no-op outside of Google3 where we have some custom logic to deal
+// with the userspace scheduler.
+void BeforeMaybeBlockingSyscall() {}
+
+// This is a no-op outside of Google3 where we have some custom logic to deal
+// with the userspace scheduler.
+void AfterMaybeBlockingSyscall() {}
+
+} // namespace platform
+} // namespace base
+} // namespace perfetto
diff --git a/src/base/file_utils.cc b/src/base/file_utils.cc
index 91a63bd..66ab5f6 100644
--- a/src/base/file_utils.cc
+++ b/src/base/file_utils.cc
@@ -29,6 +29,7 @@
#include "perfetto/base/platform_handle.h"
#include "perfetto/base/status.h"
#include "perfetto/ext/base/optional.h"
+#include "perfetto/ext/base/platform.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/utils.h"
@@ -77,11 +78,15 @@
} // namespace
ssize_t Read(int fd, void* dst, size_t dst_size) {
+ ssize_t ret;
+ platform::BeforeMaybeBlockingSyscall();
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
- return _read(fd, dst, static_cast<unsigned>(dst_size));
+ ret = _read(fd, dst, static_cast<unsigned>(dst_size));
#else
- return PERFETTO_EINTR(read(fd, dst, dst_size));
+ ret = PERFETTO_EINTR(read(fd, dst, dst_size));
#endif
+ platform::AfterMaybeBlockingSyscall();
+ return ret;
}
bool ReadFileDescriptor(int fd, std::string* out) {
@@ -156,8 +161,10 @@
// write() on windows takes an unsigned int size.
uint32_t bytes_left = static_cast<uint32_t>(
std::min(count - written, static_cast<size_t>(UINT32_MAX)));
+ platform::BeforeMaybeBlockingSyscall();
ssize_t wr = PERFETTO_EINTR(
write(fd, static_cast<const char*>(buf) + written, bytes_left));
+ platform::AfterMaybeBlockingSyscall();
if (wr == 0)
break;
if (wr < 0)
diff --git a/src/base/unix_task_runner.cc b/src/base/unix_task_runner.cc
index f6b6c19..9fc8f3c 100644
--- a/src/base/unix_task_runner.cc
+++ b/src/base/unix_task_runner.cc
@@ -16,6 +16,7 @@
#include "perfetto/base/build_config.h"
+#include "perfetto/ext/base/platform.h"
#include "perfetto/ext/base/unix_task_runner.h"
#include <errno.h>
@@ -77,8 +78,10 @@
// returned.
PostFileDescriptorWatches(ret);
#else
+ platform::BeforeMaybeBlockingSyscall();
int ret = PERFETTO_EINTR(poll(
&poll_fds_[0], static_cast<nfds_t>(poll_fds_.size()), poll_timeout_ms));
+ platform::AfterMaybeBlockingSyscall();
PERFETTO_CHECK(ret >= 0);
PostFileDescriptorWatches(0 /*ignored*/);
#endif
diff --git a/src/base/watchdog_posix.cc b/src/base/watchdog_posix.cc
index b92e9ce..fcbf713 100644
--- a/src/base/watchdog_posix.cc
+++ b/src/base/watchdog_posix.cc
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include "perfetto/ext/base/platform.h"
#include "perfetto/ext/base/watchdog.h"
#if PERFETTO_BUILDFLAG(PERFETTO_WATCHDOG)
@@ -231,7 +232,9 @@
// We use the poll() timeout to drive the periodic ticks for the cpu/memory
// checks. The only other case when the poll() unblocks is when we crash
// (or have to quit via enabled_ == false, but that happens only in tests).
+ platform::BeforeMaybeBlockingSyscall();
auto ret = poll(fds, kFdCount, static_cast<int>(polling_interval_ms_));
+ platform::AfterMaybeBlockingSyscall();
if (!enabled_)
return;
if (ret < 0) {