summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2022-04-01 18:04:35 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2022-04-01 18:04:35 +0000
commitd01120acf01401bd422df447fe18d6d0b71070ad (patch)
treec1d7043425408173045ba87986230513ec861527
parent8ce7a8d069dca31069cff018ccea1c901da27248 (diff)
parente0c446c7d2d05cf806f0539ff86a73a9fce3aa17 (diff)
downloadextras-d01120acf01401bd422df447fe18d6d0b71070ad.tar.gz
Merge changes Ib0160fe1,Ib5a11b7c am: 09fe7d7b48 am: e0c446c7d2
Original change: https://android-review.googlesource.com/c/platform/system/extras/+/2052097 Change-Id: Id98ec3f0963155d08c09a2a0968fd1f7354e6451 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--simpleperf/IOEventLoop.cpp32
-rw-r--r--simpleperf/IOEventLoop.h24
-rw-r--r--simpleperf/IOEventLoop_test.cpp42
-rw-r--r--simpleperf/cmd_monitor.cpp13
-rw-r--r--simpleperf/cmd_record.cpp29
-rw-r--r--simpleperf/event_selection_set.cpp9
6 files changed, 109 insertions, 40 deletions
diff --git a/simpleperf/IOEventLoop.cpp b/simpleperf/IOEventLoop.cpp
index 06bdd713..239fff97 100644
--- a/simpleperf/IOEventLoop.cpp
+++ b/simpleperf/IOEventLoop.cpp
@@ -84,6 +84,10 @@ bool IOEventLoop::EnsureInit() {
return false;
}
event_config_free(cfg);
+ if (event_base_priority_init(ebase_, 2) != 0) {
+ LOG(ERROR) << "event_base_priority_init failed";
+ return false;
+ }
}
if (ebase_ == nullptr) {
LOG(ERROR) << "failed to create event_base";
@@ -110,39 +114,44 @@ static bool MakeFdNonBlocking(int fd) {
return true;
}
-IOEventRef IOEventLoop::AddReadEvent(int fd, const std::function<bool()>& callback) {
+IOEventRef IOEventLoop::AddReadEvent(int fd, const std::function<bool()>& callback,
+ IOEventPriority priority) {
if (!MakeFdNonBlocking(fd)) {
return nullptr;
}
- return AddEvent(fd, EV_READ | EV_PERSIST, nullptr, callback);
+ return AddEvent(fd, EV_READ | EV_PERSIST, nullptr, callback, priority);
}
-IOEventRef IOEventLoop::AddWriteEvent(int fd, const std::function<bool()>& callback) {
+IOEventRef IOEventLoop::AddWriteEvent(int fd, const std::function<bool()>& callback,
+ IOEventPriority priority) {
if (!MakeFdNonBlocking(fd)) {
return nullptr;
}
- return AddEvent(fd, EV_WRITE | EV_PERSIST, nullptr, callback);
+ return AddEvent(fd, EV_WRITE | EV_PERSIST, nullptr, callback, priority);
}
-bool IOEventLoop::AddSignalEvent(int sig, const std::function<bool()>& callback) {
- return AddEvent(sig, EV_SIGNAL | EV_PERSIST, nullptr, callback) != nullptr;
+bool IOEventLoop::AddSignalEvent(int sig, const std::function<bool()>& callback,
+ IOEventPriority priority) {
+ return AddEvent(sig, EV_SIGNAL | EV_PERSIST, nullptr, callback, priority) != nullptr;
}
-bool IOEventLoop::AddSignalEvents(std::vector<int> sigs, const std::function<bool()>& callback) {
+bool IOEventLoop::AddSignalEvents(std::vector<int> sigs, const std::function<bool()>& callback,
+ IOEventPriority priority) {
for (auto sig : sigs) {
- if (!AddSignalEvent(sig, callback)) {
+ if (!AddSignalEvent(sig, callback, priority)) {
return false;
}
}
return true;
}
-IOEventRef IOEventLoop::AddPeriodicEvent(timeval duration, const std::function<bool()>& callback) {
- return AddEvent(-1, EV_PERSIST, &duration, callback);
+IOEventRef IOEventLoop::AddPeriodicEvent(timeval duration, const std::function<bool()>& callback,
+ IOEventPriority priority) {
+ return AddEvent(-1, EV_PERSIST, &duration, callback, priority);
}
IOEventRef IOEventLoop::AddEvent(int fd_or_sig, int16_t events, timeval* timeout,
- const std::function<bool()>& callback) {
+ const std::function<bool()>& callback, IOEventPriority priority) {
if (!EnsureInit()) {
return nullptr;
}
@@ -152,6 +161,7 @@ IOEventRef IOEventLoop::AddEvent(int fd_or_sig, int16_t events, timeval* timeout
LOG(ERROR) << "event_new() failed";
return nullptr;
}
+ event_priority_set(e->e, priority);
if (event_add(e->e, timeout) != 0) {
LOG(ERROR) << "event_add() failed";
return nullptr;
diff --git a/simpleperf/IOEventLoop.h b/simpleperf/IOEventLoop.h
index 0bbbbd01..1578a4d0 100644
--- a/simpleperf/IOEventLoop.h
+++ b/simpleperf/IOEventLoop.h
@@ -32,6 +32,12 @@ namespace simpleperf {
struct IOEvent;
typedef IOEvent* IOEventRef;
+enum IOEventPriority {
+ // Lower value means higher priority.
+ IOEventHighPriority = 0,
+ IOEventLowPriority = 1,
+};
+
// IOEventLoop is a class wrapper of libevent, it monitors events happened,
// and calls the corresponding callbacks. Possible events are: file ready to
// read, file ready to write, signal happens, periodic timer timeout.
@@ -46,22 +52,27 @@ class IOEventLoop {
// Register a read Event, so [callback] is called when [fd] can be read
// without blocking. If registered successfully, return the reference
// to control the Event, otherwise return nullptr.
- IOEventRef AddReadEvent(int fd, const std::function<bool()>& callback);
+ IOEventRef AddReadEvent(int fd, const std::function<bool()>& callback,
+ IOEventPriority priority = IOEventLowPriority);
// Register a write Event, so [callback] is called when [fd] can be written
// without blocking.
- IOEventRef AddWriteEvent(int fd, const std::function<bool()>& callback);
+ IOEventRef AddWriteEvent(int fd, const std::function<bool()>& callback,
+ IOEventPriority priority = IOEventLowPriority);
// Register a signal Event, so [callback] is called each time signal [sig]
// happens.
- bool AddSignalEvent(int sig, const std::function<bool()>& callback);
+ bool AddSignalEvent(int sig, const std::function<bool()>& callback,
+ IOEventPriority priority = IOEventLowPriority);
// Register a vector of signal Events.
- bool AddSignalEvents(std::vector<int> sigs, const std::function<bool()>& callback);
+ bool AddSignalEvents(std::vector<int> sigs, const std::function<bool()>& callback,
+ IOEventPriority priority = IOEventLowPriority);
// Register a periodic Event, so [callback] is called periodically every
// [duration].
- IOEventRef AddPeriodicEvent(timeval duration, const std::function<bool()>& callback);
+ IOEventRef AddPeriodicEvent(timeval duration, const std::function<bool()>& callback,
+ IOEventPriority priority = IOEventLowPriority);
// Run a loop polling for Events. It only exits when ExitLoop() is called
// in a callback function of registered Events.
@@ -81,7 +92,8 @@ class IOEventLoop {
private:
bool EnsureInit();
IOEventRef AddEvent(int fd_or_sig, int16_t events, timeval* timeout,
- const std::function<bool()>& callback);
+ const std::function<bool()>& callback,
+ IOEventPriority priority = IOEventLowPriority);
static void EventCallbackFn(int, int16_t, void*);
event_base* ebase_;
diff --git a/simpleperf/IOEventLoop_test.cpp b/simpleperf/IOEventLoop_test.cpp
index 09f64522..658fe820 100644
--- a/simpleperf/IOEventLoop_test.cpp
+++ b/simpleperf/IOEventLoop_test.cpp
@@ -250,3 +250,45 @@ TEST(IOEventLoop, exit_before_loop) {
IOEventLoop loop;
ASSERT_TRUE(loop.ExitLoop());
}
+
+TEST(IOEventLoop, priority) {
+ int low_priority_fd[2];
+ ASSERT_EQ(0, pipe(low_priority_fd));
+ int high_priority_fd[2];
+ ASSERT_EQ(0, pipe(high_priority_fd));
+
+ IOEventLoop loop;
+ int count = 0;
+
+ ASSERT_NE(nullptr, loop.AddReadEvent(
+ low_priority_fd[0],
+ [&]() {
+ char c;
+ read(low_priority_fd[0], &c, 1);
+ CHECK_EQ(count, 1);
+ count++;
+ return loop.ExitLoop();
+ },
+ IOEventLowPriority));
+
+ ASSERT_NE(nullptr, loop.AddReadEvent(
+ high_priority_fd[0],
+ [&]() {
+ char c;
+ read(high_priority_fd[0], &c, 1);
+ CHECK_EQ(count, 0);
+ count++;
+ return true;
+ },
+ IOEventHighPriority));
+
+ char c;
+ CHECK_EQ(write(low_priority_fd[1], &c, 1), 1);
+ CHECK_EQ(write(high_priority_fd[1], &c, 1), 1);
+ ASSERT_TRUE(loop.RunLoop());
+ ASSERT_EQ(2, count);
+ for (int i = 0; i < 2; i++) {
+ close(low_priority_fd[i]);
+ close(high_priority_fd[i]);
+ }
+}
diff --git a/simpleperf/cmd_monitor.cpp b/simpleperf/cmd_monitor.cpp
index ed9edfac..d81ccfea 100644
--- a/simpleperf/cmd_monitor.cpp
+++ b/simpleperf/cmd_monitor.cpp
@@ -266,21 +266,22 @@ bool MonitorCommand::PrepareMonitoring() {
// 5. Add read/signal/periodic Events.
IOEventLoop* loop = event_selection_set_.GetIOEventLoop();
auto exit_loop_callback = [loop]() { return loop->ExitLoop(); };
- if (!loop->AddSignalEvents({SIGCHLD, SIGINT, SIGTERM}, exit_loop_callback)) {
+ if (!loop->AddSignalEvents({SIGCHLD, SIGINT, SIGTERM}, exit_loop_callback, IOEventHighPriority)) {
return false;
}
// Only add an event for SIGHUP if we didn't inherit SIG_IGN (e.g. from
// nohup).
if (!SignalIsIgnored(SIGHUP)) {
- if (!loop->AddSignalEvent(SIGHUP, exit_loop_callback)) {
+ if (!loop->AddSignalEvent(SIGHUP, exit_loop_callback, IOEventHighPriority)) {
return false;
}
}
if (duration_in_sec_ != 0) {
- if (!loop->AddPeriodicEvent(SecondToTimeval(duration_in_sec_),
- [loop]() { return loop->ExitLoop(); })) {
+ if (!loop->AddPeriodicEvent(
+ SecondToTimeval(duration_in_sec_), [loop]() { return loop->ExitLoop(); },
+ IOEventHighPriority)) {
return false;
}
}
@@ -291,6 +292,10 @@ bool MonitorCommand::DoMonitoring() {
if (!event_selection_set_.GetIOEventLoop()->RunLoop()) {
return false;
}
+ if (!event_selection_set_.SyncKernelBuffer()) {
+ return false;
+ }
+ event_selection_set_.CloseEventFiles();
if (!event_selection_set_.FinishReadMmapEventData()) {
return false;
}
diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp
index b84bcfab..35cab822 100644
--- a/simpleperf/cmd_record.cpp
+++ b/simpleperf/cmd_record.cpp
@@ -629,25 +629,26 @@ bool RecordCommand::PrepareRecording(Workload* workload) {
}
IOEventLoop* loop = event_selection_set_.GetIOEventLoop();
auto exit_loop_callback = [loop]() { return loop->ExitLoop(); };
- if (!loop->AddSignalEvents({SIGCHLD, SIGINT, SIGTERM}, exit_loop_callback)) {
+ if (!loop->AddSignalEvents({SIGCHLD, SIGINT, SIGTERM}, exit_loop_callback, IOEventHighPriority)) {
return false;
}
// Only add an event for SIGHUP if we didn't inherit SIG_IGN (e.g. from nohup).
if (!SignalIsIgnored(SIGHUP)) {
- if (!loop->AddSignalEvent(SIGHUP, exit_loop_callback)) {
+ if (!loop->AddSignalEvent(SIGHUP, exit_loop_callback, IOEventHighPriority)) {
return false;
}
}
if (stop_signal_fd_ != -1) {
- if (!loop->AddReadEvent(stop_signal_fd_, exit_loop_callback)) {
+ if (!loop->AddReadEvent(stop_signal_fd_, exit_loop_callback, IOEventHighPriority)) {
return false;
}
}
if (duration_in_sec_ != 0) {
- if (!loop->AddPeriodicEvent(SecondToTimeval(duration_in_sec_),
- [loop]() { return loop->ExitLoop(); })) {
+ if (!loop->AddPeriodicEvent(
+ SecondToTimeval(duration_in_sec_), [loop]() { return loop->ExitLoop(); },
+ IOEventHighPriority)) {
return false;
}
}
@@ -718,9 +719,10 @@ bool RecordCommand::DoRecording(Workload* workload) {
return false;
}
time_stat_.stop_recording_time = GetSystemClock();
- if (!event_selection_set_.FinishReadMmapEventData()) {
+ if (!event_selection_set_.SyncKernelBuffer()) {
return false;
}
+ event_selection_set_.CloseEventFiles();
time_stat_.finish_recording_time = GetSystemClock();
uint64_t recording_time = time_stat_.finish_recording_time - time_stat_.start_recording_time;
LOG(INFO) << "Recorded for " << recording_time / 1e9 << " seconds. Start post processing.";
@@ -754,26 +756,31 @@ static bool WriteRecordDataToOutFd(const std::string& in_filename,
}
bool RecordCommand::PostProcessRecording(const std::vector<std::string>& args) {
- // 1. Merge map records dumped while recording by map record thread.
+ // 1. Read records left in the buffer.
+ if (!event_selection_set_.FinishReadMmapEventData()) {
+ return false;
+ }
+
+ // 2. Merge map records dumped while recording by map record thread.
if (map_record_thread_) {
if (!map_record_thread_->Join() || !MergeMapRecords()) {
return false;
}
}
- // 2. Post unwind dwarf callchain.
+ // 3. Post unwind dwarf callchain.
if (unwind_dwarf_callchain_ && post_unwind_) {
if (!PostUnwindRecords()) {
return false;
}
}
- // 3. Optionally join Callchains.
+ // 4. Optionally join Callchains.
if (callchain_joiner_) {
JoinCallChains();
}
- // 4. Dump additional features, and close record file.
+ // 5. Dump additional features, and close record file.
if (!DumpAdditionalFeatures(args)) {
return false;
}
@@ -785,7 +792,7 @@ bool RecordCommand::PostProcessRecording(const std::vector<std::string>& args) {
}
time_stat_.post_process_time = GetSystemClock();
- // 4. Show brief record result.
+ // 6. Show brief record result.
auto record_stat = event_selection_set_.GetRecordStat();
if (event_selection_set_.HasAuxTrace()) {
LOG(INFO) << "Aux data traced: " << record_stat.aux_data_size;
diff --git a/simpleperf/event_selection_set.cpp b/simpleperf/event_selection_set.cpp
index d5bca318..58b4b956 100644
--- a/simpleperf/event_selection_set.cpp
+++ b/simpleperf/event_selection_set.cpp
@@ -840,14 +840,7 @@ bool EventSelectionSet::ReadMmapEventData(bool with_time_limit) {
}
bool EventSelectionSet::FinishReadMmapEventData() {
- // Stop the read thread, so we don't get more records beyond current time.
- if (!SyncKernelBuffer() || !record_read_thread_->StopReadThread()) {
- return false;
- }
- if (!ReadMmapEventData(false)) {
- return false;
- }
- return true;
+ return ReadMmapEventData(false);
}
void EventSelectionSet::CloseEventFiles() {