SDK: remove majority of exceptions (#176)

* SDK: remove majority of exceptions

- replace with ROCP_FATAL, ROCP_CI_LOG(WARNING), etc.
- improve logging of symbolic link
- add --readlink and --realpath (hidden options) to rocprofv3 to follow symlinks for preloaded libraries

* Add rocprofv3 --rocm-root argument

* Fix registration resolved_exists

* Fix rocprofv3_avail.py

* Update logging for rocprofiler_configure search

- relax failure conditions

* Misc clang-tidy fixes

* Fix merge

* Fix merge

---------

Co-authored-by: Jonathan R. Madsen <jonathanrmadsen@gmail.com>
Co-authored-by: Bhardwaj, Gopesh <Gopesh.Bhardwaj@amd.com>
This commit is contained in:
Madsen, Jonathan
2025-02-18 10:44:37 -06:00
committed by GitHub
parent fd99654433
commit 470f347e50
17 changed files with 270 additions and 140 deletions
+51 -28
View File
@@ -207,11 +207,17 @@ read_file(const std::string& fname)
auto data = std::vector<std::string>{};
if(!is_readable(fs::path{fname}))
throw std::runtime_error{fmt::format("file '{}' cannot be read", fname)};
{
ROCP_CI_LOG(WARNING) << fmt::format("file '{}' cannot be read", fname);
return data;
}
auto ifs = std::ifstream{fname};
if(!ifs || !ifs.good())
throw std::runtime_error{fmt::format("file '{}' cannot be read", fname)};
{
ROCP_CI_LOG(WARNING) << fmt::format("file '{}' cannot be read", fname);
return data;
}
while(true)
{
@@ -231,11 +237,17 @@ read_map(const std::string& fname)
auto data = std::unordered_map<std::string, std::string>{};
if(!is_readable(fs::path{fname}))
throw std::runtime_error{fmt::format("file '{}' cannot be read", fname)};
{
ROCP_CI_LOG(WARNING) << fmt::format("file '{}' cannot be read", fname);
return data;
}
auto ifs = std::ifstream{fname};
if(!ifs || !ifs.good())
throw std::runtime_error{fmt::format("file '{}' cannot be read", fname)};
{
ROCP_CI_LOG(WARNING) << fmt::format("file '{}' cannot be read", fname);
return data;
}
auto last_label = std::string{};
while(true)
@@ -247,17 +259,23 @@ read_map(const std::string& fname)
auto entry = std::string{};
ifs >> entry;
if(ifs.eof())
throw std::runtime_error{
fmt::format("unexpected file format in '{}' at {}", fname, label)};
{
ROCP_CI_LOG(WARNING) << fmt::format(
"unexpected file format in '{}' at {}", fname, label);
continue;
}
auto ret = data.emplace(label, entry);
if(!ret.second)
throw std::runtime_error{
fmt::format("duplicate entry in '{}': '{}' (='{}'). last label was '{}'",
fname,
label,
entry,
last_label)};
{
ROCP_CI_LOG(WARNING) << fmt::format(
"duplicate entry in '{}': '{}' (='{}'). last label was '{}'",
fname,
label,
entry,
last_label);
continue;
}
if(!label.empty()) last_label = std::move(label);
}
@@ -305,21 +323,22 @@ read_property(const MapT& data, const std::string& label, Tp& value)
constexpr auto max_value = std::numeric_limits<Tp>::max();
if(local_value < min_value)
{
throw std::runtime_error{
fmt::format("data with label {} has a value (={}) which is less "
"than the min value for the type (={})",
label,
local_value,
min_value)};
ROCP_CI_LOG(WARNING) << fmt::format(
"data with label {} has a value (={}) which is less "
"than the min value for the type (={})",
label,
local_value,
min_value);
return;
}
else if(local_value > max_value)
{
throw std::runtime_error{fmt::format("data with label {} has a value (={}) which is "
"greater "
"than the max value for the type (={})",
label,
local_value,
max_value)};
ROCP_CI_LOG(WARNING) << fmt::format("data with label {} has a value (={}) which is "
"greater than the max value for the type (={})",
label,
local_value,
max_value);
return;
}
if constexpr(std::is_const<Tp>::value)
@@ -544,13 +563,17 @@ using unique_agent_t = std::unique_ptr<rocprofiler_agent_t, void (*)(rocprofiler
auto
read_topology()
{
auto sysfs_nodes_path = fs::path{"/sys/class/kfd/kfd/topology/nodes/"};
auto data = std::vector<unique_agent_t>{};
const auto sysfs_nodes_path = fs::path{"/sys/class/kfd/kfd/topology/nodes"};
if(!fs::exists(sysfs_nodes_path))
throw std::runtime_error{
fmt::format("sysfs nodes path '{}' does not exist", sysfs_nodes_path.string())};
{
ROCP_CI_LOG(WARNING) << fmt::format("sysfs nodes path '{}' does not exist",
sysfs_nodes_path.string());
return data;
}
const auto& cpu_info_v = get_cpu_info();
auto data = std::vector<unique_agent_t>{};
uint64_t idcount = 0;
uint64_t nodecount = 0;
uint64_t cpucount = 0;
+6 -5
View File
@@ -124,11 +124,12 @@ rocprofiler::buffer::instance::emplace(uint32_t category, uint32_t kind, Tp& val
{
if(buffers.at(idx).capacity() < sizeof(value))
{
auto msg = std::stringstream{};
msg << "buffer " << buffer_id << " to small (size=" << buffers.at(idx).capacity()
<< ") to hold an object of type " << common::cxx_demangle(typeid(value).name())
<< " with size " << sizeof(value);
throw std::runtime_error(msg.str());
ROCP_CI_LOG(ERROR) << "buffer " << buffer_id
<< " too small (size=" << buffers.at(idx).capacity()
<< ") to hold an object of type "
<< common::cxx_demangle(typeid(value).name()) << " with size "
<< sizeof(value);
return false;
}
if(policy == ROCPROFILER_BUFFER_POLICY_LOSSLESS)
+8 -16
View File
@@ -91,18 +91,14 @@ init_cpu_pool(const AmdExtTable& api, rocprofiler::hsa::AgentCache& agent)
auto status =
api.hsa_amd_agent_iterate_memory_pools_fn(agent.near_cpu(), FindStandardPool, &params);
if(status != HSA_STATUS_SUCCESS && status != HSA_STATUS_INFO_BREAK)
{
throw std::runtime_error("Error: Command Buffer Pool is not initialized");
}
ROCP_FATAL_IF(status != HSA_STATUS_SUCCESS && status != HSA_STATUS_INFO_BREAK)
<< "HSA Command Buffer Pool is not initialized";
params.second = &agent.kernarg_pool();
status =
api.hsa_amd_agent_iterate_memory_pools_fn(agent.near_cpu(), FindKernArgPool, &(params));
if(status != HSA_STATUS_SUCCESS && status != HSA_STATUS_INFO_BREAK)
{
throw std::runtime_error("Error: Output Buffer Pool is not initialized");
}
ROCP_FATAL_IF(status != HSA_STATUS_SUCCESS && status != HSA_STATUS_INFO_BREAK)
<< "HSA Output Buffer Pool is not initialized";
}
void
@@ -113,10 +109,8 @@ init_gpu_pool(const AmdExtTable& api, rocprofiler::hsa::AgentCache& agent)
auto status =
api.hsa_amd_agent_iterate_memory_pools_fn(agent.get_hsa_agent(), FindStandardPool, &params);
if(status != HSA_STATUS_SUCCESS && status != HSA_STATUS_INFO_BREAK)
{
throw std::runtime_error("Error: GPU Pool is not initialized");
}
ROCP_FATAL_IF(status != HSA_STATUS_SUCCESS && status != HSA_STATUS_INFO_BREAK)
<< "HSA GPU Pool is not initialized";
}
} // namespace
@@ -153,10 +147,8 @@ AgentCache::init_device_counting_service_queue(const CoreApiTable& api,
UINT32_MAX,
UINT32_MAX,
&m_profile_queue);
if(status != HSA_STATUS_SUCCESS && status != HSA_STATUS_INFO_BREAK)
{
throw std::runtime_error("Error: Queue is not initialized");
}
ROCP_FATAL_IF(status != HSA_STATUS_SUCCESS && status != HSA_STATUS_INFO_BREAK)
<< "HSA Queue is not initialized";
CHECK(ext.hsa_amd_queue_set_priority_fn) << "no hsa_amd_queue_set_priority_fn in api table";
ext.hsa_amd_queue_set_priority_fn(m_profile_queue, HSA_AMD_QUEUE_PRIORITY_HIGH);
@@ -424,8 +424,8 @@ parse_event<ROCPROFILER_PAGE_MIGRATION_DROPPED_EVENT>(std::string_view str)
template <>
page_migration_record_t parse_event<ROCPROFILER_PAGE_MIGRATION_NONE>(std::string_view)
{
throw std::runtime_error(
"ROCPROFILER_PAGE_MIGRATION_NONE for parsing page migration events should not happen");
ROCP_CI_LOG(WARNING)
<< "ROCPROFILER_PAGE_MIGRATION_NONE for parsing page migration events should not happen";
}
template <size_t OpInx, size_t... OpInxs>
@@ -648,10 +648,11 @@ struct poll_kfd_t
[&]() {
const auto retcode = pipe2(&thread_pipes[0], DEFAULT_FLAGS);
if(retcode != 0)
throw std::runtime_error{
fmt::format("Pipe creation for thread notify failed with {} code\n", retcode)};
const auto _err = errno;
ROCP_FATAL_IF(retcode != 0)
<< fmt::format("Pipe creation for page-migration thread notify returned {} :: {}\n",
retcode,
strerror(_err));
}();
thread_notify = pollfd{
@@ -792,7 +793,11 @@ poll_events(small_vector<pollfd> file_handles)
auto poll_ret = poll(file_handles.data(), file_handles.size(), -1);
if(poll_ret == -1)
throw std::runtime_error{"Background thread file descriptors are invalid"};
{
ROCP_CI_LOG(WARNING)
<< "Background thread file descriptors for page-migration are invalid";
return;
}
if((exitfd.revents & POLLIN) != 0)
{
@@ -78,14 +78,16 @@ amd_intercept_marker_handler_callback(const struct amd_aql_intercept_marker_s* p
if(ext_table_->hsa_amd_queue_get_info_fn(queue, HSA_AMD_QUEUE_INFO_AGENT, &hsa_agent) !=
HSA_STATUS_SUCCESS)
{
throw std::runtime_error("Cannot map hsa_queue_t* to hsa_agent_t");
ROCP_CI_LOG(WARNING) << "Cannot map hsa_queue_t* to hsa_agent_t";
return;
}
uint64_t doorbell_id = 0;
if(ext_table_->hsa_amd_queue_get_info_fn(queue, HSA_AMD_QUEUE_INFO_DOORBELL_ID, &doorbell_id) !=
HSA_STATUS_SUCCESS)
{
throw std::runtime_error("Cannot map hsa_queue_t* to doorbell_id");
ROCP_CI_LOG(WARNING) << "Cannot map hsa_queue_t* to doorbell id";
return;
}
auto internal_correlation = packet->user_data[0];
@@ -21,12 +21,12 @@
// SOFTWARE.
#include "lib/rocprofiler-sdk/pc_sampling/ioctl/ioctl_adapter.hpp"
#include "lib/rocprofiler-sdk/details/kfd_ioctl.h"
#include "lib/common/logging.hpp"
#include "lib/rocprofiler-sdk/details/kfd_ioctl.h"
#include "lib/rocprofiler-sdk/pc_sampling/ioctl/ioctl_adapter_types.hpp"
#include <rocprofiler-sdk/fwd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
@@ -61,14 +61,15 @@ struct pc_sampling_ioctl_version_t
int
kfd_open()
{
int fd = -1;
static const char kfd_device_name[] = "/dev/kfd";
int fd = -1;
constexpr auto* kfd_device_name = "/dev/kfd";
fd = open(kfd_device_name, O_RDWR | O_CLOEXEC);
if(fd == -1)
{
throw std::runtime_error("Cannot open /dev/kfd");
ROCP_CI_LOG(WARNING) << fmt::format("Cannot open {} for pc sampling", kfd_device_name);
return -1;
}
return fd;
@@ -485,6 +486,8 @@ ioctl_pcs_create(const rocprofiler_agent_t* agent,
args.num_sample_info = 1;
args.trace_id = INVALID_TRACE_ID;
if(get_kfd_fd() == -1) return ROCPROFILER_STATUS_ERROR_NOT_AVAILABLE;
auto ioctl_ret = ioctl(get_kfd_fd(), AMDKFD_IOC_PC_SAMPLE, &args);
*ioctl_pcs_id = args.trace_id;
@@ -21,6 +21,7 @@
// SOFTWARE.
#include "lib/rocprofiler-sdk/pc_sampling/utils.hpp"
#include "lib/common/logging.hpp"
#include "lib/rocprofiler-sdk/pc_sampling/defines.hpp"
#if ROCPROFILER_SDK_HSA_PC_SAMPLING > 0
@@ -49,7 +50,7 @@ get_matching_hsa_pcs_method(rocprofiler_pc_sampling_method_t method)
case ROCPROFILER_PC_SAMPLING_METHOD_LAST: break;
}
throw std::runtime_error("Illegal pc sampling method\n");
ROCP_FATAL << "Illegal pc sampling method " << method;
}
hsa_ven_amd_pcs_units_t
@@ -66,7 +67,7 @@ get_matching_hsa_pcs_units(rocprofiler_pc_sampling_unit_t unit)
case ROCPROFILER_PC_SAMPLING_UNIT_LAST: break;
}
throw std::runtime_error("Illegal pc sampling units\n");
ROCP_FATAL << "Illegal pc sampling unit " << unit;
}
} // namespace utils
} // namespace pc_sampling
+64 -8
View File
@@ -77,6 +77,7 @@
#include <stdexcept>
#include <string>
#include <string_view>
#include <system_error>
#include <thread>
#include <unordered_set>
#include <vector>
@@ -101,6 +102,49 @@ namespace
{
namespace fs = ::rocprofiler::common::filesystem;
bool
resolved_exists(std::string_view fname)
{
if(fs::is_symlink(fname))
{
// NOTE: Use of ROCP_CI_LOG(WARNING) causes segfault. Likely bc glog is not fully
// initialized
auto _errc = std::error_code{};
auto _symlinked = fs::read_symlink(fname, _errc);
if(_errc && _symlinked.empty())
{
ROCP_WARNING << fmt::format("Symbolic link '{}' returned error code {} :: {}",
fname,
_errc.value(),
_errc.message());
return false;
}
else if(_errc && !_symlinked.empty())
{
ROCP_WARNING << fmt::format("Symbolic link '{}' -> '{}' returned error code {} :: {}",
fname,
_symlinked.string(),
_errc.value(),
_errc.message());
return false;
}
if(_symlinked.is_relative()) _symlinked = fs::path{fname}.parent_path() / _symlinked;
ROCP_TRACE << fmt::format("Symbolic link:\n\t{}\n\t\t-> {}", fname, _symlinked.string());
if(!fs::exists(_symlinked))
{
ROCP_WARNING << fmt::format("{} is broken symbolic link", fname);
return false;
}
return resolved_exists(fs::absolute(_symlinked).string());
}
return fs::exists(fname);
}
// invoke all rocprofiler_configure symbols
bool
invoke_client_configures();
@@ -257,14 +301,17 @@ find_clients()
{
ROCP_INFO << "[ROCP_TOOL_LIBRARIES] searching " << itr << " for rocprofiler_configure";
if(fs::exists(itr))
if(fs::exists(itr) && resolved_exists(itr))
{
auto elfinfo = common::elf_utils::read(itr);
if(!elfinfo.has_symbol(std::regex{"^rocprofiler_configure$"}))
{
ROCP_FATAL << "[ROCP_TOOL_LIBRARIES] rocprofiler-sdk tool library '" << itr
<< "' did not contain rocprofiler_configure symbol (search method: "
"ELF parsing)";
ROCP_CI_LOG(WARNING) << fmt::format(
"[ROCP_TOOL_LIBRARIES] rocprofiler-sdk tool library '{}' did not "
"contain rocprofiler_configure symbol (search method: ELF parsing). "
"Attempting dlopen anyway since the library was explicitly listed in "
"ROCP_TOOL_LIBRARIES",
itr);
}
}
@@ -295,10 +342,10 @@ find_clients()
{
auto _sym = rocprofiler_configure_dlsym(handle);
// FATAL bc they explicitly said this was a tool library
ROCP_FATAL_IF(!_sym)
ROCP_CI_LOG_IF(WARNING, !_sym)
<< "[ROCP_TOOL_LIBRARIES] rocprofiler-sdk tool library '" << itr
<< "' did not contain rocprofiler_configure symbol (search method: dlsym)";
if(is_unique_configure_func(_sym)) emplace_client(itr, handle, _sym);
if(_sym && is_unique_configure_func(_sym)) emplace_client(itr, handle, _sym);
}
}
}
@@ -323,13 +370,22 @@ find_clients()
{
ROCP_INFO << "searching " << itr << " for rocprofiler_configure";
if(fs::exists(itr))
if(fs::exists(itr) && resolved_exists(itr))
{
auto elfinfo = common::elf_utils::read(itr);
if(!elfinfo.has_symbol(std::regex{"^rocprofiler_configure$"})) continue;
if(!elfinfo.has_symbol(std::regex{"^rocprofiler_configure$"}))
{
ROCP_INFO << fmt::format(
"Shared library '{}' did not contain the 'rocprofiler_configure' symbol "
"(search method: ELF parsing) required by rocprofiler-sdk for tools",
itr);
continue;
}
}
else
{
ROCP_INFO << fmt::format(
"Shared library '{}' either does not exist or is a broken symbolic link", itr);
continue;
}