diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 8882afac..a5dc11f3 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -14,7 +14,6 @@ jobs: compiler: [g++-9, g++-10, clang++-10, clang++-11, clang++-12] build-type: [Debug, RelWithDebInfo] hw_breakpoint: [ON, OFF] - perf_record_switch: [ON, OFF] perf_clockid: [ON, OFF] runs-on: ${{ matrix.os }} @@ -43,7 +42,7 @@ jobs: - name: Run CMake configure env: CXX: ${{ matrix.compiler }} - run: cmake . -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} -DUSE_HW_BREAKPOINT_COMPAT=${{ matrix.hw_breakpoint }} -DUSE_PERF_CLOCKID=${{ matrix.perf_clockid }} -DUSE_PERF_RECORD_SWITCH=${{ matrix.perf_record_switch }} + run: cmake . -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} -DUSE_HW_BREAKPOINT_COMPAT=${{ matrix.hw_breakpoint }} -DUSE_PERF_CLOCKID=${{ matrix.perf_clockid }} - name: Build run: make -j 2 - name: Create source tarball diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d99401b..3663433c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,16 +111,12 @@ if(PkgConfig_FOUND) endif() -CHECK_STRUCT_HAS_BITFIELD("struct perf_event_attr" context_switch linux/perf_event.h HAVE_PERF_RECORD_SWITCH) - # configurable options CMAKE_DEPENDENT_OPTION(USE_RADARE "Enable Radare support." ON "Radare_FOUND" OFF) option(USE_HW_BREAKPOINT_COMPAT "Time synchronization fallback for old kernels without hardware breakpoint support." OFF) add_feature_info("USE_HW_BREAKPOINT_COMPAT" USE_HW_BREAKPOINT_COMPAT "Time synchronization fallback for old kernels without hardware breakpoint support.") option(USE_PERF_CLOCKID "Enables specifying a custom reference clock for recorded events" ON) add_feature_info("USE_PERF_CLOCKID" USE_PERF_CLOCKID "Enables specifying a custom reference clock for recorded events") -CMAKE_DEPENDENT_OPTION(USE_PERF_RECORD_SWITCH "Uses PERF_RECORD_SWITCH for CPU Context Switches instead of the older tracepoint based solution" ON HAVE_PERF_RECORD_SWITCH OFF) -add_feature_info("USE_PERF_RECORD_SWITCH" USE_PERF_RECORD_SWITCH "Uses PERF_RECORD_SWITCH for CPU Context Switches instead of the older tracepoint based solution") option(IWYU "Developer option for include what you use." OFF) option(UML_LOOK "Generate graphs with an UML look" OFF) add_feature_info("USE_RADARE" USE_RADARE "Use Radare to add instruction information to samples.") @@ -139,6 +135,12 @@ if(NOT CLOCK_GETTIME_FOUND) unset(CMAKE_REQUIRED_LIBRARIES) endif() +CHECK_STRUCT_HAS_BITFIELD("struct perf_event_attr" context_switch linux/perf_event.h HAVE_PERF_RECORD_SWITCH) + +if(NOT HAVE_PERF_RECORD_SWITCH) + message(FATAL_ERROR "lo2s requires support for perf context switch recording. Make sure that you are running on a kernel that support context_switch with perf_event_open") +endif() + # detect version of running kernel string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" LINUX_VERSION ${CMAKE_SYSTEM_VERSION}) @@ -337,10 +339,6 @@ else() endif() endif() -if(NOT USE_PERF_RECORD_SWITCH) - target_sources(lo2s PRIVATE src/perf/tracepoint/switch_writer.cpp) -endif() - configure_file(include/lo2s/build_config.hpp.in include/lo2s/build_config.hpp) # define include directory of target lo2s diff --git a/include/lo2s/build_config.hpp.in b/include/lo2s/build_config.hpp.in index 13fcd32c..58a60a21 100644 --- a/include/lo2s/build_config.hpp.in +++ b/include/lo2s/build_config.hpp.in @@ -34,6 +34,4 @@ #cmakedefine USE_PERF_CLOCKID -#cmakedefine USE_PERF_RECORD_SWITCH - #cmakedefine LO2S_COPYRIGHT_YEAR "@LO2S_COPYRIGHT_YEAR@" diff --git a/include/lo2s/monitor/scope_monitor.hpp b/include/lo2s/monitor/scope_monitor.hpp index d1f4861a..f68cd6e7 100644 --- a/include/lo2s/monitor/scope_monitor.hpp +++ b/include/lo2s/monitor/scope_monitor.hpp @@ -30,10 +30,6 @@ #include #include -#ifndef USE_PERF_RECORD_SWITCH -#include -#endif - #include #include #include @@ -78,9 +74,6 @@ class ScopeMonitor : public PollMonitor std::unique_ptr sample_writer_; std::unique_ptr group_counter_writer_; std::unique_ptr userspace_counter_writer_; -#ifndef USE_PERF_RECORD_SWITCH - std::unique_ptr switch_writer_; -#endif }; } // namespace monitor } // namespace lo2s diff --git a/include/lo2s/perf/event_reader.hpp b/include/lo2s/perf/event_reader.hpp index aef04211..53f49706 100644 --- a/include/lo2s/perf/event_reader.hpp +++ b/include/lo2s/perf/event_reader.hpp @@ -194,14 +194,12 @@ class EventReader case PERF_RECORD_MMAP2: stop = crtp_this->handle((const RecordMmap2Type*)event_header_p); break; -#ifdef USE_PERF_RECORD_SWITCH case PERF_RECORD_SWITCH: stop = crtp_this->handle((const RecordSwitchType*)event_header_p); break; case PERF_RECORD_SWITCH_CPU_WIDE: stop = crtp_this->handle((const RecordSwitchCpuWideType*)event_header_p); break; -#endif case PERF_RECORD_THROTTLE: /* fall-through */ case PERF_RECORD_UNTHROTTLE: throttle_samples++; diff --git a/include/lo2s/perf/sample/reader.hpp b/include/lo2s/perf/sample/reader.hpp index b5032465..4d0ac5a9 100644 --- a/include/lo2s/perf/sample/reader.hpp +++ b/include/lo2s/perf/sample/reader.hpp @@ -123,10 +123,8 @@ class Reader : public EventReader // name of a task. This is used to write a meaningful name for any // traced thread to the archive. perf_attr.comm = 1; - -#ifdef USE_PERF_RECORD_SWITCH perf_attr.context_switch = 1; -#endif + // We need this to get all mmap_events if (enable_on_exec) { diff --git a/include/lo2s/perf/sample/writer.hpp b/include/lo2s/perf/sample/writer.hpp index c4070634..784c648a 100644 --- a/include/lo2s/perf/sample/writer.hpp +++ b/include/lo2s/perf/sample/writer.hpp @@ -66,10 +66,8 @@ class Writer : public Reader bool handle(const Reader::RecordSampleType* sample); bool handle(const Reader::RecordMmapType* mmap_event); bool handle(const Reader::RecordCommType* comm); -#ifdef USE_PERF_RECORD_SWITCH bool handle(const Reader::RecordSwitchCpuWideType* context_switch); bool handle(const Reader::RecordSwitchType* context_switch); -#endif void end(); diff --git a/include/lo2s/perf/tracepoint/switch_writer.hpp b/include/lo2s/perf/tracepoint/switch_writer.hpp deleted file mode 100644 index ee92aaa2..00000000 --- a/include/lo2s/perf/tracepoint/switch_writer.hpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * This file is part of the lo2s software. - * Linux OTF2 sampling - * - * Copyright (c) 2017, - * Technische Universitaet Dresden, Germany - * - * lo2s is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * lo2s is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with lo2s. If not, see . - */ - -#pragma once - -#include - -#include - -#include -#include -#include -#include - -#include -#include -#include - -extern "C" -{ -#include -} - -namespace lo2s -{ -namespace perf -{ -namespace tracepoint -{ -class SwitchWriter : public Reader -{ -public: - SwitchWriter(Cpu cpu, trace::Trace& trace); - ~SwitchWriter(); - -public: - using Reader::handle; - - bool handle(const Reader::RecordSampleType* sample); - -private: - otf2::writer::local& otf2_writer_; - const time::Converter time_converter_; - - CallingContextManager cctx_manager_; - - EventField prev_pid_field_; - EventField next_pid_field_; - EventField prev_state_field_; - - otf2::chrono::time_point last_time_point_ = otf2::chrono::genesis(); -}; -} // namespace tracepoint -} // namespace perf -} // namespace lo2s diff --git a/src/monitor/scope_monitor.cpp b/src/monitor/scope_monitor.cpp index f21f3c46..c97c3d1b 100644 --- a/src/monitor/scope_monitor.cpp +++ b/src/monitor/scope_monitor.cpp @@ -45,11 +45,7 @@ namespace monitor ScopeMonitor::ScopeMonitor(ExecutionScope scope, MainMonitor& parent, bool enable_on_exec) : PollMonitor(parent.trace(), scope.name(), config().perf_read_interval), scope_(scope) { -#ifndef USE_PERF_RECORD_SWITCH - if (config().sampling) -#else if (config().sampling || scope.is_cpu()) -#endif { sample_writer_ = std::make_unique(scope, parent, parent.trace(), enable_on_exec); @@ -76,14 +72,6 @@ ScopeMonitor::ScopeMonitor(ExecutionScope scope, MainMonitor& parent, bool enabl add_fd(userspace_counter_writer_->fd()); } -#ifndef USE_PERF_RECORD_SWITCH - if (scope.is_cpu()) - { - switch_writer_ = - std::make_unique(scope.as_cpu(), parent.trace()); - } -#endif - // note: start() can now be called } @@ -128,12 +116,6 @@ void ScopeMonitor::monitor(int fd) { userspace_counter_writer_->read(); } -#ifndef USE_PERF_RECORD_SWITCH - if (switch_writer_ && (fd == timer_pfd().fd || fd == stop_pfd().fd)) - { - switch_writer_->read(); - } -#endif } } // namespace monitor } // namespace lo2s diff --git a/src/perf/sample/writer.cpp b/src/perf/sample/writer.cpp index 3441887f..0bd19c2b 100644 --- a/src/perf/sample/writer.cpp +++ b/src/perf/sample/writer.cpp @@ -154,7 +154,6 @@ otf2::chrono::time_point Writer::adjust_timepoints(otf2::chrono::time_point tp) return tp; } -#ifdef USE_PERF_RECORD_SWITCH bool Writer::handle(const Reader::RecordSwitchCpuWideType* context_switch) { assert(scope_.is_cpu()); @@ -210,7 +209,6 @@ void Writer::update_calling_context(Process process, Thread thread, otf2::chrono } } -#endif bool Writer::handle(const Reader::RecordCommType* comm) { if (!scope_.is_cpu()) diff --git a/src/perf/tracepoint/switch_writer.cpp b/src/perf/tracepoint/switch_writer.cpp deleted file mode 100644 index 037b9546..00000000 --- a/src/perf/tracepoint/switch_writer.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* - * This file is part of the lo2s software. - * Linux OTF2 sampling - * - * Copyright (c) 2017, - * Technische Universitaet Dresden, Germany - * - * lo2s is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * lo2s is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with lo2s. If not, see . - */ - -#include - -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace lo2s -{ -namespace perf -{ -namespace tracepoint -{ - -static const EventFormat& get_sched_switch_event() -{ - static EventFormat evt("sched/sched_switch"); - return evt; -} - -SwitchWriter::SwitchWriter(Cpu cpu, trace::Trace& trace) -try : Reader(cpu, get_sched_switch_event().id()), otf2_writer_(trace.switch_writer(cpu.as_scope())), - time_converter_(time::Converter::instance()), cctx_manager_(trace), - prev_pid_field_(get_sched_switch_event().field("prev_pid")), - next_pid_field_(get_sched_switch_event().field("next_pid")), - prev_state_field_(get_sched_switch_event().field("prev_state")) -{ -} -// NOTE: function-try-block is intentional; catch get_sched_switch_event() -// throwing in constructor initializers if sched/sched_switch tracepoint -// event is unavailable. -catch (const EventFormat::ParseError& e) -{ - Log::error() << "Failed to open scheduler switch tracepoint event: " << e.what(); - throw std::runtime_error("Failed to open tracepoint switch writer"); -} - -SwitchWriter::~SwitchWriter() -{ - if (!cctx_manager_.current().is_undefined()) - { - otf2_writer_.write_calling_context_leave(std::max(last_time_point_, lo2s::time::now()), - cctx_manager_.current()); - } - - cctx_manager_.finalize(&otf2_writer_); -} - -bool SwitchWriter::handle(const Reader::RecordSampleType* sample) -{ - auto tp = time_converter_(sample->time); - Process prev_process = Process(sample->raw_data.get(prev_pid_field_)); - Process next_process = Process(sample->raw_data.get(next_pid_field_)); - - if (!cctx_manager_.thread_changed(next_process.as_thread())) - { - return false; - } - if (!cctx_manager_.current().is_undefined()) - { - otf2_writer_.write_calling_context_leave(tp, cctx_manager_.current()); - cctx_manager_.thread_leave(prev_process.as_thread()); - } - - cctx_manager_.thread_enter(Process::invalid(), next_process.as_thread()); - - otf2_writer_.write_calling_context_enter(tp, cctx_manager_.current(), 2); - - last_time_point_ = tp; - - if (next_process != Process::idle()) - { - summary().register_process(next_process); - } - return false; -} - -} // namespace tracepoint -} // namespace perf -} // namespace lo2s