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
This commit is contained in:
committed by
GitHub
parent
53a9547670
commit
fa4295db6b
@@ -0,0 +1,11 @@
|
||||
#
|
||||
#
|
||||
#
|
||||
rocprofiler_register_activate_clang_tidy()
|
||||
|
||||
if(ROCPROFILER_REGISTER_BUILD_CODECOV)
|
||||
set(CMAKE_BUILD_TYPE "Coverage")
|
||||
endif()
|
||||
|
||||
add_subdirectory(include)
|
||||
add_subdirectory(lib)
|
||||
@@ -0,0 +1,4 @@
|
||||
#
|
||||
#
|
||||
#
|
||||
add_subdirectory(rocprofiler-register)
|
||||
@@ -0,0 +1,13 @@
|
||||
#
|
||||
#
|
||||
# Installation of public headers
|
||||
#
|
||||
#
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.h @ONLY)
|
||||
|
||||
set(ROCPROFILER_REGISTER_INCLUDE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rocprofiler-register.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.h)
|
||||
|
||||
install(FILES ${ROCPROFILER_REGISTER_INCLUDE_FILES}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rocprofiler-register)
|
||||
@@ -0,0 +1,188 @@
|
||||
// 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 <rocprofiler-register/version.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef int (*rocprofiler_configure_callback_t)(void*);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rocprofiler_configure_callback_t initialize;
|
||||
rocprofiler_configure_callback_t finalize;
|
||||
void* user_data;
|
||||
} rocprofiler_configure_result_t;
|
||||
|
||||
typedef uint32_t (*rocprofiler_register_import_func_t)(void);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t handle;
|
||||
} rocprofiler_register_library_indentifier_t;
|
||||
|
||||
/// @enum rocprofiler_register_error_code_t
|
||||
/// @brief enumeration of error codes
|
||||
///
|
||||
/// @var ROCP_REG_SUCCESS
|
||||
/// @brief Successful call to rocprofiler-register
|
||||
///
|
||||
/// @var ROCP_REG_NO_TOOLS
|
||||
/// @brief API table was not passed to rocprofiler because no rocprofiler tool
|
||||
/// configuration symbols were requested
|
||||
///
|
||||
/// @var ROCP_REG_DEADLOCK
|
||||
/// @brief The thread that is currently communicating the API tables to rocprofiler
|
||||
/// re-entered \ref rocprofiler_register_library_api_table
|
||||
///
|
||||
/// @var ROCP_REG_BAD_API_TABLE_LENGTH
|
||||
/// @brief Library provided an invalid API table length (likely zero)
|
||||
///
|
||||
/// @var ROCP_REG_UNSUPPORTED_API
|
||||
/// @brief Library is providing an API table name that is not supported
|
||||
///
|
||||
/// @var ROCP_REG_ROCPROFILER_ERROR
|
||||
/// @brief Rocprofiler returned an error when passing the API tables
|
||||
///
|
||||
/// @var ROCP_REG_EXCESS_API_INSTANCES
|
||||
/// @brief The same API has been registered too many times
|
||||
///
|
||||
typedef enum rocprofiler_register_error_code_t // NOLINT(performance-enum-size)
|
||||
{
|
||||
ROCP_REG_SUCCESS = 0,
|
||||
ROCP_REG_NO_TOOLS,
|
||||
ROCP_REG_DEADLOCK,
|
||||
ROCP_REG_BAD_API_TABLE_LENGTH,
|
||||
ROCP_REG_UNSUPPORTED_API,
|
||||
ROCP_REG_INVALID_API_ADDRESS,
|
||||
ROCP_REG_ROCPROFILER_ERROR,
|
||||
ROCP_REG_EXCESS_API_INSTANCES,
|
||||
ROCP_REG_ERROR_CODE_END,
|
||||
} rocprofiler_register_error_code_t;
|
||||
|
||||
/// @fn rocprofiler_register_error_code_t rocprofiler_register_library_api_table(
|
||||
/// const char* lib_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)
|
||||
/// @param[in] lib_name string identifier for the library registering the API table
|
||||
/// @param[in] import_func function pointer to rocprofiler_register_import_<lib_name>
|
||||
/// symbol
|
||||
/// @param[in] lib_version lib version in form of (10000 * major ) + (100 * minor) + patch
|
||||
/// @param[in] api_tables pointer to one or more API table pointers
|
||||
/// @param[in] api_table_length number of API tables that are being passed in. Must be > 0
|
||||
/// @param[out] register_id a unique identifier for this library encoding the API category
|
||||
/// and the priority in the event that multiple libraries register with the same name
|
||||
/// @returns value of type @ref rocprofiler_register_error_code_t
|
||||
///
|
||||
/// @brief primary function call that needs to be performed when the API table of the
|
||||
/// library is initialized.
|
||||
///
|
||||
rocprofiler_register_error_code_t
|
||||
rocprofiler_register_library_api_table(
|
||||
const char* lib_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)
|
||||
ROCPROFILER_REGISTER_ATTRIBUTE(nonnull(4, 6)) ROCPROFILER_REGISTER_PUBLIC_API;
|
||||
|
||||
const char* rocprofiler_register_error_string(rocprofiler_register_error_code_t)
|
||||
ROCPROFILER_REGISTER_PUBLIC_API;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/// @def ROCPROFILER_REGISTER_COMPUTE_VERSION_1
|
||||
/// @param[in] MAJOR_VERSION major version of library (integral)
|
||||
/// @brief Helper macro for users to generate versioning int expected by
|
||||
/// rocprofiler-register when the library only maintains a major version number
|
||||
#define ROCPROFILER_REGISTER_COMPUTE_VERSION_1(MAJOR_VERSION) (10000 * MAJOR_VERSION)
|
||||
|
||||
/// @def ROCPROFILER_REGISTER_COMPUTE_VERSION_
|
||||
/// @param[in] MAJOR_VERSION major version of library (integral)
|
||||
/// @param[in] MINOR_VERSION minor version of library (integral)
|
||||
/// @brief Helper macro for users to generate versioning int expected by
|
||||
/// rocprofiler-register when the library only maintains a major and minor version number
|
||||
#define ROCPROFILER_REGISTER_COMPUTE_VERSION_2(MAJOR_VERSION, MINOR_VERSION) \
|
||||
(ROCPROFILER_REGISTER_COMPUTE_VERSION_1(MAJOR_VERSION) + (100 * MINOR_VERSION))
|
||||
|
||||
/// @def ROCPROFILER_REGISTER_COMPUTE_VERSION_3
|
||||
/// @param[in] MAJOR_VERSION major version of library (integral)
|
||||
/// @param[in] MINOR_VERSION minor version of library (integral)
|
||||
/// @param[in] PATCH_VERSION patch version of library (integral)
|
||||
/// @brief Helper macro for users to generate versioning int expected by
|
||||
/// rocprofiler-register when the library maintains a major, minor, and patch version
|
||||
/// numbers
|
||||
#define ROCPROFILER_REGISTER_COMPUTE_VERSION_3( \
|
||||
MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION) \
|
||||
(ROCPROFILER_REGISTER_COMPUTE_VERSION_2(MAJOR_VERSION, MINOR_VERSION) + \
|
||||
(PATCH_VERSION))
|
||||
|
||||
/// @def ROCPROFILER_REGISTER_COMPUTE_VERSION_4
|
||||
/// @param[in] MAJOR_VERSION major version of library (integral)
|
||||
/// @param[in] MINOR_VERSION minor version of library (integral)
|
||||
/// @param[in] PATCH_VERSION patch version of library (integral)
|
||||
/// @param[in] TWEAK_VERSION tweak version of library which will be ignored
|
||||
/// @brief Helper macro for users to generate versioning int expected by
|
||||
/// rocprofiler-register when the library maintains a major, minor, patch, and tweak
|
||||
/// version numbers
|
||||
#define ROCPROFILER_REGISTER_COMPUTE_VERSION_3( \
|
||||
MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION) \
|
||||
(ROCPROFILER_REGISTER_COMPUTE_VERSION_2(MAJOR_VERSION, MINOR_VERSION) + \
|
||||
(PATCH_VERSION))
|
||||
|
||||
/// @def ROCPROFILER_REGISTER_IMPORT_FUNC(NAME)
|
||||
/// @param[in] NAME the string identifier for the library
|
||||
/// @brief Helper macro for retrieving the name of the import function which is used by
|
||||
/// rocprofiler-register to identify the location and priority of the registering library
|
||||
#define ROCPROFILER_REGISTER_IMPORT_FUNC(NAME) \
|
||||
ROCPROFILER_REGISTER_PP_COMBINE(rocprofiler_register_import_, NAME)
|
||||
|
||||
/// @def ROCPROFILER_REGISTER_DEFINE_IMPORT(NAME, VERSION)
|
||||
/// @param[in] NAME the unquoted string identifier for the library, e.g. hip
|
||||
/// @brief Helper macro for declaring a visible import symbol for rocprofiler-register
|
||||
/// which returns the version.
|
||||
///
|
||||
#ifdef __cplusplus
|
||||
# define ROCPROFILER_REGISTER_DEFINE_IMPORT(NAME, VERSION) \
|
||||
extern "C" { \
|
||||
uint32_t ROCPROFILER_REGISTER_IMPORT_FUNC(NAME)() \
|
||||
ROCPROFILER_REGISTER_ATTRIBUTE(visibility("default")); \
|
||||
\
|
||||
uint32_t ROCPROFILER_REGISTER_IMPORT_FUNC(NAME)() { return VERSION; } \
|
||||
}
|
||||
#else
|
||||
# define ROCPROFILER_REGISTER_DEFINE_IMPORT(NAME, VERSION) \
|
||||
uint32_t ROCPROFILER_REGISTER_IMPORT_FUNC(NAME)(void) \
|
||||
ROCPROFILER_REGISTER_ATTRIBUTE(visibility("default")); \
|
||||
\
|
||||
uint32_t ROCPROFILER_REGISTER_IMPORT_FUNC(NAME)(void) { return VERSION; }
|
||||
#endif
|
||||
@@ -0,0 +1,103 @@
|
||||
// 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
|
||||
|
||||
// clang-format off
|
||||
#define ROCPROFILER_REGISTER_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
|
||||
#define ROCPROFILER_REGISTER_VERSION_MINOR @PROJECT_VERSION_MINOR@
|
||||
#define ROCPROFILER_REGISTER_VERSION_PATCH @PROJECT_VERSION_PATCH@
|
||||
#define ROCPROFILER_REGISTER_VERSION_STRING "@FULL_VERSION_STRING@"
|
||||
#define ROCPROFILER_REGISTER_SOVERSION "@PROJECT_VERSION_MAJOR@"
|
||||
#define ROCPROFILER_REGISTER_GIT_DESCRIBE "@ROCPROFILER_REGISTER_GIT_DESCRIBE@"
|
||||
#define ROCPROFILER_REGISTER_GIT_REVISION "@ROCPROFILER_REGISTER_GIT_REVISION@"
|
||||
|
||||
// system info during compilation
|
||||
#define ROCPROFILER_REGISTER_LIBRARY_ARCH "@CMAKE_LIBRARY_ARCHITECTURE@"
|
||||
#define ROCPROFILER_REGISTER_SYSTEM_NAME "@CMAKE_SYSTEM_NAME@"
|
||||
#define ROCPROFILER_REGISTER_SYSTEM_PROCESSOR "@CMAKE_SYSTEM_PROCESSOR@"
|
||||
#define ROCPROFILER_REGISTER_SYSTEM_VERSION "@CMAKE_SYSTEM_VERSION@"
|
||||
|
||||
// compiler information
|
||||
#define ROCPROFILER_REGISTER_COMPILER_ID "@CMAKE_CXX_COMPILER_ID@"
|
||||
#define ROCPROFILER_REGISTER_COMPILER_VERSION "@CMAKE_CXX_COMPILER_VERSION@"
|
||||
#define ROCPROFILER_REGISTER_COMPILER_STRING ROCPROFILER_REGISTER_COMPILER_ID " v" ROCPROFILER_REGISTER_COMPILER_VERSION
|
||||
// clang-format on
|
||||
|
||||
#define ROCPROFILER_REGISTER_VERSION \
|
||||
((10000 * ROCPROFILER_REGISTER_VERSION_MAJOR) + \
|
||||
(100 * ROCPROFILER_REGISTER_VERSION_MINOR) + ROCPROFILER_REGISTER_VERSION_PATCH)
|
||||
|
||||
#define ROCPROFILER_REGISTER_ATTRIBUTE(...) __attribute__((__VA_ARGS__))
|
||||
#define ROCPROFILER_REGISTER_PP_COMBINE(X, Y) X##Y
|
||||
|
||||
#if defined(rocprofiler_register_EXPORTS)
|
||||
// only defined in build tree
|
||||
# define ROCPROFILER_REGISTER_VISIBILITY(MODE) \
|
||||
ROCPROFILER_REGISTER_ATTRIBUTE(visibility(MODE))
|
||||
# define ROCPROFILER_REGISTER_PUBLIC_API ROCPROFILER_REGISTER_VISIBILITY("default")
|
||||
# define ROCPROFILER_REGISTER_HIDDEN_API ROCPROFILER_REGISTER_VISIBILITY("hidden")
|
||||
# define ROCPROFILER_REGISTER_INTERNAL_API ROCPROFILER_REGISTER_VISIBILITY("internal")
|
||||
# define ROCPROFILER_REGISTER_INLINE \
|
||||
ROCPROFILER_REGISTER_ATTRIBUTE(always_inline) inline
|
||||
# define ROCPROFILER_REGISTER_NOINLINE ROCPROFILER_REGISTER_ATTRIBUTE(noinline)
|
||||
# define ROCPROFILER_REGISTER_HOT ROCPROFILER_REGISTER_ATTRIBUTE(hot)
|
||||
# define ROCPROFILER_REGISTER_COLD ROCPROFILER_REGISTER_ATTRIBUTE(cold)
|
||||
# define ROCPROFILER_REGISTER_CONST ROCPROFILER_REGISTER_ATTRIBUTE(const)
|
||||
# define ROCPROFILER_REGISTER_PURE ROCPROFILER_REGISTER_ATTRIBUTE(pure)
|
||||
# define ROCPROFILER_REGISTER_WEAK ROCPROFILER_REGISTER_ATTRIBUTE(weak)
|
||||
# define ROCPROFILER_REGISTER_PACKED ROCPROFILER_REGISTER_ATTRIBUTE(__packed__)
|
||||
# define ROCPROFILER_REGISTER_PACKED_ALIGN(VAL) \
|
||||
ROCPROFILER_REGISTER_PACKED ROCPROFILER_REGISTER_ATTRIBUTE(__aligned__(VAL))
|
||||
# define ROCPROFILER_REGISTER_LIKELY(...) __builtin_expect((__VA_ARGS__), 1)
|
||||
# define ROCPROFILER_REGISTER_UNLIKELY(...) __builtin_expect((__VA_ARGS__), 0)
|
||||
|
||||
# if defined(ROCPROFILER_REGISTER_CI) && ROCPROFILER_REGISTER_CI > 0
|
||||
# if defined(NDEBUG)
|
||||
# undef NDEBUG
|
||||
# endif
|
||||
# if !defined(DEBUG)
|
||||
# define DEBUG 1
|
||||
# endif
|
||||
# if defined(__cplusplus)
|
||||
# include <cassert> // NOLINT
|
||||
# else
|
||||
# include <assert.h>
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# define ROCPROFILER_REGISTER_STRINGIZE(X) ROCPROFILER_REGISTER_STRINGIZE2(X)
|
||||
# define ROCPROFILER_REGISTER_STRINGIZE2(X) # X
|
||||
# define ROCPROFILER_REGISTER_LINESTR ROCPROFILER_REGISTER_STRINGIZE(__LINE__)
|
||||
# define ROCPROFILER_REGISTER_ESC(...) __VA_ARGS__
|
||||
|
||||
# if defined(__cplusplus)
|
||||
# if !defined(ROCPROFILER_REGISTER_FOLD_EXPRESSION)
|
||||
# define ROCPROFILER_REGISTER_FOLD_EXPRESSION(...) ((__VA_ARGS__), ...)
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
# define ROCPROFILER_REGISTER_VISIBILITY(MODE)
|
||||
# define ROCPROFILER_REGISTER_PUBLIC_API
|
||||
# define ROCPROFILER_REGISTER_HIDDEN_API
|
||||
# define ROCPROFILER_REGISTER_INTERNAL_API
|
||||
#endif
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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