diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 7e6ec145..c166b3c4 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -38,3 +38,8 @@ jobs: with: overwrite: true path: lo2s*.tar.bz2 + - name: Test + if: ${{ matrix.compiler == 'g++-12' && matrix.os == 'ubuntu-24.04' && matrix.build-type == 'RelWithDebInfo' && matrix.hw_breakpoint == 'ON' && github.event_name != 'pull_request'}} + run: | + sudo sysctl kernel.perf_event_paranoid=-1 + ctest --output-on-failure diff --git a/CMakeLists.txt b/CMakeLists.txt index ee5439a6..3437ec3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,9 @@ include(cmake/UnsetIfUpdated.cmake) include(cmake/CheckNameExists.cmake) include(cmake/CheckStructHasBitField.cmake) +enable_testing() +include(cmake/Tests.cmake) + # Intialize git submodules if not done already include(cmake/GitSubmoduleUpdate.cmake) git_submodule_update() @@ -190,6 +193,9 @@ set(SOURCE_FILES src/perf/event_resolver.cpp src/perf/event_attr.cpp + src/monitor/socket_monitor.cpp + src/monitor/ringbuf_monitor.cpp + src/perf/bio/block_device.cpp src/perf/event_composer.cpp @@ -343,6 +349,15 @@ if (USE_LIBAUDIT) endif() endif() +add_executable(rb_test src/cupti/test.cpp) +target_include_directories(rb_test PRIVATE include ${CMAKE_CURRENT_BINARY_DIR}/include) + target_link_libraries(rb_test PRIVATE fmt::fmt + Nitro::log + Nitro::env + Nitro::dl + Nitro::options + otf2xx::Writer) + set(LO2S_CUDA_INJECTIONLIB_PATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/liblo2s_injection.so") if(USE_CUPTI) if(CUDAToolkit_FOUND) diff --git a/cmake/Tests.cmake b/cmake/Tests.cmake new file mode 100644 index 00000000..ed0c6c75 --- /dev/null +++ b/cmake/Tests.cmake @@ -0,0 +1,7 @@ +set(TESTS lo2s_user_sampling) + +foreach(TEST ${TESTS}) + + add_test(NAME ${TEST} COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/cmake/tests/${TEST}.sh) + set_tests_properties(${TEST} PROPERTIES SKIP_RETURN_CODE 100) +endforeach() diff --git a/cmake/tests/lo2s_user_sampling.sh b/cmake/tests/lo2s_user_sampling.sh new file mode 100644 index 00000000..6d4f1769 --- /dev/null +++ b/cmake/tests/lo2s_user_sampling.sh @@ -0,0 +1,24 @@ +set -euo pipefail + +paranoid=$(cat /proc/sys/kernel/perf_event_paranoid) + +echo "perf_event_paranoid is: $paranoid" +if [ $paranoid -gt 2 ] +then + # skip + exit 100 +fi + +#!/bin/bash +rm -rf test_trace +./lo2s -c 1 --output-trace test_trace -- sleep 1 + +if otf2-print test_trace/traces.otf2 | grep "SAMPLE" +then + exit 0 +else + echo "Trace did not contain calling context samples!" + exit 1 +fi +rm -rf test_trace + diff --git a/include/lo2s/config.hpp b/include/lo2s/config.hpp index 1fb72fc1..14091d86 100644 --- a/include/lo2s/config.hpp +++ b/include/lo2s/config.hpp @@ -113,6 +113,8 @@ struct Config std::string cuda_injectionlib_path; uint64_t nvidia_ringbuf_size; DwarfUsage dwarf; + + std::string socket_path; }; const Config& config(); diff --git a/include/lo2s/cupti/events.hpp b/include/lo2s/cupti/events.hpp index ba994458..060e73f3 100644 --- a/include/lo2s/cupti/events.hpp +++ b/include/lo2s/cupti/events.hpp @@ -22,11 +22,10 @@ #pragma once #include +#include namespace lo2s { -namespace cupti -{ enum class EventType : uint64_t { CUPTI_KERNEL = 1, @@ -46,5 +45,4 @@ struct event_kernel char name[1]; }; -} // namespace cupti } // namespace lo2s diff --git a/include/lo2s/cupti/reader.hpp b/include/lo2s/cupti/reader.hpp deleted file mode 100644 index 5c474b67..00000000 --- a/include/lo2s/cupti/reader.hpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * This file is part of the lo2s software. - * Linux OTF2 sampling - * - * Copyright (c) 2016, - * 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 -#include - -extern "C" -{ -#include -#include -} - -namespace lo2s -{ -namespace cupti -{ - -class Reader -{ -public: - Reader(trace::Trace& trace, Process process) - : process_(process), trace_(trace), time_converter_(perf::time::Converter::instance()), - ringbuf_reader_("cupti", process.as_pid_t(), true, config().nvidia_ringbuf_size), - timer_fd_(timerfd_from_ns(config().userspace_read_interval)), - executable_name_(get_process_exe(process)) - { - } - - void read() - { - struct event_header* header = nullptr; - - while ((header = reinterpret_cast( - ringbuf_reader_.get(sizeof(struct event_header)))) != nullptr) - { - if (header->type == EventType::CUPTI_KERNEL) - { - struct event_kernel* kernel = - reinterpret_cast(ringbuf_reader_.get(header->size)); - - auto& writer = trace_.cuda_writer(Thread(process_.as_thread())); - - std::string kernel_name = kernel->name; - auto& cu_cctx = trace_.cuda_calling_context(executable_name_, kernel_name); - - writer.write_calling_context_enter(time_converter_(kernel->start), cu_cctx.ref(), - 2); - writer.write_calling_context_leave(time_converter_(kernel->end), cu_cctx.ref()); - } - - ringbuf_reader_.pop(header->size); - } - } - - int fd() - { - return timer_fd_; - } - -private: - Process process_; - trace::Trace& trace_; - perf::time::Converter& time_converter_; - RingBufReader ringbuf_reader_; - int timer_fd_; - std::string executable_name_; -}; -} // namespace cupti -} // namespace lo2s diff --git a/include/lo2s/monitor/abstract_process_monitor.hpp b/include/lo2s/monitor/abstract_process_monitor.hpp index 18bb6859..bcc93a79 100644 --- a/include/lo2s/monitor/abstract_process_monitor.hpp +++ b/include/lo2s/monitor/abstract_process_monitor.hpp @@ -41,7 +41,7 @@ class AbstractProcessMonitor virtual void insert_process(Process parent, Process process, std::string proc_name, bool spawn = false) = 0; virtual void insert_thread(Process process, Thread thread, std::string name = "", - bool spawn = false, bool is_process = false) = 0; + bool spawn = false) = 0; virtual void exit_thread(Thread thread) = 0; diff --git a/include/lo2s/monitor/fwd.hpp b/include/lo2s/monitor/fwd.hpp index baa31980..931b8caf 100644 --- a/include/lo2s/monitor/fwd.hpp +++ b/include/lo2s/monitor/fwd.hpp @@ -36,5 +36,7 @@ class CpuSwitchMonitor; class MainMonitor; class ProcessMonitor; class CpuSetMonitor; +class SocketMonitor; +class RingbufMonitor; } // namespace monitor } // namespace lo2s diff --git a/include/lo2s/monitor/main_monitor.hpp b/include/lo2s/monitor/main_monitor.hpp index 944bcd11..32b81f8b 100644 --- a/include/lo2s/monitor/main_monitor.hpp +++ b/include/lo2s/monitor/main_monitor.hpp @@ -35,6 +35,7 @@ #ifdef HAVE_VEOSINFO #include #endif +#include #include #include #include @@ -74,6 +75,7 @@ class MainMonitor metric::plugin::Metrics metrics_; std::vector> tracepoint_monitors_; + std::unique_ptr socket_monitor_; std::unique_ptr> bio_monitor_; #ifdef HAVE_X86_ADAPT std::unique_ptr x86_adapt_metrics_; diff --git a/include/lo2s/monitor/process_monitor.hpp b/include/lo2s/monitor/process_monitor.hpp index 609f5d42..d5463c63 100644 --- a/include/lo2s/monitor/process_monitor.hpp +++ b/include/lo2s/monitor/process_monitor.hpp @@ -45,8 +45,7 @@ class ProcessMonitor : public AbstractProcessMonitor, public MainMonitor ~ProcessMonitor(); void insert_process(Process parent, Process child, std::string proc_name, bool spawn = false) override; - void insert_thread(Process parent, Thread child, std::string name, bool spawn = false, - bool is_process = false) override; + void insert_thread(Process parent, Thread child, std::string name, bool spawn = false) override; void exit_thread(Thread thread) override; diff --git a/include/lo2s/monitor/ringbuf_monitor.hpp b/include/lo2s/monitor/ringbuf_monitor.hpp new file mode 100644 index 00000000..bf9d05f0 --- /dev/null +++ b/include/lo2s/monitor/ringbuf_monitor.hpp @@ -0,0 +1,53 @@ +/* + * This file is part of the lo2s software. + * Linux OTF2 sampling + * + * Copyright (c) 2016-2018, 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 + +namespace lo2s +{ +namespace monitor +{ + +class RingbufMonitor : public PollMonitor +{ +public: + RingbufMonitor(trace::Trace& trace, int fd); + + void initialize_thread() override; + void finalize_thread() override; + void monitor(int fd) override; + + std::string group() const override + { + return "lo2s::RingbufMonitor"; + } + +private: + trace::Trace& trace_; + perf::time::Converter& time_converter_; + RingBufReader ringbuf_reader_; +}; +} // namespace monitor +} // namespace lo2s diff --git a/include/lo2s/monitor/scope_monitor.hpp b/include/lo2s/monitor/scope_monitor.hpp index c809d64c..e5a07db5 100644 --- a/include/lo2s/monitor/scope_monitor.hpp +++ b/include/lo2s/monitor/scope_monitor.hpp @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -51,8 +50,7 @@ namespace monitor class ScopeMonitor : public PollMonitor { public: - ScopeMonitor(ExecutionScope scope, MainMonitor& parent, bool enable_on_exec, - bool is_process = false); + ScopeMonitor(ExecutionScope scope, MainMonitor& parent, bool enable_on_exec); void initialize_thread() override; void finalize_thread() override; @@ -76,7 +74,6 @@ class ScopeMonitor : public PollMonitor std::unique_ptr sample_writer_; std::unique_ptr group_counter_writer_; std::unique_ptr userspace_counter_writer_; - std::unique_ptr cupti_reader_; }; } // namespace monitor } // namespace lo2s diff --git a/include/lo2s/monitor/socket_monitor.hpp b/include/lo2s/monitor/socket_monitor.hpp new file mode 100644 index 00000000..f5dacd9f --- /dev/null +++ b/include/lo2s/monitor/socket_monitor.hpp @@ -0,0 +1,60 @@ +/* + * This file is part of the lo2s software. + * Linux OTF2 sampling + * + * Copyright (c) 2016-2018, 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 + +extern "C" +{ +#include +#include +} + +namespace lo2s +{ +namespace monitor +{ + +class SocketMonitor : public PollMonitor +{ +public: + SocketMonitor(trace::Trace& trace); + + void initialize_thread() override; + void finalize_thread() override; + void monitor(int fd) override; + + std::string group() const override + { + return "lo2s::SocketMonitor"; + } + +private: + trace::Trace& trace_; + std::map monitors_; + int socket = -1; +}; +} // namespace monitor +} // namespace lo2s diff --git a/include/lo2s/monitor/system_process_monitor.hpp b/include/lo2s/monitor/system_process_monitor.hpp index ed785718..3162ecde 100644 --- a/include/lo2s/monitor/system_process_monitor.hpp +++ b/include/lo2s/monitor/system_process_monitor.hpp @@ -46,8 +46,8 @@ class SystemProcessMonitor : public AbstractProcessMonitor virtual void insert_process(Process parent, Process process, std::string proc_name, bool spawn) override; - virtual void insert_thread(Process process, Thread thread, std::string name, bool spawn, - bool is_process) override; + virtual void insert_thread(Process process, Thread thread, std::string name, + bool spawn) override; virtual void exit_thread(Thread thread) override; diff --git a/include/lo2s/ringbuf.hpp b/include/lo2s/ringbuf.hpp index 02dedfc2..8fd859af 100644 --- a/include/lo2s/ringbuf.hpp +++ b/include/lo2s/ringbuf.hpp @@ -56,16 +56,8 @@ struct ringbuf_header class ShmRingbuf { public: - ShmRingbuf(std::string component, pid_t pid, bool create, size_t pages) + ShmRingbuf(int fd, bool create, size_t pages) : fd_(fd) { - std::string filename = "/lo2s-" + component + "-" + std::to_string(pid); - - fd_ = shm_open(filename.c_str(), create ? O_RDWR | O_CREAT | O_EXCL : O_RDWR, 0600); - if (fd_ == -1) - { - throw std::system_error(errno, std::system_category()); - } - size_t pagesize = sysconf(_SC_PAGESIZE); size_t size; @@ -160,8 +152,7 @@ class ShmRingbuf class RingBufWriter : public ShmRingbuf { public: - RingBufWriter(std::string component, pid_t pid, bool create, size_t pages = 0) - : ShmRingbuf(component, pid, create, pages) + RingBufWriter(int fd, bool create, size_t pages = 0) : ShmRingbuf(fd, create, pages) { } @@ -203,8 +194,7 @@ class RingBufWriter : public ShmRingbuf class RingBufReader : public ShmRingbuf { public: - RingBufReader(std::string component, pid_t pid, bool create, size_t pages = 0) - : ShmRingbuf(component, pid, create, pages) + RingBufReader(int fd, bool create, size_t pages = 0) : ShmRingbuf(fd, create, pages) { } diff --git a/include/lo2s/shared_memory.hpp b/include/lo2s/shared_memory.hpp index 35a546d8..c2b66a32 100644 --- a/include/lo2s/shared_memory.hpp +++ b/include/lo2s/shared_memory.hpp @@ -31,6 +31,7 @@ extern "C" { #include #include +#include } namespace lo2s @@ -66,7 +67,7 @@ class SharedMemory SharedMemory(int fd, size_t size, size_t offset = 0, void* location = nullptr) : size_(size) { - assert(offset % get_page_size() == 0); + assert((offset % sysconf(_SC_PAGESIZE)) == 0); if (location == nullptr) { diff --git a/src/config.cpp b/src/config.cpp index 4281c18e..e208e3f1 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -240,6 +240,9 @@ void parse_program_options(int argc, const char** argv) .default_value("local") #endif .metavar("DWARFMODE"); + general_options.option("socket", "Path to socket used for ringbuffer communication.") + .default_value("/tmp/lo2s.socket") + .metavar("PATH"); system_mode_options .toggle("all-cpus", "Start in system-monitoring mode for all CPUs. " "Monitor as long as COMMAND is running or until PID exits.") @@ -420,6 +423,7 @@ void parse_program_options(int argc, const char** argv) config.use_sensors = arguments.given("sensors"); config.use_block_io = arguments.given("block-io"); config.tracepoint_events = arguments.get_all("tracepoint"); + config.socket_path = arguments.get("socket"); #ifdef HAVE_CUDA config.cuda_injectionlib_path = arguments.get("nvidia-injection-path"); #endif diff --git a/src/cupti/lib.cpp b/src/cupti/lib.cpp index ca100f1e..e7635af6 100644 --- a/src/cupti/lib.cpp +++ b/src/cupti/lib.cpp @@ -187,7 +187,12 @@ extern "C" int InitializeInjection(void) { std::string rb_size_str; - rb_writer = std::make_unique("cupti", getpid(), false); + int fd = memfd_create("foo", 0); + if (fd == -1) + { + return -1; + } + rb_writer = std::make_unique(fd, true, 16); char* clockid_str = getenv("LO2S_CLOCKID"); if (clockid_str != nullptr) diff --git a/src/cupti/test.cpp b/src/cupti/test.cpp new file mode 100644 index 00000000..f5a76123 --- /dev/null +++ b/src/cupti/test.cpp @@ -0,0 +1,151 @@ +/* + * This file is part of the lo2s software. + * Linux OTF2 sampling + * + * Copyright (c) 2016, + * 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 + +extern "C" +{ +#include +#include +#include +#include +} + +const char* message = ""; + +ssize_t write_fd(int conn_fd, int fd) +{ + struct msghdr msg; + struct iovec iov[1]; + + union + { + struct cmsghdr cm; + char control[CMSG_SPACE(sizeof(int))]; + } control_un; + + struct cmsghdr* cmptr; + msg.msg_control = control_un.control; + msg.msg_controllen = sizeof(control_un.control); + + cmptr = CMSG_FIRSTHDR(&msg); + cmptr->cmsg_len = CMSG_LEN(sizeof(int)); + cmptr->cmsg_level = SOL_SOCKET; + cmptr->cmsg_type = SCM_RIGHTS; + *((int*)CMSG_DATA(cmptr)) = fd; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + + char foo = 42; + iov[0].iov_base = &foo; + iov[0].iov_len = 1; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + return sendmsg(conn_fd, &msg, 0); +} + +std::unique_ptr rb_writer = nullptr; + +int main(void) +{ + + char* socket_path = getenv("LO2S_SOCKET"); + std::cerr << socket_path << std::endl; + std::string rb_size_str; + int fd = memfd_create("foo", 0); + if (fd == -1) + { + return -1; + } + rb_writer = std::make_unique(fd, true, 16); + int data_socket = socket(AF_UNIX, SOCK_SEQPACKET, 0); + if (data_socket == -1) + { + perror("socket"); + exit(EXIT_FAILURE); + } + + /* + * For portability clear the whole structure, since some + * implementations have additional (nonstandard) fields in + * the structure. + */ + + struct sockaddr_un addr; + memset(&addr, 0, sizeof(addr)); + + /* Connect socket to socket address. */ + + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1); + + int ret = connect(data_socket, (const struct sockaddr*)&addr, sizeof(addr)); + if (ret < 0) + { + std::cout << "Could not connect!" << strerror(errno); + return -1; + } + + std::cout << "Connected!" << std::endl; + /* Close socket. */ + + write_fd(data_socket, fd); + + while (1) + { + struct timespec start, end; + clock_gettime(CLOCK_MONOTONIC_RAW, &start); + sleep(1); + clock_gettime(CLOCK_MONOTONIC_RAW, &end); + const char* str = "Hello World!"; + uint64_t name_len = strlen(str); + struct lo2s::event_kernel* ev = reinterpret_cast( + rb_writer->reserve(sizeof(struct lo2s::event_kernel) + name_len)); + if (ev == nullptr) + { + std::cerr << "Dropped event!"; + continue; + } + ev->header.type = lo2s::EventType::CUPTI_KERNEL; + ev->header.size = sizeof(struct lo2s::event_kernel) + name_len; + + ev->start = start.tv_nsec; + ev->end = end.tv_nsec; + mempcpy(ev->name, str, name_len + 1); + std::cerr << "Event!" << std::endl; + rb_writer->commit(); + } + close(data_socket); + + exit(EXIT_SUCCESS); + + return 1; +} diff --git a/src/monitor/main_monitor.cpp b/src/monitor/main_monitor.cpp index 339eaa17..55c4604e 100644 --- a/src/monitor/main_monitor.cpp +++ b/src/monitor/main_monitor.cpp @@ -127,6 +127,9 @@ MainMonitor::MainMonitor() : trace_(), metrics_(trace_) nec_monitors_.back()->start(); } #endif + + socket_monitor_ = std::make_unique(trace_); + socket_monitor_->start(); } static uint64_t mmap_get_time(const RecordMmap2Type* t) @@ -176,6 +179,7 @@ MainMonitor::~MainMonitor() { sensors_recorder_->stop(); } + socket_monitor_->stop(); #endif #ifdef HAVE_X86_ENERGY diff --git a/src/monitor/process_monitor.cpp b/src/monitor/process_monitor.cpp index 4ccbd752..904a473b 100644 --- a/src/monitor/process_monitor.cpp +++ b/src/monitor/process_monitor.cpp @@ -37,11 +37,10 @@ void ProcessMonitor::insert_process(Process parent, Process process, std::string bool spawn) { trace_.add_process(parent, process, proc_name); - insert_thread(process, process.as_thread(), proc_name, spawn, true); + insert_thread(process, process.as_thread(), proc_name, spawn); } -void ProcessMonitor::insert_thread(Process process, Thread thread, std::string name, bool spawn, - bool is_process) +void ProcessMonitor::insert_thread(Process process, Thread thread, std::string name, bool spawn) { trace_.add_thread(thread, name); @@ -63,7 +62,7 @@ void ProcessMonitor::insert_thread(Process process, Thread thread, std::string n { auto inserted = threads_.emplace(std::piecewise_construct, std::forward_as_tuple(thread), - std::forward_as_tuple(scope, *this, spawn, is_process)); + std::forward_as_tuple(scope, *this, spawn)); assert(inserted.second); // actually start thread inserted.first->second.start(); diff --git a/src/monitor/process_monitor_main.cpp b/src/monitor/process_monitor_main.cpp index 7927c801..a62fec11 100644 --- a/src/monitor/process_monitor_main.cpp +++ b/src/monitor/process_monitor_main.cpp @@ -153,6 +153,7 @@ std::vector to_vector_of_c_str(const std::vector& vec) ptrace(PTRACE_TRACEME, 0, NULL, NULL); std::vector env; + env.emplace_back("LO2S_SOCKET=/tmp/lo2s.socket"); #ifdef HAVE_CUDA if (config().use_nvidia) { diff --git a/src/monitor/ringbuf_monitor.cpp b/src/monitor/ringbuf_monitor.cpp new file mode 100644 index 00000000..8ef2984f --- /dev/null +++ b/src/monitor/ringbuf_monitor.cpp @@ -0,0 +1,83 @@ +/* + * This file is part of the lo2s software. + * Linux OTF2 sampling + * + * Copyright (c) 2016, + * 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 + +extern "C" +{ +#include +#include +} + +namespace lo2s +{ +namespace monitor +{ +RingbufMonitor::RingbufMonitor(trace::Trace& trace, int fd) +: PollMonitor(trace, "RingbufMonitor", std::chrono::nanoseconds(10000)), trace_(trace), + time_converter_(perf::time::Converter::instance()), ringbuf_reader_(fd, false, 0) +{ +} + +void RingbufMonitor::initialize_thread() +{ +} + +void RingbufMonitor::finalize_thread() +{ +} + +void RingbufMonitor::monitor(int fd [[maybe_unused]]) +{ + std::string executable_name_ = ""; + Process process_ = Process(1); + struct event_header* header = nullptr; + + while ((header = reinterpret_cast( + ringbuf_reader_.get(sizeof(struct event_header)))) != nullptr) + { + if (header->type == EventType::CUPTI_KERNEL) + { + struct event_kernel* kernel = + reinterpret_cast(ringbuf_reader_.get(header->size)); + + auto& writer = trace_.cuda_writer(Thread(process_.as_thread())); + + std::string kernel_name = kernel->name; + auto& cu_cctx = trace_.cuda_calling_context(executable_name_, kernel_name); + + writer.write_calling_context_enter(time_converter_(kernel->start), cu_cctx.ref(), 2); + writer.write_calling_context_leave(time_converter_(kernel->end), cu_cctx.ref()); + } + + ringbuf_reader_.pop(header->size); + } +} +} // namespace monitor +} // namespace lo2s diff --git a/src/monitor/scope_monitor.cpp b/src/monitor/scope_monitor.cpp index d2c65e68..1ca7d2b8 100644 --- a/src/monitor/scope_monitor.cpp +++ b/src/monitor/scope_monitor.cpp @@ -39,8 +39,7 @@ namespace lo2s namespace monitor { -ScopeMonitor::ScopeMonitor(ExecutionScope scope, MainMonitor& parent, bool enable_on_exec, - bool is_process) +ScopeMonitor::ScopeMonitor(ExecutionScope scope, MainMonitor& parent, bool enable_on_exec) : PollMonitor(parent.trace(), scope.name(), config().perf_read_interval), scope_(scope) { if (config().sampling || scope.is_cpu()) @@ -74,13 +73,6 @@ ScopeMonitor::ScopeMonitor(ExecutionScope scope, MainMonitor& parent, bool enabl add_fd(userspace_counter_writer_->fd()); } - if (config().use_nvidia && is_process) - { - cupti_reader_ = - std::make_unique(parent.trace(), scope.as_thread().as_process()); - add_fd(cupti_reader_->fd()); - } - // note: start() can now be called } @@ -104,11 +96,6 @@ void ScopeMonitor::monitor(int fd) try_pin_to_scope(scope_); } - if (cupti_reader_ && (fd == cupti_reader_->fd() || fd == stop_pfd().fd)) - { - cupti_reader_->read(); - } - if (syscall_writer_ && (fd == timer_pfd().fd || fd == stop_pfd().fd || syscall_writer_->fd() == fd)) { diff --git a/src/monitor/socket_monitor.cpp b/src/monitor/socket_monitor.cpp new file mode 100644 index 00000000..4a8ae5bd --- /dev/null +++ b/src/monitor/socket_monitor.cpp @@ -0,0 +1,158 @@ +/* + * This file is part of the lo2s software. + * Linux OTF2 sampling + * + * Copyright (c) 2016, + * 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 + +extern "C" +{ +#include +#include +} + +namespace lo2s +{ +namespace monitor +{ +SocketMonitor::SocketMonitor(trace::Trace& trace) +: PollMonitor(trace, "SocketMonitor", std::chrono::nanoseconds(0)), trace_(trace) +{ + socket = ::socket(AF_UNIX, SOCK_SEQPACKET, 0); + if (socket == -1) + { + throw_errno(); + } + + struct sockaddr_un name; + memset(&name, 0, sizeof(name)); + name.sun_family = AF_UNIX; + strncpy(name.sun_path, config().socket_path.c_str(), sizeof(name.sun_path) - 1); + unlink(config().socket_path.c_str()); + + int ret = bind(socket, (const struct sockaddr*)&name, sizeof(name)); + if (ret == -1) + { + throw_errno(); + } + + ret = listen(socket, 20); + if (ret == -1) + { + throw_errno(); + } + add_fd(socket); +} + +static ssize_t read_fd(int fd, int* recvfd) +{ + ssize_t n; + + union + { + struct cmsghdr cm; + char control[CMSG_SPACE(sizeof(int))]; + } control_un; + + struct msghdr msg; + msg.msg_control = control_un.control; + msg.msg_controllen = sizeof(control_un.control); + + msg.msg_name = NULL; + msg.msg_namelen = 0; + + // We have to send at least one byte with the fd, otherwise we can not distinguish receiving + // messages from receiving EOF + char sentinel; + struct iovec iov[1]; + iov[0].iov_base = &sentinel; + iov[0].iov_len = 1; + + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + if ((n = recvmsg(fd, &msg, 0)) <= 0) + { + throw_errno(); + } + + assert(sentinel == 42); + struct cmsghdr* cmptr; + if ((cmptr = CMSG_FIRSTHDR(&msg)) != nullptr && cmptr->cmsg_len == CMSG_LEN(sizeof(int))) + { + if (cmptr->cmsg_level != SOL_SOCKET) + return -1; + if (cmptr->cmsg_type != SCM_RIGHTS) + return -1; + + *recvfd = *((int*)CMSG_DATA(cmptr)); + } + else + { + *recvfd = -1; + } + return n; +} + +void SocketMonitor::initialize_thread() +{ +} + +void SocketMonitor::finalize_thread() +{ + for (auto& monitor : monitors_) + { + monitor.second.stop(); + } + close(socket); +} + +void SocketMonitor::monitor(int fd) +{ + if (fd != socket) + { + return; + } + int data_socket = accept(socket, NULL, NULL); + if (data_socket == -1) + { + throw_errno(); + } + + int foo_fd = -1; + if (read_fd(data_socket, &foo_fd) <= 0) + { + std::cout << "Couldnt read fd: " << strerror(errno) << std::endl; + } + + auto res = monitors_.emplace(std::piecewise_construct, std::forward_as_tuple(foo_fd), + std::forward_as_tuple(trace_, foo_fd)); + res.first->second.start(); + close(data_socket); +} +} // namespace monitor +} // namespace lo2s diff --git a/src/monitor/system_process_monitor.cpp b/src/monitor/system_process_monitor.cpp index a86d07d6..b87001c5 100644 --- a/src/monitor/system_process_monitor.cpp +++ b/src/monitor/system_process_monitor.cpp @@ -34,8 +34,7 @@ void SystemProcessMonitor::insert_process([[maybe_unused]] Process parent, } void SystemProcessMonitor::insert_thread([[maybe_unused]] Process process, Thread thread, - std::string name, [[maybe_unused]] bool spawn, - [[maybe_unused]] bool is_process) + std::string name, [[maybe_unused]] bool spawn) { // in system monitoring, we only need to track the threads spawned from the process lo2s spawned // itself. Without this, these threads end up as "". Sad times. diff --git a/src/util.cpp b/src/util.cpp index 43c9dfaa..5de6af47 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -421,6 +421,7 @@ int timerfd_from_ns(std::chrono::nanoseconds duration) tspec.it_interval.tv_sec = std::chrono::duration_cast(duration).count(); tspec.it_interval.tv_nsec = (duration % std::chrono::seconds(1)).count(); + tspec.it_value.tv_nsec = 1; timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);