Files
rocm-systems/projects/rocprofiler-systems/source/lib/rocprof-sys/library.cpp
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

1106 строки
36 KiB
C++
Исходник Обычный вид История

2022-01-26 23:25:00 -06:00
// MIT License
//
2025-01-15 13:06:12 -05:00
// Copyright (c) 2022-2025 Advanced Micro Devices, Inc. All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
2022-01-26 23:25:00 -06:00
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
2022-01-26 23:25:00 -06:00
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2022-01-26 23:25:00 -06:00
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2022-01-26 23:25:00 -06:00
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
2021-08-06 13:08:57 -05:00
2022-09-30 10:47:07 -05:00
#include <timemory/log/color.hpp>
2023-02-03 14:10:42 -06:00
//
// above should always be included first
//
2022-08-31 01:24:31 -05:00
#include "api.hpp"
#include "common/setup.hpp"
2024-12-13 18:48:39 -05:00
#include "common/static_object.hpp"
2025-07-28 17:33:52 +02:00
#include "core/agent.hpp"
#include "core/agent_manager.hpp"
#include "core/categories.hpp"
#include "core/components/fwd.hpp"
#include "core/concepts.hpp"
#include "core/config.hpp"
#include "core/constraint.hpp"
2025-07-28 17:33:52 +02:00
#include "core/cpu.hpp"
#include "core/debug.hpp"
#include "core/defines.hpp"
2025-03-27 16:02:17 +01:00
#include "core/dynamic_library.hpp"
#include "core/gpu.hpp"
2023-06-14 11:55:22 -05:00
#include "core/locking.hpp"
2025-07-28 17:33:52 +02:00
#include "core/node_info.hpp"
2023-02-27 12:09:03 -06:00
#include "core/perfetto_fwd.hpp"
2025-07-28 17:33:52 +02:00
#include "core/rocpd/data_processor.hpp"
#include "core/timemory.hpp"
2025-08-19 22:01:04 -04:00
#include "core/trace_cache/cache_manager.hpp"
#include "core/trace_cache/cache_utility.hpp"
#include "core/trace_cache/metadata_registry.hpp"
#include "core/utility.hpp"
2023-01-24 18:53:23 -06:00
#include "library/causal/data.hpp"
#include "library/causal/experiment.hpp"
#include "library/causal/sampling.hpp"
#include "library/components/exit_gotcha.hpp"
#include "library/components/fork_gotcha.hpp"
#include "library/components/mpi_gotcha.hpp"
2023-02-27 12:09:03 -06:00
#include "library/components/numa_gotcha.hpp"
#include "library/components/pthread_gotcha.hpp"
#include "library/components/vaapi_gotcha.hpp"
2022-04-25 17:00:52 -05:00
#include "library/coverage.hpp"
#include "library/process_sampler.hpp"
2022-02-23 06:59:32 -06:00
#include "library/ptl.hpp"
2024-12-13 18:48:39 -05:00
#include "library/rocprofiler-sdk.hpp"
2022-08-31 01:24:31 -05:00
#include "library/runtime.hpp"
#include "library/sampling.hpp"
#include "library/thread_data.hpp"
2022-08-31 01:24:31 -05:00
#include "library/thread_info.hpp"
#include "library/tracing.hpp"
#include "rocprofiler-systems/categories.h" // in rocprof-sys-user
2022-08-31 01:24:31 -05:00
#include <timemory/hash/types.hpp>
2023-06-14 11:55:22 -05:00
#include <timemory/log/logger.hpp>
2022-09-26 07:52:14 -05:00
#include <timemory/manager/manager.hpp>
2023-02-03 14:10:42 -06:00
#include <timemory/mpl/type_traits.hpp>
2022-08-31 01:24:31 -05:00
#include <timemory/operations/types/file_output_message.hpp>
2023-06-14 11:55:22 -05:00
#include <timemory/process/process.hpp>
2023-02-03 14:10:42 -06:00
#include <timemory/process/threading.hpp>
2022-09-26 07:52:14 -05:00
#include <timemory/settings/types.hpp>
2023-02-03 14:10:42 -06:00
#include <timemory/signals/signal_handlers.hpp>
#include <timemory/signals/signal_mask.hpp>
#include <timemory/signals/types.hpp>
2023-06-14 11:55:22 -05:00
#include <timemory/units.hpp>
2022-08-31 01:24:31 -05:00
#include <timemory/utility/backtrace.hpp>
2023-02-08 01:31:38 -06:00
#include <timemory/utility/join.hpp>
2022-05-19 16:07:11 -05:00
#include <timemory/utility/procfs/maps.hpp>
2025-07-28 17:33:52 +02:00
#if ROCPROFSYS_USE_ROCM > 0
# include <rocprofiler-sdk/agent.h>
2025-08-26 16:54:01 -04:00
# include <rocprofiler-sdk/registration.h>
2025-07-28 17:33:52 +02:00
#endif
2022-02-25 03:56:41 -06:00
#include <atomic>
2023-06-14 11:55:22 -05:00
#include <chrono>
#include <csignal>
#include <cstdio>
2023-02-03 14:10:42 -06:00
#include <cstdlib>
#include <mutex>
2023-06-14 11:55:22 -05:00
#include <pthread.h>
2023-02-03 14:10:42 -06:00
#include <stdexcept>
#include <string_view>
2025-07-28 17:33:52 +02:00
#include <unistd.h>
#include <utility>
2021-09-06 22:23:24 -05:00
using namespace rocprofsys;
2022-02-25 03:56:41 -06:00
//======================================================================================//
namespace rocprofsys
2023-06-14 11:55:22 -05:00
{
namespace timeout
{
void
setup() ROCPROFSYS_INTERNAL_API;
2023-06-14 11:55:22 -05:00
}
} // namespace rocprofsys
2023-06-14 11:55:22 -05:00
2021-09-06 22:23:24 -05:00
namespace
{
auto _timemory_manager = tim::manager::instance();
auto _timemory_settings = tim::settings::shared_instance();
void
set_metadata_process_start_timestamp(int64_t _ts)
{
auto process_info = trace_cache::get_metadata_registry().get_process_info();
process_info.start = _ts;
trace_cache::get_metadata_registry().set_process(process_info);
}
void
set_metadata_process_end_timestamp(int64_t _ts)
{
auto process_info = trace_cache::get_metadata_registry().get_process_info();
process_info.end = _ts;
trace_cache::get_metadata_registry().set_process(process_info);
}
2023-01-24 18:53:23 -06:00
bool
ensure_initialization(bool _offset, int64_t _glob_n, int64_t _offset_n)
{
auto _exit_info = component::exit_gotcha::get_exit_info();
if(_exit_info.is_known && _exit_info.exit_code != EXIT_SUCCESS) return _offset;
2023-10-16 18:04:47 -05:00
auto _tid = utility::get_thread_index();
auto _peak_num_threads = grow_data(_tid + 1);
2023-01-24 18:53:23 -06:00
2023-10-16 18:04:47 -05:00
if(_tid > 0 && _tid < _peak_num_threads)
2023-01-24 18:53:23 -06:00
{
const auto& _info = thread_info::get();
ROCPROFSYS_BASIC_VERBOSE_F(3,
"thread info: %s, offset: %s, global counter: %li, "
"offset counter: %li, max threads: %li\n",
std::to_string(static_cast<bool>(_info)).c_str(),
std::to_string(_offset).c_str(), _glob_n, _offset_n,
_peak_num_threads);
2023-01-24 18:53:23 -06:00
}
return _offset;
}
2023-02-03 14:10:42 -06:00
void
finalization_handler()
{
if(get_state() == State::Active) rocprofsys_finalize();
2023-02-03 14:10:42 -06:00
}
2021-08-06 13:08:57 -05:00
auto
ensure_finalization(bool _static_init = false)
2021-08-06 13:08:57 -05:00
{
2023-02-03 14:10:42 -06:00
if(config::set_signal_handler(nullptr) == nullptr)
config::set_signal_handler(&finalization_handler);
2023-01-24 18:53:23 -06:00
if(_static_init)
{
auto _idx = threading::add_callback(&ensure_initialization);
if(_idx < 0)
throw exception<std::runtime_error>("failure adding threading callback");
}
ROCPROFSYS_CI_BASIC_THROW(
2023-02-03 14:10:42 -06:00
config::set_signal_handler(nullptr) != &finalization_handler,
"Assignment of signal handler failed. signal handler is %s, expected %s\n",
as_hex(reinterpret_cast<void*>(config::set_signal_handler(nullptr))).c_str(),
as_hex(reinterpret_cast<void*>(&finalization_handler)).c_str());
2022-08-31 01:24:31 -05:00
const auto& _info = thread_info::init();
const auto& _tid = _info->index_data;
if(_tid)
{
ROCPROFSYS_CI_THROW(_tid->sequent_value != threading::get_id(),
"Error! internal tid != %li :: %li", threading::get_id(),
_tid->sequent_value);
ROCPROFSYS_CI_THROW(_tid->system_value != threading::get_sys_tid(),
"Error! system tid != %li :: %li", threading::get_sys_tid(),
_tid->system_value);
}
2022-08-31 01:24:31 -05:00
if(common::get_env("ROCPROFSYS_MONOCHROME", false)) tim::log::monochrome() = true;
2023-06-14 11:55:22 -05:00
timeout::setup();
2022-09-26 07:52:14 -05:00
(void) tim::manager::instance();
(void) tim::settings::shared_instance();
if(!tim::get_shared_ptr_pair_callback())
{
tim::get_shared_ptr_pair_callback() =
new tim::shared_ptr_pair_callback_t{ [](int64_t _n) {
if(_n == 0) rocprofsys_finalize_hidden();
} };
}
if(_static_init)
{
ROCPROFSYS_BASIC_DEBUG_F("\n");
auto _verbose =
get_verbose_env() + ((get_debug_env() || get_debug_init()) ? 16 : 0);
auto _search_paths = JOIN(':', tim::get_env<std::string>("ROCPROFSYS_PATH", ""),
tim::get_env<std::string>("PWD"), ".",
tim::get_env<std::string>("LD_LIBRARY_PATH", ""),
tim::get_env<std::string>("LIBRARY_PATH", ""),
tim::get_env<std::string>("PATH", ""));
common::setup_environ(_verbose, _search_paths);
}
else
{
ROCPROFSYS_DEBUG_F("\n");
}
2023-03-07 06:04:19 -06:00
if(_timemory_manager) _timemory_manager->set_write_metadata(-1);
return scope::destructor{ []() { rocprofsys_finalize_hidden(); } };
2021-08-06 13:08:57 -05:00
}
2023-01-24 18:53:23 -06:00
template <typename... Tp>
struct fini_bundle
{
using data_type = std::tuple<Tp...>;
ROCPROFSYS_DEFAULT_OBJECT(fini_bundle)
2023-01-24 18:53:23 -06:00
fini_bundle(std::string_view _label)
: m_label{ _label }
{}
template <typename... Args>
void start(Args&&... _args)
{
TIMEMORY_FOLD_EXPRESSION(tim::operation::start<Tp>{}(
std::get<Tp>(m_data), std::forward<Args>(_args)...));
}
template <typename... Args>
void stop(Args&&... _args)
{
TIMEMORY_FOLD_EXPRESSION(tim::operation::stop<Tp>{}(
std::get<Tp>(m_data), std::forward<Args>(_args)...));
}
std::string as_string(bool _print_prefix = true) const
{
std::stringstream _ss;
if(_print_prefix && m_label.length() > 0) _ss << m_label << " : ";
_ss << timemory::join::join(", ", std::get<Tp>(m_data)...);
return _ss.str();
}
std::string_view m_label = {};
data_type m_data = {};
};
template <typename... Tp>
struct fini_bundle<tim::lightweight_tuple<Tp...>>
{
using base_type = fini_bundle<Tp...>;
};
using fini_bundle_t = typename fini_bundle<main_bundle_t>::base_type;
2022-02-08 17:42:17 -06:00
} // namespace
//======================================================================================//
///
///
///
//======================================================================================//
2022-07-25 07:25:43 -05:00
namespace
{
struct set_env_s // NOLINT
{};
} // namespace
2022-02-08 17:42:17 -06:00
extern "C" void
rocprofsys_set_env_hidden(const char* env_name, const char* env_val)
2022-02-08 17:42:17 -06:00
{
2022-04-25 17:00:52 -05:00
tim::auto_lock_t _lk{ tim::type_mutex<set_env_s>() };
static auto _set_envs = std::set<std::string_view>{};
bool _success = _set_envs.emplace(env_name).second;
2022-02-08 17:42:17 -06:00
// just search env to avoid initializing the settings
ROCPROFSYS_CONDITIONAL_PRINT_F(get_debug_init() || get_verbose_env() > 2,
"Setting env: %s=%s\n", env_name, env_val);
2022-02-08 17:42:17 -06:00
tim::set_env(env_name, env_val, 0);
2022-09-26 07:52:14 -05:00
if(_success && get_state() >= State::Init)
{
ROCPROFSYS_WARNING_F(
2022-09-26 07:52:14 -05:00
0,
"rocprofsys_set_env(\"%s\", \"%s\") called after rocprof-sys was "
"initialized. "
2022-09-26 07:52:14 -05:00
"state = %s. This environment variable will have no effect\n",
env_name, env_val, std::to_string(get_state()).c_str());
}
2022-02-08 17:42:17 -06:00
}
//======================================================================================//
///
2022-02-25 03:56:41 -06:00
///
2022-02-08 17:42:17 -06:00
///
//======================================================================================//
namespace
{
bool _set_mpi_called = false;
2022-09-26 07:52:14 -05:00
std::function<void()> _preinit_callback = []() { get_preinit_bundle()->start(); };
2025-07-28 17:33:52 +02:00
std::vector<std::string>
read_command_line(pid_t _pid)
{
auto _cmdline = std::vector<std::string>{};
auto fcmdline = std::stringstream{};
fcmdline << "/proc/" << _pid << "/cmdline";
auto ifs = std::ifstream{ fcmdline.str().c_str() };
if(ifs)
{
std::string sarg;
while(std::getline(ifs, sarg, '\0'))
{
_cmdline.push_back(sarg);
}
ifs.close();
}
return _cmdline;
}
void
2025-08-19 22:01:04 -04:00
rocprofsys_preinit_cache()
2025-07-28 17:33:52 +02:00
{
2025-08-19 22:01:04 -04:00
auto _cmd_line = read_command_line(getpid());
2025-07-28 17:33:52 +02:00
if(_cmd_line.empty())
{
_cmd_line.emplace_back("rocprofiler-systems");
}
2025-08-19 22:01:04 -04:00
trace_cache::get_metadata_registry().set_process(
{ getpid(), getppid(), _cmd_line.at(0) });
2025-07-28 17:33:52 +02:00
}
void
rocprofsys_preinit_cpu_agents()
{
cpu::query_cpu_agents();
}
2022-09-26 07:52:14 -05:00
void
rocprofsys_preinit_hidden()
2022-09-26 07:52:14 -05:00
{
// run once and discard
_preinit_callback();
_preinit_callback = []() {};
}
2022-02-08 17:42:17 -06:00
} // namespace
extern "C" void
rocprofsys_set_mpi_hidden(bool use, bool attached)
2022-02-08 17:42:17 -06:00
{
2022-04-25 17:00:52 -05:00
static bool _once = false;
static auto _args = std::make_pair(use, attached);
// this function may be called multiple times if multiple libraries are instrumented
// we want to guard against multiple calls which with different arguments
if(_once && std::tie(_args.first, _args.second) == std::tie(use, attached)) return;
_once = true;
2022-02-08 17:42:17 -06:00
// just search env to avoid initializing the settings
ROCPROFSYS_CONDITIONAL_PRINT_F(get_debug_init() || get_verbose_env() > 2,
"use: %s, attached: %s\n", (use) ? "y" : "n",
(attached) ? "y" : "n");
2022-02-08 17:42:17 -06:00
_set_mpi_called = true;
config::is_attached() = attached;
if(use && !attached && get_state() == State::PreInit)
2022-02-08 17:42:17 -06:00
{
tim::set_env("ROCPROFSYS_USE_PID", "ON", 1);
2022-02-08 17:42:17 -06:00
}
else if(!use)
{
trait::runtime_enabled<mpi_gotcha_t>::set(false);
}
2022-09-26 07:52:14 -05:00
if(get_state() >= State::Init)
{
ROCPROFSYS_WARNING_F(
2022-09-26 07:52:14 -05:00
0,
"rocprofsys_set_mpi(use=%s, attached=%s) called after rocprof-sys was "
2022-09-26 07:52:14 -05:00
"initialized. state = %s. MPI support may not be properly initialized. Use "
"ROCPROFSYS_USE_MPIP=ON and ROCPROFSYS_USE_PID=ON to ensure full support\n",
2022-09-26 07:52:14 -05:00
std::to_string(use).c_str(), std::to_string(attached).c_str(),
std::to_string(get_state()).c_str());
}
2022-02-08 17:42:17 -06:00
rocprofsys_preinit_hidden();
2022-02-08 17:42:17 -06:00
}
//======================================================================================//
extern "C" void
rocprofsys_init_library_hidden()
2022-02-08 17:42:17 -06:00
{
auto _tid = threading::get_id();
(void) _tid;
2022-03-07 20:40:48 -06:00
static bool _once = false;
auto _debug_init = get_debug_init();
int _selinux_mode = 0;
{
std::ifstream _fenforcing{ "/sys/fs/selinux/enforce" };
if(!(_fenforcing >> _selinux_mode)) _selinux_mode = 0;
_fenforcing.close();
}
if(_selinux_mode == 1)
{
ROCPROFSYS_BASIC_VERBOSE(0, "/sys/fs/selinux/enforce has a value of %i. \n",
_selinux_mode);
std::cerr << "SELinux enforcing mode detected. Consider disabling SELinux "
<< "or configure permissive mode with 'sudo setenforce 0'. Aborting.\n";
std::exit(EXIT_FAILURE);
}
ROCPROFSYS_CONDITIONAL_BASIC_PRINT_F(_debug_init, "State is %s...\n",
std::to_string(get_state()).c_str());
2022-03-07 20:40:48 -06:00
ROCPROFSYS_CI_THROW(get_state() != State::PreInit, "State is not PreInit :: %s",
std::to_string(get_state()).c_str());
2022-03-07 20:40:48 -06:00
if(get_state() != State::PreInit || get_state() == State::Init || _once) return;
_once = true;
2022-02-25 03:56:41 -06:00
ROCPROFSYS_SCOPED_THREAD_STATE(ThreadState::Internal);
2022-05-08 04:40:10 -05:00
ROCPROFSYS_CONDITIONAL_BASIC_PRINT_F(_debug_init, "State is %s. Setting to %s...\n",
std::to_string(get_state()).c_str(),
std::to_string(State::Init).c_str());
2022-02-25 03:56:41 -06:00
ROCPROFSYS_CONDITIONAL_BASIC_PRINT_F(
2022-03-07 20:40:48 -06:00
_debug_init, "Calling backtrace once so that the one-time call of malloc in "
"glibc's backtrace() occurs...\n");
2022-02-25 03:56:41 -06:00
{
std::stringstream _ss{};
2022-08-31 01:24:31 -05:00
timemory_print_backtrace<16>(_ss);
2022-02-25 03:56:41 -06:00
(void) _ss;
}
2022-02-08 17:42:17 -06:00
2022-03-07 20:40:48 -06:00
set_state(State::Init);
ROCPROFSYS_CI_THROW(get_state() != State::Init,
"set_state(State::Init) failed. state is %s",
std::to_string(get_state()).c_str());
ROCPROFSYS_CONDITIONAL_BASIC_PRINT_F(_debug_init, "Configuring settings...\n");
2022-02-25 03:56:41 -06:00
// configure the settings
configure_settings();
2022-02-08 17:42:17 -06:00
auto _debug_value = get_debug();
if(_debug_init) config::set_setting_value("ROCPROFSYS_DEBUG", true);
2022-02-08 17:42:17 -06:00
scope::destructor _debug_dtor{ [_debug_value, _debug_init]() {
if(_debug_init) config::set_setting_value("ROCPROFSYS_DEBUG", _debug_value);
2022-02-08 17:42:17 -06:00
} };
ROCPROFSYS_CONDITIONAL_BASIC_PRINT_F(_debug_init, "\n");
2022-02-08 17:42:17 -06:00
}
//======================================================================================//
2022-02-19 02:00:59 -06:00
extern "C" bool
rocprofsys_init_tooling_hidden(void)
2022-02-08 17:42:17 -06:00
{
if(get_env("ROCPROFSYS_MONOCHROME", false, false)) tim::log::monochrome() = true;
2022-09-30 10:47:07 -05:00
if(!tim::get_env("ROCPROFSYS_INIT_TOOLING", true))
2022-04-21 22:59:50 -05:00
{
rocprofsys_init_library_hidden();
2022-04-21 22:59:50 -05:00
return false;
}
2025-03-27 16:02:17 +01:00
#if ROCPROFSYS_USE_ROCM > 0
dynamic_library _amdhip64{ "ROCPROFSYS_ROCTRACER_LIBAMDHIP64",
find_library_path("libamdhip64.so",
{ "ROCPROFSYS_ROCM_PATH", "ROCM_PATH" },
{ ROCPROFSYS_DEFAULT_ROCM_PATH }) };
#endif
2025-07-28 17:33:52 +02:00
static pid_t _once = 0;
static auto _debug_init = get_debug_init();
2022-02-25 03:56:41 -06:00
ROCPROFSYS_CONDITIONAL_BASIC_PRINT_F(_debug_init, "State is %s...\n",
std::to_string(get_state()).c_str());
2022-02-25 03:56:41 -06:00
2025-07-28 17:33:52 +02:00
if(get_state() != State::PreInit || get_state() == State::Init || _once == getpid())
{
return false;
}
2025-07-28 17:33:52 +02:00
_once = getpid();
2022-02-08 17:42:17 -06:00
ROCPROFSYS_SCOPED_THREAD_STATE(ThreadState::Internal);
2022-05-08 04:40:10 -05:00
ROCPROFSYS_CONDITIONAL_THROW(
2022-02-08 17:42:17 -06:00
get_state() == State::Init,
"%s called after rocprofsys_init_library() was explicitly called",
ROCPROFSYS_FUNCTION);
2022-02-08 17:42:17 -06:00
ROCPROFSYS_CONDITIONAL_BASIC_PRINT_F(get_verbose_env() >= 0,
"Instrumentation mode: %s\n",
std::to_string(config::get_mode()).c_str());
2022-02-25 03:56:41 -06:00
ROCPROFSYS_CONDITIONAL_BASIC_PRINT_F(_debug_init, "Printing banner...\n");
2022-02-08 17:42:17 -06:00
if(get_verbose_env() >= 0) print_banner();
ROCPROFSYS_CONDITIONAL_BASIC_PRINT_F(_debug_init,
"Calling rocprofsys_init_library()...\n");
2022-02-25 03:56:41 -06:00
rocprofsys_init_library_hidden();
2022-02-08 17:42:17 -06:00
ROCPROFSYS_DEBUG_F("\n");
2022-02-08 17:42:17 -06:00
auto _dtor = scope::destructor{ []() {
2022-05-08 04:40:10 -05:00
// if set to finalized, don't continue
if(get_state() > State::Active) return;
2025-07-28 17:33:52 +02:00
#if !(ROCPROFSYS_USE_ROCM > 0)
rocprofsys_preinit_cpu_agents();
#endif
2025-08-19 22:01:04 -04:00
rocprofsys_preinit_cache();
2025-07-28 17:33:52 +02:00
if(get_use_process_sampling())
{
ROCPROFSYS_SCOPED_SAMPLING_ON_CHILD_THREADS(false);
process_sampler::setup();
2022-04-27 16:56:38 -05:00
}
2023-01-24 18:53:23 -06:00
if(get_use_causal())
2022-04-27 16:56:38 -05:00
{
2023-01-24 18:53:23 -06:00
{
ROCPROFSYS_SCOPED_SAMPLING_ON_CHILD_THREADS(false);
2023-01-24 18:53:23 -06:00
causal::sampling::setup();
}
push_enable_sampling_on_child_threads(get_use_causal());
sampling::unblock_signals();
}
2023-01-24 18:53:23 -06:00
else if(get_use_sampling())
{
2023-01-24 18:53:23 -06:00
{
ROCPROFSYS_SCOPED_SAMPLING_ON_CHILD_THREADS(false);
2023-01-24 18:53:23 -06:00
sampling::setup();
}
push_enable_sampling_on_child_threads(get_use_sampling());
sampling::unblock_signals();
}
2022-02-08 17:42:17 -06:00
get_main_bundle()->start();
ROCPROFSYS_DEBUG_F("State: %s -> State::Active\n",
std::to_string(get_state()).c_str());
trace_cache::get_buffer_storage().start_flushing_thread(getpid());
2022-04-27 16:56:38 -05:00
set_state(State::Active); // set to active as very last operation
} };
ROCPROFSYS_SCOPED_SAMPLING_ON_CHILD_THREADS(false);
2022-09-26 07:52:14 -05:00
// ideally these have already been started
rocprofsys_preinit_hidden();
2022-09-26 07:52:14 -05:00
// start these gotchas once settings have been initialized
2022-10-21 17:39:08 -05:00
if(get_init_bundle()) get_init_bundle()->start();
if(get_use_vaapi_tracing())
{
ROCPROFSYS_VERBOSE_F(1, "Setting up VA-API traces...\n");
component::vaapi_gotcha::start();
}
if(get_use_sampling()) sampling::block_signals();
2023-06-15 22:37:33 -05:00
// perfetto initialization
if(get_use_perfetto())
{
ROCPROFSYS_VERBOSE_F(1, "Setting up Perfetto...\n");
rocprofsys::perfetto::setup();
2023-06-15 22:37:33 -05:00
}
2022-09-26 07:52:14 -05:00
tasking::setup();
2022-05-08 04:40:10 -05:00
2023-01-24 18:53:23 -06:00
if(get_use_causal()) causal::start_experimenting();
if(get_use_timemory())
{
comp::user_global_bundle::global_init();
std::set<int> _comps{};
// convert string into set of enumerations
for(auto&& itr : tim::delimit(tim::settings::global_components()))
_comps.emplace(tim::runtime::enumerate(itr));
if(_comps.size() == 1 && _comps.find(TIMEMORY_WALL_CLOCK) != _comps.end())
{
// using wall_clock directly is lower overhead than using it via user_bundle
instrumentation_bundle_t::get_initializer() =
[](instrumentation_bundle_t& _bundle) {
_bundle.initialize<comp::wall_clock>();
};
}
else if(!_comps.empty())
{
// use user_bundle for other than wall-clock
instrumentation_bundle_t::get_initializer() =
[](instrumentation_bundle_t& _bundle) {
_bundle.initialize<comp::user_global_bundle>();
};
}
else
{
tim::trait::runtime_enabled<project::rocprofsys>::set(false);
}
}
2021-08-17 17:34:34 -05:00
2023-02-27 12:09:03 -06:00
if(get_use_perfetto())
2021-08-06 13:08:57 -05:00
{
ROCPROFSYS_VERBOSE_F(1, "Starting Perfetto...\n");
rocprofsys::perfetto::start();
2021-08-06 13:08:57 -05:00
}
2023-02-03 14:10:42 -06:00
categories::setup();
2021-08-06 13:08:57 -05:00
// if static objects are destroyed in the inverse order of when they are
// created this should ensure that finalization is called before perfetto
// ends the tracing session
static auto _ensure_finalization = ensure_finalization();
2021-08-17 17:34:34 -05:00
2021-08-06 13:08:57 -05:00
return true;
}
2022-02-08 17:42:17 -06:00
//======================================================================================//
2022-01-27 21:31:08 -06:00
extern "C" void
rocprofsys_init_hidden(const char* _mode, bool _is_binary_rewrite, const char* _argv0_c)
2021-08-06 13:08:57 -05:00
{
2022-04-25 17:00:52 -05:00
static int _total_count = 0;
static auto _args = std::make_pair(std::string_view{ _mode }, _is_binary_rewrite);
auto _count = _total_count++;
auto _mode_sv = std::string_view{ _mode };
2023-01-24 18:53:23 -06:00
auto _argv0 = (_argv0_c) ? std::string{ _argv0_c } : config::get_exe_name();
2022-04-25 17:00:52 -05:00
// this function may be called multiple times if multiple libraries are instrumented
// we want to guard against multiple calls which with different arguments
if(_count > 0 &&
std::tie(_args.first, _args.second) == std::tie(_mode_sv, _is_binary_rewrite))
return;
ROCPROFSYS_CONDITIONAL_THROW(
2022-04-25 17:00:52 -05:00
_count > 0 &&
std::tie(_args.first, _args.second) != std::tie(_mode_sv, _is_binary_rewrite),
"\nrocprofsys_init(...) called multiple times with different arguments for mode "
2022-04-25 17:00:52 -05:00
"and/or is_binary_rewrite:"
"\n Invocation #1: rocprofsys_init(mode=%-8s, is_binary_rewrite=%-5s, ...)"
"\n Invocation #%i: rocprofsys_init(mode=%-8s, is_binary_rewrite=%-5s, ...)",
2022-04-25 17:00:52 -05:00
_args.first.data(), std::to_string(_args.second).c_str(), _count + 1, _mode,
std::to_string(_is_binary_rewrite).c_str());
2022-02-08 17:42:17 -06:00
// always the first
2022-02-25 03:56:41 -06:00
(void) get_state();
(void) tracing::push_count();
(void) tracing::pop_count();
2022-02-25 03:56:41 -06:00
2022-09-26 07:52:14 -05:00
if(get_state() >= State::Init)
{
if(std::string_view{ _mode } != "trace" && std::string_view{ _mode } != "Trace")
{
ROCPROFSYS_WARNING_F(
2022-09-26 07:52:14 -05:00
0,
"rocprofsys_init(mode=%s, is_binary_rewrite=%s, argv0=%s) "
"called after rocprof-sys was initialized. state = %s. Mode-based "
"settings (via -M <MODE> passed to rocprof-sys exe) may not be "
"properly configured.\n",
2023-01-24 18:53:23 -06:00
_mode, std::to_string(_is_binary_rewrite).c_str(), _argv0.c_str(),
2022-09-26 07:52:14 -05:00
std::to_string(get_state()).c_str());
}
}
2022-04-25 17:00:52 -05:00
2023-01-24 18:53:23 -06:00
tracing::get_finalization_functions().emplace_back([_argv0_c]() {
ROCPROFSYS_CI_THROW(get_state() != State::Active,
"Finalizer function for popping main invoked in non-active "
"state :: state = %s\n",
std::to_string(get_state()).c_str());
2022-03-07 20:40:48 -06:00
if(get_state() == State::Active)
{
2023-01-24 18:53:23 -06:00
auto _name = (_argv0_c) ? std::string{ _argv0_c } : config::get_exe_name();
2022-03-07 20:40:48 -06:00
// if main hasn't been popped yet, pop it
ROCPROFSYS_BASIC_VERBOSE(2, "Running rocprofsys_pop_trace(%s)...\n",
_name.c_str());
rocprofsys_pop_trace_hidden(_name.c_str());
2022-03-07 20:40:48 -06:00
}
2022-02-25 03:56:41 -06:00
});
std::atexit([]() {
2022-05-08 04:40:10 -05:00
// if active (not already finalized) then we should finalize
if(get_state() == State::Active) rocprofsys_finalize_hidden();
2022-02-25 03:56:41 -06:00
});
set_metadata_process_start_timestamp(comp::wall_clock::record());
ROCPROFSYS_CONDITIONAL_BASIC_PRINT_F(
2022-02-08 17:42:17 -06:00
get_debug_env() || get_verbose_env() > 2,
2022-03-22 15:51:57 -05:00
"mode: %s | is binary rewrite: %s | command: %s\n", _mode,
2023-01-24 18:53:23 -06:00
(_is_binary_rewrite) ? "y" : "n", _argv0.c_str());
tim::set_env("ROCPROFSYS_MODE", _mode, 0);
2022-02-08 17:42:17 -06:00
config::is_binary_rewrite() = _is_binary_rewrite;
2021-08-06 13:08:57 -05:00
2022-09-26 07:52:14 -05:00
if(_set_mpi_called)
2021-08-06 13:08:57 -05:00
{
rocprofsys_preinit_hidden();
2021-08-06 13:08:57 -05:00
}
2022-01-27 21:31:08 -06:00
}
2021-08-06 13:08:57 -05:00
2022-02-08 17:42:17 -06:00
//======================================================================================//
2021-08-06 13:08:57 -05:00
2022-10-21 17:39:08 -05:00
extern "C" void
rocprofsys_reset_preload_hidden(void)
2022-10-21 17:39:08 -05:00
{
tim::set_env("ROCPROFSYS_PRELOAD", "0", 1);
auto&& _preload_libs = common::get_env("LD_PRELOAD", std::string{});
if(_preload_libs.find("librocprof-sys") != std::string::npos)
2022-10-21 17:39:08 -05:00
{
auto _modified_preload = std::string{};
for(const auto& itr : delimit(_preload_libs, ":"))
{
if(itr.find("librocprof-sys") != std::string::npos) continue;
2022-10-21 17:39:08 -05:00
_modified_preload += common::join("", ":", itr);
}
if(!_modified_preload.empty() && _modified_preload.find(':') == 0)
_modified_preload = _modified_preload.substr(1);
tim::set_env("LD_PRELOAD", _modified_preload, 1);
}
}
//======================================================================================//
2022-01-27 21:31:08 -06:00
extern "C" void
rocprofsys_finalize_hidden(void)
2022-01-27 21:31:08 -06:00
{
2022-04-26 22:08:51 -05:00
// disable thread id recycling during finalization
threading::recycle_ids() = false;
2023-01-24 18:53:23 -06:00
// disable initialization callback
threading::remove_callback(&ensure_initialization);
2022-04-26 22:08:51 -05:00
2023-02-08 01:31:38 -06:00
bool _is_child = is_child_process();
2022-05-08 04:40:10 -05:00
set_thread_state(ThreadState::Completed);
2022-01-27 21:31:08 -06:00
// return if not active
2022-02-19 02:00:59 -06:00
if(get_state() != State::Active)
{
ROCPROFSYS_BASIC_DEBUG_F("State = %s. Finalization skipped\n",
std::to_string(get_state()).c_str());
2022-02-19 02:00:59 -06:00
return;
}
set_metadata_process_end_timestamp(comp::wall_clock::record());
if(_is_child)
2023-02-08 01:31:38 -06:00
{
set_state(State::Finalized);
2025-07-28 17:33:52 +02:00
#if defined(ROCPROFSYS_USE_ROCM) && ROCPROFSYS_USE_ROCM > 0
// Flush buffered traces in case of child process
if(get_use_rocm())
{
ROCPROFSYS_VERBOSE_F(1, "Shutting down ROCm...\n");
rocprofiler_sdk::shutdown();
}
#endif
auto& _manager = rocprofsys::trace_cache::cache_manager::get_instance();
const auto _agents = get_agent_manager_instance().get_agents();
2025-08-19 22:01:04 -04:00
_manager.shutdown();
const auto metadata_filepath =
trace_cache::get_metadata_filepath(get_root_process_id(), getpid());
_manager.get_metadata_registry().save_to_file(metadata_filepath, _agents);
2025-08-19 22:01:04 -04:00
2023-02-08 01:31:38 -06:00
std::quick_exit(EXIT_SUCCESS);
return;
}
2022-10-19 03:30:00 -05:00
if(get_verbose() >= 0 || get_debug()) fprintf(stderr, "\n");
ROCPROFSYS_VERBOSE_F(0, "finalizing...\n");
2022-09-26 07:52:14 -05:00
sampling::block_samples();
2022-08-31 01:24:31 -05:00
thread_info::set_stop(comp::wall_clock::record());
2022-10-04 00:00:05 -05:00
tim::signals::block_signals(get_sampling_signals(),
tim::signals::sigmask_scope::process);
2022-04-27 16:56:38 -05:00
rocprofsys_reset_preload_hidden();
2022-10-21 17:39:08 -05:00
2022-02-25 03:56:41 -06:00
// some functions called during finalization may alter the push/pop count so we need
// to save them here
auto _push_count = tracing::push_count().load();
auto _pop_count = tracing::pop_count().load();
2022-02-23 06:59:32 -06:00
// e.g. rocprofsys_pop_trace("main");
2022-02-25 03:56:41 -06:00
if(_push_count > _pop_count)
2022-02-23 06:59:32 -06:00
{
for(auto& itr : tracing::get_finalization_functions())
2022-02-23 06:59:32 -06:00
{
2022-02-25 03:56:41 -06:00
itr();
++_pop_count;
2022-02-23 06:59:32 -06:00
}
}
2022-03-07 20:40:48 -06:00
set_state(State::Finalized);
2022-02-25 03:56:41 -06:00
push_enable_sampling_on_child_threads(false);
set_sampling_on_all_future_threads(false);
2022-02-08 17:42:17 -06:00
2023-02-03 14:10:42 -06:00
// if the categories are not enabled, it can/will suppress generating output for data
// in category
categories::enable_categories();
2022-02-08 17:42:17 -06:00
auto _debug_init = get_debug_finalize();
auto _debug_value = get_debug();
if(_debug_init) config::set_setting_value("ROCPROFSYS_DEBUG", true);
2022-02-08 17:42:17 -06:00
scope::destructor _debug_dtor{ [_debug_value, _debug_init]() {
if(_debug_init) config::set_setting_value("ROCPROFSYS_DEBUG", _debug_value);
2022-02-08 17:42:17 -06:00
} };
auto& _thread_bundle = thread_data<thread_bundle_t>::instance();
2022-02-08 17:42:17 -06:00
if(_thread_bundle) _thread_bundle->stop();
2022-09-30 10:47:07 -05:00
if(get_verbose() >= 1 || get_debug())
{
if(dmp::rank() == 0)
{
ROCPROFSYS_PRINT_F("\n");
config::print_settings(
tim::get_env<bool>("ROCPROFSYS_PRINT_ENV", get_debug()));
2022-09-30 10:47:07 -05:00
}
}
ROCPROFSYS_VERBOSE_F(1, "rocprofsys_push_trace :: called %zux\n", _push_count);
ROCPROFSYS_VERBOSE_F(1, "rocprofsys_pop_trace :: called %zux\n", _pop_count);
2022-02-25 03:56:41 -06:00
tim::signals::enable_signal_detection({ tim::signals::sys_signal::Interrupt },
[](int) {});
ROCPROFSYS_DEBUG_F("Copying over all timemory hash information to main thread...\n");
2023-10-16 18:04:47 -05:00
tracing::copy_timemory_hash_ids();
2023-02-27 12:09:03 -06:00
// stop the main bundle which has stats for run
2022-08-31 01:24:31 -05:00
if(get_main_bundle())
{
ROCPROFSYS_DEBUG_F("Stopping main bundle...\n");
2022-08-31 01:24:31 -05:00
get_main_bundle()->stop();
}
2023-01-24 18:53:23 -06:00
fini_bundle_t _finalization{};
_finalization.start();
if(get_use_vaapi_tracing())
{
ROCPROFSYS_VERBOSE_F(1, "Shutting down VA-API tracing...\n");
component::vaapi_gotcha::shutdown();
}
2024-12-13 18:48:39 -05:00
#if defined(ROCPROFSYS_USE_ROCM) && ROCPROFSYS_USE_ROCM > 0
if(get_use_rocm())
2024-12-13 18:48:39 -05:00
{
ROCPROFSYS_VERBOSE_F(1, "Shutting down ROCm...\n");
rocprofiler_sdk::shutdown();
}
#endif
ROCPROFSYS_DEBUG_F("Stopping and destroying instrumentation bundles...\n");
2023-10-16 18:04:47 -05:00
for(size_t i = 0; i < thread_info::get_peak_num_threads(); ++i)
2022-02-25 03:56:41 -06:00
{
2023-10-16 18:04:47 -05:00
if(!instrumentation_bundles::get()) continue;
2022-09-21 13:58:14 -05:00
const auto& _info = thread_info::get(i, SequentTID);
2023-10-16 18:04:47 -05:00
auto& itr = instrumentation_bundles::get()->at(i);
while(itr != nullptr && !itr->empty())
2022-02-25 03:56:41 -06:00
{
2022-08-31 01:24:31 -05:00
int _lvl = 1;
if(_info->is_offset)
{
++_pop_count;
_lvl = 4;
}
ROCPROFSYS_VERBOSE_F(
_lvl,
"Warning! instrumentation bundle on thread %zu (TID=%li) "
"with label '%s' was not stopped.\n",
i, itr->back()->tid(), itr->back()->key().c_str());
2023-10-16 18:04:47 -05:00
itr->back()->stop();
itr->back()->pop();
itr->pop_back();
2022-02-25 03:56:41 -06:00
}
}
// stop the main gotcha which shuts down the pthread gotchas
if(get_init_bundle())
{
ROCPROFSYS_DEBUG_F("Stopping main gotcha...\n");
get_init_bundle()->stop();
2023-02-27 12:09:03 -06:00
pthread_gotcha::shutdown();
component::numa_gotcha::shutdown();
}
2022-01-27 21:31:08 -06:00
// stop the gotcha bundle
if(get_preinit_bundle())
2022-01-27 21:31:08 -06:00
{
ROCPROFSYS_VERBOSE_F(1, "Shutting down miscellaneous gotchas...\n");
get_preinit_bundle()->stop();
2022-08-31 01:24:31 -05:00
component::mpi_gotcha::shutdown();
2022-01-27 21:31:08 -06:00
}
2021-08-06 13:08:57 -05:00
if(get_use_process_sampling())
2022-04-27 16:56:38 -05:00
{
ROCPROFSYS_VERBOSE_F(1, "Shutting down background sampler...\n");
process_sampler::shutdown();
2022-04-27 16:56:38 -05:00
}
2023-01-24 18:53:23 -06:00
if(get_use_causal())
{
ROCPROFSYS_VERBOSE_F(1, "Shutting down causal sampling...\n");
2023-01-24 18:53:23 -06:00
causal::sampling::shutdown();
}
2022-08-31 01:24:31 -05:00
if(get_use_sampling())
{
ROCPROFSYS_VERBOSE_F(1, "Shutting down sampling...\n");
2022-08-31 01:24:31 -05:00
sampling::shutdown();
}
2021-09-15 16:45:49 -05:00
ROCPROFSYS_VERBOSE_F(3, "Reporting the process- and thread-level metrics...\n");
2022-08-31 01:24:31 -05:00
// report the high-level metrics for the process
2022-01-27 21:31:08 -06:00
if(get_main_bundle())
{
ROCPROFSYS_VERBOSE_F(0, "\n");
2022-01-27 21:31:08 -06:00
std::string _msg = JOIN("", *get_main_bundle());
auto _pos = _msg.find(">>> ");
if(_pos != std::string::npos) _msg = _msg.substr(_pos + 5);
ROCPROFSYS_VERBOSE_F(0, "%s\n", _msg.c_str());
ROCPROFSYS_DEBUG_F("Resetting main bundle...\n");
2022-04-05 00:24:34 -05:00
get_main_bundle()->reset();
2022-01-27 21:31:08 -06:00
}
2022-01-27 21:31:08 -06:00
// print out thread-data if they are not still running
// if they are still running (e.g. thread-pool still alive), the
// thread-specific data will be wrong if try to stop them from
// the main thread.
2023-01-24 18:53:23 -06:00
auto _thr_verbose = (config::get_use_causal()) ? 1 : 0;
2023-10-16 18:04:47 -05:00
if(thread_data<thread_bundle_t>::get())
2022-01-27 21:31:08 -06:00
{
2023-10-16 18:04:47 -05:00
for(auto& itr : *thread_data<thread_bundle_t>::get())
2021-08-17 17:34:34 -05:00
{
2023-10-16 18:04:47 -05:00
if(itr && itr->get<comp::wall_clock>() &&
!itr->get<comp::wall_clock>()->get_is_running())
{
std::string _msg = JOIN("", *itr);
auto _pos = _msg.find(">>> ");
if(_pos != std::string::npos) _msg = _msg.substr(_pos + 5);
ROCPROFSYS_VERBOSE_F(_thr_verbose, "%s\n", _msg.c_str());
2023-10-16 18:04:47 -05:00
}
2021-08-17 17:34:34 -05:00
}
2022-01-27 21:31:08 -06:00
}
2021-08-17 17:34:34 -05:00
ROCPROFSYS_VERBOSE_F(0, "\n");
2022-01-27 21:31:08 -06:00
// ensure that all the MT instances are flushed
if(get_use_sampling())
{
ROCPROFSYS_VERBOSE_F(1, "Post-processing the sampling backtraces...\n");
2022-08-31 01:24:31 -05:00
sampling::post_process();
2022-01-27 21:31:08 -06:00
}
2023-01-24 18:53:23 -06:00
if(get_use_causal())
{
ROCPROFSYS_VERBOSE_F(1, "Finishing the causal experiments...\n");
2023-01-24 18:53:23 -06:00
causal::finish_experimenting();
}
if(get_use_process_sampling())
2022-04-27 16:56:38 -05:00
{
ROCPROFSYS_VERBOSE_F(1, "Post-processing the system-level samples...\n");
process_sampler::post_process();
2022-04-27 16:56:38 -05:00
}
2022-02-08 17:42:17 -06:00
2024-12-13 18:48:39 -05:00
// shutdown tasking before timemory is finalized
ROCPROFSYS_VERBOSE_F(1, "Shutting down thread-pools...\n");
tasking::shutdown();
if(get_use_code_coverage())
{
ROCPROFSYS_VERBOSE_F(1, "Post-processing the code coverage...\n");
coverage::post_process();
}
2023-10-16 18:04:47 -05:00
tracing::copy_timemory_hash_ids();
2022-01-27 21:31:08 -06:00
bool _perfetto_output_error = false;
2023-02-27 12:09:03 -06:00
if(get_use_perfetto())
2022-01-27 21:31:08 -06:00
{
ROCPROFSYS_VERBOSE_F(0, "Finalizing perfetto...\n");
rocprofsys::perfetto::post_process(_timemory_manager.get(),
_perfetto_output_error);
2022-01-27 21:31:08 -06:00
}
2021-08-17 17:34:34 -05:00
{
auto& _manager = rocprofsys::trace_cache::cache_manager::get_instance();
_manager.shutdown();
_manager.post_process_bulk();
}
if(_timemory_manager && _timemory_manager != nullptr)
{
_timemory_manager->add_metadata([](auto& ar) {
auto _maps = tim::procfs::read_maps(process::get_id());
auto _libs = std::set<std::string>{};
for(auto& itr : _maps)
{
auto&& _path = itr.pathname;
2022-10-31 15:39:45 -05:00
if(!_path.empty() && _path.at(0) != '[' && filepath::exists(_path))
_libs.emplace(_path);
}
ar(tim::cereal::make_nvp("memory_maps_files", _libs),
tim::cereal::make_nvp("memory_maps", _maps));
});
2022-05-19 16:07:11 -05:00
ROCPROFSYS_VERBOSE_F(1, "Finalizing timemory...\n");
tim::timemory_finalize(_timemory_manager.get());
2022-02-23 06:59:32 -06:00
2022-10-31 22:23:10 -05:00
auto _cfg = settings::compose_filename_config{};
_cfg.use_suffix = config::get_use_pid();
2023-06-14 11:55:22 -05:00
_cfg.suffix = settings::default_process_suffix();
_timemory_manager->write_metadata(settings::get_global_output_prefix(),
"rocprofsys", _cfg);
2022-09-26 07:52:14 -05:00
}
2023-02-03 14:10:42 -06:00
categories::shutdown();
2023-01-24 18:53:23 -06:00
_finalization.stop();
2022-01-27 21:31:08 -06:00
if(_perfetto_output_error)
{
ROCPROFSYS_THROW("Error opening perfetto output file: %s",
get_perfetto_output_filename().c_str());
2022-01-27 21:31:08 -06:00
}
2022-02-25 03:56:41 -06:00
ROCPROFSYS_CI_THROW(
_push_count > _pop_count, "%s",
2022-02-25 03:56:41 -06:00
TIMEMORY_JOIN(" ",
"rocprofsys_push_trace was called more times than "
"rocprofsys_pop_trace. The inverse is fine but the current state "
2022-02-25 03:56:41 -06:00
"means not every measurement was ended :: pushed:",
_push_count, "vs. popped:", _pop_count)
.c_str());
2023-02-08 01:31:38 -06:00
debug::close_file();
2022-07-17 21:52:09 -05:00
config::finalize();
ROCPROFSYS_VERBOSE_F(0, "Finalized: %s\n", _finalization.as_string().c_str());
2023-02-08 01:31:38 -06:00
tim::signals::enable_signal_detection(
{ tim::signals::sys_signal::SegFault, tim::signals::sys_signal::Stop },
[](int) {});
2024-12-13 18:48:39 -05:00
common::destroy_static_objects();
2021-08-17 17:34:34 -05:00
}
2022-02-08 17:42:17 -06:00
//======================================================================================//
2021-08-06 13:08:57 -05:00
namespace
{
// if static objects are destroyed randomly (relatively uncommon behavior)
// this might call finalization before perfetto ends the tracing session
// but static variable in rocprofsys_init_tooling_hidden is more likely
auto _ensure_finalization = ensure_finalization(true);
2022-09-26 07:52:14 -05:00
auto _manager = tim::manager::instance();
auto _settings = tim::settings::shared_instance();
2021-08-06 13:08:57 -05:00
} // namespace