diff options
65 files changed, 228 insertions, 157 deletions
diff --git a/simpleperf/ETMDecoder.cpp b/simpleperf/ETMDecoder.cpp index c110e9fc..b077de51 100644 --- a/simpleperf/ETMDecoder.cpp +++ b/simpleperf/ETMDecoder.cpp @@ -21,8 +21,7 @@ #include <llvm/Support/MemoryBuffer.h> #include <opencsd.h> -using namespace simpleperf; - +namespace simpleperf { namespace { class DecoderLogStr : public ocsdMsgLogStrOutI { @@ -757,8 +756,6 @@ class ETMDecoderImpl : public ETMDecoder { } // namespace -namespace simpleperf { - bool ParseEtmDumpOption(const std::string& s, ETMDumpOption* option) { for (auto& value : android::base::Split(s, ",")) { if (value == "raw") { diff --git a/simpleperf/IOEventLoop.cpp b/simpleperf/IOEventLoop.cpp index b87a05d3..06bdd713 100644 --- a/simpleperf/IOEventLoop.cpp +++ b/simpleperf/IOEventLoop.cpp @@ -21,6 +21,8 @@ #include <android-base/logging.h> +namespace simpleperf { + struct IOEvent { IOEventLoop* loop; event* e; @@ -221,3 +223,5 @@ bool IOEventLoop::DelEvent(IOEventRef ref) { } return true; } + +} // namespace simpleperf diff --git a/simpleperf/IOEventLoop.h b/simpleperf/IOEventLoop.h index 6f78d789..f0192969 100644 --- a/simpleperf/IOEventLoop.h +++ b/simpleperf/IOEventLoop.h @@ -24,9 +24,12 @@ #include <memory> #include <vector> +struct event_base; + +namespace simpleperf { + struct IOEvent; typedef IOEvent* IOEventRef; -struct event_base; // IOEventLoop is a class wrapper of libevent, it monitors events happened, // and calls the corresponding callbacks. Possible events are: file ready to @@ -87,4 +90,6 @@ class IOEventLoop { bool in_loop_; }; +} // namespace simpleperf + #endif // SIMPLE_PERF_IOEVENT_LOOP_H_ diff --git a/simpleperf/IOEventLoop_test.cpp b/simpleperf/IOEventLoop_test.cpp index 546f0d77..95971aef 100644 --- a/simpleperf/IOEventLoop_test.cpp +++ b/simpleperf/IOEventLoop_test.cpp @@ -24,6 +24,8 @@ #include <android-base/logging.h> +using namespace simpleperf; + TEST(IOEventLoop, read) { int fd[2]; ASSERT_EQ(0, pipe(fd)); diff --git a/simpleperf/JITDebugReader.cpp b/simpleperf/JITDebugReader.cpp index f483c49d..3b58407d 100644 --- a/simpleperf/JITDebugReader.cpp +++ b/simpleperf/JITDebugReader.cpp @@ -39,11 +39,11 @@ #include "read_elf.h" #include "utils.h" +namespace simpleperf { + using android::base::StartsWith; using android::base::StringPrintf; -namespace simpleperf { - // If the size of a symfile is larger than EXPECTED_MAX_SYMFILE_SIZE, we don't want to read it // remotely. static constexpr size_t MAX_JIT_SYMFILE_SIZE = 1024 * 1024u; diff --git a/simpleperf/ProbeEvents.cpp b/simpleperf/ProbeEvents.cpp index c09652a5..636923f9 100644 --- a/simpleperf/ProbeEvents.cpp +++ b/simpleperf/ProbeEvents.cpp @@ -33,15 +33,14 @@ #include "event_type.h" #include "utils.h" +namespace simpleperf { + using android::base::ParseInt; using android::base::ParseUint; using android::base::Split; using android::base::StringPrintf; using android::base::unique_fd; using android::base::WriteStringToFd; -using namespace simpleperf; - -namespace simpleperf { static const std::string kKprobeEventPrefix = "kprobes:"; diff --git a/simpleperf/SampleComparator.h b/simpleperf/SampleComparator.h index 7c2a53be..e13f2346 100644 --- a/simpleperf/SampleComparator.h +++ b/simpleperf/SampleComparator.h @@ -21,6 +21,8 @@ #include <vector> +namespace simpleperf { + // The compare functions below are used to compare two samples by their item // content. @@ -121,4 +123,6 @@ class SampleComparator { std::vector<compare_sample_func_t> compare_v_; }; +} // namespace simpleperf + #endif // SIMPLE_PERF_SAMPLE_COMPARATOR_H_ diff --git a/simpleperf/SampleDisplayer.h b/simpleperf/SampleDisplayer.h index 02165944..cc27a46c 100644 --- a/simpleperf/SampleDisplayer.h +++ b/simpleperf/SampleDisplayer.h @@ -25,6 +25,8 @@ #include <android-base/logging.h> #include <android-base/stringprintf.h> +namespace simpleperf { + // The display functions below are used to show items in a sample. template <typename EntryT, typename InfoT> @@ -278,4 +280,6 @@ class SampleDisplayer { bool report_csv_ = false; }; +} // namespace simpleperf + #endif // SIMPLE_PERF_SAMPLE_DISPLAYER_H_ diff --git a/simpleperf/build_id.h b/simpleperf/build_id.h index fabf0fb5..05acc266 100644 --- a/simpleperf/build_id.h +++ b/simpleperf/build_id.h @@ -21,6 +21,8 @@ #include <string.h> #include <algorithm> +namespace simpleperf { + constexpr size_t BUILD_ID_SIZE = 20; // Shared libraries can have a section called .note.gnu.build-id, containing @@ -86,4 +88,6 @@ inline std::ostream& operator<<(std::ostream& os, const BuildId& build_id) { return os; } +} // namespace simpleperf + #endif // SIMPLE_PERF_BUILD_ID_H_ diff --git a/simpleperf/callchain.h b/simpleperf/callchain.h index 96d1e688..0a9f173b 100644 --- a/simpleperf/callchain.h +++ b/simpleperf/callchain.h @@ -27,6 +27,8 @@ #include <android-base/logging.h> +namespace simpleperf { + template <typename EntryT> struct CallChainNode { uint64_t period; @@ -150,4 +152,6 @@ struct CallChainRoot { } }; +} // namespace simpleperf + #endif // SIMPLE_PERF_CALLCHAIN_H_ diff --git a/simpleperf/cmd_api.cpp b/simpleperf/cmd_api.cpp index 0bae4206..736f239c 100644 --- a/simpleperf/cmd_api.cpp +++ b/simpleperf/cmd_api.cpp @@ -35,9 +35,9 @@ #include "utils.h" #include "workload.h" -using namespace simpleperf; - +namespace simpleperf { namespace { + const std::string SIMPLEPERF_DATA_DIR = "simpleperf_data"; class PrepareCommand : public Command { @@ -207,8 +207,6 @@ bool CollectCommand::RemoveRecordingData() { } } // namespace -namespace simpleperf { - void RegisterAPICommands() { RegisterCommand("api-prepare", [] { return std::unique_ptr<Command>(new PrepareCommand()); }); RegisterCommand("api-collect", [] { return std::unique_ptr<Command>(new CollectCommand()); }); diff --git a/simpleperf/cmd_debug_unwind.cpp b/simpleperf/cmd_debug_unwind.cpp index 481e24f8..b2fd1a79 100644 --- a/simpleperf/cmd_debug_unwind.cpp +++ b/simpleperf/cmd_debug_unwind.cpp @@ -36,7 +36,8 @@ #include "utils.h" #include "workload.h" -using namespace simpleperf; +namespace simpleperf { +namespace { // Cache size used by CallChainJoiner to cache call chains in memory. constexpr size_t DEFAULT_CALL_CHAIN_JOINER_CACHE_SIZE = 8 * 1024 * 1024; @@ -404,7 +405,7 @@ void DebugUnwindCommand::PrintStat() { printf("Please use debug_unwind_reporter.py to get a report in details.\n"); } -namespace simpleperf { +} // namespace void RegisterDebugUnwindCommand() { RegisterCommand("debug-unwind", diff --git a/simpleperf/cmd_dumprecord.cpp b/simpleperf/cmd_dumprecord.cpp index a9f7dba0..8e8bcd21 100644 --- a/simpleperf/cmd_dumprecord.cpp +++ b/simpleperf/cmd_dumprecord.cpp @@ -36,11 +36,11 @@ #include "tracing.h" #include "utils.h" -using namespace simpleperf; -using namespace simpleperf::PerfFileFormat; - +namespace simpleperf { namespace { +using namespace PerfFileFormat; + struct SymbolInfo { Dso* dso; const Symbol* symbol; @@ -509,8 +509,6 @@ bool DumpRecordCommand::DumpFeatureSection() { } // namespace -namespace simpleperf { - void RegisterDumpRecordCommand() { RegisterCommand("dump", [] { return std::unique_ptr<Command>(new DumpRecordCommand); }); } diff --git a/simpleperf/cmd_help.cpp b/simpleperf/cmd_help.cpp index 8f45c62b..1c8cd631 100644 --- a/simpleperf/cmd_help.cpp +++ b/simpleperf/cmd_help.cpp @@ -22,7 +22,8 @@ #include "command.h" -using namespace simpleperf; +namespace simpleperf { +namespace { class HelpCommand : public Command { public: @@ -86,7 +87,7 @@ void HelpCommand::PrintLongHelpForOneCommand(const Command& command) { printf("%s\n", command.LongHelpString().c_str()); } -namespace simpleperf { +} // namespace void RegisterHelpCommand() { RegisterCommand("help", [] { return std::unique_ptr<Command>(new HelpCommand); }); diff --git a/simpleperf/cmd_inject.cpp b/simpleperf/cmd_inject.cpp index d0925731..a2b5b09b 100644 --- a/simpleperf/cmd_inject.cpp +++ b/simpleperf/cmd_inject.cpp @@ -31,8 +31,6 @@ #include "thread_tree.h" #include "utils.h" -using namespace simpleperf; - namespace simpleperf { std::string BranchToProtoString(const std::vector<bool>& branch) { @@ -56,8 +54,6 @@ std::vector<bool> ProtoStringToBranch(const std::string& s, size_t bit_size) { return branch; } -} // namespace simpleperf - namespace { using AddrPair = std::pair<uint64_t, uint64_t>; @@ -512,8 +508,6 @@ class InjectCommand : public Command { } // namespace -namespace simpleperf { - void RegisterInjectCommand() { return RegisterCommand("inject", [] { return std::unique_ptr<Command>(new InjectCommand); }); } diff --git a/simpleperf/cmd_kmem.cpp b/simpleperf/cmd_kmem.cpp index a4ff3d6f..98603969 100644 --- a/simpleperf/cmd_kmem.cpp +++ b/simpleperf/cmd_kmem.cpp @@ -29,6 +29,7 @@ #include "tracing.h" #include "utils.h" +namespace simpleperf { namespace { struct SlabSample { @@ -678,8 +679,6 @@ void KmemCommand::PrintSlabReportContext(FILE* fp) { } // namespace -namespace simpleperf { - void RegisterKmemCommand() { RegisterCommand("kmem", [] { return std::unique_ptr<Command>(new KmemCommand()); }); } diff --git a/simpleperf/cmd_list.cpp b/simpleperf/cmd_list.cpp index ceb04018..4966b9c6 100644 --- a/simpleperf/cmd_list.cpp +++ b/simpleperf/cmd_list.cpp @@ -30,8 +30,7 @@ #include "event_selection_set.h" #include "event_type.h" -using namespace simpleperf; - +namespace simpleperf { namespace { enum EventTypeStatus { @@ -214,8 +213,6 @@ void ListCommand::ShowFeatures() { } // namespace -namespace simpleperf { - void RegisterListCommand() { RegisterCommand("list", [] { return std::unique_ptr<Command>(new ListCommand); }); } diff --git a/simpleperf/cmd_merge.cpp b/simpleperf/cmd_merge.cpp index bf2848cc..9d413083 100644 --- a/simpleperf/cmd_merge.cpp +++ b/simpleperf/cmd_merge.cpp @@ -29,8 +29,7 @@ #include "thread_tree.h" #include "utils.h" -using namespace simpleperf; - +namespace simpleperf { namespace { class MergedFileFeature { @@ -419,8 +418,6 @@ class MergeCommand : public Command { } // namespace -namespace simpleperf { - void RegisterMergeCommand() { return RegisterCommand("merge", [] { return std::unique_ptr<Command>(new MergeCommand); }); } diff --git a/simpleperf/cmd_monitor.cpp b/simpleperf/cmd_monitor.cpp index 06eca5c8..6acce4db 100644 --- a/simpleperf/cmd_monitor.cpp +++ b/simpleperf/cmd_monitor.cpp @@ -53,12 +53,12 @@ #include "tracing.h" #include "utils.h" +namespace simpleperf { +namespace { + using android::base::ParseUint; using android::base::Realpath; using android::base::StringAppendF; -using namespace simpleperf; - -namespace { struct SymbolInfo { Dso* dso; @@ -592,8 +592,6 @@ bool MonitorCommand::UnwindRecord(SampleRecord& r) { } } // namespace -namespace simpleperf { - void RegisterMonitorCommand() { RegisterCommand("monitor", [] { return std::unique_ptr<Command>(new MonitorCommand()); }); } diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp index 60677a7c..18b80946 100644 --- a/simpleperf/cmd_record.cpp +++ b/simpleperf/cmd_record.cpp @@ -64,11 +64,11 @@ #include "utils.h" #include "workload.h" +namespace simpleperf { +namespace { + using android::base::ParseUint; using android::base::Realpath; -using namespace simpleperf; - -namespace { static std::string default_measured_event_type = "cpu-cycles"; @@ -1885,8 +1885,6 @@ void RecordCommand::CollectHitFileInfo(const SampleRecord& r) { } // namespace -namespace simpleperf { - static bool ConsumeStr(const char*& p, const char* s) { if (strncmp(p, s, strlen(s)) == 0) { p += strlen(s); diff --git a/simpleperf/cmd_report.cpp b/simpleperf/cmd_report.cpp index c77c47bc..399e4d82 100644 --- a/simpleperf/cmd_report.cpp +++ b/simpleperf/cmd_report.cpp @@ -41,10 +41,11 @@ #include "tracing.h" #include "utils.h" -using android::base::Split; - +namespace simpleperf { namespace { +using android::base::Split; + static std::set<std::string> branch_sort_keys = { "dso_from", "dso_to", @@ -962,8 +963,6 @@ void ReportCommand::PrintReportContext(FILE* report_fp) { } // namespace -namespace simpleperf { - void RegisterReportCommand() { RegisterCommand("report", [] { return std::unique_ptr<Command>(new ReportCommand()); }); } diff --git a/simpleperf/cmd_report_sample.cpp b/simpleperf/cmd_report_sample.cpp index 5d8c532b..51ae748b 100644 --- a/simpleperf/cmd_report_sample.cpp +++ b/simpleperf/cmd_report_sample.cpp @@ -34,11 +34,11 @@ #include "thread_tree.h" #include "utils.h" -using namespace simpleperf; -namespace proto = simpleperf_report_proto; - +namespace simpleperf { namespace { +namespace proto = simpleperf_report_proto; + static const char PROT_FILE_MAGIC[] = "SIMPLEPERF"; static const uint16_t PROT_FILE_VERSION = 1u; @@ -686,8 +686,6 @@ void ReportSampleCommand::PrintLostSituation() { } // namespace -namespace simpleperf { - void RegisterReportSampleCommand() { RegisterCommand("report-sample", [] { return std::unique_ptr<Command>(new ReportSampleCommand()); }); diff --git a/simpleperf/cmd_stat.cpp b/simpleperf/cmd_stat.cpp index b9139743..6a4fb1ab 100644 --- a/simpleperf/cmd_stat.cpp +++ b/simpleperf/cmd_stat.cpp @@ -44,11 +44,10 @@ #include "utils.h" #include "workload.h" -using android::base::Split; -using namespace simpleperf; - namespace simpleperf { +using android::base::Split; + static std::vector<std::string> default_measured_event_types{ "cpu-cycles", "stalled-cycles-frontend", "stalled-cycles-backend", "instructions", "branch-instructions", "branch-misses", @@ -293,8 +292,6 @@ std::string CounterSummaries::GetRateComment(const CounterSummary& s, char sep) return ""; } -} // namespace simpleperf - namespace { // devfreq may use performance counters to calculate memory latency (as in @@ -884,8 +881,6 @@ bool StatCommand::ShowCounters(const std::vector<CountersInfo>& counters, double } // namespace -namespace simpleperf { - void RegisterStatCommand() { RegisterCommand("stat", [] { return std::unique_ptr<Command>(new StatCommand); }); } diff --git a/simpleperf/cmd_trace_sched.cpp b/simpleperf/cmd_trace_sched.cpp index 42c49545..0fcabd28 100644 --- a/simpleperf/cmd_trace_sched.cpp +++ b/simpleperf/cmd_trace_sched.cpp @@ -32,11 +32,11 @@ #include "tracing.h" #include "utils.h" -using android::base::StringPrintf; -using namespace simpleperf; - +namespace simpleperf { namespace { +using android::base::StringPrintf; + struct SampleInfo { uint64_t timestamp; // the time when the kernel generates the sample uint64_t runtime_in_ns; // the runtime of the thread in the sample @@ -414,8 +414,6 @@ void TraceSchedCommand::ReportProcessInfo(const std::vector<ProcessInfo>& proces } // namespace -namespace simpleperf { - void RegisterTraceSchedCommand() { RegisterCommand("trace-sched", [] { return std::unique_ptr<Command>(new TraceSchedCommand()); }); } diff --git a/simpleperf/dso.cpp b/simpleperf/dso.cpp index fbff62b7..77a8b15f 100644 --- a/simpleperf/dso.cpp +++ b/simpleperf/dso.cpp @@ -38,9 +38,10 @@ #include "read_elf.h" #include "utils.h" +namespace simpleperf { + using android::base::EndsWith; using android::base::StartsWith; -using namespace simpleperf; namespace simpleperf_dso_impl { @@ -947,3 +948,5 @@ bool GetBuildIdFromDsoPath(const std::string& dso_path, BuildId* build_id) { } return false; } + +} // namespace simpleperf diff --git a/simpleperf/dso.h b/simpleperf/dso.h index e8577b2a..15a640dd 100644 --- a/simpleperf/dso.h +++ b/simpleperf/dso.h @@ -31,6 +31,7 @@ #include "kallsyms.h" #include "read_elf.h" +namespace simpleperf { namespace simpleperf_dso_impl { // Find elf files with symbol table and debug information. @@ -218,4 +219,6 @@ class Dso { const char* DsoTypeToString(DsoType dso_type); bool GetBuildIdFromDsoPath(const std::string& dso_path, BuildId* build_id); +} // namespace simpleperf + #endif // SIMPLE_PERF_DSO_H_ diff --git a/simpleperf/dso_test.cpp b/simpleperf/dso_test.cpp index 331353f8..02958ce6 100644 --- a/simpleperf/dso_test.cpp +++ b/simpleperf/dso_test.cpp @@ -27,6 +27,7 @@ #include "thread_tree.h" #include "utils.h" +using namespace simpleperf; using namespace simpleperf_dso_impl; TEST(DebugElfFileFinder, use_build_id_list) { diff --git a/simpleperf/environment.cpp b/simpleperf/environment.cpp index e373871c..e31163bb 100644 --- a/simpleperf/environment.cpp +++ b/simpleperf/environment.cpp @@ -50,7 +50,7 @@ #include "utils.h" #include "workload.h" -using namespace simpleperf; +namespace simpleperf { std::vector<int> GetOnlineCpus() { std::vector<int> result; @@ -915,3 +915,5 @@ std::optional<std::pair<int, int>> GetKernelVersion() { } return std::make_pair(major, minor); } + +} // namespace simpleperf diff --git a/simpleperf/environment.h b/simpleperf/environment.h index 67819d81..10715528 100644 --- a/simpleperf/environment.h +++ b/simpleperf/environment.h @@ -37,6 +37,8 @@ #include "build_id.h" #include "perf_regs.h" +namespace simpleperf { + std::vector<int> GetOnlineCpus(); struct KernelMmap { @@ -138,4 +140,6 @@ std::string GetCompleteProcessName(pid_t pid); const char* GetTraceFsDir(); +} // namespace simpleperf + #endif // SIMPLE_PERF_ENVIRONMENT_H_ diff --git a/simpleperf/environment_test.cpp b/simpleperf/environment_test.cpp index 0e89094b..88230346 100644 --- a/simpleperf/environment_test.cpp +++ b/simpleperf/environment_test.cpp @@ -27,6 +27,7 @@ #include "thread_tree.h" namespace fs = std::filesystem; +using namespace simpleperf; TEST(environment, PrepareVdsoFile) { std::string content; diff --git a/simpleperf/event_fd.cpp b/simpleperf/event_fd.cpp index d3eb1f6b..0343e156 100644 --- a/simpleperf/event_fd.cpp +++ b/simpleperf/event_fd.cpp @@ -38,6 +38,8 @@ #include "perf_event.h" #include "utils.h" +namespace simpleperf { + static int perf_event_open(const perf_event_attr& attr, pid_t pid, int cpu, int group_fd, unsigned long flags) { // NOLINT return syscall(__NR_perf_event_open, &attr, pid, cpu, group_fd, flags); @@ -322,3 +324,5 @@ bool EventFd::StopPolling() { bool IsEventAttrSupported(const perf_event_attr& attr, const std::string& event_name) { return EventFd::OpenEventFile(attr, getpid(), -1, nullptr, event_name, false) != nullptr; } + +} // namespace simpleperf diff --git a/simpleperf/event_fd.h b/simpleperf/event_fd.h index 2112978f..90791a53 100644 --- a/simpleperf/event_fd.h +++ b/simpleperf/event_fd.h @@ -28,6 +28,8 @@ #include "IOEventLoop.h" #include "perf_event.h" +namespace simpleperf { + struct PerfCounter { uint64_t value; // The value of the event specified by the perf_event_file. uint64_t time_enabled; // The enabled time. @@ -153,4 +155,6 @@ class EventFd { bool IsEventAttrSupported(const perf_event_attr& attr, const std::string& event_name); +} // namespace simpleperf + #endif // SIMPLE_PERF_EVENT_FD_H_ diff --git a/simpleperf/event_selection_set.cpp b/simpleperf/event_selection_set.cpp index dbf085f1..f1e9d3a0 100644 --- a/simpleperf/event_selection_set.cpp +++ b/simpleperf/event_selection_set.cpp @@ -35,10 +35,10 @@ #include "tracing.h" #include "utils.h" -using android::base::StringPrintf; - namespace simpleperf { +using android::base::StringPrintf; + bool IsBranchSamplingSupported() { const EventType* type = FindEventTypeByName("cpu-cycles"); if (type == nullptr) { diff --git a/simpleperf/get_test_data.h b/simpleperf/get_test_data.h index fc3c84c2..1ef663b9 100644 --- a/simpleperf/get_test_data.h +++ b/simpleperf/get_test_data.h @@ -21,6 +21,8 @@ #include "build_id.h" +using BuildId = simpleperf::BuildId; + std::string GetTestData(const std::string& filename); const std::string& GetTestDataDir(); diff --git a/simpleperf/nonlinux_support/nonlinux_support.cpp b/simpleperf/nonlinux_support/nonlinux_support.cpp index 65c82d3b..823b6e5d 100644 --- a/simpleperf/nonlinux_support/nonlinux_support.cpp +++ b/simpleperf/nonlinux_support/nonlinux_support.cpp @@ -21,6 +21,8 @@ #include "environment.h" #include "read_dex_file.h" +namespace simpleperf { + bool GetKernelBuildId(BuildId*) { return false; } @@ -43,8 +45,6 @@ const char* GetTraceFsDir() { return nullptr; } -namespace simpleperf { - class NoOpOfflineUnwinder : public OfflineUnwinder { public: bool UnwindCallChain(const ThreadEntry&, const RegSet&, const char*, size_t, diff --git a/simpleperf/perf_regs.cpp b/simpleperf/perf_regs.cpp index 114cb16c..cccd136f 100644 --- a/simpleperf/perf_regs.cpp +++ b/simpleperf/perf_regs.cpp @@ -25,6 +25,8 @@ #include "perf_event.h" +namespace simpleperf { + ArchType ScopedCurrentArch::current_arch = ARCH_UNSUPPORTED; ArchType GetArchType(const std::string& arch) { @@ -221,3 +223,5 @@ bool RegSet::GetIpRegValue(uint64_t* value) const { } return GetRegValue(regno, value); } + +} // namespace simpleperf diff --git a/simpleperf/perf_regs.h b/simpleperf/perf_regs.h index f5b30aa0..17e28a65 100644 --- a/simpleperf/perf_regs.h +++ b/simpleperf/perf_regs.h @@ -35,6 +35,8 @@ #include "perf_event.h" +namespace simpleperf { + enum ArchType { ARCH_X86_32, ARCH_X86_64, @@ -92,4 +94,6 @@ struct RegSet { bool GetIpRegValue(uint64_t* value) const; }; +} // namespace simpleperf + #endif // SIMPLE_PERF_PERF_REGS_H_ diff --git a/simpleperf/perf_regs_test.cpp b/simpleperf/perf_regs_test.cpp index c0977b29..fc75cca3 100644 --- a/simpleperf/perf_regs_test.cpp +++ b/simpleperf/perf_regs_test.cpp @@ -18,6 +18,8 @@ #include <gtest/gtest.h> +using namespace simpleperf; + TEST(RegSet, arch) { ArchType arch_pairs[2][2] = { {ARCH_X86_32, ARCH_X86_64}, diff --git a/simpleperf/read_apk.cpp b/simpleperf/read_apk.cpp index aeb2caf7..f5838397 100644 --- a/simpleperf/read_apk.cpp +++ b/simpleperf/read_apk.cpp @@ -33,6 +33,8 @@ #include "read_elf.h" #include "utils.h" +namespace simpleperf { + std::unordered_map<std::string, ApkInspector::ApkNode> ApkInspector::embedded_elf_cache_; EmbeddedElf* ApkInspector::FindElfInApkByOffset(const std::string& apk_path, uint64_t file_offset) { @@ -165,3 +167,5 @@ bool ParseExtractedInMemoryPath(const std::string& path, std::string* zip_path, } return false; } + +} // namespace simpleperf diff --git a/simpleperf/read_apk.h b/simpleperf/read_apk.h index 2296288c..baee2874 100644 --- a/simpleperf/read_apk.h +++ b/simpleperf/read_apk.h @@ -26,6 +26,8 @@ #include "read_elf.h" +namespace simpleperf { + // Container for info an on ELF file embedded into an APK file class EmbeddedElf { public: @@ -87,4 +89,6 @@ std::tuple<bool, std::string, std::string> SplitUrlInApk(const std::string& path bool ParseExtractedInMemoryPath(const std::string& path, std::string* zip_path, std::string* entry_name); +} // namespace simpleperf + #endif // SIMPLE_PERF_READ_APK_H_ diff --git a/simpleperf/read_apk_test.cpp b/simpleperf/read_apk_test.cpp index 80b58cd7..e4dd71f5 100644 --- a/simpleperf/read_apk_test.cpp +++ b/simpleperf/read_apk_test.cpp @@ -20,6 +20,8 @@ #include "get_test_data.h" #include "test_util.h" +using namespace simpleperf; + TEST(read_apk, FindElfInApkByOffset) { ApkInspector inspector; ASSERT_TRUE(inspector.FindElfInApkByOffset("/dev/null", 0) == nullptr); diff --git a/simpleperf/read_dex_file.cpp b/simpleperf/read_dex_file.cpp index 5644f7fc..055a4082 100644 --- a/simpleperf/read_dex_file.cpp +++ b/simpleperf/read_dex_file.cpp @@ -28,6 +28,8 @@ #include <android-base/unique_fd.h> #include <art_api/dex_file_support.h> +namespace simpleperf { + static bool ReadSymbols( const std::vector<uint64_t>& dex_file_offsets, std::vector<DexFileSymbol>* symbols, const std::function<std::unique_ptr<art_api::dex::DexFile>(uint64_t offset)>& open_file_cb) { @@ -96,3 +98,5 @@ bool ReadSymbolsFromDexFile(const std::string& file_path, return dex_file; }); } + +} // namespace simpleperf diff --git a/simpleperf/read_dex_file.h b/simpleperf/read_dex_file.h index 4563b3d0..ebddc87d 100644 --- a/simpleperf/read_dex_file.h +++ b/simpleperf/read_dex_file.h @@ -26,8 +26,10 @@ #include <art_api/dex_file_support.h> #endif +namespace simpleperf { + #ifndef NO_LIBDEXFILE_SUPPORT -typedef art_api::dex::MethodInfo DexFileSymbol; +using DexFileSymbol = art_api::dex::MethodInfo; #else struct DexFileSymbol { uint64_t offset; @@ -43,4 +45,6 @@ bool ReadSymbolsFromDexFile(const std::string& file_path, const std::vector<uint64_t>& dex_file_offsets, std::vector<DexFileSymbol>* symbols); +} // namespace simpleperf + #endif // SIMPLE_PERF_READ_DEX_FILE_H_ diff --git a/simpleperf/read_dex_file_test.cpp b/simpleperf/read_dex_file_test.cpp index 7e727689..3d0e900f 100644 --- a/simpleperf/read_dex_file_test.cpp +++ b/simpleperf/read_dex_file_test.cpp @@ -24,6 +24,8 @@ #include "test_util.h" #include "utils.h" +using namespace simpleperf; + TEST(read_dex_file, smoke) { std::vector<DexFileSymbol> symbols; ASSERT_TRUE(ReadSymbolsFromDexFile(GetTestData("base.vdex"), {0x28}, &symbols)); diff --git a/simpleperf/read_elf.cpp b/simpleperf/read_elf.cpp index ba88d148..2322db61 100644 --- a/simpleperf/read_elf.cpp +++ b/simpleperf/read_elf.cpp @@ -41,10 +41,10 @@ #include "JITDebugReader.h" #include "utils.h" -#define ELF_NOTE_GNU "GNU" -#define NT_GNU_BUILD_ID 3 +namespace simpleperf { -using namespace simpleperf; +const static char* ELF_NOTE_GNU = "GNU"; +const static int NT_GNU_BUILD_ID = 3; std::ostream& operator<<(std::ostream& os, const ElfStatus& status) { switch (status) { @@ -130,6 +130,16 @@ ElfStatus GetBuildIdFromNoteFile(const std::string& filename, BuildId* build_id) return ElfStatus::NO_ERROR; } +bool IsArmMappingSymbol(const char* name) { + // Mapping symbols in arm, which are described in "ELF for ARM Architecture" and + // "ELF for ARM 64-bit Architecture". The regular expression to match mapping symbol + // is ^\$(a|d|t|x)(\..*)?$ + return name[0] == '$' && strchr("adtx", name[1]) != nullptr && + (name[2] == '\0' || name[2] == '.'); +} + +namespace { + struct BinaryWrapper { std::unique_ptr<llvm::MemoryBuffer> buffer; std::unique_ptr<llvm::object::Binary> binary; @@ -187,14 +197,6 @@ static ElfStatus OpenObjectFileInMemory(const char* data, size_t size, BinaryWra return ElfStatus::NO_ERROR; } -bool IsArmMappingSymbol(const char* name) { - // Mapping symbols in arm, which are described in "ELF for ARM Architecture" and - // "ELF for ARM 64-bit Architecture". The regular expression to match mapping symbol - // is ^\$(a|d|t|x)(\..*)?$ - return name[0] == '$' && strchr("adtx", name[1]) != nullptr && - (name[2] == '\0' || name[2] == '.'); -} - void ReadSymbolTable(llvm::object::symbol_iterator sym_begin, llvm::object::symbol_iterator sym_end, const std::function<void(const ElfFileSymbol&)>& callback, bool is_arm, const llvm::object::section_iterator& section_end) { @@ -306,8 +308,6 @@ void CheckSymbolSections(const llvm::object::ELFObjectFile<ELFT>* elf, bool* has } } -namespace { - template <typename T> class ElfFileImpl {}; @@ -487,8 +487,6 @@ std::unique_ptr<ElfFile> CreateElfFileImpl(BinaryWrapper&& wrapper, ElfStatus* s } // namespace -namespace simpleperf { - std::unique_ptr<ElfFile> ElfFile::Open(const std::string& filename) { ElfStatus status; auto elf = Open(filename, &status); diff --git a/simpleperf/read_elf.h b/simpleperf/read_elf.h index c99350ff..bf5cb8b2 100644 --- a/simpleperf/read_elf.h +++ b/simpleperf/read_elf.h @@ -22,6 +22,12 @@ #include <string> #include "build_id.h" +namespace llvm { +class MemoryBuffer; +} + +namespace simpleperf { + // Read ELF functions are called in different situations, so it is hard to // decide whether to report error or not. So read ELF functions don't report // error when something wrong happens, instead they return ElfStatus, which @@ -55,12 +61,6 @@ struct ElfFileSymbol { ElfFileSymbol() : vaddr(0), len(0), is_func(false), is_label(false), is_in_text_section(false) {} }; -namespace llvm { -class MemoryBuffer; -} - -namespace simpleperf { - struct ElfSegment { uint64_t vaddr = 0; uint64_t file_offset = 0; @@ -106,11 +106,11 @@ class ElfFile { ElfFile() {} }; -} // namespace simpleperf - bool IsArmMappingSymbol(const char* name); ElfStatus IsValidElfFile(int fd, uint64_t file_offset = 0); bool IsValidElfFileMagic(const char* buf, size_t buf_size); bool GetBuildIdFromNoteSection(const char* section, size_t section_size, BuildId* build_id); +} // namespace simpleperf + #endif // SIMPLE_PERF_READ_ELF_H_ diff --git a/simpleperf/read_symbol_map.cpp b/simpleperf/read_symbol_map.cpp index f40fc2e0..15d59e06 100644 --- a/simpleperf/read_symbol_map.cpp +++ b/simpleperf/read_symbol_map.cpp @@ -28,7 +28,6 @@ #include "dso.h" namespace simpleperf { - namespace { std::optional<std::string_view> ConsumeWord(std::string_view& content_ref) { diff --git a/simpleperf/read_symbol_map.h b/simpleperf/read_symbol_map.h index 733df4ad..dea22eb5 100644 --- a/simpleperf/read_symbol_map.h +++ b/simpleperf/read_symbol_map.h @@ -16,13 +16,13 @@ #pragma once -#include "dso.h" - #include <string> #include <vector> #include <android-base/file.h> +#include "dso.h" + namespace simpleperf { std::vector<Symbol> ReadSymbolMapFromString(const std::string& content); diff --git a/simpleperf/read_symbol_map_test.cpp b/simpleperf/read_symbol_map_test.cpp index 1f668719..234bea8c 100644 --- a/simpleperf/read_symbol_map_test.cpp +++ b/simpleperf/read_symbol_map_test.cpp @@ -23,9 +23,7 @@ #include "dso.h" -namespace simpleperf { - -namespace { +using namespace simpleperf; TEST(read_symbol_map, smoke) { std::string content( @@ -56,7 +54,3 @@ TEST(read_symbol_map, smoke) { ASSERT_EQ(0x30, symbols[2].len); ASSERT_STREQ("three", symbols[2].Name()); } - -} // namespace - -} // namespace simpleperf diff --git a/simpleperf/record.cpp b/simpleperf/record.cpp index c44b6f64..50c31a9e 100644 --- a/simpleperf/record.cpp +++ b/simpleperf/record.cpp @@ -29,7 +29,7 @@ #include "tracing.h" #include "utils.h" -using namespace simpleperf; +namespace simpleperf { static std::string RecordTypeToString(int record_type) { static std::unordered_map<int, std::string> record_type_names = { @@ -1362,3 +1362,5 @@ std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, char* auto header = reinterpret_cast<const perf_event_header*>(p); return ReadRecordFromBuffer(attr, header->type, p); } + +} // namespace simpleperf diff --git a/simpleperf/record.h b/simpleperf/record.h index 26a1dbea..db5610f4 100644 --- a/simpleperf/record.h +++ b/simpleperf/record.h @@ -32,6 +32,8 @@ #include "build_id.h" #include "perf_event.h" +namespace simpleperf { + enum user_record_type { PERF_RECORD_USER_DEFINED_TYPE_START = 64, PERF_RECORD_ATTR = 64, @@ -632,4 +634,6 @@ std::vector<std::unique_ptr<Record>> ReadRecordsFromBuffer(const perf_event_attr // own the buffer. std::unique_ptr<Record> ReadRecordFromBuffer(const perf_event_attr& attr, char* p); +} // namespace simpleperf + #endif // SIMPLE_PERF_RECORD_H_ diff --git a/simpleperf/record_equal_test.h b/simpleperf/record_equal_test.h index 40157edd..8e27e1ea 100644 --- a/simpleperf/record_equal_test.h +++ b/simpleperf/record_equal_test.h @@ -14,6 +14,8 @@ * limitations under the License. */ +namespace simpleperf { + static void CheckMmapRecordDataEqual(const MmapRecord& r1, const MmapRecord& r2) { ASSERT_EQ(0, memcmp(r1.data, r2.data, sizeof(*r1.data))); ASSERT_STREQ(r1.filename, r2.filename); @@ -96,3 +98,5 @@ static void CheckRecordEqual(const Record& r1, const Record& r2) { static_cast<const BuildIdRecord&>(r2)); } } + +} // namespace simpleperf diff --git a/simpleperf/report_lib_interface.cpp b/simpleperf/report_lib_interface.cpp index 841d1aa9..6f39db46 100644 --- a/simpleperf/report_lib_interface.cpp +++ b/simpleperf/report_lib_interface.cpp @@ -31,14 +31,8 @@ #include "tracing.h" #include "utils.h" -using namespace simpleperf; - -class ReportLib; - extern "C" { -#define EXPORT __attribute__((visibility("default"))) - struct Sample { uint64_t ip; uint32_t pid; @@ -100,30 +94,9 @@ struct FeatureSection { uint32_t data_size; }; -// Create a new instance, -// pass the instance to the other functions below. -ReportLib* CreateReportLib() EXPORT; -void DestroyReportLib(ReportLib* report_lib) EXPORT; +} // extern "C" -// Set log severity, different levels are: -// verbose, debug, info, warning, error, fatal. -bool SetLogSeverity(ReportLib* report_lib, const char* log_level) EXPORT; -bool SetSymfs(ReportLib* report_lib, const char* symfs_dir) EXPORT; -bool SetRecordFile(ReportLib* report_lib, const char* record_file) EXPORT; -bool SetKallsymsFile(ReportLib* report_lib, const char* kallsyms_file) EXPORT; -void ShowIpForUnknownSymbol(ReportLib* report_lib) EXPORT; -void ShowArtFrames(ReportLib* report_lib, bool show) EXPORT; -void MergeJavaMethods(ReportLib* report_lib, bool merge) EXPORT; - -Sample* GetNextSample(ReportLib* report_lib) EXPORT; -Event* GetEventOfCurrentSample(ReportLib* report_lib) EXPORT; -SymbolEntry* GetSymbolOfCurrentSample(ReportLib* report_lib) EXPORT; -CallChain* GetCallChainOfCurrentSample(ReportLib* report_lib) EXPORT; -const char* GetTracingDataOfCurrentSample(ReportLib* report_lib) EXPORT; - -const char* GetBuildIdForPath(ReportLib* report_lib, const char* path) EXPORT; -FeatureSection* GetFeatureSection(ReportLib* report_lib, const char* feature_name) EXPORT; -} +namespace simpleperf { struct EventInfo { perf_event_attr attr; @@ -418,6 +391,39 @@ FeatureSection* ReportLib::GetFeatureSection(const char* feature_name) { return &feature_section_; } +} // namespace simpleperf + +using ReportLib = simpleperf::ReportLib; + +extern "C" { + +#define EXPORT __attribute__((visibility("default"))) + +// Create a new instance, +// pass the instance to the other functions below. +ReportLib* CreateReportLib() EXPORT; +void DestroyReportLib(ReportLib* report_lib) EXPORT; + +// Set log severity, different levels are: +// verbose, debug, info, warning, error, fatal. +bool SetLogSeverity(ReportLib* report_lib, const char* log_level) EXPORT; +bool SetSymfs(ReportLib* report_lib, const char* symfs_dir) EXPORT; +bool SetRecordFile(ReportLib* report_lib, const char* record_file) EXPORT; +bool SetKallsymsFile(ReportLib* report_lib, const char* kallsyms_file) EXPORT; +void ShowIpForUnknownSymbol(ReportLib* report_lib) EXPORT; +void ShowArtFrames(ReportLib* report_lib, bool show) EXPORT; +void MergeJavaMethods(ReportLib* report_lib, bool merge) EXPORT; + +Sample* GetNextSample(ReportLib* report_lib) EXPORT; +Event* GetEventOfCurrentSample(ReportLib* report_lib) EXPORT; +SymbolEntry* GetSymbolOfCurrentSample(ReportLib* report_lib) EXPORT; +CallChain* GetCallChainOfCurrentSample(ReportLib* report_lib) EXPORT; +const char* GetTracingDataOfCurrentSample(ReportLib* report_lib) EXPORT; + +const char* GetBuildIdForPath(ReportLib* report_lib, const char* path) EXPORT; +FeatureSection* GetFeatureSection(ReportLib* report_lib, const char* feature_name) EXPORT; +} + // Exported methods working with a client created instance ReportLib* CreateReportLib() { return new ReportLib(); diff --git a/simpleperf/sample_tree.h b/simpleperf/sample_tree.h index 3e5936af..4d5152fb 100644 --- a/simpleperf/sample_tree.h +++ b/simpleperf/sample_tree.h @@ -27,7 +27,7 @@ #include "record.h" #include "thread_tree.h" -using namespace simpleperf; +namespace simpleperf { // A SampleTree is a collection of samples. A profiling report is mainly about // constructing a SampleTree and display it. There are three steps involved: @@ -346,4 +346,6 @@ class SampleTreeDisplayer { SampleDisplayer<EntryT, InfoT> displayer_; }; +} // namespace simpleperf + #endif // SIMPLE_PERF_SAMPLE_TREE_H_ diff --git a/simpleperf/sample_tree_test.cpp b/simpleperf/sample_tree_test.cpp index 56f4a7e7..bee187d7 100644 --- a/simpleperf/sample_tree_test.cpp +++ b/simpleperf/sample_tree_test.cpp @@ -19,6 +19,8 @@ #include "sample_tree.h" #include "thread_tree.h" +using namespace simpleperf; + namespace { struct SampleEntry { diff --git a/simpleperf/test_util.h b/simpleperf/test_util.h index 8c4a41c3..d3d9b469 100644 --- a/simpleperf/test_util.h +++ b/simpleperf/test_util.h @@ -24,8 +24,11 @@ #include "environment.h" #include "read_elf.h" +#include "utils.h" #include "workload.h" +using namespace simpleperf; + static const std::string SLEEP_SEC = "0.001"; void RunWorkloadFunction(); @@ -34,8 +37,6 @@ void CreateProcesses(size_t count, std::vector<std::unique_ptr<Workload>>* workl void ParseSymbol(const ElfFileSymbol& symbol, std::map<std::string, ElfFileSymbol>* symbols); void CheckElfFileSymbols(const std::map<std::string, ElfFileSymbol>& symbols); -bool IsRoot(); - #define TEST_IN_ROOT(TestStatement) \ do { \ if (IsRoot()) { \ diff --git a/simpleperf/thread_tree.cpp b/simpleperf/thread_tree.cpp index b7389372..9aad38bc 100644 --- a/simpleperf/thread_tree.cpp +++ b/simpleperf/thread_tree.cpp @@ -30,7 +30,6 @@ #include "utils.h" namespace simpleperf { - namespace { // Real map file path depends on where the process can create files. diff --git a/simpleperf/thread_tree.h b/simpleperf/thread_tree.h index d2a365f9..4003fda5 100644 --- a/simpleperf/thread_tree.h +++ b/simpleperf/thread_tree.h @@ -26,13 +26,13 @@ #include "dso.h" +namespace simpleperf { + struct Record; constexpr char DEFAULT_KERNEL_MMAP_NAME[] = "[kernel.kallsyms]"; constexpr char DEFAULT_EXECNAME_FOR_THREAD_MMAP[] = "//anon"; -namespace simpleperf { - namespace map_flags { constexpr uint32_t PROT_JIT_SYMFILE_MAP = 0x4000; } // namespace map_flags @@ -170,8 +170,4 @@ class ThreadTree { } // namespace simpleperf -using MapEntry = simpleperf::MapEntry; -using ThreadEntry = simpleperf::ThreadEntry; -using ThreadTree = simpleperf::ThreadTree; - #endif // SIMPLE_PERF_THREAD_TREE_H_ diff --git a/simpleperf/tracing.cpp b/simpleperf/tracing.cpp index 08a63353..cb6a862c 100644 --- a/simpleperf/tracing.cpp +++ b/simpleperf/tracing.cpp @@ -38,6 +38,8 @@ using android::base::Split; using android::base::StartsWith; +namespace simpleperf { + template <> void MoveFromBinaryFormat(std::string& data, const char*& p) { data.clear(); @@ -47,8 +49,6 @@ void MoveFromBinaryFormat(std::string& data, const char*& p) { p++; } -namespace simpleperf { - const char TRACING_INFO_MAGIC[10] = {23, 8, 68, 't', 'r', 'a', 'c', 'i', 'n', 'g'}; template <class T> @@ -147,7 +147,7 @@ TracingFile::TracingFile() { version = "0.5"; endian = 0; size_of_long = static_cast<int>(sizeof(long)); // NOLINT(google-runtime-int) - page_size = static_cast<uint32_t>(::GetPageSize()); + page_size = static_cast<uint32_t>(simpleperf::GetPageSize()); } bool TracingFile::RecordHeaderFiles() { diff --git a/simpleperf/utils.cpp b/simpleperf/utils.cpp index 387c3453..b89f21a5 100644 --- a/simpleperf/utils.cpp +++ b/simpleperf/utils.cpp @@ -40,6 +40,8 @@ #include <Xz.h> #include <XzCrc64.h> +namespace simpleperf { + using android::base::ParseInt; using android::base::Split; using android::base::StringPrintf; @@ -430,3 +432,5 @@ std::optional<std::set<pid_t>> GetTidsFromString(const std::string& s, bool chec } return tids; } + +} // namespace simpleperf diff --git a/simpleperf/utils.h b/simpleperf/utils.h index c041f9bd..1e3b52b3 100644 --- a/simpleperf/utils.h +++ b/simpleperf/utils.h @@ -32,6 +32,8 @@ #include <android-base/unique_fd.h> #include <ziparchive/zip_archive.h> +namespace simpleperf { + static inline uint64_t AlignDown(uint64_t value, uint64_t alignment) { return value & ~(alignment - 1); } @@ -178,14 +180,12 @@ std::string GetSimpleperfVersion(); std::optional<std::set<int>> GetCpusFromString(const std::string& s); std::optional<std::set<pid_t>> GetTidsFromString(const std::string& s, bool check_if_exists); -namespace { - // from boost::hash_combine template <typename T> -void HashCombine(size_t& seed, const T& val) { +static inline void HashCombine(size_t& seed, const T& val) { seed ^= std::hash<T>()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2); } -} // namespace +} // namespace simpleperf #endif // SIMPLE_PERF_UTILS_H_ diff --git a/simpleperf/utils_test.cpp b/simpleperf/utils_test.cpp index 27941a4b..78548622 100644 --- a/simpleperf/utils_test.cpp +++ b/simpleperf/utils_test.cpp @@ -19,6 +19,8 @@ #include "get_test_data.h" #include "utils.h" +using namespace simpleperf; + TEST(utils, ConvertBytesToValue) { char buf[8]; for (int i = 0; i < 8; ++i) { diff --git a/simpleperf/workload.cpp b/simpleperf/workload.cpp index 6fd55108..e82e47b6 100644 --- a/simpleperf/workload.cpp +++ b/simpleperf/workload.cpp @@ -25,6 +25,8 @@ #include <android-base/logging.h> #include <android-base/strings.h> +namespace simpleperf { + std::unique_ptr<Workload> Workload::CreateWorkload(const std::vector<std::string>& args) { std::unique_ptr<Workload> workload(new Workload(args, std::function<void()>())); if (workload != nullptr && workload->CreateNewProcess()) { @@ -202,3 +204,5 @@ bool Workload::WaitChildProcess(bool wait_forever, bool is_child_killed, int* ex } return finished; } + +} // namespace simpleperf diff --git a/simpleperf/workload.h b/simpleperf/workload.h index cfb5fece..22718a99 100644 --- a/simpleperf/workload.h +++ b/simpleperf/workload.h @@ -25,6 +25,8 @@ #include <android-base/macros.h> +namespace simpleperf { + class Workload { private: enum WorkState { @@ -71,4 +73,6 @@ class Workload { DISALLOW_COPY_AND_ASSIGN(Workload); }; +} // namespace simpleperf + #endif // SIMPLE_PERF_WORKLOAD_H_ diff --git a/simpleperf/workload_test.cpp b/simpleperf/workload_test.cpp index 33d1c3e2..f99ec753 100644 --- a/simpleperf/workload_test.cpp +++ b/simpleperf/workload_test.cpp @@ -22,6 +22,8 @@ #include "utils.h" #include "workload.h" +using namespace simpleperf; + TEST(workload, success) { IOEventLoop loop; ASSERT_TRUE(loop.AddSignalEvent(SIGCHLD, [&]() { return loop.ExitLoop(); })); |