Merge "Hopefully actually fix Windows build."
diff --git a/Android.bp b/Android.bp
index 541e66f..480e618 100644
--- a/Android.bp
+++ b/Android.bp
@@ -32,6 +32,7 @@
":perfetto_protos_perfetto_trace_trusted_lite_gen",
":perfetto_protos_perfetto_trace_zero_gen",
":perfetto_src_ipc_wire_protocol_gen",
+ "src/base/event.cc",
"src/base/file_utils.cc",
"src/base/metatrace.cc",
"src/base/page_allocator.cc",
@@ -157,6 +158,7 @@
":perfetto_src_ipc_wire_protocol_gen",
":perfetto_src_perfetto_cmd_protos_gen",
"src/base/android_task_runner.cc",
+ "src/base/event.cc",
"src/base/file_utils.cc",
"src/base/metatrace.cc",
"src/base/page_allocator.cc",
@@ -297,6 +299,7 @@
":perfetto_protos_perfetto_trace_zero_gen",
":perfetto_src_ipc_wire_protocol_gen",
"src/base/android_task_runner.cc",
+ "src/base/event.cc",
"src/base/file_utils.cc",
"src/base/metatrace.cc",
"src/base/page_allocator.cc",
@@ -3612,6 +3615,7 @@
":perfetto_protos_perfetto_trace_trusted_lite_gen",
":perfetto_protos_perfetto_trace_zero_gen",
":perfetto_src_ipc_wire_protocol_gen",
+ "src/base/event.cc",
"src/base/file_utils.cc",
"src/base/metatrace.cc",
"src/base/page_allocator.cc",
@@ -3800,6 +3804,7 @@
":perfetto_src_traced_probes_ftrace_test_messages_lite_gen",
":perfetto_src_traced_probes_ftrace_test_messages_zero_gen",
"src/base/android_task_runner.cc",
+ "src/base/event.cc",
"src/base/file_utils.cc",
"src/base/metatrace.cc",
"src/base/page_allocator.cc",
@@ -4033,6 +4038,7 @@
":perfetto_protos_perfetto_trace_minimal_lite_gen",
":perfetto_protos_perfetto_trace_ps_lite_gen",
":perfetto_protos_perfetto_trace_sys_stats_lite_gen",
+ "src/base/event.cc",
"src/base/file_utils.cc",
"src/base/metatrace.cc",
"src/base/page_allocator.cc",
diff --git a/include/perfetto/base/BUILD.gn b/include/perfetto/base/BUILD.gn
index 10da3d0..5ee76ba 100644
--- a/include/perfetto/base/BUILD.gn
+++ b/include/perfetto/base/BUILD.gn
@@ -17,6 +17,7 @@
source_set("base") {
sources = [
"build_config.h",
+ "event.h",
"export.h",
"file_utils.h",
"logging.h",
diff --git a/include/perfetto/base/android_task_runner.h b/include/perfetto/base/android_task_runner.h
index 5087330..5aebbac 100644
--- a/include/perfetto/base/android_task_runner.h
+++ b/include/perfetto/base/android_task_runner.h
@@ -17,6 +17,7 @@
#ifndef INCLUDE_PERFETTO_BASE_ANDROID_TASK_RUNNER_H_
#define INCLUDE_PERFETTO_BASE_ANDROID_TASK_RUNNER_H_
+#include "perfetto/base/event.h"
#include "perfetto/base/scoped_file.h"
#include "perfetto/base/task_runner.h"
#include "perfetto/base/thread_checker.h"
@@ -69,7 +70,7 @@
void ScheduleDelayedWakeUp(TimeMillis time);
ALooper* const looper_;
- ScopedFile immediate_event_;
+ Event immediate_event_;
ScopedFile delayed_timer_;
ThreadChecker thread_checker_;
diff --git a/include/perfetto/base/event.h b/include/perfetto/base/event.h
new file mode 100644
index 0000000..bca6c00
--- /dev/null
+++ b/include/perfetto/base/event.h
@@ -0,0 +1,67 @@
+/*
+ * 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_EVENT_H_
+#define INCLUDE_PERFETTO_BASE_EVENT_H_
+
+#include "perfetto/base/build_config.h"
+#include "perfetto/base/scoped_file.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+#define PERFETTO_USE_EVENTFD() 1
+#else
+#define PERFETTO_USE_EVENTFD() 0
+#endif
+
+namespace perfetto {
+namespace base {
+
+// A waitable event that can be used with poll/select.
+// This is really a wrapper around eventfd_create with a pipe-based fallback
+// for other platforms where eventfd is not supported.
+class Event {
+ public:
+ Event();
+ ~Event();
+ Event(Event&&) noexcept = default;
+ Event& operator=(Event&&) = default;
+
+ // The non-blocking file descriptor that can be polled to wait for the event.
+ int fd() const { return fd_.get(); }
+
+ // Can be called from any thread.
+ void Notify();
+
+ // Can be called from any thread. If more Notify() are queued a Clear() call
+ // can clear all of them (up to 16 per call).
+ void Clear();
+
+ private:
+ // The eventfd, when eventfd is supported, otherwise this is the read end of
+ // the pipe for fallback mode.
+ ScopedFile fd_;
+
+#if !PERFETTO_USE_EVENTFD()
+ // The write end of the wakeup pipe.
+ ScopedFile write_fd_;
+#endif
+};
+
+} // namespace base
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_BASE_EVENT_H_
diff --git a/include/perfetto/base/unix_task_runner.h b/include/perfetto/base/unix_task_runner.h
index 65c8361..3d1a896 100644
--- a/include/perfetto/base/unix_task_runner.h
+++ b/include/perfetto/base/unix_task_runner.h
@@ -18,6 +18,7 @@
#define INCLUDE_PERFETTO_BASE_UNIX_TASK_RUNNER_H_
#include "perfetto/base/build_config.h"
+#include "perfetto/base/event.h"
#include "perfetto/base/scoped_file.h"
#include "perfetto/base/task_runner.h"
#include "perfetto/base/thread_checker.h"
@@ -30,13 +31,6 @@
#include <mutex>
#include <vector>
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
- PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-#define PERFETTO_USE_EVENTFD() 1
-#else
-#define PERFETTO_USE_EVENTFD() 0
-#endif
-
namespace perfetto {
namespace base {
@@ -75,11 +69,7 @@
// On Linux, an eventfd(2) used to waking up the task runner when a new task
// is posted. Otherwise the read end of a pipe used for the same purpose.
- ScopedFile event_;
-#if !PERFETTO_USE_EVENTFD()
- // The write end of the wakeup pipe.
- ScopedFile event_write_;
-#endif
+ Event event_;
std::vector<struct pollfd> poll_fds_;
diff --git a/src/base/BUILD.gn b/src/base/BUILD.gn
index 019cd7b..ad3f170 100644
--- a/src/base/BUILD.gn
+++ b/src/base/BUILD.gn
@@ -37,6 +37,7 @@
# TODO(brucedawson): Enable these for Windows when possible.
if (!is_win) {
sources += [
+ "event.cc",
"temp_file.cc",
"unix_task_runner.cc",
]
diff --git a/src/base/android_task_runner.cc b/src/base/android_task_runner.cc
index d8e7cc7..23697c8 100644
--- a/src/base/android_task_runner.cc
+++ b/src/base/android_task_runner.cc
@@ -17,7 +17,6 @@
#include "perfetto/base/android_task_runner.h"
#include <errno.h>
-#include <sys/eventfd.h>
#include <sys/timerfd.h>
namespace perfetto {
@@ -25,13 +24,11 @@
AndroidTaskRunner::AndroidTaskRunner()
: looper_(ALooper_prepare(0 /* require callbacks */)),
- immediate_event_(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC)),
delayed_timer_(
timerfd_create(kWallTimeClockSource, TFD_NONBLOCK | TFD_CLOEXEC)) {
ALooper_acquire(looper_);
- PERFETTO_CHECK(immediate_event_);
PERFETTO_CHECK(delayed_timer_);
- AddFileDescriptorWatch(immediate_event_.get(),
+ AddFileDescriptorWatch(immediate_event_.fd(),
std::bind(&AndroidTaskRunner::RunImmediateTask, this));
AddFileDescriptorWatch(delayed_timer_.get(),
std::bind(&AndroidTaskRunner::RunDelayedTask, this));
@@ -81,11 +78,7 @@
}
void AndroidTaskRunner::RunImmediateTask() {
- uint64_t unused = 0;
- if (read(immediate_event_.get(), &unused, sizeof(unused)) != sizeof(unused) &&
- errno != EAGAIN) {
- PERFETTO_DPLOG("read");
- }
+ immediate_event_.Clear();
// If locking overhead becomes an issue, add a separate work queue.
bool has_next;
@@ -133,11 +126,7 @@
}
void AndroidTaskRunner::ScheduleImmediateWakeUp() {
- uint64_t value = 1;
- if (write(immediate_event_.get(), &value, sizeof(value)) == -1 &&
- errno != EAGAIN) {
- PERFETTO_DPLOG("write");
- }
+ immediate_event_.Notify();
}
void AndroidTaskRunner::ScheduleDelayedWakeUp(TimeMillis time) {
diff --git a/src/base/event.cc b/src/base/event.cc
new file mode 100644
index 0000000..4085618
--- /dev/null
+++ b/src/base/event.cc
@@ -0,0 +1,83 @@
+/*
+ * 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 <stdint.h>
+#include <unistd.h>
+
+#include "perfetto/base/event.h"
+#include "perfetto/base/logging.h"
+
+#if PERFETTO_USE_EVENTFD()
+#include <sys/eventfd.h>
+#endif
+
+namespace perfetto {
+namespace base {
+
+Event::Event() {
+#if PERFETTO_USE_EVENTFD()
+ fd_.reset(eventfd(/* start value */ 0, EFD_CLOEXEC | EFD_NONBLOCK));
+ PERFETTO_CHECK(fd_);
+#else
+ int pipe_fds[2];
+ PERFETTO_CHECK(pipe(pipe_fds) == 0);
+
+ // Make the pipe non-blocking so that we never block the waking thread (either
+ // the main thread or another one) when scheduling a wake-up.
+ for (auto fd : pipe_fds) {
+ int flags = fcntl(fd, F_GETFL, 0);
+ PERFETTO_CHECK(flags != -1);
+ PERFETTO_CHECK(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0);
+ PERFETTO_CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
+ }
+ fd_.reset(pipe_fds[0]);
+ write_fd_.reset(pipe_fds[1]);
+#endif // !PERFETTO_USE_EVENTFD()
+}
+
+Event::~Event() = default;
+
+void Event::Notify() {
+ const uint64_t value = 1;
+
+#if PERFETTO_USE_EVENTFD()
+ ssize_t ret = write(fd_.get(), &value, sizeof(value));
+#else
+ ssize_t ret = write(write_fd_.get(), &value, sizeof(uint8_t));
+#endif
+
+ if (ret <= 0 && errno != EAGAIN) {
+ PERFETTO_DPLOG("write()");
+ PERFETTO_DCHECK(false);
+ }
+}
+
+void Event::Clear() {
+#if PERFETTO_USE_EVENTFD()
+ uint64_t value;
+ ssize_t ret = read(fd_.get(), &value, sizeof(value));
+#else
+ // Drain the byte(s) written to the wake-up pipe. We can potentially read
+ // more than one byte if several wake-ups have been scheduled.
+ char buffer[16];
+ ssize_t ret = read(fd_.get(), &buffer[0], sizeof(buffer));
+#endif
+ if (ret <= 0 && errno != EAGAIN)
+ PERFETTO_DPLOG("read()");
+}
+
+} // namespace base
+} // namespace perfetto
diff --git a/src/base/unix_task_runner.cc b/src/base/unix_task_runner.cc
index 006b7af..44501df 100644
--- a/src/base/unix_task_runner.cc
+++ b/src/base/unix_task_runner.cc
@@ -24,32 +24,11 @@
#include <limits>
-#if PERFETTO_USE_EVENTFD()
-#include <sys/eventfd.h>
-#endif
-
namespace perfetto {
namespace base {
UnixTaskRunner::UnixTaskRunner() {
-#if PERFETTO_USE_EVENTFD()
- event_.reset(eventfd(/* start value */ 0, EFD_CLOEXEC | EFD_NONBLOCK));
-#else
- int pipe_fds[2];
- PERFETTO_CHECK(pipe(pipe_fds) == 0);
-
- // Make the pipe non-blocking so that we never block the waking thread (either
- // the main thread or another one) when scheduling a wake-up.
- for (auto fd : pipe_fds) {
- int flags = fcntl(fd, F_GETFL, 0);
- PERFETTO_CHECK(flags != -1);
- PERFETTO_CHECK(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0);
- PERFETTO_CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0);
- }
- event_.reset(pipe_fds[0]);
- event_write_.reset(pipe_fds[1]);
-#endif // !PERFETTO_USE_EVENTFD()
- AddFileDescriptorWatch(event_.get(), [] {
+ AddFileDescriptorWatch(event_.fd(), [] {
// Not reached -- see PostFileDescriptorWatches().
PERFETTO_DCHECK(false);
});
@@ -58,14 +37,7 @@
UnixTaskRunner::~UnixTaskRunner() = default;
void UnixTaskRunner::WakeUp() {
- const uint64_t value = 1;
-#if PERFETTO_USE_EVENTFD()
- ssize_t ret = write(event_.get(), &value, sizeof(value));
-#else
- ssize_t ret = write(event_write_.get(), &value, sizeof(uint8_t));
-#endif
- if (ret <= 0 && errno != EAGAIN)
- PERFETTO_DPLOG("write()");
+ event_.Notify();
}
void UnixTaskRunner::Run() {
@@ -153,18 +125,8 @@
// The wake-up event is handled inline to avoid an infinite recursion of
// posted tasks.
- if (poll_fds_[i].fd == event_.get()) {
-#if PERFETTO_USE_EVENTFD()
- uint64_t value;
- ssize_t ret = read(event_.get(), &value, sizeof(value));
-#else
- // Drain the byte(s) written to the wake-up pipe. We can potentially read
- // more than one byte if several wake-ups have been scheduled.
- char buffer[16];
- ssize_t ret = read(event_.get(), &buffer[0], sizeof(buffer));
-#endif
- if (ret <= 0 && errno != EAGAIN)
- PERFETTO_DPLOG("read()");
+ if (poll_fds_[i].fd == event_.fd()) {
+ event_.Clear();
continue;
}