Initial Implementation: include (#10)
* Initial Implementation: include
* Initial Implementation: lib details (#11)
* Initial Implementation: lib details
* Initial Implementation: lib (#12)
* Initial Implementation: lib
* Initial Implementation: source (#13)
* Initial Implementation: source
* Initial Implementation: samples (#14)
* Initial Implementation: samples
* Initial Implementation: tests (#15)
* Initial Implementation: tests
* Initial Implementation: scripts (#16)
* Initial Implementation: scripts
* Initial Implementation: cmake (#17)
* Initial Implementation: cmake
* Initial Implementation: top-level files (#18)
* Initial Implementation: top-level files
- clang-format
- clang-tidy
- cmake-format
- ignore build and cache directories
- main CMakeLists.txt
- pyproject.toml (python formatting)
- VERSION file
* Initial Implementation: workflow (#19)
* Fix unused variable
- rocprofiler_register_warn_level
[ROCm/rocprofiler-register commit: fa4295db6b]
This commit is contained in:
committed by
GitHub
parent
8ef9cf2642
commit
7e6e33cfce
@@ -0,0 +1,4 @@
|
||||
#
|
||||
#
|
||||
#
|
||||
add_subdirectory(rocprofiler-register)
|
||||
@@ -0,0 +1,36 @@
|
||||
#
|
||||
# builds the rocprofiler-register library
|
||||
#
|
||||
add_library(rocprofiler-register SHARED)
|
||||
add_library(rocprofiler-register::rocprofiler-register ALIAS rocprofiler-register)
|
||||
|
||||
add_subdirectory(details)
|
||||
|
||||
target_sources(rocprofiler-register PRIVATE rocprofiler_register.cpp)
|
||||
|
||||
if(ROCPROFILER_REGISTER_BUILD_TESTS)
|
||||
# make sure header is C-compatible
|
||||
target_sources(rocprofiler-register PRIVATE rocprofiler_register.c)
|
||||
endif()
|
||||
|
||||
target_include_directories(
|
||||
rocprofiler-register PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/source
|
||||
${PROJECT_BINARY_DIR}/source)
|
||||
|
||||
target_link_libraries(
|
||||
rocprofiler-register
|
||||
PUBLIC rocprofiler-register::headers
|
||||
PRIVATE rocprofiler-register::build-flags rocprofiler-register::memcheck
|
||||
rocprofiler-register::stdcxxfs rocprofiler-register::dl)
|
||||
|
||||
set_target_properties(
|
||||
rocprofiler-register
|
||||
PROPERTIES OUTPUT_NAME rocprofiler-register
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
VERSION ${PROJECT_VERSION})
|
||||
|
||||
install(
|
||||
TARGETS rocprofiler-register
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
COMPONENT core
|
||||
EXPORT ${PROJECT_NAME}-library-targets)
|
||||
@@ -0,0 +1,10 @@
|
||||
#
|
||||
# builds the rocprofiler-register library
|
||||
#
|
||||
set(rocprofiler_register_details_sources dl.cpp utility.cpp)
|
||||
|
||||
set(rocprofiler_register_details_headers environment.hpp join.hpp dl.hpp log.hpp
|
||||
utility.hpp)
|
||||
|
||||
target_sources(rocprofiler-register PRIVATE ${rocprofiler_register_details_sources}
|
||||
${rocprofiler_register_details_headers})
|
||||
@@ -0,0 +1,125 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 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
|
||||
// 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:
|
||||
//
|
||||
// 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
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#define GNU_SOURCE 1
|
||||
|
||||
#include "dl.hpp"
|
||||
#include "join.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <elf.h>
|
||||
#include <link.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace fs = ::std::filesystem;
|
||||
|
||||
namespace rocprofiler_register
|
||||
{
|
||||
namespace binary
|
||||
{
|
||||
namespace
|
||||
{
|
||||
const open_modes_vec_t default_link_open_modes = { (RTLD_LAZY | RTLD_NOLOAD),
|
||||
(RTLD_LAZY | RTLD_LOCAL) };
|
||||
} // namespace
|
||||
|
||||
std::vector<segment_address_ranges>
|
||||
get_segment_addresses(pid_t _pid)
|
||||
{
|
||||
auto _data = std::vector<segment_address_ranges>{};
|
||||
auto _fname = common::join('/', "/proc", _pid, "maps");
|
||||
auto ifs = std::ifstream{ _fname };
|
||||
if(!ifs)
|
||||
{
|
||||
fprintf(stderr, "Failure opening %s\n", _fname.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
auto _get_entry = [&_data](std::string_view _name) -> segment_address_ranges& {
|
||||
for(auto& itr : _data)
|
||||
{
|
||||
if(itr.filepath == _name) return itr;
|
||||
}
|
||||
return _data.emplace_back(
|
||||
segment_address_ranges{ .filepath = std::string{ _name } });
|
||||
};
|
||||
|
||||
while(ifs)
|
||||
{
|
||||
std::string _line = {};
|
||||
if(std::getline(ifs, _line) && !_line.empty())
|
||||
{
|
||||
auto _delim = utility::delimit(_line, " \t\n\r");
|
||||
if(_delim.size() > 5 && fs::exists(fs::path{ _delim.back() }))
|
||||
{
|
||||
auto& _entry = _get_entry(_delim.back());
|
||||
auto _addr = utility::delimit(_delim.front(), "-");
|
||||
auto load_address = std::stoull(_addr.front(), nullptr, 16);
|
||||
auto last_address = std::stoull(_addr.back(), nullptr, 16);
|
||||
_entry.ranges.emplace_back(
|
||||
address_range{ load_address, last_address });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return _data;
|
||||
}
|
||||
|
||||
std::optional<std::string>
|
||||
get_linked_path(std::string_view _name, open_modes_vec_t&& _open_modes)
|
||||
{
|
||||
if(_name.empty()) return fs::current_path().string();
|
||||
|
||||
if(_open_modes.empty()) _open_modes = default_link_open_modes;
|
||||
|
||||
void* _handle = nullptr;
|
||||
bool _noload = false;
|
||||
for(auto _mode : _open_modes)
|
||||
{
|
||||
_handle = dlopen(_name.data(), _mode);
|
||||
_noload = (_mode & RTLD_NOLOAD) == RTLD_NOLOAD;
|
||||
if(_handle) break;
|
||||
}
|
||||
|
||||
if(_handle)
|
||||
{
|
||||
struct link_map* _link_map = nullptr;
|
||||
dlinfo(_handle, RTLD_DI_LINKMAP, &_link_map);
|
||||
if(_link_map != nullptr && !std::string_view{ _link_map->l_name }.empty())
|
||||
{
|
||||
return fs::absolute(fs::path{ _link_map->l_name }).string();
|
||||
}
|
||||
if(_noload == false) dlclose(_handle);
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
} // namespace binary
|
||||
} // namespace rocprofiler_register
|
||||
@@ -0,0 +1,60 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 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
|
||||
// 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:
|
||||
//
|
||||
// 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
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace rocprofiler_register
|
||||
{
|
||||
namespace binary
|
||||
{
|
||||
using open_modes_vec_t = std::vector<int>;
|
||||
|
||||
struct address_range
|
||||
{
|
||||
uintptr_t start = 0;
|
||||
uintptr_t last = 0;
|
||||
};
|
||||
|
||||
struct segment_address_ranges
|
||||
{
|
||||
std::string filepath = {};
|
||||
std::vector<address_range> ranges = {};
|
||||
};
|
||||
|
||||
std::vector<segment_address_ranges>
|
||||
get_segment_addresses(pid_t _pid = getpid());
|
||||
|
||||
// helper function for translating generic lib name to resolved path
|
||||
std::optional<std::string>
|
||||
get_linked_path(std::string_view, open_modes_vec_t&& = {});
|
||||
} // namespace binary
|
||||
} // namespace rocprofiler_register
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
// Copyright (c) 2023 Advanced Micro Devices, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// 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:
|
||||
//
|
||||
// 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
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "log.hpp"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
||||
#if !defined(ROCPROFILER_REGISTER_ENVIRON_LOG_NAME)
|
||||
# if defined(ROCPROFILER_REGISTER_COMMON_LIBRARY_NAME)
|
||||
# define ROCPROFILER_REGISTER_ENVIRON_LOG_NAME \
|
||||
"[" ROCPROFILER_REGISTER_COMMON_LIBRARY_NAME "]"
|
||||
# else
|
||||
# define ROCPROFILER_REGISTER_ENVIRON_LOG_NAME "[environ]"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(ROCPROFILER_REGISTER_ENVIRON_LOG_START)
|
||||
# if defined(ROCPROFILER_REGISTER_COMMON_LIBRARY_LOG_START)
|
||||
# define ROCPROFILER_REGISTER_ENVIRON_LOG_START \
|
||||
ROCPROFILER_REGISTER_COMMON_LIBRARY_LOG_START
|
||||
# elif defined(ROCPROFILER_REGISTER_LOG_COLORS_AVAILABLE)
|
||||
# define ROCPROFILER_REGISTER_ENVIRON_LOG_START \
|
||||
fprintf(stderr, "%s", ::rocprofiler_register::log::color::dmesg());
|
||||
# else
|
||||
# define ROCPROFILER_REGISTER_ENVIRON_LOG_START
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(ROCPROFILER_REGISTER_ENVIRON_LOG_END)
|
||||
# if defined(ROCPROFILER_REGISTER_COMMON_LIBRARY_LOG_END)
|
||||
# define ROCPROFILER_REGISTER_ENVIRON_LOG_END \
|
||||
ROCPROFILER_REGISTER_COMMON_LIBRARY_LOG_END
|
||||
# elif defined(ROCPROFILER_REGISTER_LOG_COLORS_AVAILABLE)
|
||||
# define ROCPROFILER_REGISTER_ENVIRON_LOG_END \
|
||||
fprintf(stderr, "%s", ::rocprofiler_register::log::color::end());
|
||||
# else
|
||||
# define ROCPROFILER_REGISTER_ENVIRON_LOG_END
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define ROCPROFILER_REGISTER_ENVIRON_LOG(CONDITION, ...) \
|
||||
if(CONDITION) \
|
||||
{ \
|
||||
fflush(stderr); \
|
||||
ROCPROFILER_REGISTER_ENVIRON_LOG_START \
|
||||
fprintf(stderr, \
|
||||
"[rocprofiler-register]" ROCPROFILER_REGISTER_ENVIRON_LOG_NAME "[%i] ", \
|
||||
getpid()); \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
ROCPROFILER_REGISTER_ENVIRON_LOG_END \
|
||||
fflush(stderr); \
|
||||
}
|
||||
|
||||
namespace rocprofiler_register
|
||||
{
|
||||
namespace common
|
||||
{
|
||||
namespace
|
||||
{
|
||||
inline std::string
|
||||
get_env_impl(std::string_view env_id, std::string_view _default)
|
||||
{
|
||||
if(env_id.empty()) return std::string{ _default };
|
||||
char* env_var = ::std::getenv(env_id.data());
|
||||
if(env_var) return std::string{ env_var };
|
||||
return std::string{ _default };
|
||||
}
|
||||
|
||||
inline std::string
|
||||
get_env_impl(std::string_view env_id, const char* _default)
|
||||
{
|
||||
return get_env_impl(env_id, std::string_view{ _default });
|
||||
}
|
||||
|
||||
inline int
|
||||
get_env_impl(std::string_view env_id, int _default)
|
||||
{
|
||||
if(env_id.empty()) return _default;
|
||||
char* env_var = ::std::getenv(env_id.data());
|
||||
if(env_var)
|
||||
{
|
||||
try
|
||||
{
|
||||
return std::stoi(env_var);
|
||||
} catch(std::exception& _e)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"[rocprofiler_register][get_env] Exception thrown converting "
|
||||
"getenv(\"%s\") = "
|
||||
"%s to integer :: %s. Using default value of %i\n",
|
||||
env_id.data(),
|
||||
env_var,
|
||||
_e.what(),
|
||||
_default);
|
||||
}
|
||||
return _default;
|
||||
}
|
||||
return _default;
|
||||
}
|
||||
|
||||
inline bool
|
||||
get_env_impl(std::string_view env_id, bool _default)
|
||||
{
|
||||
if(env_id.empty()) return _default;
|
||||
char* env_var = ::std::getenv(env_id.data());
|
||||
if(env_var)
|
||||
{
|
||||
if(std::string_view{ env_var }.empty())
|
||||
{
|
||||
throw std::runtime_error(std::string{ "No boolean value provided for " } +
|
||||
std::string{ env_id });
|
||||
}
|
||||
|
||||
if(std::string_view{ env_var }.find_first_not_of("0123456789") ==
|
||||
std::string_view::npos)
|
||||
{
|
||||
return static_cast<bool>(std::stoi(env_var));
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < strlen(env_var); ++i)
|
||||
env_var[i] = tolower(env_var[i]);
|
||||
for(const auto& itr : { "off", "false", "no", "n", "f", "0" })
|
||||
if(strcmp(env_var, itr) == 0) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return _default;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template <typename Tp>
|
||||
inline auto
|
||||
get_env(std::string_view env_id, Tp&& _default)
|
||||
{
|
||||
if constexpr(std::is_enum<Tp>::value)
|
||||
{
|
||||
using Up = std::underlying_type_t<Tp>;
|
||||
// cast to underlying type -> get_env -> cast to enum type
|
||||
return static_cast<Tp>(get_env_impl(env_id, static_cast<Up>(_default)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return get_env_impl(env_id, std::forward<Tp>(_default));
|
||||
}
|
||||
}
|
||||
|
||||
struct env_config
|
||||
{
|
||||
std::string env_name = {};
|
||||
std::string env_value = {};
|
||||
int override = 0;
|
||||
|
||||
auto operator()(bool _verbose = false) const
|
||||
{
|
||||
if(env_name.empty()) return -1;
|
||||
ROCPROFILER_REGISTER_ENVIRON_LOG(_verbose,
|
||||
"setenv(\"%s\", \"%s\", %i)\n",
|
||||
env_name.c_str(),
|
||||
env_value.c_str(),
|
||||
override);
|
||||
return setenv(env_name.c_str(), env_value.c_str(), override);
|
||||
}
|
||||
};
|
||||
} // namespace common
|
||||
} // namespace rocprofiler_register
|
||||
@@ -0,0 +1,184 @@
|
||||
// Copyright (c) 2023 Advanced Micro Devices, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// 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:
|
||||
//
|
||||
// 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
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <initializer_list>
|
||||
#include <ios>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
#if !defined(ROCPROFILER_REGISTER_FOLD_EXPRESSION)
|
||||
# define ROCPROFILER_REGISTER_FOLD_EXPRESSION(...) ((__VA_ARGS__), ...)
|
||||
#endif
|
||||
|
||||
namespace rocprofiler_register
|
||||
{
|
||||
namespace common
|
||||
{
|
||||
namespace
|
||||
{
|
||||
template <typename Tp>
|
||||
struct is_string_impl : std::false_type
|
||||
{ };
|
||||
|
||||
template <>
|
||||
struct is_string_impl<std::string> : std::true_type
|
||||
{ };
|
||||
|
||||
template <>
|
||||
struct is_string_impl<std::string_view> : std::true_type
|
||||
{ };
|
||||
|
||||
template <>
|
||||
struct is_string_impl<const char*> : std::true_type
|
||||
{ };
|
||||
|
||||
template <>
|
||||
struct is_string_impl<char*> : std::true_type
|
||||
{ };
|
||||
|
||||
template <typename Tp>
|
||||
struct is_string : is_string_impl<std::remove_cv_t<std::decay_t<Tp>>>
|
||||
{ };
|
||||
|
||||
template <typename ArgT>
|
||||
auto
|
||||
as_string(ArgT&& _v, std::enable_if_t<is_string<ArgT>::value, int> = 0)
|
||||
{
|
||||
if constexpr(std::is_pointer<std::decay_t<ArgT>>::value)
|
||||
{
|
||||
return (_v == nullptr) ? std::string{ "\"\"" }
|
||||
: (std::string{ "\"" } + _v + std::string{ "\"" });
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::string{ "\"" } + _v + std::string{ "\"" };
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ArgT>
|
||||
auto
|
||||
as_string(ArgT&& _v, std::enable_if_t<!is_string<ArgT>::value, long> = 0)
|
||||
{
|
||||
return _v;
|
||||
}
|
||||
|
||||
template <typename DelimT, typename... Args>
|
||||
auto
|
||||
join(DelimT&& _delim, Args&&... _args)
|
||||
{
|
||||
using delim_type = std::remove_cv_t<std::remove_reference_t<DelimT>>;
|
||||
|
||||
std::stringstream _ss{};
|
||||
_ss << std::boolalpha;
|
||||
|
||||
if constexpr(std::is_same<delim_type, char>::value)
|
||||
{
|
||||
const char _delim_c[2] = { _delim, '\0' };
|
||||
ROCPROFILER_REGISTER_FOLD_EXPRESSION(_ss << _delim_c << _args);
|
||||
auto _ret = _ss.str();
|
||||
return (_ret.length() > 1) ? _ret.substr(1) : std::string{};
|
||||
}
|
||||
else
|
||||
{
|
||||
ROCPROFILER_REGISTER_FOLD_EXPRESSION(_ss << _delim << _args);
|
||||
auto _ret = _ss.str();
|
||||
auto&& _len = std::string{ _delim }.length();
|
||||
return (_ret.length() > _len) ? _ret.substr(_len) : std::string{};
|
||||
}
|
||||
}
|
||||
|
||||
struct QuoteStrings
|
||||
{ };
|
||||
|
||||
template <typename DelimT, typename... Args>
|
||||
auto
|
||||
join(QuoteStrings&&, DelimT&& _delim, Args&&... _args)
|
||||
{
|
||||
using delim_type = std::remove_cv_t<std::remove_reference_t<DelimT>>;
|
||||
|
||||
std::stringstream _ss{};
|
||||
_ss << std::boolalpha;
|
||||
|
||||
if constexpr(std::is_same<delim_type, char>::value)
|
||||
{
|
||||
const char _delim_c[2] = { _delim, '\0' };
|
||||
ROCPROFILER_REGISTER_FOLD_EXPRESSION(_ss << _delim_c << as_string(_args));
|
||||
auto _ret = _ss.str();
|
||||
return (_ret.length() > 1) ? _ret.substr(1) : std::string{};
|
||||
}
|
||||
else
|
||||
{
|
||||
ROCPROFILER_REGISTER_FOLD_EXPRESSION(_ss << _delim << as_string(_args));
|
||||
auto _ret = _ss.str();
|
||||
auto&& _len = std::string{ _delim }.length();
|
||||
return (_ret.length() > _len) ? _ret.substr(_len) : std::string{};
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
auto
|
||||
join(std::array<std::string_view, 3>&& _delim, Args&&... _args)
|
||||
{
|
||||
return join("",
|
||||
std::get<0>(_delim),
|
||||
join(std::get<1>(_delim), std::forward<Args>(_args)...),
|
||||
std::get<2>(_delim));
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
auto
|
||||
join(QuoteStrings&&, std::array<std::string_view, 3>&& _delim, Args&&... _args)
|
||||
{
|
||||
return join(QuoteStrings{},
|
||||
"",
|
||||
std::get<0>(_delim),
|
||||
join(std::get<1>(_delim), std::forward<Args>(_args)...),
|
||||
std::get<2>(_delim));
|
||||
}
|
||||
|
||||
template <typename DelimB, typename DelimT, typename DelimE, typename... Args>
|
||||
auto
|
||||
join(std::tuple<DelimB, DelimT, DelimE>&& _delim, Args&&... _args)
|
||||
{
|
||||
return join("",
|
||||
std::get<0>(_delim),
|
||||
join(std::get<1>(_delim), std::forward<Args>(_args)...),
|
||||
std::get<2>(_delim));
|
||||
}
|
||||
|
||||
template <typename DelimB, typename DelimT, typename DelimE, typename... Args>
|
||||
auto
|
||||
join(QuoteStrings&&, std::tuple<DelimB, DelimT, DelimE>&& _delim, Args&&... _args)
|
||||
{
|
||||
return join(QuoteStrings{},
|
||||
"",
|
||||
std::get<0>(_delim),
|
||||
join(std::get<1>(_delim), std::forward<Args>(_args)...),
|
||||
std::get<2>(_delim));
|
||||
}
|
||||
} // namespace
|
||||
} // namespace common
|
||||
} // namespace rocprofiler_register
|
||||
@@ -0,0 +1,518 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). 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
|
||||
// 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:
|
||||
//
|
||||
// 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
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR rhs
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR rhsWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR rhs DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <rocprofiler-register/version.h>
|
||||
|
||||
#ifndef ROCPROFILER_REGISTER_LOG_COLORS_AVAILABLE
|
||||
# define ROCPROFILER_REGISTER_LOG_COLORS_AVAILABLE 1
|
||||
#endif
|
||||
|
||||
#ifndef ROCPROFILER_REGISTER_PROJECT_NAME
|
||||
# define ROCPROFILER_REGISTER_PROJECT_NAME "rocprofiler-register"
|
||||
#endif
|
||||
|
||||
#ifndef ROCP_REG_FILE_NAME
|
||||
# define ROCP_REG_FILE_NAME \
|
||||
::std::string{ __FILE__ } \
|
||||
.substr(::std::string_view{ __FILE__ }.find_last_of('/') + 1) \
|
||||
.c_str()
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace rocprofiler_register
|
||||
{
|
||||
namespace log
|
||||
{
|
||||
bool&
|
||||
monochrome();
|
||||
|
||||
inline bool&
|
||||
monochrome()
|
||||
{
|
||||
static bool _v = []() {
|
||||
auto _val = false;
|
||||
const char* _env_cstr = nullptr;
|
||||
_env_cstr = std::getenv("ROCPROFILER_REGISTER_MONOCHROME");
|
||||
|
||||
if(!_env_cstr) _env_cstr = std::getenv("MONOCHROME");
|
||||
|
||||
if(_env_cstr)
|
||||
{
|
||||
auto _env = std::string{ _env_cstr };
|
||||
|
||||
// check if numeric
|
||||
if(_env.find_first_not_of("0123456789") == std::string::npos)
|
||||
{
|
||||
return _env.length() > 1 || _env[0] != '0';
|
||||
}
|
||||
|
||||
for(auto& itr : _env)
|
||||
itr = tolower(itr);
|
||||
|
||||
// check for matches to acceptable forms of false
|
||||
for(const auto& itr : { "off", "false", "no", "n", "f" })
|
||||
{
|
||||
if(_env == itr) return false;
|
||||
}
|
||||
|
||||
// check for matches to acceptable forms of true
|
||||
for(const auto& itr : { "on", "true", "yes", "y", "t" })
|
||||
{
|
||||
if(_env == itr) return true;
|
||||
}
|
||||
}
|
||||
return _val;
|
||||
}();
|
||||
return _v;
|
||||
}
|
||||
|
||||
namespace color
|
||||
{
|
||||
static constexpr auto info_value = "\033[01;34m";
|
||||
static constexpr auto warning_value = "\033[01;33m";
|
||||
static constexpr auto fatal_value = "\033[01;31m";
|
||||
static constexpr auto source_value = "\033[01;32m";
|
||||
static constexpr auto dmesg_value = "\033[01;37m";
|
||||
static constexpr auto end_value = "\033[0m";
|
||||
|
||||
inline const char*
|
||||
info()
|
||||
{
|
||||
return (log::monochrome()) ? "" : info_value;
|
||||
}
|
||||
|
||||
inline const char*
|
||||
warning()
|
||||
{
|
||||
return (log::monochrome()) ? "" : warning_value;
|
||||
}
|
||||
|
||||
inline const char*
|
||||
fatal()
|
||||
{
|
||||
return (log::monochrome()) ? "" : fatal_value;
|
||||
}
|
||||
|
||||
inline const char*
|
||||
source()
|
||||
{
|
||||
return (log::monochrome()) ? "" : source_value;
|
||||
}
|
||||
|
||||
inline const char*
|
||||
dmesg()
|
||||
{
|
||||
return (log::monochrome()) ? "" : dmesg_value;
|
||||
}
|
||||
|
||||
inline const char*
|
||||
end()
|
||||
{
|
||||
return (log::monochrome()) ? "" : end_value;
|
||||
}
|
||||
} // namespace color
|
||||
} // namespace log
|
||||
} // namespace rocprofiler_register
|
||||
|
||||
namespace rocprofiler_register
|
||||
{
|
||||
namespace log
|
||||
{
|
||||
struct base
|
||||
{
|
||||
public:
|
||||
static base indent(size_t, size_t = 2) { return base{}; }
|
||||
|
||||
template <typename Tp>
|
||||
auto operator<<(Tp&&)
|
||||
{
|
||||
return base{};
|
||||
}
|
||||
};
|
||||
|
||||
struct logger : public base
|
||||
{
|
||||
logger() = default;
|
||||
|
||||
explicit logger(bool _exit)
|
||||
: m_exit{ _exit }
|
||||
{ }
|
||||
|
||||
~logger()
|
||||
{
|
||||
if(m_done)
|
||||
{
|
||||
std::cerr << color::end() << "\n";
|
||||
if(m_exit) abort();
|
||||
}
|
||||
}
|
||||
|
||||
logger(logger&& rhs) noexcept
|
||||
{
|
||||
m_exit = rhs.m_exit;
|
||||
m_done = rhs.m_done;
|
||||
rhs.m_done = false;
|
||||
}
|
||||
|
||||
logger& operator=(logger&& rhs) noexcept
|
||||
{
|
||||
m_exit = rhs.m_exit;
|
||||
m_done = rhs.m_done;
|
||||
rhs.m_done = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
logger&& indent(size_t _n, size_t _tab_size = 4)
|
||||
{
|
||||
for(size_t i = 0; i < _n; i++)
|
||||
for(size_t j = 0; j < _tab_size; j++)
|
||||
std::cerr << " ";
|
||||
return std::move(*this);
|
||||
}
|
||||
|
||||
template <typename Tp>
|
||||
logger&& operator<<(Tp&& _v)
|
||||
{
|
||||
std::cerr << std::forward<Tp>(_v);
|
||||
return std::move(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_exit = false;
|
||||
bool m_done = true;
|
||||
};
|
||||
|
||||
template <typename Tp>
|
||||
inline auto&
|
||||
get_color_hist()
|
||||
{
|
||||
static thread_local std::vector<std::pair<Tp*, const char*>> _v{};
|
||||
return _v;
|
||||
}
|
||||
|
||||
template <typename Tp>
|
||||
inline auto
|
||||
push_color_hist(Tp* _v, const char* _c)
|
||||
{
|
||||
if(!monochrome()) get_color_hist<Tp>().emplace_back(_v, _c);
|
||||
return _c;
|
||||
}
|
||||
|
||||
template <typename Tp>
|
||||
inline std::string
|
||||
pop_color_hist(Tp* _v)
|
||||
{
|
||||
if(monochrome()) return std::string{};
|
||||
|
||||
auto& _hist = get_color_hist<Tp>();
|
||||
for(auto itr = _hist.rbegin(); itr != _hist.rend(); ++itr)
|
||||
{
|
||||
Tp* _addr = itr->first;
|
||||
if(_addr == _v)
|
||||
{
|
||||
auto fitr = _hist.begin();
|
||||
std::advance(fitr, std::distance(_hist.rbegin(), itr));
|
||||
_hist.erase(fitr);
|
||||
}
|
||||
}
|
||||
for(auto itr = _hist.rbegin(); itr != _hist.rend(); ++itr)
|
||||
{
|
||||
if(itr->first == _v) return itr->second;
|
||||
}
|
||||
return color::end();
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
info(std::basic_ostream<CharT, Traits>& os)
|
||||
{
|
||||
return (os << push_color_hist(&os, color::info()));
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
warning(std::basic_ostream<CharT, Traits>& os)
|
||||
{
|
||||
return (os << push_color_hist(&os, color::warning()));
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
fatal(std::basic_ostream<CharT, Traits>& os)
|
||||
{
|
||||
return (os << push_color_hist(&os, color::fatal()));
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
source(std::basic_ostream<CharT, Traits>& os)
|
||||
{
|
||||
return (os << push_color_hist(&os, color::source()));
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
end(std::basic_ostream<CharT, Traits>& os)
|
||||
{
|
||||
return (os << push_color_hist(&os, color::end()));
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
pop(std::basic_ostream<CharT, Traits>& os)
|
||||
{
|
||||
return (os << pop_color_hist(&os));
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
reset(std::basic_ostream<CharT, Traits>& os)
|
||||
{
|
||||
pop_color_hist(&os);
|
||||
return (os << color::end());
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
flush(std::basic_ostream<CharT, Traits>& os)
|
||||
{
|
||||
return (os << pop << std::flush);
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
std::basic_ostream<CharT, Traits>&
|
||||
endl(std::basic_ostream<CharT, Traits>& os)
|
||||
{
|
||||
return (os << pop << "\n" << std::flush);
|
||||
}
|
||||
|
||||
template <typename StreamT>
|
||||
struct stream_base
|
||||
{
|
||||
stream_base(StreamT& _os, const char* _color)
|
||||
: m_os{ _os }
|
||||
{
|
||||
m_os << push_color_hist(&_os, _color);
|
||||
}
|
||||
|
||||
~stream_base() { m_os << pop_color_hist(&m_os); }
|
||||
|
||||
stream_base(const stream_base&) = delete;
|
||||
stream_base& operator=(const stream_base&) = delete;
|
||||
|
||||
stream_base(stream_base&& rhs) noexcept = default;
|
||||
stream_base& operator=(stream_base&& rhs) noexcept = default;
|
||||
|
||||
template <typename Tp>
|
||||
stream_base& operator<<(Tp&& _v)
|
||||
{
|
||||
m_os << std::forward<Tp>(_v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Tp>
|
||||
stream_base& operator<<(Tp& _v)
|
||||
{
|
||||
m_os << _v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
stream_base& put(char _c)
|
||||
{
|
||||
m_os.put(_c);
|
||||
return *this;
|
||||
}
|
||||
|
||||
stream_base& endl()
|
||||
{
|
||||
m_os << std::endl;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
stream_base& write(Args&&... _args)
|
||||
{
|
||||
m_os.write(std::forward<Args>(_args)...);
|
||||
return *this;
|
||||
}
|
||||
|
||||
stream_base& flush()
|
||||
{
|
||||
m_os << std::flush;
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto tellp() { return m_os.tellp(); }
|
||||
|
||||
template <typename... Args>
|
||||
stream_base& seekp(Args&&... _args)
|
||||
{
|
||||
m_os.seekp(std::forward<Args>(_args)...);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
StreamT& m_os;
|
||||
};
|
||||
|
||||
template <typename StreamT>
|
||||
stream_base<StreamT>
|
||||
stream(StreamT& _os, const char* _color)
|
||||
{
|
||||
return stream_base<StreamT>{ _os, _color };
|
||||
}
|
||||
|
||||
template <typename StreamT>
|
||||
stream_base<StreamT>
|
||||
info_stream(StreamT& _os)
|
||||
{
|
||||
return stream_base<StreamT>{ _os, color::info() };
|
||||
}
|
||||
|
||||
template <typename StreamT>
|
||||
stream_base<StreamT>
|
||||
source_stream(StreamT& _os)
|
||||
{
|
||||
return stream_base<StreamT>{ _os, color::source() };
|
||||
}
|
||||
|
||||
template <typename StreamT>
|
||||
stream_base<StreamT>
|
||||
warning_stream(StreamT& _os)
|
||||
{
|
||||
return stream_base<StreamT>{ _os, color::warning() };
|
||||
}
|
||||
|
||||
template <typename StreamT>
|
||||
stream_base<StreamT>
|
||||
fatal_stream(StreamT& _os)
|
||||
{
|
||||
return stream_base<StreamT>{ _os, color::fatal() };
|
||||
}
|
||||
|
||||
inline std::string
|
||||
string(const char* _color, std::string_view _v)
|
||||
{
|
||||
return std::string{ _color } + std::string{ _v } + std::string{ color::end() };
|
||||
}
|
||||
|
||||
inline std::string
|
||||
string(const char* _color, std::stringstream& _v)
|
||||
{
|
||||
return std::string{ _color } + _v.str() + std::string{ color::end() };
|
||||
}
|
||||
|
||||
inline std::string
|
||||
string(const char* _color, std::stringstream&& _v)
|
||||
{
|
||||
return std::string{ _color } + _v.str() + std::string{ color::end() };
|
||||
}
|
||||
|
||||
template <typename Tp>
|
||||
inline auto
|
||||
info_string(Tp&& _v)
|
||||
{
|
||||
return string(color::info(), std::forward<Tp>(_v));
|
||||
}
|
||||
|
||||
template <typename Tp>
|
||||
inline auto
|
||||
source_string(Tp&& _v)
|
||||
{
|
||||
return string(color::source(), std::forward<Tp>(_v));
|
||||
}
|
||||
|
||||
template <typename Tp>
|
||||
inline auto
|
||||
warning_string(Tp&& _v)
|
||||
{
|
||||
return string(color::warning(), std::forward<Tp>(_v));
|
||||
}
|
||||
|
||||
template <typename Tp>
|
||||
inline auto
|
||||
fatal_string(Tp&& _v)
|
||||
{
|
||||
return string(color::fatal(), std::forward<Tp>(_v));
|
||||
}
|
||||
} // namespace log
|
||||
} // namespace rocprofiler_register
|
||||
|
||||
#if !defined(ROCPROFILER_REGISTER_LOG)
|
||||
# define ROCPROFILER_REGISTER_LOG(COLOR, EXIT_CODE) \
|
||||
(::rocprofiler_register::log::logger(EXIT_CODE) \
|
||||
<< ::rocprofiler_register::log::color::end() \
|
||||
<< ::rocprofiler_register::log::color::source() << "[" \
|
||||
<< ROCPROFILER_REGISTER_PROJECT_NAME << "][" << ROCP_REG_FILE_NAME << ":" \
|
||||
<< __LINE__ << "][" << getpid() << "] " \
|
||||
<< ::rocprofiler_register::log::color::end() << COLOR)
|
||||
#endif
|
||||
|
||||
#if defined(NDEBUG)
|
||||
# if !defined(ROCPROFILER_REGISTER_INFO)
|
||||
# define ROCPROFILER_REGISTER_INFO (::rocprofiler_register::log::base())
|
||||
# endif
|
||||
# if !defined(ROCPROFILER_REGISTER_ASSERT)
|
||||
# define ROCPROFILER_REGISTER_ASSERT(COND) (::rocprofiler_register::log::base())
|
||||
# endif
|
||||
#else
|
||||
# if !defined(ROCPROFILER_REGISTER_INFO)
|
||||
# define ROCPROFILER_REGISTER_INFO \
|
||||
ROCPROFILER_REGISTER_LOG(::rocprofiler_register::log::color::info(), false)
|
||||
# endif
|
||||
# if !defined(ROCPROFILER_REGISTER_ASSERT)
|
||||
# define ROCPROFILER_REGISTER_ASSERT(COND) \
|
||||
(COND) ? ::rocprofiler_register::log::base() : ROCPROFILER_REGISTER_FATAL
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(ROCPROFILER_REGISTER_WARNING)
|
||||
# define ROCPROFILER_REGISTER_WARNING \
|
||||
ROCPROFILER_REGISTER_LOG(::rocprofiler_register::log::color::warning(), false)
|
||||
#endif
|
||||
|
||||
#if !defined(ROCPROFILER_REGISTER_FATAL)
|
||||
# define ROCPROFILER_REGISTER_FATAL \
|
||||
ROCPROFILER_REGISTER_LOG(::rocprofiler_register::log::color::fatal(), true)
|
||||
#endif
|
||||
|
||||
#if !defined(ROCPROFILER_REGISTER_PREFER)
|
||||
# define ROCPROFILER_REGISTER_PREFER(COND) \
|
||||
(COND) ? ::rocprofiler_register::log::base() : ROCPROFILER_REGISTER_WARNING
|
||||
#endif
|
||||
|
||||
#if !defined(ROCPROFILER_REGISTER_REQUIRE)
|
||||
# define ROCPROFILER_REGISTER_REQUIRE(COND) \
|
||||
(COND) ? ::rocprofiler_register::log::base() : ROCPROFILER_REGISTER_FATAL
|
||||
#endif
|
||||
@@ -0,0 +1,127 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 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
|
||||
// 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:
|
||||
//
|
||||
// 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
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace rocprofiler_register
|
||||
{
|
||||
namespace utility
|
||||
{
|
||||
namespace
|
||||
{
|
||||
template <typename ContainerT, typename... Args>
|
||||
inline auto
|
||||
emplace_impl(ContainerT& _c, int, Args&&... _args)
|
||||
-> decltype(_c.emplace_back(std::forward<Args>(_args)...))
|
||||
{
|
||||
return _c.emplace_back(std::forward<Args>(_args)...);
|
||||
}
|
||||
|
||||
template <typename ContainerT, typename... Args>
|
||||
inline auto
|
||||
emplace_impl(ContainerT& _c, long, Args&&... _args)
|
||||
-> decltype(_c.emplace(std::forward<Args>(_args)...))
|
||||
{
|
||||
return _c.emplace(std::forward<Args>(_args)...);
|
||||
}
|
||||
|
||||
template <typename ContainerT, typename... Args>
|
||||
inline auto
|
||||
emplace(ContainerT& _c, Args&&... _args)
|
||||
{
|
||||
return emplace_impl(_c, 0, std::forward<Args>(_args)...);
|
||||
}
|
||||
|
||||
template <typename ContainerT, typename ArgT>
|
||||
inline auto
|
||||
reserve_impl(ContainerT& _c, int, ArgT _arg) -> decltype(_c.reserve(_arg), bool())
|
||||
{
|
||||
_c.reserve(_arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename ContainerT, typename ArgT>
|
||||
inline auto
|
||||
reserve_impl(ContainerT&, long, ArgT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename ContainerT, typename ArgT>
|
||||
inline auto
|
||||
reserve(ContainerT& _c, ArgT _arg)
|
||||
{
|
||||
return reserve_impl(_c, 0, _arg);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template <typename ContainerT>
|
||||
ContainerT
|
||||
delimit(const std::string& line, std::string_view delimiters)
|
||||
{
|
||||
ContainerT _result{};
|
||||
size_t _beginp = 0; // position that is the beginning of the new string
|
||||
size_t _delimp = 0; // position of the delimiter in the string
|
||||
if(reserve(_result, 0))
|
||||
{
|
||||
size_t _nmax = 0;
|
||||
for(char itr : line)
|
||||
{
|
||||
for(size_t j = 0; j < delimiters.length(); ++j)
|
||||
{
|
||||
if(itr == delimiters.at(j)) ++_nmax;
|
||||
}
|
||||
}
|
||||
reserve(_result, _nmax);
|
||||
}
|
||||
while(_beginp < line.length() && _delimp < line.length())
|
||||
{
|
||||
// find the first character (starting at _delimp) that is not a delimiter
|
||||
_beginp = line.find_first_not_of(delimiters, _delimp);
|
||||
// if no a character after or at _end that is not a delimiter is not found
|
||||
// then we are done
|
||||
if(_beginp == std::string::npos) break;
|
||||
// starting at the position of the new string, find the next delimiter
|
||||
_delimp = line.find_first_of(delimiters, _beginp);
|
||||
std::string _tmp{};
|
||||
// starting at the position of the new string, get the characters
|
||||
// between this position and the next delimiter
|
||||
_tmp = line.substr(_beginp, _delimp - _beginp);
|
||||
// don't add empty strings
|
||||
if(!_tmp.empty()) emplace(_result, _tmp);
|
||||
}
|
||||
return _result;
|
||||
}
|
||||
|
||||
template std::vector<std::string>
|
||||
delimit(const std::string&, std::string_view);
|
||||
|
||||
template std::set<std::string>
|
||||
delimit(const std::string&, std::string_view);
|
||||
} // namespace utility
|
||||
} // namespace rocprofiler_register
|
||||
@@ -0,0 +1,44 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 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
|
||||
// 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:
|
||||
//
|
||||
// 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
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace rocprofiler_register
|
||||
{
|
||||
namespace utility
|
||||
{
|
||||
template <typename ContainerT = std::vector<std::string>>
|
||||
ContainerT
|
||||
delimit(const std::string& line, std::string_view delimiters = "\"',;: ");
|
||||
|
||||
extern template std::vector<std::string>
|
||||
delimit(const std::string&, std::string_view);
|
||||
|
||||
extern template std::set<std::string>
|
||||
delimit(const std::string&, std::string_view);
|
||||
} // namespace utility
|
||||
} // namespace rocprofiler_register
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) 2023 Advanced Micro Devices, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// 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:
|
||||
//
|
||||
// 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
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include <rocprofiler-register/rocprofiler-register.h>
|
||||
#include <rocprofiler-register/version.h>
|
||||
|
||||
int ROCPROFILER_REGISTER_INTERNAL_API rocp_register_sym = 0;
|
||||
+374
@@ -0,0 +1,374 @@
|
||||
// Copyright (c) 2023 Advanced Micro Devices, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// 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:
|
||||
//
|
||||
// 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
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#define GNU_SOURCE 1
|
||||
|
||||
#include <rocprofiler-register/rocprofiler-register.h>
|
||||
|
||||
#include "details/dl.hpp"
|
||||
#include "details/environment.hpp"
|
||||
#include "details/log.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <bitset>
|
||||
#include <filesystem>
|
||||
#include <mutex>
|
||||
#include <regex>
|
||||
#include <stdexcept>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
extern "C" {
|
||||
#pragma weak rocprofiler_configure
|
||||
#pragma weak rocprofiler_set_api_table
|
||||
#pragma weak rocprofiler_register_import_hip
|
||||
#pragma weak rocprofiler_register_import_hip_static
|
||||
#pragma weak rocprofiler_register_import_hsa
|
||||
#pragma weak rocprofiler_register_import_hsa_static
|
||||
#pragma weak rocprofiler_register_import_roctx
|
||||
#pragma weak rocprofiler_register_import_roctx_static
|
||||
|
||||
extern rocprofiler_configure_result_t*
|
||||
rocprofiler_configure(uint32_t, const char*, uint32_t, uint32_t);
|
||||
|
||||
extern int
|
||||
rocprofiler_set_api_table(const char*, uint64_t, uint64_t, void**, uint64_t);
|
||||
|
||||
extern uint32_t
|
||||
rocprofiler_register_import_hip(void);
|
||||
|
||||
extern uint32_t
|
||||
rocprofiler_register_import_hsa(void);
|
||||
|
||||
extern uint32_t
|
||||
rocprofiler_register_import_roctx(void);
|
||||
|
||||
extern uint32_t
|
||||
rocprofiler_register_import_hip_static(void);
|
||||
|
||||
extern uint32_t
|
||||
rocprofiler_register_import_hsa_static(void);
|
||||
|
||||
extern uint32_t
|
||||
rocprofiler_register_import_roctx_static(void);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace fs = ::std::filesystem;
|
||||
using namespace rocprofiler_register;
|
||||
using rocprofiler_set_api_table_t = decltype(::rocprofiler_set_api_table)*;
|
||||
using bitset_t = std::bitset<sizeof(rocprofiler_register_library_indentifier_t::handle)>;
|
||||
|
||||
static_assert(sizeof(bitset_t) ==
|
||||
sizeof(rocprofiler_register_library_indentifier_t::handle),
|
||||
"bitset should be same at uint64_t");
|
||||
|
||||
int rocprofiler_register_verbose = common::get_env("ROCPROFILER_REGISTER_VERBOSE", 0);
|
||||
constexpr int rocprofiler_register_info_level = 2;
|
||||
constexpr auto rocprofiler_lib_name = "librocprofiler64.so";
|
||||
constexpr auto rocprofiler_lib_register_entrypoint = "rocprofiler_set_api_table";
|
||||
constexpr auto rocprofiler_register_lib_name =
|
||||
"librocprofiler-register.so." ROCPROFILER_REGISTER_SOVERSION;
|
||||
|
||||
enum rocp_reg_supported_library // NOLINT(performance-enum-size)
|
||||
{
|
||||
ROCP_REG_HSA = 0,
|
||||
ROCP_REG_HIP,
|
||||
ROCP_REG_ROCTX,
|
||||
ROCP_REG_LAST,
|
||||
};
|
||||
|
||||
template <size_t>
|
||||
struct supported_library_trait
|
||||
{
|
||||
static constexpr bool specialized = false;
|
||||
static constexpr auto value = ROCP_REG_LAST;
|
||||
static constexpr const char* const common_name = nullptr;
|
||||
static constexpr const char* const symbol_name = nullptr;
|
||||
static constexpr const char* const library_name = nullptr;
|
||||
};
|
||||
|
||||
#define ROCP_REG_DEFINE_LIBRARY_TRAITS(ENUM, NAME, SYM_NAME, LIB_NAME) \
|
||||
template <> \
|
||||
struct supported_library_trait<ENUM> \
|
||||
{ \
|
||||
static constexpr bool specialized = true; \
|
||||
static constexpr auto value = ENUM; \
|
||||
static constexpr auto common_name = NAME; \
|
||||
static constexpr auto symbol_name = SYM_NAME; \
|
||||
static constexpr auto library_name = LIB_NAME; \
|
||||
};
|
||||
|
||||
ROCP_REG_DEFINE_LIBRARY_TRAITS(ROCP_REG_HSA,
|
||||
"hsa",
|
||||
"rocprofiler_register_import_hsa",
|
||||
"libhsa-runtime64.so.[2-9]($|\\.[0-9\\.]+)")
|
||||
|
||||
ROCP_REG_DEFINE_LIBRARY_TRAITS(ROCP_REG_HIP,
|
||||
"hip",
|
||||
"rocprofiler_register_import_hip",
|
||||
"libamdhip64.so.[6-9]($|\\.[0-9\\.]+)")
|
||||
|
||||
ROCP_REG_DEFINE_LIBRARY_TRAITS(ROCP_REG_ROCTX,
|
||||
"roctx",
|
||||
"rocprofiler_register_import_roctx",
|
||||
"libroctx64.so.[4-9]($|\\.[0-9\\.]+)")
|
||||
|
||||
auto
|
||||
get_this_library_path()
|
||||
{
|
||||
auto _this_lib_path = binary::get_linked_path(rocprofiler_register_lib_name,
|
||||
{ RTLD_NOLOAD | RTLD_LAZY });
|
||||
ROCPROFILER_REGISTER_REQUIRE(_this_lib_path)
|
||||
<< rocprofiler_register_lib_name
|
||||
<< " could not locate itself in the list of loaded libraries";
|
||||
return fs::path{ *_this_lib_path }.parent_path().string();
|
||||
}
|
||||
|
||||
struct rocp_import
|
||||
{
|
||||
rocp_reg_supported_library library_idx = ROCP_REG_LAST;
|
||||
std::string_view common_name = {};
|
||||
std::string_view symbol_name = {};
|
||||
std::string_view library_name = {};
|
||||
};
|
||||
|
||||
template <size_t... Idx>
|
||||
auto rocp_reg_get_imports(std::index_sequence<Idx...>)
|
||||
{
|
||||
auto _data = std::vector<rocp_import>{};
|
||||
auto _import_scan = [&_data](auto _info) {
|
||||
if(_info.specialized)
|
||||
{
|
||||
_data.emplace_back(rocp_import{
|
||||
_info.value, _info.common_name, _info.symbol_name, _info.library_name });
|
||||
}
|
||||
};
|
||||
|
||||
(_import_scan(supported_library_trait<Idx>{}), ...);
|
||||
return _data;
|
||||
}
|
||||
|
||||
auto
|
||||
rocp_reg_scan_for_tools()
|
||||
{
|
||||
auto _rocp_reg_lib = common::get_env("ROCPROFILER_REGISTER_LIBRARY", std::string{});
|
||||
bool _force_tool =
|
||||
common::get_env("ROCPROFILER_REGISTER_FORCE_LOAD", !_rocp_reg_lib.empty());
|
||||
bool _found_tool = (rocprofiler_configure != nullptr || _force_tool);
|
||||
|
||||
static void* rocprofiler_lib_handle = nullptr;
|
||||
static rocprofiler_set_api_table_t rocprofiler_lib_config_fn = nullptr;
|
||||
|
||||
if(_force_tool)
|
||||
{
|
||||
if(rocprofiler_lib_handle && rocprofiler_lib_config_fn)
|
||||
return std::make_pair(rocprofiler_lib_handle, rocprofiler_lib_config_fn);
|
||||
|
||||
if(_rocp_reg_lib.empty()) _rocp_reg_lib = rocprofiler_lib_name;
|
||||
|
||||
auto _rocp_reg_lib_path = fs::path{ _rocp_reg_lib };
|
||||
auto _rocp_reg_lib_path_fname = _rocp_reg_lib_path.filename();
|
||||
auto _rocp_reg_lib_path_abs =
|
||||
(_rocp_reg_lib_path.is_absolute())
|
||||
? _rocp_reg_lib_path
|
||||
: (fs::path{ get_this_library_path() } / _rocp_reg_lib_path_fname);
|
||||
|
||||
// check to see if the rocprofiler library is already loaded
|
||||
rocprofiler_lib_handle =
|
||||
dlopen(_rocp_reg_lib_path.c_str(), RTLD_NOLOAD | RTLD_LAZY);
|
||||
|
||||
// try to load with the given path
|
||||
if(!rocprofiler_lib_handle)
|
||||
{
|
||||
rocprofiler_lib_handle =
|
||||
dlopen(_rocp_reg_lib_path.c_str(), RTLD_GLOBAL | RTLD_LAZY);
|
||||
}
|
||||
|
||||
// try to load with the absoulte path
|
||||
if(!rocprofiler_lib_handle)
|
||||
{
|
||||
_rocp_reg_lib_path = _rocp_reg_lib_path_abs;
|
||||
rocprofiler_lib_handle =
|
||||
dlopen(_rocp_reg_lib_path.c_str(), RTLD_GLOBAL | RTLD_LAZY);
|
||||
}
|
||||
|
||||
// try to load with the basename path
|
||||
if(!rocprofiler_lib_handle)
|
||||
{
|
||||
_rocp_reg_lib_path = _rocp_reg_lib_path_fname;
|
||||
rocprofiler_lib_handle =
|
||||
dlopen(_rocp_reg_lib_path.c_str(), RTLD_GLOBAL | RTLD_LAZY);
|
||||
}
|
||||
|
||||
if(rocprofiler_register_verbose >= rocprofiler_register_info_level)
|
||||
ROCPROFILER_REGISTER_INFO << "loaded " << _rocp_reg_lib_path_fname.string()
|
||||
<< " library at " << _rocp_reg_lib_path.string();
|
||||
|
||||
ROCPROFILER_REGISTER_REQUIRE(rocprofiler_lib_handle)
|
||||
<< _rocp_reg_lib << " failed to load\n";
|
||||
|
||||
*(void**) (&rocprofiler_lib_config_fn) =
|
||||
dlsym(rocprofiler_lib_handle, rocprofiler_lib_register_entrypoint);
|
||||
|
||||
ROCPROFILER_REGISTER_REQUIRE(rocprofiler_lib_config_fn)
|
||||
<< _rocp_reg_lib << " did not contain '"
|
||||
<< rocprofiler_lib_register_entrypoint << "' symbol\n";
|
||||
}
|
||||
else if(_found_tool && rocprofiler_set_api_table)
|
||||
{
|
||||
rocprofiler_lib_config_fn = &rocprofiler_set_api_table;
|
||||
}
|
||||
|
||||
return std::make_pair(rocprofiler_lib_handle, rocprofiler_lib_config_fn);
|
||||
}
|
||||
|
||||
constexpr auto library_seq = std::make_index_sequence<ROCP_REG_LAST>{};
|
||||
auto global_mutex = std::recursive_mutex{};
|
||||
auto import_info = rocp_reg_get_imports(library_seq);
|
||||
auto instance_counters = std::array<std::atomic_uint64_t, ROCP_REG_LAST>{};
|
||||
} // namespace
|
||||
|
||||
extern "C" {
|
||||
rocprofiler_register_error_code_t
|
||||
rocprofiler_register_library_api_table(
|
||||
const char* common_name,
|
||||
rocprofiler_register_import_func_t import_func,
|
||||
uint32_t lib_version,
|
||||
void** api_tables,
|
||||
uint64_t api_table_length,
|
||||
rocprofiler_register_library_indentifier_t* register_id)
|
||||
{
|
||||
if(api_table_length < 1) return ROCP_REG_BAD_API_TABLE_LENGTH;
|
||||
|
||||
(void) lib_version;
|
||||
(void) api_tables;
|
||||
|
||||
auto _lk = std::unique_lock<std::recursive_mutex>{ global_mutex, std::defer_lock };
|
||||
if(_lk.owns_lock()) return ROCP_REG_DEADLOCK;
|
||||
|
||||
auto _scan_result = rocp_reg_scan_for_tools();
|
||||
|
||||
rocp_import* _import_match = nullptr;
|
||||
for(auto& itr : import_info)
|
||||
{
|
||||
if(itr.common_name == common_name)
|
||||
{
|
||||
_import_match = &itr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// not a supported library name
|
||||
if(!_import_match || _import_match->library_idx == ROCP_REG_LAST)
|
||||
return ROCP_REG_UNSUPPORTED_API;
|
||||
|
||||
if(import_func != nullptr &&
|
||||
common::get_env<bool>("ROCPROFILER_REGISTER_SECURE", false))
|
||||
{
|
||||
auto _import_func_addr = reinterpret_cast<uintptr_t>(import_func);
|
||||
auto _segment_addresses = binary::get_segment_addresses();
|
||||
auto _in_address_range = [](uintptr_t _addr,
|
||||
const std::vector<binary::address_range>& _range) {
|
||||
for(auto ritr : _range)
|
||||
{
|
||||
if(_addr >= ritr.start && _addr < ritr.last) return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// check that the address of the import function is within the expected library
|
||||
// name
|
||||
bool _valid_addr = false;
|
||||
for(const auto& itr : _segment_addresses)
|
||||
{
|
||||
if(_in_address_range(_import_func_addr, itr.ranges))
|
||||
{
|
||||
if(std::regex_search(fs::path{ itr.filepath }.filename().string(),
|
||||
std::regex{ _import_match->library_name.data() }))
|
||||
{
|
||||
_valid_addr = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the library provided
|
||||
if(!_valid_addr) return ROCP_REG_INVALID_API_ADDRESS;
|
||||
}
|
||||
|
||||
constexpr auto offset_factor = 64 / std::max<size_t>(ROCP_REG_LAST, 8);
|
||||
// if ROCP_REG_LAST > 8, then we can no longer encode 8 instances per lib
|
||||
// because we ran out of bits (i.e. max of 8 * 8 = 64)
|
||||
static_assert((offset_factor * ROCP_REG_LAST) <= sizeof(uint64_t) * 8,
|
||||
"ROCP_REG_LAST has exceeded the max allowable size");
|
||||
|
||||
// too many instances of the same library
|
||||
if(instance_counters.at(_import_match->library_idx) >= offset_factor)
|
||||
return ROCP_REG_EXCESS_API_INSTANCES;
|
||||
|
||||
auto _instance_val = instance_counters.at(_import_match->library_idx)++;
|
||||
auto& _bits = *reinterpret_cast<bitset_t*>(®ister_id->handle);
|
||||
_bits = bitset_t{ (offset_factor * _import_match->library_idx) + _instance_val };
|
||||
|
||||
if(_bits.to_ulong() != register_id->handle)
|
||||
throw std::runtime_error("error encoding register_id");
|
||||
|
||||
// rocprofiler library is dlopened and we have the functor to pass the API data
|
||||
auto _activate_rocprofiler = (_scan_result.second != nullptr);
|
||||
|
||||
if(_activate_rocprofiler)
|
||||
{
|
||||
auto _ret = _scan_result.second(
|
||||
common_name, lib_version, _instance_val, api_tables, api_table_length);
|
||||
if(_ret != 0) return ROCP_REG_ROCPROFILER_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ROCP_REG_NO_TOOLS;
|
||||
}
|
||||
|
||||
return ROCP_REG_SUCCESS;
|
||||
}
|
||||
|
||||
const char*
|
||||
rocprofiler_register_error_string(rocprofiler_register_error_code_t _ec)
|
||||
{
|
||||
switch(_ec)
|
||||
{
|
||||
case ROCP_REG_SUCCESS: return "rocprofiler_register_success";
|
||||
case ROCP_REG_NO_TOOLS: return "rocprofiler_register_no_tools";
|
||||
case ROCP_REG_DEADLOCK: return "rocprofiler_register_deadlock";
|
||||
case ROCP_REG_BAD_API_TABLE_LENGTH:
|
||||
return "rocprofiler_register_bad_api_table_length";
|
||||
case ROCP_REG_UNSUPPORTED_API: return "rocprofiler_register_unsupported_api";
|
||||
case ROCP_REG_INVALID_API_ADDRESS:
|
||||
return "rocprofiler_register_invalid_api_address";
|
||||
case ROCP_REG_ROCPROFILER_ERROR: return "rocprofiler_register_rocprofiler_error";
|
||||
case ROCP_REG_EXCESS_API_INSTANCES:
|
||||
return "rocprofiler_register_excess_api_instances";
|
||||
case ROCP_REG_ERROR_CODE_END: return "rocprofiler_register_unknown_error";
|
||||
}
|
||||
return "rocprofiler_register_unknown_error";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user