User API + reorganized lib folders (#30)

* User API + reorganized lib folders

- omnitrace_user_start_trace
- omnitrace_user_stop_trace
- omnitrace_user_start_thread_trace
- omnitrace_user_stop_thread_trace
- omnitrace_user_push_region
- omnitrace_user_pop_region

* New OpenMP examples/tests

* Fix to KokkosP

* OMPT support

- fixed omnitrace instrumenting reporting
- common invoke improvements
- component::user_region

* exclude kmp_threadprivate_

* Separate omnitrace into multiple files

* PTL and timemory submodule updates

* Active guards + USE_OMPT guards in omnitrace-dl

* Tweak transpose default iterations

* omnitrace-precommit build target

* Omnitrace exe restructuring pt 2

- Never instrument functions with less than 4 instructions
- Never instrument ompt_start_tool or nanosleep
- module_function serializes heuristics
- removed hash stuff from omnitrace
- removed instr_procedures lambda
- WAITPID_DEBUG_MESSAGE

* set_state, "_hidden" fix, CI exceptions, backtrace fix

- set_state function
- fixed "_hidden" from appearing in print macros using __FUNCTION__
- OMNITRACE_CI_THROW
- more CI checks in library
- fixed backtrace init value sample issue being ignored

* Tweaks to OMPT tests

* cmake-formatting

* Removed debug output from backtrace processing

* Fix warnings and verbosity

* omnitrace-dl fix for libomp

* omnitrace-avail fixes

- remove second omnitrace_init_library call
- fix -r option not working

* Additional testing

- source/bin/tests
- tests for omnitrace-exe
- tests for omnitrace-avail

* cmake-format

* Reduce runtime of openmp-lu

* Update openmp-lu and tests timeout

* openmp-lu and CI tweaks

- decrease iterations
- OMP_NUM_THREADS=2
- install clang and libomp-dev in linux-ci
- fix data-files in linux-ci
Цей коміт міститься в:
Jonathan R. Madsen authored and GitHub committed 2022-03-07 20:40:48 -06:00
1 джерело 2acaa7aa9f
коміт d80752bc69
106 files changed
+9180 -1947

No files matched your search

+10
Переглянути файл
@@ -12,3 +12,13 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
add_subdirectory(lib)
add_subdirectory(bin)
if(OMNITRACE_BUILD_DEVELOPER)
add_custom_target(omnitrace-precommit)
foreach(_TARGET format-omnitrace-source format-omnitrace-cmake format-timemory-source
format-timemory-cmake)
if(TARGET ${_TARGET})
add_dependencies(omnitrace-precommit ${_TARGET})
endif()
endforeach()
endif()
+4
Переглянути файл
@@ -1,3 +1,7 @@
add_subdirectory(omnitrace-avail)
add_subdirectory(omnitrace-critical-trace)
add_subdirectory(omnitrace)
if(OMNITRACE_BUILD_TESTING)
add_subdirectory(tests)
endif()
+6 -4
Переглянути файл
@@ -30,6 +30,7 @@
#include "library/components/omnitrace.hpp"
#include "library/components/pthread_gotcha.hpp"
#include "library/components/roctracer.hpp"
#include "library/components/user_region.hpp"
#include "library/config.hpp"
#include <timemory/components.hpp>
@@ -613,8 +614,6 @@ main(int argc, char** argv)
if(!os) os = &std::cout;
omnitrace_init_library();
if(include_components) write_component_info(*os, options, use_mark, fields);
dump_log();
@@ -766,7 +765,9 @@ write_component_info(std::ostream& os, const array_t<bool, N>& options,
_mark.at(i));
}
_selected += (is_category_selected(std::get<2>(itr).at(CATEGORY))) ? 1 : 0;
if(!category_regex_keys.empty())
_selected +=
(is_category_selected(std::get<2>(itr).at(CATEGORY))) ? 1 : 0;
if(_selected == 0) continue;
}
@@ -834,7 +835,8 @@ write_component_info(std::ostream& os, const array_t<bool, N>& options,
_mark.at(i));
}
_selected += (is_category_selected(std::get<2>(itr).at(CATEGORY))) ? 1 : 0;
if(!category_regex_keys.empty())
_selected += (is_category_selected(std::get<2>(itr).at(CATEGORY))) ? 1 : 0;
if(_selected > 0)
{
+12 -3
Переглянути файл
@@ -4,10 +4,19 @@
#
# ------------------------------------------------------------------------------#
add_executable(
add_executable(omnitrace-exe ${_EXCLUDE})
target_sources(
omnitrace-exe
${_EXCLUDE} ${CMAKE_CURRENT_LIST_DIR}/omnitrace.cpp
${CMAKE_CURRENT_LIST_DIR}/omnitrace.hpp ${CMAKE_CURRENT_LIST_DIR}/details.cpp)
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/omnitrace.cpp
${CMAKE_CURRENT_LIST_DIR}/details.cpp
${CMAKE_CURRENT_LIST_DIR}/function_signature.cpp
${CMAKE_CURRENT_LIST_DIR}/module_function.cpp
${CMAKE_CURRENT_LIST_DIR}/omnitrace.hpp
${CMAKE_CURRENT_LIST_DIR}/info.hpp
${CMAKE_CURRENT_LIST_DIR}/fwd.hpp
${CMAKE_CURRENT_LIST_DIR}/function_signature.hpp
${CMAKE_CURRENT_LIST_DIR}/module_function.hpp)
target_link_libraries(
omnitrace-exe
+85 -87
Переглянути файл
@@ -40,7 +40,7 @@ get_whole_function_names()
"backtrace", "backtrace_symbols", "backtrace_symbols_fd", "sigaddset",
"sigandset", "sigdelset", "sigemptyset", "sigfillset", "sighold", "sigisemptyset",
"sigismember", "sigorset", "sigrelse", "sigvec", "strtok", "strstr", "sbrk",
"strxfrm",
"strxfrm", "atexit", "ompt_start_tool", "nanosleep",
// below are functions which never terminate
"rocr::core::Signal::WaitAny", "rocr::core::Runtime::AsyncEventsLoop",
"rocr::core::BusyWaitSignal::WaitAcquire",
@@ -525,10 +525,32 @@ are_file_include_exclude_lists_empty()
// the instrumented loop and formats it properly.
//
function_signature
get_loop_file_line_info(module_t* mutatee_module, procedure_t* f, flow_graph_t* cfGraph,
get_loop_file_line_info(module_t* module, procedure_t* func, flow_graph_t* cfGraph,
basic_loop_t* loopToInstrument)
{
if(!cfGraph || !loopToInstrument || !f) return function_signature{ "", "", "" };
if(!cfGraph || !loopToInstrument || !func) return function_signature{ "", "", "" };
std::vector<BPatch_basicBlock*> basic_blocks{};
loopToInstrument->getLoopBasicBlocksExclusive(basic_blocks);
if(basic_blocks.empty()) return function_signature{ "", "", "" };
auto base_addr = basic_blocks.front()->getStartAddress();
auto last_addr = basic_blocks.front()->getEndAddress();
basic_block_t* block = basic_blocks.front();
for(const auto& itr : basic_blocks)
{
if(itr == block) continue;
if(itr->dominates(block))
{
base_addr = itr->getStartAddress();
last_addr = itr->getEndAddress();
block = itr;
}
}
verbprintf(4, "Loop: size = %lu: base_addr = %lu, last_addr = %lu\n",
(unsigned long) (last_addr - base_addr), base_addr, last_addr);
char fname[FUNCNAMELEN + 1];
char mname[FUNCNAMELEN + 1];
@@ -537,32 +559,14 @@ get_loop_file_line_info(module_t* mutatee_module, procedure_t* f, flow_graph_t*
memset(fname, '\0', FUNCNAMELEN + 1);
memset(mname, '\0', FUNCNAMELEN + 1);
mutatee_module->getName(mname, FUNCNAMELEN);
module->getName(mname, FUNCNAMELEN);
func->getName(fname, FUNCNAMELEN);
bpvector_t<point_t*>* loopStartInst =
cfGraph->findLoopInstPoints(BPatch_locLoopStartIter, loopToInstrument);
bpvector_t<point_t*>* loopExitInst =
cfGraph->findLoopInstPoints(BPatch_locLoopEndIter, loopToInstrument);
auto* returnType = func->getReturnType();
if(!loopStartInst || !loopExitInst) return function_signature{ "", "", "" };
if(returnType) typeName = returnType->getName();
unsigned long baseAddr = (unsigned long) (*loopStartInst)[0]->getAddress();
unsigned long lastAddr =
(unsigned long) (*loopExitInst)[loopExitInst->size() - 1]->getAddress();
verbprintf(3, "Loop: size of lastAddr = %lu: baseAddr = %lu, lastAddr = %lu\n",
(unsigned long) loopExitInst->size(), (unsigned long) baseAddr,
(unsigned long) lastAddr);
f->getName(fname, FUNCNAMELEN);
auto* returnType = f->getReturnType();
if(returnType)
{
typeName = returnType->getName();
}
auto* params = f->getParams();
auto* params = func->getParams();
std::vector<string_t> _params;
if(params)
{
@@ -574,36 +578,51 @@ get_loop_file_line_info(module_t* mutatee_module, procedure_t* f, flow_graph_t*
}
}
bpvector_t<BPatch_statement> lines;
bpvector_t<BPatch_statement> linesEnd;
bpvector_t<BPatch_statement> lines{};
bpvector_t<BPatch_statement> linesEnd{};
bool info1 = mutatee_module->getSourceLines(baseAddr, lines);
bool info1 = module->getSourceLines(base_addr, lines);
string_t filename = mname;
if(info1)
{
// filename = lines[0].fileName();
auto row1 = lines[0].lineNumber();
auto col1 = lines[0].lineOffset();
int row1 = 0;
int col1 = 0;
for(auto& itr : lines)
{
if(itr.lineNumber() > 0)
{
row1 = itr.lineNumber();
col1 = itr.lineOffset();
break;
}
}
if(row1 == 0 && col1 == 0)
return function_signature(typeName, fname, filename, _params);
int row2 = 0;
int col2 = 0;
for(auto& itr : lines)
{
row2 = std::max(row2, itr.lineNumber());
col2 = std::max(col2, itr.lineOffset());
}
if(col1 < 0) col1 = 0;
// This following section is attempting to remedy the limitations of
// getSourceLines for loops. As the program goes through the loop, the resulting
// lines go from the loop head, through the instructions present in the loop, to
// the last instruction in the loop, back to the loop head, then to the next
// instruction outside of the loop. What this section does is starts at the last
// instruction in the loop, then goes through the addresses until it reaches the
// next instruction outside of the loop. We then bump back a line. This is not a
// perfect solution, but we will work with the Dyninst team to find something
// better.
bool info2 = mutatee_module->getSourceLines((unsigned long) lastAddr, linesEnd);
verbprintf(3, "size of linesEnd = %lu\n", (unsigned long) linesEnd.size());
bool info2 = module->getSourceLines(last_addr, linesEnd);
verbprintf(4, "size of linesEnd = %lu\n", (unsigned long) linesEnd.size());
if(info2)
{
auto row2 = linesEnd[0].lineNumber();
auto col2 = linesEnd[0].lineOffset();
for(auto& itr : linesEnd)
{
row2 = std::max(row2, itr.lineNumber());
col2 = std::max(col2, itr.lineOffset());
}
if(col2 < 0) col2 = 0;
if(row2 < row1) row1 = row2; // Fix for wrong line numbers
@@ -627,35 +646,30 @@ get_loop_file_line_info(module_t* mutatee_module, procedure_t* f, flow_graph_t*
// We create a new name that embeds the file and line information in the name
//
function_signature
get_func_file_line_info(module_t* mutatee_module, procedure_t* f)
get_func_file_line_info(module_t* module, procedure_t* func)
{
bool info1, info2;
unsigned long baseAddr, lastAddr;
char fname[FUNCNAMELEN + 1];
char mname[FUNCNAMELEN + 1];
int row1, col1, row2, col2;
string_t filename = {};
string_t typeName = {};
using address_t = Dyninst::Address;
char fname[FUNCNAMELEN + 1];
char mname[FUNCNAMELEN + 1];
string_t typeName = {};
memset(fname, '\0', FUNCNAMELEN + 1);
memset(mname, '\0', FUNCNAMELEN + 1);
mutatee_module->getName(mname, FUNCNAMELEN);
module->getName(mname, FUNCNAMELEN);
func->getName(fname, FUNCNAMELEN);
baseAddr = (unsigned long) (f->getBaseAddr());
f->getAddressRange(baseAddr, lastAddr);
bpvector_t<BPatch_statement> lines;
f->getName(fname, FUNCNAMELEN);
address_t base_addr{};
address_t last_addr{};
func->getAddressRange(base_addr, last_addr);
auto* returnType = f->getReturnType();
auto* returnType = func->getReturnType();
if(returnType)
{
typeName = returnType->getName();
}
if(returnType) typeName = returnType->getName();
auto* params = f->getParams();
std::vector<string_t> _params;
auto* params = func->getParams();
std::vector<string_t> _params = {};
if(params)
{
for(auto* itr : *params)
@@ -666,32 +680,16 @@ get_func_file_line_info(module_t* mutatee_module, procedure_t* f)
}
}
info1 = mutatee_module->getSourceLines((unsigned long) baseAddr, lines);
bpvector_t<BPatch_statement> lines = {};
bool info = module->getSourceLines(base_addr, lines);
filename = mname;
string_t filename = mname;
if(info1)
if(info && !lines.empty())
{
// filename = lines[0].fileName();
row1 = lines[0].lineNumber();
col1 = lines[0].lineOffset();
if(col1 < 0) col1 = 0;
info2 = mutatee_module->getSourceLines((unsigned long) (lastAddr - 1), lines);
if(info2)
{
row2 = lines[1].lineNumber();
col2 = lines[1].lineOffset();
if(col2 < 0) col2 = 0;
if(row2 < row1) row1 = row2;
return function_signature(typeName, fname, filename, _params, { row1, 0 },
{ 0, 0 }, false, info1, info2);
}
else
{
return function_signature(typeName, fname, filename, _params, { row1, 0 },
{ 0, 0 }, false, info1, info2);
}
auto row = lines.front().lineNumber();
return function_signature(typeName, fname, filename, _params, { row, 0 },
{ 0, 0 }, false, info, false);
}
else
{
+99
Переглянути файл
@@ -0,0 +1,99 @@
// 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 "function_signature.hpp"
function_signature::function_signature(string_t _ret, const string_t& _name,
string_t _file, location_t _row, location_t _col,
bool _loop, bool _info_beg, bool _info_end)
: m_loop(_loop)
, m_info_beg(_info_beg)
, m_info_end(_info_end)
, m_row(std::move(_row))
, m_col(std::move(_col))
, m_return(std::move(_ret))
, m_name(tim::demangle(_name))
, m_file(std::move(_file))
{
if(m_file.find('/') != string_t::npos)
m_file = m_file.substr(m_file.find_last_of('/') + 1);
}
function_signature::function_signature(const string_t& _ret, const string_t& _name,
const string_t& _file,
const std::vector<string_t>& _params,
location_t _row, location_t _col, bool _loop,
bool _info_beg, bool _info_end)
: function_signature(_ret, _name, _file, _row, _col, _loop, _info_beg, _info_end)
{
m_params = "(";
for(const auto& itr : _params)
m_params.append(itr + ", ");
if(!_params.empty()) m_params = m_params.substr(0, m_params.length() - 2);
m_params += ")";
}
string_t
function_signature::get(function_signature& sig)
{
return sig.get();
}
string_t
function_signature::get() const
{
std::stringstream ss;
if(use_return_info && !m_return.empty()) ss << m_return << " ";
ss << m_name;
if(use_args_info) ss << m_params;
if(m_loop && m_info_beg)
{
auto _row_col_str = [](unsigned long _row, unsigned long _col) {
std::stringstream _ss{};
if(_row == 0 && _col == 0) return std::string{};
if(_col > 0)
_ss << "{" << _row << "," << _col << "}";
else
_ss << "{" << _row << "}";
return _ss.str();
};
auto _rc1 = _row_col_str(m_row.first, m_col.first);
auto _rc2 = _row_col_str(m_row.second, m_col.second);
if(m_info_end && !_rc1.empty() && !_rc2.empty() && _rc1 != _rc2)
ss << " [" << _rc1 << "-" << _rc2 << "]";
else if(m_info_end && !_rc1.empty() && !_rc2.empty() && _rc1 == _rc2)
ss << " [" << _rc1 << "]";
else if(m_info_end && !_rc1.empty() && _rc2.empty())
ss << " [" << _rc1 << "]";
else if(!m_info_end && !_rc1.empty())
ss << " [" << _rc1 << "]";
else
errprintf(1, "loop line info is empty!");
}
if(use_file_info && m_file.length() > 0) ss << " [" << m_file;
if(use_line_info && m_row.first > 0) ss << ":" << m_row.first;
if(use_file_info && m_file.length() > 0) ss << "]";
m_signature = ss.str();
return m_signature;
}
+74
Переглянути файл
@@ -0,0 +1,74 @@
// 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 "fwd.hpp"
struct function_signature
{
using location_t = std::pair<unsigned long, unsigned long>;
TIMEMORY_DEFAULT_OBJECT(function_signature)
function_signature(string_t _ret, const string_t& _name, string_t _file,
location_t _row = { 0, 0 }, location_t _col = { 0, 0 },
bool _loop = false, bool _info_beg = false,
bool _info_end = false);
function_signature(const string_t& _ret, const string_t& _name, const string_t& _file,
const std::vector<string_t>& _params, location_t _row = { 0, 0 },
location_t _col = { 0, 0 }, bool _loop = false,
bool _info_beg = false, bool _info_end = false);
static string_t get(function_signature& sig);
string_t get() const;
bool m_loop = false;
bool m_info_beg = false;
bool m_info_end = false;
location_t m_row = { 0, 0 };
location_t m_col = { 0, 0 };
string_t m_return = {};
string_t m_name = {};
string_t m_params = "()";
string_t m_file = {};
mutable string_t m_signature = {};
friend bool operator==(const function_signature& lhs, const function_signature& rhs)
{
return lhs.get() == rhs.get();
}
template <typename ArchiveT>
void serialize(ArchiveT& _ar, const unsigned)
{
namespace cereal = tim::cereal;
(void) get();
_ar(cereal::make_nvp("loop", m_loop), cereal::make_nvp("info_beg", m_info_beg),
cereal::make_nvp("info_end", m_info_end), cereal::make_nvp("row", m_row),
cereal::make_nvp("col", m_col), cereal::make_nvp("return", m_return),
cereal::make_nvp("name", m_name), cereal::make_nvp("params", m_params),
cereal::make_nvp("file", m_file), cereal::make_nvp("signature", m_signature));
(void) get();
}
};
+273
Переглянути файл
@@ -0,0 +1,273 @@
// 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 <string_view>
#include <timemory/backends/process.hpp>
#include <timemory/environment.hpp>
#include <timemory/mpl/apply.hpp>
#include <timemory/mpl/concepts.hpp>
#include <timemory/mpl/policy.hpp>
#include <timemory/tpls/cereal/archives.hpp>
#include <timemory/tpls/cereal/cereal.hpp>
#include <timemory/utility/argparse.hpp>
#include <timemory/utility/demangle.hpp>
#include <timemory/utility/popen.hpp>
#include <timemory/variadic/macros.hpp>
#include <BPatch.h>
#include <BPatch_Vector.h>
#include <BPatch_addressSpace.h>
#include <BPatch_basicBlock.h>
#include <BPatch_basicBlockLoop.h>
#include <BPatch_callbacks.h>
#include <BPatch_function.h>
#include <BPatch_instruction.h>
#include <BPatch_point.h>
#include <BPatch_process.h>
#include <BPatch_snippet.h>
#include <BPatch_statement.h>
#include <Instruction.h>
#include <dyntypes.h>
#include <climits>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <exception>
#include <fstream>
#include <limits>
#include <memory>
#include <numeric>
#include <ostream>
#include <regex>
#include <set>
#include <sstream>
#include <stdexcept>
#include <string>
#include <unistd.h>
#include <vector>
#define MUTNAMELEN 1024
#define FUNCNAMELEN 32 * 1024
#define NO_ERROR -1
#define TIMEMORY_BIN_DIR "bin"
#if !defined(PATH_MAX)
# define PATH_MAX std::numeric_limits<int>::max();
#endif
struct function_signature;
struct module_function;
template <typename Tp>
using bpvector_t = BPatch_Vector<Tp>;
using string_t = std::string;
using string_view_t = std::string_view;
using stringstream_t = std::stringstream;
using strvec_t = std::vector<string_t>;
using strset_t = std::set<string_t>;
using regexvec_t = std::vector<std::regex>;
using fmodset_t = std::set<module_function>;
using fixed_modset_t = std::map<fmodset_t*, bool>;
using exec_callback_t = BPatchExecCallback;
using exit_callback_t = BPatchExitCallback;
using fork_callback_t = BPatchForkCallback;
using patch_t = BPatch;
using process_t = BPatch_process;
using thread_t = BPatch_thread;
using binary_edit_t = BPatch_binaryEdit;
using image_t = BPatch_image;
using module_t = BPatch_module;
using procedure_t = BPatch_function;
using snippet_t = BPatch_snippet;
using call_expr_t = BPatch_funcCallExpr;
using address_space_t = BPatch_addressSpace;
using flow_graph_t = BPatch_flowGraph;
using basic_block_t = BPatch_basicBlock;
using basic_loop_t = BPatch_basicBlockLoop;
using procedure_loc_t = BPatch_procedureLocation;
using point_t = BPatch_point;
using local_var_t = BPatch_localVar;
using const_expr_t = BPatch_constExpr;
using error_level_t = BPatchErrorLevel;
using patch_pointer_t = std::shared_ptr<patch_t>;
using snippet_pointer_t = std::shared_ptr<snippet_t>;
using call_expr_pointer_t = std::shared_ptr<call_expr_t>;
using snippet_vec_t = bpvector_t<snippet_t*>;
using procedure_vec_t = bpvector_t<procedure_t*>;
using basic_block_set_t = std::set<basic_block_t*>;
using basic_loop_vec_t = bpvector_t<basic_loop_t*>;
using snippet_pointer_vec_t = std::vector<snippet_pointer_t>;
using instruction_t = Dyninst::InstructionAPI::Instruction;
void
omnitrace_prefork_callback(thread_t* parent, thread_t* child);
//======================================================================================//
//
// Global Variables
//
//======================================================================================//
//
// label settings
//
extern bool use_return_info;
extern bool use_args_info;
extern bool use_file_info;
extern bool use_line_info;
//
// heuristic settings
//
extern bool allow_overlapping;
extern bool loop_level_instr;
extern bool instr_dynamic_callsites;
extern bool instr_traps;
extern bool instr_loop_traps;
extern size_t min_address_range;
extern size_t min_loop_address_range;
extern size_t min_instructions;
//
// debug settings
//
extern bool werror;
extern bool debug_print;
extern int verbose_level;
//
// string settings
//
extern string_t main_fname;
extern string_t argv0;
extern string_t cmdv0;
extern string_t default_components;
extern string_t prefer_library;
//
// global variables
//
extern patch_pointer_t bpatch;
extern call_expr_t* terminate_expr;
extern snippet_vec_t init_names;
extern snippet_vec_t fini_names;
extern fmodset_t available_module_functions;
extern fmodset_t instrumented_module_functions;
extern fmodset_t overlapping_module_functions;
extern fmodset_t excluded_module_functions;
extern fixed_modset_t fixed_module_functions;
extern regexvec_t func_include;
extern regexvec_t func_exclude;
extern regexvec_t file_include;
extern regexvec_t file_exclude;
extern regexvec_t file_restrict;
extern regexvec_t func_restrict;
//
//======================================================================================//
// control debug printf statements
#define errprintf(LEVEL, ...) \
{ \
if(werror || LEVEL < 0) \
{ \
if(debug_print || verbose_level >= LEVEL) \
fprintf(stderr, "[omnitrace][exe] Error! " __VA_ARGS__); \
char _buff[FUNCNAMELEN]; \
sprintf(_buff, "[omnitrace][exe] Error! " __VA_ARGS__); \
throw std::runtime_error(std::string{ _buff }); \
} \
else \
{ \
if(debug_print || verbose_level >= LEVEL) \
fprintf(stderr, "[omnitrace][exe] Warning! " __VA_ARGS__); \
} \
fflush(stderr); \
}
// control verbose printf statements
#define verbprintf(LEVEL, ...) \
{ \
if(debug_print || verbose_level >= LEVEL) \
fprintf(stdout, "[omnitrace][exe] " __VA_ARGS__); \
fflush(stdout); \
}
#define verbprintf_bare(LEVEL, ...) \
{ \
if(debug_print || verbose_level >= LEVEL) fprintf(stdout, __VA_ARGS__); \
fflush(stdout); \
}
//======================================================================================//
template <typename... T>
void
consume_parameters(T&&...)
{}
//======================================================================================//
extern "C"
{
bool are_file_include_exclude_lists_empty();
bool instrument_module(const string_t& file_name);
bool instrument_entity(const string_t& function_name);
bool module_constraint(string_view_t fname);
bool routine_constraint(string_view_t fname);
}
//======================================================================================//
strset_t
get_whole_function_names();
function_signature
get_func_file_line_info(module_t* mutatee_module, procedure_t* f);
function_signature
get_loop_file_line_info(module_t* mutatee_module, procedure_t* f, flow_graph_t* cfGraph,
basic_loop_t* loopToInstrument);
std::tuple<size_t, size_t>
query_instr(procedure_t* funcToInstr, procedure_loc_t traceLoc,
flow_graph_t* cfGraph = nullptr, basic_loop_t* loopToInstrument = nullptr);
bool
query_instr(procedure_t* funcToInstr, procedure_loc_t traceLoc, flow_graph_t* cfGraph,
basic_loop_t* loopToInstrument, bool allow_traps);
template <typename Tp>
bool
insert_instr(address_space_t* mutatee, procedure_t* funcToInstr, Tp traceFunc,
procedure_loc_t traceLoc, flow_graph_t* cfGraph = nullptr,
basic_loop_t* loopToInstrument = nullptr, bool allow_traps = true);
void
errorFunc(error_level_t level, int num, const char** params);
procedure_t*
find_function(image_t* appImage, const string_t& functionName, const strset_t& = {});
void
error_func_real(error_level_t level, int num, const char* const* params);
void
error_func_fake(error_level_t level, int num, const char* const* params);
+251
Переглянути файл
@@ -0,0 +1,251 @@
// 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 "fwd.hpp"
#include "module_function.hpp"
static inline void
dump_info(std::ostream& _os, const fmodset_t& _data)
{
module_function::reset_width();
for(const auto& itr : _data)
module_function::update_width(itr);
module_function::write_header(_os);
for(const auto& itr : _data)
_os << itr << '\n';
module_function::reset_width();
}
//
template <typename ArchiveT,
std::enable_if_t<tim::concepts::is_archive<ArchiveT>::value, int> = 0>
static inline void
dump_info(ArchiveT& _ar, const fmodset_t& _data)
{
_ar(tim::cereal::make_nvp("module_functions", _data));
}
//
static inline void
dump_info(const string_t& _label, string_t _oname, const string_t& _ext,
const fmodset_t& _data, int _level, bool _fail)
{
namespace cereal = tim::cereal;
namespace policy = tim::policy;
_oname += "." + _ext;
auto _handle_error = [&]() {
std::stringstream _msg{};
_msg << "[dump_info] Error opening '" << _oname << " for output";
verbprintf(_level, "%s\n", _msg.str().c_str());
if(_fail)
throw std::runtime_error(std::string{ "[omnitrace][exe]" } + _msg.str());
};
if(!debug_print && verbose_level < _level) return;
if(_ext == "txt")
{
std::ofstream ofs{};
if(!tim::filepath::open(ofs, _oname))
_handle_error();
else
{
verbprintf(_level, "Outputting '%s'... ", _oname.c_str());
dump_info(ofs, _data);
verbprintf_bare(_level, "Done\n");
}
ofs.close();
}
else if(_ext == "xml")
{
std::stringstream oss{};
{
using output_policy = policy::output_archive<cereal::XMLOutputArchive>;
output_policy::indent() = true;
auto ar = output_policy::get(oss);
ar->setNextName("omnitrace");
ar->startNode();
ar->setNextName(_label.c_str());
ar->startNode();
(*ar)(cereal::make_nvp("module_functions", _data));
ar->finishNode();
ar->finishNode();
}
std::ofstream ofs{};
if(!tim::filepath::open(ofs, _oname))
_handle_error();
else
{
verbprintf(_level, "Outputting '%s'... ", _oname.c_str());
ofs << oss.str() << std::endl;
verbprintf_bare(_level, "Done\n");
}
ofs.close();
}
else if(_ext == "json")
{
std::stringstream oss{};
{
using output_policy = policy::output_archive<cereal::PrettyJSONOutputArchive>;
auto ar = output_policy::get(oss);
ar->setNextName("omnitrace");
ar->startNode();
ar->setNextName(_label.c_str());
ar->startNode();
(*ar)(cereal::make_nvp("module_functions", _data));
ar->finishNode();
ar->finishNode();
}
std::ofstream ofs{};
if(!tim::filepath::open(ofs, _oname))
_handle_error();
else
{
verbprintf(_level, "Outputting '%s'... ", _oname.c_str());
ofs << oss.str() << std::endl;
verbprintf_bare(_level, "Done\n");
}
ofs.close();
}
else
{
throw std::runtime_error(TIMEMORY_JOIN(
"", "[omnitrace][exe] Error in ", __FUNCTION__, " :: filename '", _oname,
"' does not have one of recognized file extensions: txt, json, xml"));
}
}
//
static inline void
dump_info(const string_t& _oname, const fmodset_t& _data, int _level, bool _fail,
const string_t& _type, const strset_t& _ext)
{
for(const auto& itr : _ext)
dump_info(_type, _oname, itr, _data, _level, _fail);
}
//
static inline void
load_info(const string_t& _label, const string_t& _iname, fmodset_t& _data, int _level)
{
namespace cereal = tim::cereal;
namespace policy = tim::policy;
auto _pos = _iname.find_last_of('.');
std::string _ext = {};
if(_pos != std::string::npos) _ext = _iname.substr(_pos + 1, _iname.length());
auto _handle_error = [&]() {
std::stringstream _msg{};
_msg << "[load_info] Error opening '" << _iname << " for input";
verbprintf(_level, "%s\n", _msg.str().c_str());
throw std::runtime_error(std::string{ "[omnitrace][exe]" } + _msg.str());
};
if(_ext == "xml")
{
verbprintf(_level, "Reading '%s'... ", _iname.c_str());
std::ifstream ifs{ _iname };
if(!ifs)
_handle_error();
else
{
using input_policy = policy::input_archive<cereal::XMLInputArchive>;
auto ar = input_policy::get(ifs);
ar->setNextName("omnitrace");
ar->startNode();
ar->setNextName(_label.c_str());
ar->startNode();
(*ar)(cereal::make_nvp("module_functions", _data));
ar->finishNode();
ar->finishNode();
}
verbprintf_bare(_level, "Done\n");
ifs.close();
}
else if(_ext == "json")
{
verbprintf(_level, "Reading '%s'... ", _iname.c_str());
std::ifstream ifs{ _iname };
if(!ifs)
_handle_error();
else
{
using input_policy = policy::input_archive<cereal::JSONInputArchive>;
auto ar = input_policy::get(ifs);
ar->setNextName("omnitrace");
ar->startNode();
ar->setNextName(_label.c_str());
ar->startNode();
(*ar)(cereal::make_nvp("module_functions", _data));
ar->finishNode();
ar->finishNode();
}
verbprintf_bare(_level, "Done\n");
ifs.close();
}
else
{
throw std::runtime_error(TIMEMORY_JOIN(
"", "[omnitrace][exe] Error in ", __FUNCTION__, " :: filename '", _iname,
"' does not have one of recognized extentions: txt, json, xml :: ", _ext));
}
}
//
static inline void
load_info(const string_t& _inp, std::map<std::string, fmodset_t*>& _data, int _level)
{
std::vector<std::string> _exceptions{};
_exceptions.reserve(_data.size());
for(auto& itr : _data)
{
try
{
fmodset_t _tmp{};
load_info(itr.first, _inp, _tmp, _level);
// add to the existing
itr.second->insert(_tmp.begin(), _tmp.end());
// if it did not throw it was successfully loaded
_exceptions.clear();
break;
} catch(std::exception& _e)
{
_exceptions.emplace_back(_e.what());
}
}
if(!_exceptions.empty())
{
std::stringstream _msg{};
for(auto& itr : _exceptions)
{
_msg << "[omnitrace][exe] " << itr << "\n";
}
throw std::runtime_error(_msg.str());
}
}
+511
Переглянути файл
@@ -0,0 +1,511 @@
// 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 "module_function.hpp"
#include "fwd.hpp"
#include "omnitrace.hpp"
module_function::width_t&
module_function::get_width()
{
static width_t _instance = []() {
width_t _tmp;
_tmp.fill(0);
return _tmp;
}();
return _instance;
}
void
module_function::reset_width()
{
get_width().fill(0);
}
void
module_function::update_width(const module_function& rhs)
{
get_width()[0] = std::max<size_t>(get_width()[0], rhs.module_name.length());
get_width()[1] = std::max<size_t>(get_width()[1], rhs.function_name.length());
get_width()[2] = std::max<size_t>(get_width()[2], rhs.signature.get().length());
}
module_function::module_function(module_t* mod, procedure_t* proc)
: module{ mod }
, function{ proc }
, flow_graph{ proc->getCFG() }
{
if(flow_graph)
{
flow_graph->getAllBasicBlocks(basic_blocks);
flow_graph->getOuterLoops(loop_blocks);
}
for(const auto& itr : basic_blocks)
{
std::vector<instruction_t> instructions{};
itr->getInstructions(instructions);
num_instructions += instructions.size();
}
char modname[FUNCNAMELEN];
char fname[FUNCNAMELEN];
module->getFullName(modname, FUNCNAMELEN);
function->getName(fname, FUNCNAMELEN);
module_name = modname;
function_name = fname;
signature = get_func_file_line_info(module, function);
if(!function->isInstrumentable())
{
verbprintf(0,
"Warning! module function generated for un-instrumentable "
"function: %s [%s]\n",
function_name.c_str(), module_name.c_str());
}
std::pair<address_t, address_t> _range{};
if(function->getAddressRange(_range.first, _range.second))
address_range = _range.second - _range.first;
}
void
module_function::write_header(std::ostream& os)
{
auto w0 = std::min<size_t>(get_width()[0], absolute_max_width);
auto w1 = std::min<size_t>(get_width()[1], absolute_max_width);
auto w2 = std::min<size_t>(get_width()[2], absolute_max_width);
std::stringstream ss;
ss << std::setw(14) << "AddressRange"
<< " " << std::setw(14) << "#Instructions"
<< " " << std::setw(6) << "Ratio"
<< " " << std::setw(w0 + 8) << std::left << "Module"
<< " " << std::setw(w1 + 8) << std::left << "Function"
<< " " << std::setw(w2 + 8) << std::left << "FunctionSignature"
<< "\n";
os << ss.str();
}
bool
module_function::should_instrument() const
{
// hard constraints
if(!is_instrumentable()) return false;
if(!can_instrument_entry()) return false;
if(!can_instrument_exit()) return false;
if(is_module_constrained()) return false;
if(is_routine_constrained()) return false;
// should be before user selection
constexpr int absolute_min_instructions = 4;
if(num_instructions < absolute_min_instructions)
{
messages.emplace_back(
2, "Skipping", "function",
TIMEMORY_JOIN("-", "less-than", absolute_min_instructions, "instructions"));
return false;
}
// user selection
if(is_user_excluded()) return false;
if(is_user_restricted()) return true;
if(is_user_included()) return true;
// should be applied before dynamic-callsite check
if(is_overlapping_constrained()) return false;
if(is_entry_trap_constrained()) return false;
if(is_exit_trap_constrained()) return false;
// needs to be applied before address range and number of instruction constraints
if(is_dynamic_callsite_forced()) return true;
if(is_address_range_constrained()) return false;
if(is_num_instructions_constrained()) return false;
return true;
}
bool
module_function::is_instrumentable() const
{
if(!function->isInstrumentable())
{
messages.emplace_back(2, "Skipping", "module", "not-instrumentable");
return false;
}
return true;
}
namespace
{
bool
check_regex_restrictions(const std::string& _name, const regexvec_t& _regexes)
{
// NOLINTNEXTLINE
for(auto& itr : _regexes)
if(std::regex_search(_name, itr)) return true;
return false;
}
} // namespace
bool
module_function::is_user_restricted() const
{
if(!file_restrict.empty())
{
if(check_regex_restrictions(module_name, file_restrict))
{
messages.emplace_back(2, "Forcing", "module", "module-restrict-regex");
return false;
}
else
{
messages.emplace_back(3, "Skipping", "module", "module-restrict-regex");
return true;
}
}
if(!func_restrict.empty())
{
if(check_regex_restrictions(module_name, func_restrict))
{
messages.emplace_back(2, "Forcing", "function", "function-restrict-regex");
return false;
}
else if(check_regex_restrictions(signature.get(), func_restrict))
{
messages.emplace_back(2, "Forcing", "function", "function-restrict-regex");
return false;
}
else
{
messages.emplace_back(3, "Skipping", "function", "function-restrict-regex");
return true;
}
}
return false;
}
bool
module_function::is_user_included() const
{
if(!file_include.empty())
{
if(check_regex_restrictions(module_name, file_include))
{
messages.emplace_back(2, "Forcing", "module", "module-include-regex");
return true;
}
}
if(!func_include.empty())
{
if(check_regex_restrictions(function_name, func_include))
{
messages.emplace_back(2, "Forcing", "function", "function-include-regex");
return true;
}
else if(check_regex_restrictions(signature.get(), func_include))
{
messages.emplace_back(2, "Forcing", "function", "function-include-regex");
return true;
}
}
return false;
}
bool
module_function::is_user_excluded() const
{
if(!file_exclude.empty())
{
if(check_regex_restrictions(module_name, file_exclude))
{
messages.emplace_back(2, "Skipping", "module", "module-exclude-regex");
return true;
}
}
if(!func_exclude.empty())
{
if(check_regex_restrictions(function_name, func_exclude))
{
messages.emplace_back(2, "Skipping", "function", "function-exclude-regex");
return true;
}
else if(check_regex_restrictions(signature.get(), func_exclude))
{
messages.emplace_back(2, "Skipping", "function", "function-exclude-regex");
return true;
}
}
return false;
}
bool
module_function::is_overlapping() const
{
procedure_vec_t _overlapping{};
return function->findOverlapping(_overlapping);
}
bool
module_function::is_module_constrained() const
{
if(!instrument_module(module_name) || module_constraint(module_name.c_str()))
{
messages.emplace_back(2, "Skipping", "module", "module-constraint");
return true;
}
return false;
}
bool
module_function::is_routine_constrained() const
{
if(!instrument_entity(function_name) || !instrument_entity(signature.get()) ||
routine_constraint(function_name) || routine_constraint(signature.get()))
{
messages.emplace_back(2, "Skipping", "function", "function-constraint");
return true;
}
return false;
}
bool
module_function::is_overlapping_constrained() const
{
if(!allow_overlapping && is_overlapping())
{
messages.emplace_back(2, "Skipping", "function", "overlapping");
return true;
}
return false;
}
bool
module_function::contains_dynamic_callsites() const
{
if(flow_graph) return flow_graph->containsDynamicCallsites();
return false;
}
bool
module_function::is_dynamic_callsite_forced() const
{
if(instr_dynamic_callsites && contains_dynamic_callsites())
{
messages.emplace_back(2, "Forcing", "function", "dynamic-callsites");
return true;
}
return false;
}
bool
module_function::is_address_range_constrained() const
{
if(!loop_blocks.empty()) return is_loop_address_range_constrained();
if(address_range < min_address_range)
{
messages.emplace_back(2, "Skipping", "function", "min-address-range");
return true;
}
return false;
}
bool
module_function::is_loop_address_range_constrained() const
{
if(loop_blocks.empty()) return false;
if(address_range < min_loop_address_range)
{
messages.emplace_back(2, "Skipping", "function", "min-address-range-loop");
return true;
}
return false;
}
bool
module_function::is_num_instructions_constrained() const
{
if(num_instructions < min_instructions)
{
messages.emplace_back(2, "Skipping", "function", "min-instructions");
return true;
}
return false;
}
bool
module_function::can_instrument_entry() const
{
size_t _num_points = 0;
size_t _num_traps = 0;
std::tie(_num_points, _num_traps) = query_instr(function, BPatch_entry);
if(_num_points == 0)
{
messages.emplace_back(3, "Skipping", "function", "no-instrumentable-entry-point");
return false;
}
return true;
}
bool
module_function::can_instrument_exit() const
{
size_t _num_points = 0;
size_t _num_traps = 0;
std::tie(_num_points, _num_traps) = query_instr(function, BPatch_exit);
if(_num_points == 0)
{
messages.emplace_back(3, "Skipping", "function", "no-instrumentable-exit-point");
return false;
}
return true;
}
bool
module_function::is_entry_trap_constrained() const
{
if(instr_traps) return false;
size_t _num_points = 0;
size_t _num_traps = 0;
std::tie(_num_points, _num_traps) = query_instr(function, BPatch_entry);
if(!instr_traps && (_num_points - _num_traps) == 0)
{
messages.emplace_back(3, "Skipping", "function",
"entry-point-trap-instrumentation");
return true;
}
return false;
}
bool
module_function::is_exit_trap_constrained() const
{
if(instr_traps) return false;
size_t _num_points = 0;
size_t _num_traps = 0;
std::tie(_num_points, _num_traps) = query_instr(function, BPatch_exit);
if((_num_points - _num_traps) == 0)
{
messages.emplace_back(3, "Skipping", "function",
"exit-point-trap-instrumentation");
return true;
}
return false;
}
std::pair<size_t, size_t>
module_function::operator()(address_space_t* _addr_space, procedure_t* _entr_trace,
procedure_t* _exit_trace) const
{
std::pair<size_t, size_t> _count = { 0, 0 };
auto _name = signature.get();
auto _trace_entr = omnitrace_call_expr(_name.c_str());
auto _trace_exit = omnitrace_call_expr(_name.c_str());
auto _entr = _trace_entr.get(_entr_trace);
auto _exit = _trace_exit.get(_exit_trace);
if(insert_instr(_addr_space, function, _entr, BPatch_entry, nullptr, nullptr,
instr_traps) &&
insert_instr(_addr_space, function, _exit, BPatch_exit, nullptr, nullptr,
instr_traps))
{
messages.emplace_back(1, "Instrumenting", "function", "no-constraint");
++_count.first;
}
for(auto* itr : loop_blocks)
{
if(!loop_level_instr) continue;
auto _is_constrained = [this](bool _v, const std::string& _label) {
if(!_v)
{
messages.emplace_back(3, "Skipping", "function", _label);
return true;
}
return false;
};
size_t _points = 0;
size_t _ntraps = 0;
std::tie(_points, _ntraps) = query_instr(function, BPatch_entry, flow_graph, itr);
if(_is_constrained(_points == 0, "no-instrumentable-loop-entry-point")) continue;
if(_is_constrained(!instr_traps && (_points - _ntraps) == 0,
"loop-entry-point-trap-instrumentation"))
continue;
std::tie(_points, _ntraps) = query_instr(function, BPatch_exit, flow_graph, itr);
if(_is_constrained(_points == 0, "no-instrumentable-loop-exit-point")) continue;
if(_is_constrained(!instr_traps && (_points - _ntraps) == 0,
"loop-exit-point-trap-instrumentation"))
continue;
auto lname = get_loop_file_line_info(module, function, flow_graph, itr);
auto _lname = lname.get();
messages.emplace_back(1, "Loop Instrumenting", "function", "no-constraint");
++_count.second;
auto _ltrace_entr = omnitrace_call_expr(_lname.c_str());
auto _ltrace_exit = omnitrace_call_expr(_lname.c_str());
auto _lentr = _ltrace_entr.get(_entr_trace);
auto _lexit = _ltrace_exit.get(_exit_trace);
insert_instr(_addr_space, function, _lentr, BPatch_entry, flow_graph, itr,
instr_loop_traps);
insert_instr(_addr_space, function, _lexit, BPatch_exit, flow_graph, itr,
instr_loop_traps);
}
return _count;
}
+185
Переглянути файл
@@ -0,0 +1,185 @@
// 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 "function_signature.hpp"
#include "fwd.hpp"
#include <timemory/mpl/concepts.hpp>
#include <timemory/tpls/cereal/cereal/cereal.hpp>
struct module_function
{
using width_t = std::array<size_t, 4>;
using address_t = Dyninst::Address;
static constexpr size_t absolute_max_width = 80;
static width_t& get_width();
static void reset_width();
static void update_width(const module_function& rhs);
static void write_header(std::ostream& os);
TIMEMORY_DEFAULT_OBJECT(module_function)
module_function(module_t* mod, procedure_t* proc);
std::pair<size_t, size_t> operator()(address_space_t* _addr_space,
procedure_t* _entr_trace,
procedure_t* _exit_trace) const;
// applies logic for all "is_*" and "can_*" checks below
bool should_instrument() const;
// hard constraints
bool is_instrumentable() const; // checks whether can instrument
bool can_instrument_entry() const; // checks for entry points
bool can_instrument_exit() const; // checks for exit points
bool is_module_constrained() const; // checks module constraints
bool is_routine_constrained() const; // checks function constraints
// user bypass of heuristics
bool is_user_restricted() const; // checks user restrict regexes
bool is_user_included() const; // checks user include regexes
bool is_user_excluded() const; // checks user exclude regexes
// applied before dynamic-callsite constraint
bool is_overlapping_constrained() const; // checks overlapping constrains
bool is_entry_trap_constrained() const; // checks entry trap constraint
bool is_exit_trap_constrained() const; // checks exit trap constraint
// applied before address range and # instruction constraints
bool is_dynamic_callsite_forced() const; // checks dynamic callsites
// estimate the size/work of the function
bool is_address_range_constrained() const; // checks address range constraint
bool is_num_instructions_constrained() const; // check # instructions constraint
uint64_t address_range = 0;
uint64_t num_instructions = 0;
module_t* module = nullptr;
procedure_t* function = nullptr;
flow_graph_t* flow_graph = nullptr;
string_t module_name = {};
string_t function_name = {};
function_signature signature = {};
basic_block_set_t basic_blocks = {};
basic_loop_vec_t loop_blocks = {};
using str_msg_t = std::tuple<int, string_t, string_t, string_t>;
using str_msg_vec_t = std::vector<str_msg_t>;
mutable str_msg_vec_t messages = {};
bool is_overlapping() const; // checks if func overlaps
private:
bool is_loop_address_range_constrained() const; // checks loop addr range constraint
bool contains_dynamic_callsites() const;
public:
template <typename ArchiveT>
void serialize(ArchiveT& ar, const unsigned);
friend bool operator<(const module_function& lhs, const module_function& rhs)
{
return (lhs.module_name == rhs.module_name)
? ((lhs.function_name == rhs.function_name)
? (lhs.signature.get() < rhs.signature.get())
: (lhs.function_name < rhs.function_name))
: (lhs.module_name < rhs.module_name);
}
friend bool operator==(const module_function& lhs, const module_function& rhs)
{
return std::tie(lhs.module_name, lhs.function_name, lhs.signature,
lhs.address_range, lhs.num_instructions) ==
std::tie(rhs.module_name, rhs.function_name, rhs.signature,
rhs.address_range, rhs.num_instructions);
}
friend std::ostream& operator<<(std::ostream& os, const module_function& rhs)
{
std::stringstream ss;
auto w0 = std::min<size_t>(get_width()[0], absolute_max_width);
auto w1 = std::min<size_t>(get_width()[1], absolute_max_width);
auto w2 = std::min<size_t>(get_width()[2], absolute_max_width);
auto _get_str = [](const std::string& _inc) {
if(_inc.length() > absolute_max_width)
return _inc.substr(0, absolute_max_width - 3) + "...";
return _inc;
};
// clang-format off
ss << std::setw(14) << rhs.address_range << " "
<< std::setw(14) << rhs.num_instructions << " "
<< std::setw(6) << std::setprecision(2) << std::fixed << (rhs.address_range / static_cast<double>(rhs.num_instructions)) << " "
<< std::setw(w0 + 8) << std::left << _get_str(rhs.module_name) << " "
<< std::setw(w1 + 8) << std::left << _get_str(rhs.function_name) << " "
<< std::setw(w2 + 8) << std::left << _get_str(rhs.signature.get());
// clang-format on
os << ss.str();
return os;
}
};
template <typename ArchiveT>
void
module_function::serialize(ArchiveT& ar, const unsigned)
{
namespace cereal = tim::cereal;
ar(cereal::make_nvp("address_range", address_range),
cereal::make_nvp("instructions", num_instructions),
cereal::make_nvp("module", module_name),
cereal::make_nvp("function", function_name),
cereal::make_nvp("signature", signature));
if constexpr(tim::concepts::is_output_archive<ArchiveT>::value)
{
ar.setNextName("heuristics");
ar.startNode();
ar(cereal::make_nvp("should_instrument", should_instrument()),
cereal::make_nvp("is_instrumentable", is_instrumentable()),
cereal::make_nvp("can_instrument_entry", can_instrument_entry()),
cereal::make_nvp("can_instrument_exit", can_instrument_exit()),
cereal::make_nvp("contains_dynamic_callsites", contains_dynamic_callsites()),
cereal::make_nvp("is_module_constrained", is_module_constrained()),
cereal::make_nvp("is_routine_constrained", is_routine_constrained()),
cereal::make_nvp("is_user_restricted", is_user_restricted()),
cereal::make_nvp("is_user_included", is_user_included()),
cereal::make_nvp("is_user_excluded", is_user_excluded()),
cereal::make_nvp("is_overlapping_constrained", is_overlapping_constrained()),
cereal::make_nvp("is_entry_trap_constrained", is_entry_trap_constrained()),
cereal::make_nvp("is_exit_trap_constrained", is_exit_trap_constrained()),
cereal::make_nvp("is_dynamic_callsite_forced", is_dynamic_callsite_forced()),
cereal::make_nvp("is_address_range_constrained",
is_address_range_constrained()),
cereal::make_nvp("is_loop_address_range_constrained",
is_loop_address_range_constrained()),
cereal::make_nvp("is_num_instructions_constrained",
is_num_instructions_constrained()));
ar.finishNode();
}
}
File diff suppressed because it is too large. Load diff
+79 -684
Переглянути файл
@@ -22,231 +22,10 @@
#pragma once
#include <timemory/backends/process.hpp>
#include <timemory/environment.hpp>
#include <timemory/mpl/apply.hpp>
#include <timemory/mpl/concepts.hpp>
#include <timemory/mpl/policy.hpp>
#include <timemory/tpls/cereal/archives.hpp>
#include <timemory/tpls/cereal/cereal.hpp>
#include <timemory/utility/argparse.hpp>
#include <timemory/utility/demangle.hpp>
#include <timemory/utility/popen.hpp>
#include <timemory/variadic/macros.hpp>
#include <BPatch.h>
#include <BPatch_Vector.h>
#include <BPatch_addressSpace.h>
#include <BPatch_basicBlockLoop.h>
#include <BPatch_callbacks.h>
#include <BPatch_function.h>
#include <BPatch_point.h>
#include <BPatch_process.h>
#include <BPatch_snippet.h>
#include <BPatch_statement.h>
#include <climits>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <exception>
#include <fstream>
#include <limits>
#include <memory>
#include <numeric>
#include <ostream>
#include <regex>
#include <set>
#include <sstream>
#include <stdexcept>
#include <string>
#include <unistd.h>
#include <vector>
#define MUTNAMELEN 1024
#define FUNCNAMELEN 32 * 1024
#define NO_ERROR -1
#define TIMEMORY_BIN_DIR "bin"
#if !defined(PATH_MAX)
# define PATH_MAX std::numeric_limits<int>::max();
#endif
struct function_signature;
struct module_function;
template <typename Tp>
using bpvector_t = BPatch_Vector<Tp>;
using string_t = std::string;
using stringstream_t = std::stringstream;
using strvec_t = std::vector<string_t>;
using strset_t = std::set<string_t>;
using regexvec_t = std::vector<std::regex>;
using fmodset_t = std::set<module_function>;
using fixed_modset_t = std::map<fmodset_t*, bool>;
using exec_callback_t = BPatchExecCallback;
using exit_callback_t = BPatchExitCallback;
using fork_callback_t = BPatchForkCallback;
using patch_t = BPatch;
using process_t = BPatch_process;
using thread_t = BPatch_thread;
using binary_edit_t = BPatch_binaryEdit;
using image_t = BPatch_image;
using module_t = BPatch_module;
using procedure_t = BPatch_function;
using snippet_t = BPatch_snippet;
using call_expr_t = BPatch_funcCallExpr;
using address_space_t = BPatch_addressSpace;
using flow_graph_t = BPatch_flowGraph;
using basic_loop_t = BPatch_basicBlockLoop;
using procedure_loc_t = BPatch_procedureLocation;
using point_t = BPatch_point;
using local_var_t = BPatch_localVar;
using const_expr_t = BPatch_constExpr;
using error_level_t = BPatchErrorLevel;
using patch_pointer_t = std::shared_ptr<patch_t>;
using snippet_pointer_t = std::shared_ptr<snippet_t>;
using call_expr_pointer_t = std::shared_ptr<call_expr_t>;
using snippet_vec_t = bpvector_t<snippet_t*>;
using procedure_vec_t = bpvector_t<procedure_t*>;
using basic_loop_vec_t = bpvector_t<basic_loop_t*>;
using snippet_pointer_vec_t = std::vector<snippet_pointer_t>;
void
omnitrace_prefork_callback(thread_t* parent, thread_t* child);
//======================================================================================//
//
// Global Variables
//
//======================================================================================//
//
// boolean settings
//
static bool use_return_info = false;
static bool use_args_info = false;
static bool use_file_info = false;
static bool use_line_info = false;
//
// integral settings
//
extern bool debug_print;
extern int verbose_level;
//
// string settings
//
static string_t main_fname = "main";
static string_t argv0 = {};
static string_t cmdv0 = {};
static string_t default_components = "wall_clock";
static string_t prefer_library = {};
//
// global variables
//
static patch_pointer_t bpatch = {};
static call_expr_t* terminate_expr = nullptr;
static snippet_vec_t init_names = {};
static snippet_vec_t fini_names = {};
static fmodset_t available_module_functions = {};
static fmodset_t instrumented_module_functions = {};
static fmodset_t overlapping_module_functions = {};
static fmodset_t excluded_module_functions = {};
static fixed_modset_t fixed_module_functions = {};
static regexvec_t func_include = {};
static regexvec_t func_exclude = {};
static regexvec_t file_include = {};
static regexvec_t file_exclude = {};
static regexvec_t file_restrict = {};
static regexvec_t func_restrict = {};
//
//======================================================================================//
// control debug printf statements
#define errprintf(LEVEL, ...) \
{ \
if(werror || LEVEL < 0) \
{ \
if(debug_print || verbose_level >= LEVEL) \
fprintf(stderr, "[omnitrace][exe] Error! " __VA_ARGS__); \
char _buff[FUNCNAMELEN]; \
sprintf(_buff, "[omnitrace][exe] Error! " __VA_ARGS__); \
throw std::runtime_error(std::string{ _buff }); \
} \
else \
{ \
if(debug_print || verbose_level >= LEVEL) \
fprintf(stderr, "[omnitrace][exe] Warning! " __VA_ARGS__); \
} \
fflush(stderr); \
}
// control verbose printf statements
#define verbprintf(LEVEL, ...) \
{ \
if(debug_print || verbose_level >= LEVEL) \
fprintf(stdout, "[omnitrace][exe] " __VA_ARGS__); \
fflush(stdout); \
}
#define verbprintf_bare(LEVEL, ...) \
{ \
if(debug_print || verbose_level >= LEVEL) fprintf(stdout, __VA_ARGS__); \
fflush(stdout); \
}
//======================================================================================//
template <typename... T>
void
consume_parameters(T&&...)
{}
//======================================================================================//
extern "C"
{
bool are_file_include_exclude_lists_empty();
bool instrument_module(const string_t& file_name);
bool instrument_entity(const string_t& function_name);
bool module_constraint(char* fname);
bool routine_constraint(const char* fname);
}
//======================================================================================//
strset_t
get_whole_function_names();
function_signature
get_func_file_line_info(module_t* mutatee_module, procedure_t* f);
function_signature
get_loop_file_line_info(module_t* mutatee_module, procedure_t* f, flow_graph_t* cfGraph,
basic_loop_t* loopToInstrument);
bool
query_instr(procedure_t* funcToInstr, procedure_loc_t traceLoc,
flow_graph_t* cfGraph = nullptr, basic_loop_t* loopToInstrument = nullptr,
bool allow_traps = true);
template <typename Tp>
bool
insert_instr(address_space_t* mutatee, procedure_t* funcToInstr, Tp traceFunc,
procedure_loc_t traceLoc, flow_graph_t* cfGraph = nullptr,
basic_loop_t* loopToInstrument = nullptr, bool allow_traps = true);
void
errorFunc(error_level_t level, int num, const char** params);
procedure_t*
find_function(image_t* appImage, const string_t& functionName, const strset_t& = {});
void
error_func_real(error_level_t level, int num, const char* const* params);
void
error_func_fake(error_level_t level, int num, const char* const* params);
#include "function_signature.hpp"
#include "fwd.hpp"
#include "info.hpp"
#include "module_function.hpp"
//======================================================================================//
@@ -285,465 +64,6 @@ to_lower(string_t s)
//
//======================================================================================//
//
struct function_signature
{
using location_t = std::pair<unsigned long, unsigned long>;
bool m_loop = false;
bool m_info_beg = false;
bool m_info_end = false;
location_t m_row = { 0, 0 };
location_t m_col = { 0, 0 };
string_t m_return = {};
string_t m_name = {};
string_t m_params = "()";
string_t m_file = {};
mutable string_t m_signature = {};
TIMEMORY_DEFAULT_OBJECT(function_signature)
template <typename ArchiveT>
void serialize(ArchiveT& _ar, const unsigned)
{
namespace cereal = tim::cereal;
(void) get();
_ar(cereal::make_nvp("loop", m_loop), cereal::make_nvp("info_beg", m_info_beg),
cereal::make_nvp("info_end", m_info_end), cereal::make_nvp("row", m_row),
cereal::make_nvp("col", m_col), cereal::make_nvp("return", m_return),
cereal::make_nvp("name", m_name), cereal::make_nvp("params", m_params),
cereal::make_nvp("file", m_file), cereal::make_nvp("signature", m_signature));
(void) get();
}
function_signature(string_t _ret, const string_t& _name, string_t _file,
location_t _row = { 0, 0 }, location_t _col = { 0, 0 },
bool _loop = false, bool _info_beg = false, bool _info_end = false)
: m_loop(_loop)
, m_info_beg(_info_beg)
, m_info_end(_info_end)
, m_row(std::move(_row))
, m_col(std::move(_col))
, m_return(std::move(_ret))
, m_name(tim::demangle(_name))
, m_file(std::move(_file))
{
if(m_file.find('/') != string_t::npos)
m_file = m_file.substr(m_file.find_last_of('/') + 1);
}
function_signature(const string_t& _ret, const string_t& _name, const string_t& _file,
const std::vector<string_t>& _params, location_t _row = { 0, 0 },
location_t _col = { 0, 0 }, bool _loop = false,
bool _info_beg = false, bool _info_end = false)
: function_signature(_ret, _name, _file, _row, _col, _loop, _info_beg, _info_end)
{
m_params = "(";
for(const auto& itr : _params)
m_params.append(itr + ", ");
if(!_params.empty()) m_params = m_params.substr(0, m_params.length() - 2);
m_params += ")";
}
friend bool operator==(const function_signature& lhs, const function_signature& rhs)
{
return lhs.get() == rhs.get();
}
static auto get(function_signature& sig) { return sig.get(); }
string_t get() const
{
std::stringstream ss;
if(use_return_info && !m_return.empty()) ss << m_return << " ";
ss << m_name;
if(use_args_info) ss << m_params;
if(m_loop && m_info_beg)
{
if(m_info_end)
{
ss << " [{" << m_row.first << "," << m_col.first << "}-{" << m_row.second
<< "," << m_col.second << "}]";
}
else
{
ss << "[{" << m_row.first << "," << m_col.first << "}]";
}
}
if(use_file_info && m_file.length() > 0) ss << " [" << m_file;
if(use_line_info && m_row.first > 0) ss << ":" << m_row.first;
if(use_file_info && m_file.length() > 0) ss << "]";
m_signature = ss.str();
return m_signature;
}
};
//
//======================================================================================//
//
struct module_function
{
using width_t = std::array<size_t, 3>;
using address_t = Dyninst::Address;
static constexpr size_t absolute_max_width = 80;
static auto& get_width()
{
static width_t _instance = []() {
width_t _tmp;
_tmp.fill(0);
return _tmp;
}();
return _instance;
}
TIMEMORY_DEFAULT_OBJECT(module_function)
static void reset_width() { get_width().fill(0); }
static void update_width(const module_function& rhs)
{
get_width()[0] = std::max<size_t>(get_width()[0], rhs.module.length());
get_width()[1] = std::max<size_t>(get_width()[1], rhs.function.length());
get_width()[2] = std::max<size_t>(get_width()[2], rhs.signature.get().length());
}
module_function(string_t _module, string_t _func, function_signature _sign,
procedure_t* proc)
: module(std::move(_module))
, function(std::move(_func))
, signature(std::move(_sign))
{
if(proc)
{
std::pair<address_t, address_t> _range{};
if(proc->getAddressRange(_range.first, _range.second))
address_range = _range.second - _range.first;
}
}
module_function(module_t* mod, procedure_t* proc)
{
char modname[FUNCNAMELEN];
char fname[FUNCNAMELEN];
mod->getFullName(modname, FUNCNAMELEN);
proc->getName(fname, FUNCNAMELEN);
module = modname;
function = fname;
signature = get_func_file_line_info(mod, proc);
if(!proc->isInstrumentable())
{
verbprintf(0,
"Warning! module function generated for un-instrumentable "
"function: %s [%s]\n",
function.c_str(), module.c_str());
}
std::pair<address_t, address_t> _range{};
if(proc->getAddressRange(_range.first, _range.second))
address_range = _range.second - _range.first;
}
friend bool operator<(const module_function& lhs, const module_function& rhs)
{
return (lhs.module == rhs.module)
? ((lhs.function == rhs.function)
? (lhs.signature.get() < rhs.signature.get())
: (lhs.function < rhs.function))
: (lhs.module < rhs.module);
}
friend bool operator==(const module_function& lhs, const module_function& rhs)
{
return std::tie(lhs.module, lhs.function, lhs.signature, lhs.address_range) ==
std::tie(rhs.module, rhs.function, rhs.signature, rhs.address_range);
}
static void write_header(std::ostream& os)
{
auto w0 = std::min<size_t>(get_width()[0], absolute_max_width);
auto w1 = std::min<size_t>(get_width()[1], absolute_max_width);
auto w2 = std::min<size_t>(get_width()[2], absolute_max_width);
std::stringstream ss;
ss << std::setw(14) << "AddressRange"
<< " " << std::setw(w0 + 8) << std::left << "Module"
<< " " << std::setw(w1 + 8) << std::left << "Function"
<< " " << std::setw(w2 + 8) << std::left << "FunctionSignature"
<< "\n";
os << ss.str();
}
friend std::ostream& operator<<(std::ostream& os, const module_function& rhs)
{
std::stringstream ss;
auto w0 = std::min<size_t>(get_width()[0], absolute_max_width);
auto w1 = std::min<size_t>(get_width()[1], absolute_max_width);
auto w2 = std::min<size_t>(get_width()[2], absolute_max_width);
auto _get_str = [](const std::string& _inc) {
if(_inc.length() > absolute_max_width)
return _inc.substr(0, absolute_max_width - 3) + "...";
return _inc;
};
// clang-format off
ss << std::setw(14) << rhs.address_range << " "
<< std::setw(w0 + 8) << std::left << _get_str(rhs.module) << " "
<< std::setw(w1 + 8) << std::left << _get_str(rhs.function) << " "
<< std::setw(w2 + 8) << std::left << _get_str(rhs.signature.get());
// clang-format on
os << ss.str();
return os;
}
size_t address_range = 0;
string_t module = {};
string_t function = {};
function_signature signature = {};
template <typename ArchiveT>
void serialize(ArchiveT& _ar, const unsigned)
{
namespace cereal = tim::cereal;
_ar(cereal::make_nvp("address_range", address_range),
cereal::make_nvp("module", module), cereal::make_nvp("function", function),
cereal::make_nvp("signature", signature));
}
};
//
//======================================================================================//
//
static inline void
dump_info(std::ostream& _os, const fmodset_t& _data)
{
module_function::reset_width();
for(const auto& itr : _data)
module_function::update_width(itr);
module_function::write_header(_os);
for(const auto& itr : _data)
_os << itr << '\n';
module_function::reset_width();
}
//
template <typename ArchiveT,
std::enable_if_t<tim::concepts::is_archive<ArchiveT>::value, int> = 0>
static inline void
dump_info(ArchiveT& _ar, const fmodset_t& _data)
{
_ar(tim::cereal::make_nvp("module_functions", _data));
}
//
static inline void
dump_info(const string_t& _label, string_t _oname, const string_t& _ext,
const fmodset_t& _data, int _level, bool _fail)
{
namespace cereal = tim::cereal;
namespace policy = tim::policy;
_oname += "." + _ext;
auto _handle_error = [&]() {
std::stringstream _msg{};
_msg << "[dump_info] Error opening '" << _oname << " for output";
verbprintf(_level, "%s\n", _msg.str().c_str());
if(_fail)
throw std::runtime_error(std::string{ "[omnitrace][exe]" } + _msg.str());
};
if(!debug_print && verbose_level < _level) return;
if(_ext == "txt")
{
std::ofstream ofs{};
if(!tim::filepath::open(ofs, _oname))
_handle_error();
else
{
verbprintf(_level, "Outputting '%s'... ", _oname.c_str());
dump_info(ofs, _data);
verbprintf_bare(_level, "Done\n");
}
ofs.close();
}
else if(_ext == "xml")
{
std::stringstream oss{};
{
using output_policy = policy::output_archive<cereal::XMLOutputArchive>;
output_policy::indent() = true;
auto ar = output_policy::get(oss);
ar->setNextName("omnitrace");
ar->startNode();
ar->setNextName(_label.c_str());
ar->startNode();
(*ar)(cereal::make_nvp("module_functions", _data));
ar->finishNode();
ar->finishNode();
}
std::ofstream ofs{};
if(!tim::filepath::open(ofs, _oname))
_handle_error();
else
{
verbprintf(_level, "Outputting '%s'... ", _oname.c_str());
ofs << oss.str() << std::endl;
verbprintf_bare(_level, "Done\n");
}
ofs.close();
}
else if(_ext == "json")
{
std::stringstream oss{};
{
using output_policy = policy::output_archive<cereal::PrettyJSONOutputArchive>;
auto ar = output_policy::get(oss);
ar->setNextName("omnitrace");
ar->startNode();
ar->setNextName(_label.c_str());
ar->startNode();
(*ar)(cereal::make_nvp("module_functions", _data));
ar->finishNode();
ar->finishNode();
}
std::ofstream ofs{};
if(!tim::filepath::open(ofs, _oname))
_handle_error();
else
{
verbprintf(_level, "Outputting '%s'... ", _oname.c_str());
ofs << oss.str() << std::endl;
verbprintf_bare(_level, "Done\n");
}
ofs.close();
}
else
{
throw std::runtime_error(TIMEMORY_JOIN(
"", "[omnitrace][exe] Error in ", __FUNCTION__, " :: filename '", _oname,
"' does not have one of recognized file extensions: txt, json, xml"));
}
}
//
static inline void
dump_info(const string_t& _oname, const fmodset_t& _data, int _level, bool _fail,
const string_t& _type, const strset_t& _ext)
{
for(const auto& itr : _ext)
dump_info(_type, _oname, itr, _data, _level, _fail);
}
//
static inline void
load_info(const string_t& _label, const string_t& _iname, fmodset_t& _data, int _level)
{
namespace cereal = tim::cereal;
namespace policy = tim::policy;
auto _pos = _iname.find_last_of('.');
std::string _ext = {};
if(_pos != std::string::npos) _ext = _iname.substr(_pos + 1, _iname.length());
auto _handle_error = [&]() {
std::stringstream _msg{};
_msg << "[load_info] Error opening '" << _iname << " for input";
verbprintf(_level, "%s\n", _msg.str().c_str());
throw std::runtime_error(std::string{ "[omnitrace][exe]" } + _msg.str());
};
if(_ext == "xml")
{
verbprintf(_level, "Reading '%s'... ", _iname.c_str());
std::ifstream ifs{ _iname };
if(!ifs)
_handle_error();
else
{
using input_policy = policy::input_archive<cereal::XMLInputArchive>;
auto ar = input_policy::get(ifs);
ar->setNextName("omnitrace");
ar->startNode();
ar->setNextName(_label.c_str());
ar->startNode();
(*ar)(cereal::make_nvp("module_functions", _data));
ar->finishNode();
ar->finishNode();
}
verbprintf_bare(_level, "Done\n");
ifs.close();
}
else if(_ext == "json")
{
verbprintf(_level, "Reading '%s'... ", _iname.c_str());
std::ifstream ifs{ _iname };
if(!ifs)
_handle_error();
else
{
using input_policy = policy::input_archive<cereal::JSONInputArchive>;
auto ar = input_policy::get(ifs);
ar->setNextName("omnitrace");
ar->startNode();
ar->setNextName(_label.c_str());
ar->startNode();
(*ar)(cereal::make_nvp("module_functions", _data));
ar->finishNode();
ar->finishNode();
}
verbprintf_bare(_level, "Done\n");
ifs.close();
}
else
{
throw std::runtime_error(TIMEMORY_JOIN(
"", "[omnitrace][exe] Error in ", __FUNCTION__, " :: filename '", _iname,
"' does not have one of recognized extentions: txt, json, xml :: ", _ext));
}
}
//
static inline void
load_info(const string_t& _inp, std::map<std::string, fmodset_t*>& _data, int _level)
{
std::vector<std::string> _exceptions{};
_exceptions.reserve(_data.size());
for(auto& itr : _data)
{
try
{
fmodset_t _tmp{};
load_info(itr.first, _inp, _tmp, _level);
// add to the existing
itr.second->insert(_tmp.begin(), _tmp.end());
// if it did not throw it was successfully loaded
_exceptions.clear();
break;
} catch(std::exception& _e)
{
_exceptions.emplace_back(_e.what());
}
}
if(!_exceptions.empty())
{
std::stringstream _msg{};
for(auto& itr : _exceptions)
{
_msg << "[omnitrace][exe] " << itr << "\n";
}
throw std::runtime_error(_msg.str());
}
}
//
//======================================================================================//
//
template <typename Tp, std::enable_if_t<!std::is_same<Tp, std::string>::value, int> = 0>
snippet_pointer_t
get_snippet(Tp arg)
@@ -962,4 +282,79 @@ omnitrace_fork_callback(thread_t* parent, thread_t* child)
}
//
//======================================================================================//
// insert_instr -- generic insert instrumentation function
//
template <typename Tp>
bool
insert_instr(address_space_t* mutatee, procedure_t* funcToInstr, Tp traceFunc,
procedure_loc_t traceLoc, flow_graph_t* cfGraph,
basic_loop_t* loopToInstrument, bool allow_traps)
{
module_t* module = funcToInstr->getModule();
if(!module || !traceFunc) return false;
bpvector_t<point_t*>* _points = nullptr;
auto _trace = traceFunc.get();
if(cfGraph && loopToInstrument)
{
if(traceLoc == BPatch_entry)
_points = cfGraph->findLoopInstPoints(BPatch_locLoopEntry, loopToInstrument);
else if(traceLoc == BPatch_exit)
_points = cfGraph->findLoopInstPoints(BPatch_locLoopExit, loopToInstrument);
}
else
{
_points = funcToInstr->findPoint(traceLoc);
}
if(_points == nullptr) return false;
if(_points->empty()) return false;
/*if(loop_level_instr)
{
flow_graph_t* flow = funcToInstr->getCFG();
bpvector_t<basic_loop_t*> basicLoop;
flow->getOuterLoops(basicLoop);
for(auto litr = basicLoop.begin(); litr != basicLoop.end(); ++litr)
{
bpvector_t<point_t*>* _tmp;
if(traceLoc == BPatch_entry)
_tmp = cfGraph->findLoopInstPoints(BPatch_locLoopEntry, *litr);
else if(traceLoc == BPatch_exit)
_tmp = cfGraph->findLoopInstPoints(BPatch_locLoopExit, *litr);
if(!_tmp)
continue;
for(auto& itr : *_tmp)
_points->push_back(itr);
}
}*/
// verbprintf(0, "Instrumenting |> [ %s ]\n", name.m_name.c_str());
std::set<point_t*> _traps{};
if(!allow_traps)
{
for(auto& itr : *_points)
{
if(itr && itr->usesTrap_NP()) _traps.insert(itr);
}
}
size_t _n = 0;
for(auto& itr : *_points)
{
if(!itr || _traps.count(itr) > 0)
continue;
else if(traceLoc == BPatch_entry)
mutatee->insertSnippet(*_trace, *itr, BPatch_callBefore, BPatch_firstSnippet);
// else if(traceLoc == BPatch_exit)
// mutatee->insertSnippet(*_trace, *itr, BPatch_callAfter,
// BPatch_firstSnippet);
else
mutatee->insertSnippet(*_trace, *itr);
++_n;
}
return (_n > 0);
}
+149
Переглянути файл
@@ -0,0 +1,149 @@
# adds a ctest for executable
function(OMNITRACE_ADD_BIN_TEST)
cmake_parse_arguments(
TEST
"" # options
"NAME;TARGET;TIMEOUT;WORKING_DIRECTORY" # single value args
"ARGS;ENVIRONMENT;LABELS;PROPERTIES;PASS_REGULAR_EXPRESSION;FAIL_REGULAR_EXPRESSION;SKIP_REGULAR_EXPRESSION;DEPENDS;COMMAND" # multiple
# value args
${ARGN})
if(NOT OMNITRACE_DYNINST_API_RT_DIR AND OMNITRACE_DYNINST_API_RT)
get_filename_component(OMNITRACE_DYNINST_API_RT_DIR "${OMNITRACE_DYNINST_API_RT}"
DIRECTORY)
endif()
if(OMNITRACE_BUILD_DYNINST)
set(OMNITRACE_DYNINST_API_RT_DIR
"${PROJECT_BINARY_DIR}/external/dyninst/dyninstAPI_RT:${PROJECT_BINARY_DIR}/external/dyninst/dyninstAPI"
)
endif()
if(NOT TEST_ENVIRONMENT)
set(TEST_ENVIRONMENT
"OMNITRACE_USE_PERFETTO=ON"
"OMNITRACE_USE_TIMEMORY=ON"
"OMNITRACE_USE_SAMPLING=ON"
"OMNITRACE_TIME_OUTPUT=OFF"
"LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}"
)
endif()
list(APPEND TEST_ENVIRONMENT "OMNITRACE_CI=ON"
"OMNITRACE_OUTPUT_PATH=omnitrace-tests-output"
"OMNITRACE_OUTPUT_PREFIX=${TEST_NAME}/")
if(TEST_COMMAND)
add_test(
NAME ${TEST_NAME}
COMMAND ${TEST_COMMAND} ${TEST_ARGS}
WORKING_DIRECTORY ${TEST_WORKING_DIRECTORY})
set_tests_properties(
${TEST_NAME}
PROPERTIES ENVIRONMENT
"${TEST_ENVIRONMENT}"
TIMEOUT
${TEST_TIMEOUT}
LABELS
"omnitrace-bin;${TEST_LABELS}"
PASS_REGULAR_EXPRESSION
"${TEST_PASS_REGULAR_EXPRESSION}"
FAIL_REGULAR_EXPRESSION
"${TEST_FAIL_REGULAR_EXPRESSION}"
SKIP_REGULAR_EXPRESSION
"${TEST_SKIP_REGULAR_EXPRESSION}"
${TEST_PROPERTIES})
elseif(TARGET ${TEST_TARGET})
add_test(
NAME ${TEST_NAME}
COMMAND $<TARGET_FILE:${TEST_TARGET}> ${TEST_ARGS}
WORKING_DIRECTORY $<TARGET_FILE_DIR:${TEST_TARGET}>)
set_tests_properties(
${TEST_NAME}
PROPERTIES ENVIRONMENT
"${TEST_ENVIRONMENT}"
TIMEOUT
${TEST_TIMEOUT}
LABELS
"omnitrace-bin;${TEST_LABELS}"
PASS_REGULAR_EXPRESSION
"${TEST_PASS_REGULAR_EXPRESSION}"
FAIL_REGULAR_EXPRESSION
"${TEST_FAIL_REGULAR_EXPRESSION}"
SKIP_REGULAR_EXPRESSION
"${TEST_SKIP_REGULAR_EXPRESSION}"
${TEST_PROPERTIES})
elseif(OMNITRACE_BUILD_TESTING)
message(FATAL_ERROR "Error! ${TEST_TARGET} does not exist")
endif()
endfunction()
omnitrace_add_bin_test(
NAME omnitrace-exe-help
TARGET omnitrace-exe
ARGS --help
LABELS omnitrace-exe
TIMEOUT 15
PASS_REGULAR_EXPRESSION
".*\\\[omnitrace\\\] Usage:.*\\\[DEBUG OPTIONS\\\].*\\\[MODE OPTIONS\\\].*\\\[LIBRARY OPTIONS\\\].*\\\[SYMBOL SELECTION OPTIONS\\\].*\\\[RUNTIME OPTIONS\\\].*\\\[GRANULARITY OPTIONS\\\].*\\\[DYNINST OPTIONS\\\].*"
)
omnitrace_add_bin_test(
NAME omnitrace-exe-simulate-ls
TARGET omnitrace-exe
ARGS --simulate --print-format json txt xml -- ls
TIMEOUT 60)
omnitrace_add_bin_test(
NAME omnitrace-exe-simulate-ls-check
DEPENDS omnitrace-exe-simulate-ls
COMMAND ls
WORKING_DIRECTORY
${PROJECT_BINARY_DIR}/omnitrace-tests-output/omnitrace-exe-simulate-ls
TIMEOUT 30
PASS_REGULAR_EXPRESSION
".*available-instr.json.*available-instr.txt.*available-instr.xml.*excluded-instr.json.*excluded-instr.txt.*excluded-instr.xml.*instrumented-instr.json.*instrumented-instr.txt.*instrumented-instr.xml.*overlapping-instr.json.*overlapping-instr.txt.*overlapping-instr.xml.*"
)
omnitrace_add_bin_test(
NAME omnitrace-avail-help
TARGET omnitrace-avail
ARGS --help
LABELS omnitrace-avail
TIMEOUT 15
PASS_REGULAR_EXPRESSION
".*\\\[omnitrace-avail\\\] Usage:.*\\\[CATEGORIES\\\].*\\\[VIEW OPTIONS\\\].*\\\[COLUMN OPTIONS\\\].*\\\[WIDTH OPTIONS\\\].*\\\[OUTPUT OPTIONS\\\].*"
)
omnitrace_add_bin_test(
NAME omnitrace-avail-filter-wall-clock-available
TARGET omnitrace-avail
ARGS -r wall_clock -C --available
LABELS omnitrace-avail
TIMEOUT 15
PASS_REGULAR_EXPRESSION
"\\\|[-]+\\\|\n\\\|[ ]+COMPONENT[ ]+\\\|\n\\\|[-]+\\\|\n\\\| (wall_clock)[ ]+\\\|\n\\\| (sampling_wall_clock)[ ]+\\\|\n\\\|[-]+\\\|"
)
omnitrace_add_bin_test(
NAME omnitrace-avail-category-filer-omnitrace
TARGET omnitrace-avail
ARGS --categories settings::omnitrace --brief
LABELS omnitrace-avail
TIMEOUT 15
PASS_REGULAR_EXPRESSION "OMNITRACE_(SETTINGS_DESC|OUTPUT_FILE|OUTPUT_PREFIX)"
FAIL_REGULAR_EXPRESSION
"OMNITRACE_(ADD_SECONDARY|SCIENTIFIC|PRECISION|MEMORY_PRECISION|TIMING_PRECISION)"
)
omnitrace_add_bin_test(
NAME omnitrace-avail-category-filer-timemory
TARGET omnitrace-avail
ARGS --categories settings::timemory --brief
LABELS omnitrace-avail
TIMEOUT 15
PASS_REGULAR_EXPRESSION
"OMNITRACE_(ADD_SECONDARY|SCIENTIFIC|PRECISION|MEMORY_PRECISION|TIMING_PRECISION)"
FAIL_REGULAR_EXPRESSION "OMNITRACE_(SETTINGS_DESC|OUTPUT_FILE)")
+9 -181
Переглянути файл
@@ -1,186 +1,14 @@
# ------------------------------------------------------------------------------#
# ----------------------------------------------------------------------------- #
#
# omnitrace interface library
# omnitrace: contains all instrumentation functionality
#
# ------------------------------------------------------------------------------#
add_library(omnitrace-interface-library INTERFACE)
add_library(omnitrace::omnitrace-interface-library ALIAS omnitrace-interface-library)
target_include_directories(
omnitrace-interface-library INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_BINARY_DIR}/include)
target_include_directories(omnitrace-interface-library SYSTEM
INTERFACE ${perfetto_DIR}/sdk)
target_compile_definitions(
omnitrace-interface-library
INTERFACE OMNITRACE_MAX_THREADS=${OMNITRACE_MAX_THREADS}
$<IF:$<BOOL:${OMNITRACE_CUSTOM_DATA_SOURCE}>,CUSTOM_DATA_SOURCE,>)
target_link_libraries(
omnitrace-interface-library
INTERFACE $<BUILD_INTERFACE:omnitrace::omnitrace-headers>
$<BUILD_INTERFACE:omnitrace::omnitrace-threading>
$<BUILD_INTERFACE:omnitrace::omnitrace-compile-options>
$<BUILD_INTERFACE:omnitrace::omnitrace-hip>
$<BUILD_INTERFACE:omnitrace::omnitrace-roctracer>
$<BUILD_INTERFACE:omnitrace::omnitrace-rocm-smi>
$<BUILD_INTERFACE:omnitrace::omnitrace-mpi>
$<BUILD_INTERFACE:omnitrace::omnitrace-ptl>
$<BUILD_INTERFACE:timemory::timemory-headers>
$<BUILD_INTERFACE:timemory::timemory-gotcha>
$<BUILD_INTERFACE:timemory::timemory-cxx-static>
$<IF:$<BOOL:${OMNITRACE_USE_SANITIZER}>,omnitrace::omnitrace-sanitizer,>)
# ------------------------------------------------------------------------------#
# omnitrace-dl: contains minimal symbols and dlopen's omnitrace
#
# omnitrace object library
# omnitrace-user: contains symbols for user API
#
# ------------------------------------------------------------------------------#
# ----------------------------------------------------------------------------- #
add_library(omnitrace-object-library OBJECT)
add_library(omnitrace::omnitrace-object-library ALIAS omnitrace-object-library)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/library/defines.hpp.in
${CMAKE_CURRENT_BINARY_DIR}/include/library/defines.hpp @ONLY)
set(library_sources
${CMAKE_CURRENT_LIST_DIR}/src/library.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/api.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/config.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/cpu_freq.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/critical_trace.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/kokkosp.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/gpu.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/perfetto.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/ptl.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/sampling.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/state.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/thread_data.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/thread_sampler.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/timemory.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/backtrace.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/fork_gotcha.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/mpi_gotcha.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/omnitrace.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/pthread_gotcha.cpp
${perfetto_DIR}/sdk/perfetto.cc)
set(library_headers
${CMAKE_CURRENT_LIST_DIR}/include/library.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/api.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/config.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/common.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/cpu_freq.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/critical_trace.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/debug.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/gpu.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/perfetto.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/ptl.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/sampling.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/state.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/thread_data.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/thread_sampler.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/timemory.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/fwd.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/backtrace.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/fork_gotcha.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/functors.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/mpi_gotcha.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/omnitrace.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/rocm_smi.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/roctracer.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/roctracer_callbacks.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/pthread_gotcha.hpp
${perfetto_DIR}/sdk/perfetto.h)
target_sources(omnitrace-object-library PRIVATE ${library_sources} ${library_headers})
if(OMNITRACE_USE_ROCTRACER)
target_sources(
omnitrace-object-library
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/library/components/roctracer.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/roctracer_callbacks.cpp)
endif()
if(OMNITRACE_USE_ROCM_SMI)
target_sources(omnitrace-object-library
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/library/components/rocm_smi.cpp)
endif()
target_link_libraries(omnitrace-object-library PRIVATE omnitrace-interface-library)
if(OMNITRACE_DYNINST_API_RT)
get_filename_component(OMNITRACE_DYNINST_API_RT_DIR "${OMNITRACE_DYNINST_API_RT}"
DIRECTORY)
endif()
# ------------------------------------------------------------------------------#
#
# omnitrace shared library
#
# ------------------------------------------------------------------------------#
add_library(omnitrace-library SHARED $<TARGET_OBJECTS:omnitrace-object-library>)
add_library(omnitrace::omnitrace-library ALIAS omnitrace-library)
target_link_libraries(omnitrace-library PRIVATE omnitrace-interface-library)
set_target_properties(
omnitrace-library
PROPERTIES OUTPUT_NAME omnitrace
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
INSTALL_RPATH
"\$ORIGIN:\$ORIGIN/timemory/libunwind:\$ORIGIN/dyninst-tpls/libs")
install(
TARGETS omnitrace-library
DESTINATION ${CMAKE_INSTALL_LIBDIR}
OPTIONAL)
# ------------------------------------------------------------------------------#
#
# omnitrace dl library
#
# ------------------------------------------------------------------------------#
set(CMAKE_BUILD_TYPE "Release")
set(CMAKE_SKIP_RPATH OFF)
set(BUILD_RPATH_USE_ORIGIN ON)
add_library(omnitrace-dl-library SHARED)
add_library(omnitrace::omnitrace-dl-library ALIAS omnitrace-dl-library)
target_sources(omnitrace-dl-library PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/dl.cpp)
target_link_libraries(omnitrace-dl-library PRIVATE ${dl_LIBRARY})
check_cxx_compiler_flag("-fno-exceptions" omnitrace_dl_library_fno_exceptions)
check_cxx_compiler_flag("-ftls-model=local-dynamic"
omnitrace_dl_library_ftls_module_local_dynamic)
if(OMNITRACE_BUILD_DEVELOPER)
if(omnitrace_dl_library_fno_exceptions)
target_compile_options(omnitrace-dl-library PRIVATE -fno-exceptions)
endif()
if(omnitrace_dl_library_ftls_module_local_dynamic)
target_compile_options(omnitrace-dl-library PRIVATE -ftls-model=local-dynamic)
endif()
endif()
set_target_properties(
omnitrace-dl-library
PROPERTIES OUTPUT_NAME omnitrace-dl
CXX_VISIBILITY_PRESET "protected"
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
POSITION_INDEPENDENT_CODE ON
BUILD_RPATH "\$ORIGIN"
INSTALL_RPATH "\$ORIGIN")
install(
TARGETS omnitrace-dl-library
DESTINATION ${CMAKE_INSTALL_LIBDIR}
OPTIONAL)
add_subdirectory(common)
add_subdirectory(omnitrace)
add_subdirectory(omnitrace-dl)
add_subdirectory(omnitrace-user)
+22
Переглянути файл
@@ -0,0 +1,22 @@
# ------------------------------------------------------------------------------#
#
# omnitrace common headers
#
# ------------------------------------------------------------------------------#
add_library(omnitrace-common-library INTERFACE)
add_library(omnitrace::common-library ALIAS omnitrace-common-library)
target_sources(
omnitrace-common-library
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/defines.h
${CMAKE_CURRENT_SOURCE_DIR}/delimit.hpp
${CMAKE_CURRENT_SOURCE_DIR}/environment.hpp
${CMAKE_CURRENT_SOURCE_DIR}/invoke.hpp
${CMAKE_CURRENT_SOURCE_DIR}/join.hpp)
get_filename_component(COMMON_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" DIRECTORY)
target_include_directories(omnitrace-common-library INTERFACE ${COMMON_INCLUDE_DIR})
target_compile_definitions(omnitrace-common-library
INTERFACE $<BUILD_INTERFACE:OMNITRACE_INTERNAL_BUILD>)
+36
Переглянути файл
@@ -0,0 +1,36 @@
// 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
#define OMNITRACE_ATTRIBUTE(...) __attribute__((__VA_ARGS__))
#define OMNITRACE_VISIBILITY(MODE) OMNITRACE_ATTRIBUTE(visibility(MODE))
#define OMNITRACE_PUBLIC_API OMNITRACE_VISIBILITY("default")
#define OMNITRACE_HIDDEN_API OMNITRACE_VISIBILITY("hidden")
#define OMNITRACE_WEAK_API OMNITRACE_ATTRIBUTE(weak)
#define OMNITRACE_INLINE OMNITRACE_ATTRIBUTE(__always_inline__)
#if defined(__cplusplus)
# if !defined(OMNITRACE_FOLD_EXPRESSION)
# define OMNITRACE_FOLD_EXPRESSION(...) ((__VA_ARGS__), ...)
# endif
#endif
+65
Переглянути файл
@@ -0,0 +1,65 @@
// 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 <string>
#include <vector>
namespace omnitrace
{
inline namespace common
{
namespace
{
template <typename ContainerT = std::vector<std::string>>
inline ContainerT
delimit(const std::string& line, const char* delimiters = "\"',;: ");
template <typename ContainerT>
inline ContainerT
delimit(const std::string& line, const char* 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
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()) _result.emplace(_result.end(), _tmp);
}
return _result;
}
} // namespace
} // namespace common
} // namespace omnitrace
+77
Переглянути файл
@@ -0,0 +1,77 @@
// 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 <cstdlib>
#include <cstring>
#include <string>
#include <string_view>
namespace omnitrace
{
inline namespace common
{
namespace
{
inline std::string
get_env(const char* env_id, const char* _default)
{
if(strlen(env_id) == 0) return _default;
char* env_var = ::std::getenv(env_id);
if(env_var) return std::string{ env_var };
return _default;
}
inline int
get_env(const char* env_id, int _default)
{
if(strlen(env_id) == 0) return _default;
char* env_var = ::std::getenv(env_id);
if(env_var) return std::stoi(env_var);
return _default;
}
inline bool
get_env(const char* env_id, bool _default)
{
if(strlen(env_id) == 0) return _default;
char* env_var = ::std::getenv(env_id);
if(env_var)
{
if(std::string_view{ env_var }.find_first_not_of("0123456789") ==
std::string_view::npos)
return static_cast<bool>(std::stoi(env_var));
else
{
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
} // namespace common
} // namespace omnitrace
+114
Переглянути файл
@@ -0,0 +1,114 @@
// 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 "common/defines.h"
#include "common/join.hpp"
#include <atomic>
#include <cstring>
#include <functional>
#include <string>
#if !defined(OMNITRACE_COMMON_LIBRARY_NAME)
# define OMNITRACE_COMMON_LIBRARY_NAME "common"
# error OMNITRACE_COMMON_LIBRARY_NAME must be defined
#endif
namespace omnitrace
{
inline namespace common
{
namespace
{
template <typename FuncT, typename... Args>
inline auto
invoke(const char* _name, FuncT&& _func, Args... _args) OMNITRACE_HIDDEN_API;
inline int32_t&
get_guard()
{
static thread_local int32_t _v = 0;
return _v;
}
inline int64_t
get_thread_index()
{
static std::atomic<int64_t> _c{ 0 };
static thread_local auto _v = _c++;
return _v;
}
template <typename FuncT, typename... Args>
auto
invoke(const char* _name, int _verbose, FuncT&& _func, Args... _args)
{
if(_func)
{
struct decrement_guard
{
// decrement the guard as it exits the scope
~decrement_guard() { --get_guard(); }
} _unlk{};
// if _lk is ever greater than zero on the same thread, this
// means a function within the current function is calling
// our instrumentation so we ignore the call
int32_t _lk = get_guard()++;
if(_lk == 0)
{
if(_verbose > 3)
{
fflush(stderr);
fprintf(stderr,
"[omnitrace][" OMNITRACE_COMMON_LIBRARY_NAME "][%li] %s(%s)\n",
get_thread_index(), _name, join(", ", _args...).c_str());
fflush(stderr);
}
return std::invoke(std::forward<FuncT>(_func), _args...);
}
else if(_verbose > 2)
{
fflush(stderr);
fprintf(stderr,
"[omnitrace][" OMNITRACE_COMMON_LIBRARY_NAME
"][%li] %s(%s) was guarded :: value = %i\n",
get_thread_index(), _name, join(", ", _args...).c_str(), _lk);
fflush(stderr);
}
}
else if(_verbose >= 0)
{
fprintf(stderr,
"[omnitrace][" OMNITRACE_COMMON_LIBRARY_NAME
"][%li] %s(%s) ignored :: null function pointer\n",
get_thread_index(), _name, join(", ", _args...).c_str());
}
using return_type = decltype(std::invoke(std::forward<FuncT>(_func), _args...));
if constexpr(!std::is_void<return_type>::value) return return_type();
}
} // namespace
} // namespace common
} // namespace omnitrace
+55
Переглянути файл
@@ -0,0 +1,55 @@
// 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 <sstream>
#include <string>
#if !defined(OMNITRACE_FOLD_EXPRESSION)
# define OMNITRACE_FOLD_EXPRESSION(...) ((__VA_ARGS__), ...)
#endif
namespace omnitrace
{
inline namespace common
{
namespace
{
template <typename DelimT, typename... Args>
auto
join(DelimT&& _delim, Args&&... _args)
{
std::stringstream _ss{};
OMNITRACE_FOLD_EXPRESSION(_ss << _delim << _args);
if constexpr(std::is_same<DelimT, char>::value)
{
return _ss.str().substr(1);
}
else
{
return _ss.str().substr(std::string{ _delim }.length());
}
}
} // namespace
} // namespace common
} // namespace omnitrace
+55
Переглянути файл
@@ -0,0 +1,55 @@
# ------------------------------------------------------------------------------#
#
# omnitrace dl library
#
# ------------------------------------------------------------------------------#
set(CMAKE_BUILD_TYPE "Release")
set(CMAKE_SKIP_RPATH OFF)
set(BUILD_RPATH_USE_ORIGIN ON)
add_library(omnitrace-dl-library SHARED)
add_library(omnitrace::omnitrace-dl-library ALIAS omnitrace-dl-library)
target_sources(omnitrace-dl-library PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/dl.cpp)
target_link_libraries(omnitrace-dl-library PRIVATE ${dl_LIBRARY}
omnitrace::common-library)
check_cxx_compiler_flag("-fno-exceptions" omnitrace_dl_library_fno_exceptions)
check_cxx_compiler_flag("-ftls-model=local-dynamic"
omnitrace_dl_library_ftls_module_local_dynamic)
if(OMNITRACE_BUILD_DEVELOPER)
if(omnitrace_dl_library_fno_exceptions)
target_compile_options(omnitrace-dl-library PRIVATE -fno-exceptions)
endif()
if(omnitrace_dl_library_ftls_module_local_dynamic)
target_compile_options(omnitrace-dl-library PRIVATE -ftls-model=local-dynamic)
endif()
endif()
omnitrace_target_compile_definitions(
omnitrace-dl-library PRIVATE OMNITRACE_USE_OMPT=$<BOOL:${OMNITRACE_USE_OMPT}>)
set_target_properties(
omnitrace-dl-library
PROPERTIES OUTPUT_NAME omnitrace-dl
CXX_VISIBILITY_PRESET "protected"
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
POSITION_INDEPENDENT_CODE ON
BUILD_RPATH "\$ORIGIN"
INSTALL_RPATH "\$ORIGIN")
install(
TARGETS omnitrace-dl-library
EXPORT omnitrace-dl-library-targets
DESTINATION ${CMAKE_INSTALL_LIBDIR}
OPTIONAL)
install(
EXPORT omnitrace-dl-library-targets
FILE omnitrace-dl-library-targets.cmake
NAMESPACE omnitrace::
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/omnitrace)
+199 -204
Переглянути файл
@@ -22,6 +22,15 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#define OMNITRACE_COMMON_LIBRARY_NAME "dl"
#include "common/defines.h"
#include "common/delimit.hpp"
#include "common/environment.hpp"
#include "common/invoke.hpp"
#include "common/join.hpp"
#include <atomic>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
@@ -38,15 +47,15 @@
#include <sys/stat.h>
#include <unistd.h>
#define OMNITRACE_FOLD_EXPRESSION(...) ((__VA_ARGS__), ...)
#define OMNITRACE_VISIBLE __attribute__((visibility("default")))
#define OMNITRACE_HIDDEN __attribute__((visibility("internal")))
#define OMNITRACE_INLINE __attribute__((__always_inline__))
#if !defined(OMNITRACE_USE_OMPT)
# define OMNITRACE_USE_OMPT 0
#endif
#define OMNITRACE_DLSYM(VARNAME, HANDLE, FUNCNAME) \
if(HANDLE) \
{ \
*(void**) (&VARNAME) = dlsym(HANDLE, FUNCNAME); \
if(VARNAME == nullptr && _omnitrace_dl_verbose >= 0) \
if(VARNAME == nullptr && _omnitrace_dl_verbose >= _warn_verbose) \
{ \
fprintf(stderr, "[omnitrace][dl][pid=%i]> %s :: %s\n", getpid(), FUNCNAME, \
dlerror()); \
@@ -61,50 +70,45 @@
extern "C"
{
void omnitrace_init_library(void) OMNITRACE_VISIBLE;
void omnitrace_init(const char*, bool, const char*) OMNITRACE_VISIBLE;
void omnitrace_finalize(void) OMNITRACE_VISIBLE;
void omnitrace_set_env(const char* env_name, const char* env_val) OMNITRACE_VISIBLE;
void omnitrace_set_mpi(bool use, bool attached) OMNITRACE_VISIBLE;
void omnitrace_push_trace(const char* name) OMNITRACE_VISIBLE;
void omnitrace_pop_trace(const char* name) OMNITRACE_VISIBLE;
struct ompt_start_tool_result_t;
void omnitrace_init_library(void) OMNITRACE_PUBLIC_API;
void omnitrace_init(const char*, bool, const char*) OMNITRACE_PUBLIC_API;
void omnitrace_finalize(void) OMNITRACE_PUBLIC_API;
void omnitrace_set_env(const char* env_name,
const char* env_val) OMNITRACE_PUBLIC_API;
void omnitrace_set_mpi(bool use, bool attached) OMNITRACE_PUBLIC_API;
void omnitrace_push_trace(const char* name) OMNITRACE_PUBLIC_API;
void omnitrace_pop_trace(const char* name) OMNITRACE_PUBLIC_API;
void omnitrace_user_start_trace_dl(void) OMNITRACE_HIDDEN_API;
void omnitrace_user_stop_trace_dl(void) OMNITRACE_HIDDEN_API;
void omnitrace_user_start_thread_trace_dl(void) OMNITRACE_HIDDEN_API;
void omnitrace_user_stop_thread_trace_dl(void) OMNITRACE_HIDDEN_API;
void omnitrace_user_push_region_dl(const char*) OMNITRACE_HIDDEN_API;
void omnitrace_user_pop_region_dl(const char*) OMNITRACE_HIDDEN_API;
ompt_start_tool_result_t* ompt_start_tool(unsigned int,
const char*) OMNITRACE_PUBLIC_API;
}
//--------------------------------------------------------------------------------------//
inline namespace omnitrace
namespace omnitrace
{
inline namespace dl
{
namespace
{
inline int
get_omnitrace_env();
bool
get_env(const char* env_id, bool _default);
std::string
get_env(const char* env_id, const char* _default);
int
get_env(const char* env_id, int _default);
template <typename DelimT, typename... Args>
auto
join(DelimT&& _delim, Args&&... _args)
get_omnitrace_env()
{
std::stringstream _ss{};
OMNITRACE_FOLD_EXPRESSION(_ss << _delim << _args);
if constexpr(std::is_same<DelimT, char>::value)
{
return _ss.str().substr(1);
}
else
{
return _ss.str().substr(std::string{ _delim }.length());
}
auto&& _debug = get_env("OMNITRACE_DEBUG", false);
return get_env("OMNITRACE_VERBOSE", (_debug) ? 100 : 0);
}
// environment priority:
// - OMNITRACE_DL_DEBUG
// - OMNITRACE_DL_VERBOSE
@@ -114,10 +118,6 @@ int _omnitrace_dl_verbose = get_env("OMNITRACE_DL_DEBUG", false)
? 100
: get_env("OMNITRACE_DL_VERBOSE", get_omnitrace_env());
template <typename ContainerT = std::vector<std::string>>
inline ContainerT
delimit(const std::string& line, const char* delimiters = "\"',;: ");
// The docs for dlopen suggest that the combination of RTLD_LOCAL + RTLD_DEEPBIND
// (when available) helps ensure that the symbols in the instrumentation library
// libomnitrace.so will use it's own symbols... not symbols that are potentially
@@ -162,39 +162,38 @@ const char* _omnitrace_dl_dlopen_descr = "RTLD_LAZY | RTLD_LOCAL";
#endif
/// This class contains function pointers for omnitrace's instrumentation functions
struct OMNITRACE_HIDDEN indirect
struct OMNITRACE_HIDDEN_API indirect
{
explicit OMNITRACE_INLINE indirect(std::string libpath)
: m_libpath{ find_path(std::move(libpath)) }
OMNITRACE_INLINE indirect(std::string omnilib, std::string userlib)
: m_omnilib{ find_path(std::move(omnilib)) }
, m_userlib{ find_path(std::move(userlib)) }
{
if(_omnitrace_dl_verbose > 0)
{
fprintf(stderr, "[omnitrace][dl][pid=%i] libomnitrace.so resolved to '%s'\n",
getpid(), m_libpath.c_str());
getpid(), m_omnilib.c_str());
}
auto _omni_hsa_lib = m_libpath;
auto _omni_hsa_lib = m_omnilib;
const char* _hsa_lib = getenv("HSA_TOOLS_LIB");
if(_hsa_lib) _omni_hsa_lib.append(":").append(_hsa_lib);
setenv("HSA_TOOLS_LIB", _omni_hsa_lib.c_str(), 1);
open();
m_omnihandle = open(m_omnilib);
m_userhandle = open(m_userlib);
init();
}
OMNITRACE_INLINE ~indirect() { dlclose(m_libhandle); }
OMNITRACE_INLINE ~indirect() { dlclose(m_omnihandle); }
OMNITRACE_INLINE void open()
static OMNITRACE_INLINE void* open(const std::string& _lib)
{
if(m_libhandle) return;
auto* libhandle = dlopen(m_libpath.c_str(), _omnitrace_dl_dlopen_flags);
auto* libhandle = dlopen(_lib.c_str(), _omnitrace_dl_dlopen_flags);
if(libhandle)
{
m_libhandle = libhandle;
if(_omnitrace_dl_verbose > 0)
{
fprintf(stderr, "[omnitrace][dl][pid=%i] dlopen(%s, %s) :: success\n",
getpid(), m_libpath.c_str(), _omnitrace_dl_dlopen_descr);
getpid(), _lib.c_str(), _omnitrace_dl_dlopen_descr);
}
}
else
@@ -203,26 +202,48 @@ struct OMNITRACE_HIDDEN indirect
{
perror("dlopen");
fprintf(stderr, "[omnitrace][dl][pid=%i] dlopen(%s, %s) :: %s\n",
getpid(), m_libpath.c_str(), _omnitrace_dl_dlopen_descr,
dlerror());
getpid(), _lib.c_str(), _omnitrace_dl_dlopen_descr, dlerror());
}
}
dlerror(); // Clear any existing error
return libhandle;
}
OMNITRACE_INLINE void init()
{
if(!m_libhandle) open();
if(!m_omnihandle) m_omnihandle = open(m_omnilib);
int _warn_verbose = 0;
// Initialize all pointers
OMNITRACE_DLSYM(omnitrace_init_library_f, m_libhandle, "omnitrace_init_library");
OMNITRACE_DLSYM(omnitrace_init_f, m_libhandle, "omnitrace_init");
OMNITRACE_DLSYM(omnitrace_finalize_f, m_libhandle, "omnitrace_finalize");
OMNITRACE_DLSYM(omnitrace_set_env_f, m_libhandle, "omnitrace_set_env");
OMNITRACE_DLSYM(omnitrace_set_mpi_f, m_libhandle, "omnitrace_set_mpi");
OMNITRACE_DLSYM(omnitrace_push_trace_f, m_libhandle, "omnitrace_push_trace");
OMNITRACE_DLSYM(omnitrace_pop_trace_f, m_libhandle, "omnitrace_pop_trace");
OMNITRACE_DLSYM(omnitrace_init_library_f, m_omnihandle, "omnitrace_init_library");
OMNITRACE_DLSYM(omnitrace_init_f, m_omnihandle, "omnitrace_init");
OMNITRACE_DLSYM(omnitrace_finalize_f, m_omnihandle, "omnitrace_finalize");
OMNITRACE_DLSYM(omnitrace_set_env_f, m_omnihandle, "omnitrace_set_env");
OMNITRACE_DLSYM(omnitrace_set_mpi_f, m_omnihandle, "omnitrace_set_mpi");
OMNITRACE_DLSYM(omnitrace_push_trace_f, m_omnihandle, "omnitrace_push_trace");
OMNITRACE_DLSYM(omnitrace_pop_trace_f, m_omnihandle, "omnitrace_pop_trace");
OMNITRACE_DLSYM(omnitrace_push_region_f, m_omnihandle, "omnitrace_push_region");
OMNITRACE_DLSYM(omnitrace_pop_region_f, m_omnihandle, "omnitrace_pop_region");
#if OMNITRACE_USE_OMPT == 0
_warn_verbose = 5;
#endif
OMNITRACE_DLSYM(ompt_start_tool_f, m_omnihandle, "ompt_start_tool");
if(!m_userhandle) m_userhandle = open(m_userlib);
_warn_verbose = 0;
OMNITRACE_DLSYM(omnitrace_user_configure_f, m_userhandle,
"omnitrace_user_configure");
if(omnitrace_user_configure_f)
{
(*omnitrace_user_configure_f)(
&omnitrace_user_start_trace_dl, &omnitrace_user_stop_trace_dl,
&omnitrace_user_start_thread_trace_dl,
&omnitrace_user_stop_thread_trace_dl, &omnitrace_user_push_region_dl,
&omnitrace_user_pop_region_dl);
}
}
static OMNITRACE_INLINE std::string find_path(std::string&& _path)
@@ -246,196 +267,170 @@ struct OMNITRACE_HIDDEN indirect
}
public:
void (*omnitrace_init_library_f)(void) = nullptr;
void (*omnitrace_init_f)(const char*, bool, const char*) = nullptr;
void (*omnitrace_finalize_f)(void) = nullptr;
void (*omnitrace_set_env_f)(const char*, const char*) = nullptr;
void (*omnitrace_set_mpi_f)(bool, bool) = nullptr;
void (*omnitrace_push_trace_f)(const char*) = nullptr;
void (*omnitrace_pop_trace_f)(const char*) = nullptr;
void (*omnitrace_init_library_f)(void) = nullptr;
void (*omnitrace_init_f)(const char*, bool, const char*) = nullptr;
void (*omnitrace_finalize_f)(void) = nullptr;
void (*omnitrace_set_env_f)(const char*, const char*) = nullptr;
void (*omnitrace_set_mpi_f)(bool, bool) = nullptr;
void (*omnitrace_push_trace_f)(const char*) = nullptr;
void (*omnitrace_pop_trace_f)(const char*) = nullptr;
void (*omnitrace_push_region_f)(const char*) = nullptr;
void (*omnitrace_pop_region_f)(const char*) = nullptr;
void (*omnitrace_user_configure_f)(void (*)(void), void (*)(void), void (*)(void),
void (*)(void), void (*)(const char*),
void (*)(const char*)) = nullptr;
ompt_start_tool_result_t* (*ompt_start_tool_f)(unsigned int, const char*);
private:
void* m_libhandle = nullptr;
std::string m_libpath = {};
void* m_omnihandle = nullptr;
void* m_userhandle = nullptr;
std::string m_omnilib = {};
std::string m_userlib = {};
};
inline indirect&
get_indirect() OMNITRACE_HIDDEN;
get_indirect() OMNITRACE_HIDDEN_API;
template <typename FuncT, typename... Args>
inline void
invoke(const char* _name, FuncT&& _func, Args... _args) OMNITRACE_HIDDEN;
indirect&
get_indirect()
{
static auto _v =
indirect{ get_env("OMNITRACE_LIBRARY", "libomnitrace.so"),
get_env("OMNITRACE_USER_LIBRARY", "libomnitrace-user.so") };
return _v;
}
auto&
get_active()
{
static bool _v = false;
return _v;
}
auto&
get_enabled()
{
static std::atomic<bool> _v{ get_env("OMNITRACE_INIT_ENABLED", true) };
return _v;
}
auto&
get_thread_enabled()
{
static thread_local bool _v = get_enabled();
return _v;
}
auto&
get_count()
{
static std::atomic<int64_t> _v{ 0 };
return _v;
}
auto&
get_thread_count()
{
static thread_local int64_t _v = 0;
return _v;
}
} // namespace
} // namespace dl
} // namespace omnitrace
//--------------------------------------------------------------------------------------//
#define OMNITRACE_DL_INVOKE(...) \
::omnitrace::common::invoke(__FUNCTION__, ::omnitrace::dl::_omnitrace_dl_verbose, \
__VA_ARGS__)
using omnitrace::get_indirect;
namespace dl = omnitrace::dl;
extern "C"
{
void omnitrace_init_library(void)
{
invoke(__FUNCTION__, get_indirect().omnitrace_init_library_f);
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_init_library_f);
}
void omnitrace_init(const char* a, bool b, const char* c)
{
invoke(__FUNCTION__, get_indirect().omnitrace_init_f, a, b, c);
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_init_f, a, b, c);
dl::get_active() = true;
}
void omnitrace_finalize(void)
{
invoke(__FUNCTION__, get_indirect().omnitrace_finalize_f);
dl::get_active() = false;
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_finalize_f);
}
void omnitrace_push_trace(const char* name)
{
invoke(__FUNCTION__, get_indirect().omnitrace_push_trace_f, name);
if(!dl::get_active()) return;
if(dl::get_thread_enabled())
{
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_push_trace_f, name);
}
else
{
++dl::get_thread_count();
}
}
void omnitrace_pop_trace(const char* name)
{
invoke(__FUNCTION__, get_indirect().omnitrace_pop_trace_f, name);
if(!dl::get_active()) return;
if(dl::get_thread_enabled())
{
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_pop_trace_f, name);
}
else
{
if(dl::get_thread_count()-- == 0) omnitrace_user_start_thread_trace_dl();
}
}
void omnitrace_set_env(const char* a, const char* b)
{
setenv(a, b, 0);
invoke(__FUNCTION__, get_indirect().omnitrace_set_env_f, a, b);
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_set_env_f, a, b);
}
void omnitrace_set_mpi(bool a, bool b)
{
invoke(__FUNCTION__, get_indirect().omnitrace_set_mpi_f, a, b);
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_set_mpi_f, a, b);
}
}
//--------------------------------------------------------------------------------------//
void omnitrace_user_start_trace_dl(void) { dl::get_enabled().store(true); }
void omnitrace_user_stop_trace_dl(void) { dl::get_enabled().store(false); }
void omnitrace_user_start_thread_trace_dl(void) { dl::get_thread_enabled() = true; }
void omnitrace_user_stop_thread_trace_dl(void) { dl::get_thread_enabled() = false; }
inline namespace omnitrace
{
inline namespace dl
{
namespace
{
template <typename ContainerT>
inline ContainerT
delimit(const std::string& line, const char* 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
while(_beginp < line.length() && _delimp < line.length())
void omnitrace_user_push_region_dl(const char* name)
{
// 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()) _result.emplace(_result.end(), _tmp);
if(!dl::get_active()) return;
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_push_region_f, name);
}
return _result;
}
std::string
get_env(const char* env_id, const char* _default)
{
if(strlen(env_id) == 0) return _default;
char* env_var = ::std::getenv(env_id);
if(env_var) return std::string{ env_var };
return _default;
}
int
get_env(const char* env_id, int _default)
{
if(strlen(env_id) == 0) return _default;
char* env_var = ::std::getenv(env_id);
if(env_var) return std::stoi(env_var);
return _default;
}
bool
get_env(const char* env_id, bool _default)
{
if(strlen(env_id) == 0) return _default;
char* env_var = ::std::getenv(env_id);
if(env_var)
void omnitrace_user_pop_region_dl(const char* name)
{
if(std::string{ env_var }.find_first_not_of("0123456789") == std::string::npos)
return static_cast<bool>(std::stoi(env_var));
else
{
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;
if(!dl::get_active()) return;
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_pop_region_f, name);
}
return _default;
}
int
get_omnitrace_env()
{
auto&& _debug = get_env("OMNITRACE_DEBUG", false);
return get_env("OMNITRACE_VERBOSE", (_debug) ? 100 : 0);
}
indirect&
get_indirect()
{
static auto _v = indirect{ get_env("OMNITRACE_LIBRARY", "libomnitrace.so") };
return _v;
}
int32_t&
get_guard()
{
static thread_local int32_t _v = 0;
return _v;
}
template <typename FuncT, typename... Args>
void
invoke(const char* _name, FuncT&& _func, Args... _args)
{
if(_func)
ompt_start_tool_result_t* ompt_start_tool(unsigned int omp_version,
const char* runtime_version)
{
// if _lk is ever greater than zero on the same thread, this
// means a function within the current function is calling
// our instrumentation so we ignore the call
int32_t _lk = get_guard()++;
if(_lk == 0)
{
std::invoke(std::forward<FuncT>(_func), _args...);
}
else if(_omnitrace_dl_verbose > 2)
{
fflush(stderr);
fprintf(stderr, "[omnitrace][dl] call to %s was guarded :: value = %i\n",
_name, _lk);
fflush(stderr);
}
// decrement the guard as it exits the scope
--get_guard();
}
else if(_omnitrace_dl_verbose >= 0)
{
fprintf(stderr, "[omnitrace][dl] %s\n",
join("", "null function pointer to ", _name, ". Ignoring ", _name, "(",
_args..., ")")
.c_str());
#if OMNITRACE_USE_OMPT == 0
(void) omp_version;
(void) runtime_version;
return nullptr;
#else
if(!omnitrace::common::get_env("OMNITRACE_USE_OMPT", true)) return nullptr;
return OMNITRACE_DL_INVOKE(get_indirect().ompt_start_tool_f, omp_version,
runtime_version);
#endif
}
}
} // namespace
} // namespace dl
} // namespace omnitrace
+61
Переглянути файл
@@ -0,0 +1,61 @@
# ------------------------------------------------------------------------------#
#
# omnitrace user library
#
# ------------------------------------------------------------------------------#
set(CMAKE_BUILD_TYPE "Release")
set(CMAKE_SKIP_RPATH OFF)
set(BUILD_RPATH_USE_ORIGIN ON)
set(CMAKE_CXX_VISIBILITY_PRESET "hidden")
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
add_library(omnitrace-user-library SHARED)
add_library(omnitrace::omnitrace-user-library ALIAS omnitrace-user-library)
target_sources(
omnitrace-user-library PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/user.cpp
${CMAKE_CURRENT_SOURCE_DIR}/omnitrace/user.h)
target_include_directories(
omnitrace-user-library PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
check_cxx_compiler_flag("-fno-exceptions" omnitrace_user_library_fno_exceptions)
check_cxx_compiler_flag("-ftls-model=local-dynamic"
omnitrace_user_library_ftls_module_local_dynamic)
if(OMNITRACE_BUILD_DEVELOPER)
if(omnitrace_user_library_fno_exceptions)
target_compile_options(omnitrace-user-library PRIVATE -fno-exceptions)
endif()
if(omnitrace_user_library_ftls_module_local_dynamic)
target_compile_options(omnitrace-user-library PRIVATE -ftls-model=local-dynamic)
endif()
endif()
set_target_properties(
omnitrace-user-library
PROPERTIES OUTPUT_NAME omnitrace-user
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
POSITION_INDEPENDENT_CODE ON
BUILD_RPATH "\$ORIGIN"
INSTALL_RPATH "\$ORIGIN")
install(
TARGETS omnitrace-user-library
EXPORT omnitrace-user-library-targets
DESTINATION ${CMAKE_INSTALL_LIBDIR}
OPTIONAL)
install(
FILES ${CMAKE_CURRENT_SOURCE_DIR}/omnitrace/user.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/omnitrace
OPTIONAL)
install(
EXPORT omnitrace-user-library-targets
FILE omnitrace-user-library-targets.cmake
NAMESPACE omnitrace::
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/omnitrace)
+50
Переглянути файл
@@ -0,0 +1,50 @@
// 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.
#ifndef OMNITRACE_USER_H_
#define OMNITRACE_USER_H_ 1
#define OMNITRACE_ATTRIBUTE(...) __attribute__((__VA_ARGS__))
#define OMNITRACE_VISIBILITY(MODE) OMNITRACE_ATTRIBUTE(visibility(MODE))
#define OMNITRACE_PUBLIC_API OMNITRACE_VISIBILITY("default")
#define OMNITRACE_HIDDEN_API OMNITRACE_VISIBILITY("hidden")
#if defined(__cplusplus)
extern "C"
{
#endif
extern void omnitrace_user_start_trace(void) OMNITRACE_PUBLIC_API;
extern void omnitrace_user_stop_trace(void) OMNITRACE_PUBLIC_API;
extern void omnitrace_user_start_thread_trace(void) OMNITRACE_PUBLIC_API;
extern void omnitrace_user_stop_thread_trace(void) OMNITRACE_PUBLIC_API;
extern void omnitrace_user_push_region(const char*) OMNITRACE_PUBLIC_API;
extern void omnitrace_user_pop_region(const char*) OMNITRACE_PUBLIC_API;
extern void omnitrace_user_configure(void (*)(void), void (*)(void), void (*)(void),
void (*)(void), void (*)(const char*),
void (*)(const char*)) OMNITRACE_PUBLIC_API;
#if defined(__cplusplus)
}
#endif
#endif // OMNITRACE_USER_H_
+84
Переглянути файл
@@ -0,0 +1,84 @@
// 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 OMNITRACE_SOURCE 1
#include "omnitrace/user.h"
#include <cstdio>
namespace
{
using void_func_t = void (*)(void);
using region_func_t = void (*)(const char*);
void_func_t _start_trace = nullptr;
void_func_t _stop_trace = nullptr;
void_func_t _start_thread_trace = nullptr;
void_func_t _stop_thread_trace = nullptr;
region_func_t _push_region = nullptr;
region_func_t _pop_region = nullptr;
} // namespace
extern "C"
{
void omnitrace_user_start_trace(void)
{
if(_start_trace) (*_start_trace)();
}
void omnitrace_user_stop_trace(void)
{
if(_stop_trace) (*_stop_trace)();
}
void omnitrace_user_start_thread_trace(void)
{
if(_start_thread_trace) (*_start_thread_trace)();
}
void omnitrace_user_stop_thread_trace(void)
{
if(_stop_thread_trace) (*_stop_thread_trace)();
}
void omnitrace_user_push_region(const char* name)
{
if(_push_region) (*_push_region)(name);
}
void omnitrace_user_pop_region(const char* name)
{
if(_pop_region) (*_pop_region)(name);
}
void omnitrace_user_configure(void (*_a)(), void (*_b)(), void (*_c)(), void (*_d)(),
void (*_e)(const char*), void (*_f)(const char*))
{
_start_trace = _a;
_stop_trace = _b;
_start_thread_trace = _c;
_stop_thread_trace = _d;
_push_region = _e;
_pop_region = _f;
}
}
+145
Переглянути файл
@@ -0,0 +1,145 @@
# ------------------------------------------------------------------------------#
#
# omnitrace interface library
#
# ------------------------------------------------------------------------------#
add_library(omnitrace-interface-library INTERFACE)
add_library(omnitrace::omnitrace-interface-library ALIAS omnitrace-interface-library)
target_include_directories(
omnitrace-interface-library INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_BINARY_DIR}/include)
target_include_directories(omnitrace-interface-library SYSTEM
INTERFACE ${perfetto_DIR}/sdk)
target_compile_definitions(
omnitrace-interface-library
INTERFACE OMNITRACE_MAX_THREADS=${OMNITRACE_MAX_THREADS}
$<IF:$<BOOL:${OMNITRACE_CUSTOM_DATA_SOURCE}>,CUSTOM_DATA_SOURCE,>)
target_link_libraries(
omnitrace-interface-library
INTERFACE $<BUILD_INTERFACE:omnitrace::omnitrace-headers>
$<BUILD_INTERFACE:omnitrace::omnitrace-threading>
$<BUILD_INTERFACE:omnitrace::omnitrace-compile-options>
$<BUILD_INTERFACE:omnitrace::omnitrace-hip>
$<BUILD_INTERFACE:omnitrace::omnitrace-roctracer>
$<BUILD_INTERFACE:omnitrace::omnitrace-rocm-smi>
$<BUILD_INTERFACE:omnitrace::omnitrace-mpi>
$<BUILD_INTERFACE:omnitrace::omnitrace-ptl>
$<BUILD_INTERFACE:timemory::timemory-headers>
$<BUILD_INTERFACE:timemory::timemory-gotcha>
$<BUILD_INTERFACE:timemory::timemory-cxx-static>
$<IF:$<BOOL:${OMNITRACE_USE_SANITIZER}>,omnitrace::omnitrace-sanitizer,>)
# ------------------------------------------------------------------------------#
#
# omnitrace object library
#
# ------------------------------------------------------------------------------#
add_library(omnitrace-object-library OBJECT)
add_library(omnitrace::omnitrace-object-library ALIAS omnitrace-object-library)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/library/defines.hpp.in
${CMAKE_CURRENT_BINARY_DIR}/include/library/defines.hpp @ONLY)
set(library_sources
${CMAKE_CURRENT_LIST_DIR}/src/library.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/api.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/config.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/cpu_freq.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/critical_trace.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/kokkosp.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/gpu.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/ompt.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/perfetto.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/ptl.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/sampling.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/state.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/thread_data.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/thread_sampler.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/timemory.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/backtrace.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/fork_gotcha.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/mpi_gotcha.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/omnitrace.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/pthread_gotcha.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/user_region.cpp
${perfetto_DIR}/sdk/perfetto.cc)
set(library_headers
${CMAKE_CURRENT_LIST_DIR}/include/library.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/api.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/config.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/common.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/cpu_freq.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/critical_trace.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/debug.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/gpu.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/ompt.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/perfetto.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/ptl.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/sampling.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/state.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/thread_data.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/thread_sampler.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/timemory.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/fwd.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/backtrace.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/fork_gotcha.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/functors.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/mpi_gotcha.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/omnitrace.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/rocm_smi.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/roctracer.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/roctracer_callbacks.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/pthread_gotcha.hpp
${CMAKE_CURRENT_LIST_DIR}/include/library/components/user_region.hpp
${perfetto_DIR}/sdk/perfetto.h)
target_sources(omnitrace-object-library PRIVATE ${library_sources} ${library_headers})
if(OMNITRACE_USE_ROCTRACER)
target_sources(
omnitrace-object-library
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/library/components/roctracer.cpp
${CMAKE_CURRENT_LIST_DIR}/src/library/components/roctracer_callbacks.cpp)
endif()
if(OMNITRACE_USE_ROCM_SMI)
target_sources(omnitrace-object-library
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/library/components/rocm_smi.cpp)
endif()
target_link_libraries(omnitrace-object-library PRIVATE omnitrace-interface-library)
if(OMNITRACE_DYNINST_API_RT)
get_filename_component(OMNITRACE_DYNINST_API_RT_DIR "${OMNITRACE_DYNINST_API_RT}"
DIRECTORY)
endif()
# ------------------------------------------------------------------------------#
#
# omnitrace shared library
#
# ------------------------------------------------------------------------------#
add_library(omnitrace-library SHARED $<TARGET_OBJECTS:omnitrace-object-library>)
add_library(omnitrace::omnitrace-library ALIAS omnitrace-library)
target_link_libraries(omnitrace-library PRIVATE omnitrace-interface-library)
set_target_properties(
omnitrace-library
PROPERTIES OUTPUT_NAME omnitrace
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
INSTALL_RPATH
"\$ORIGIN:\$ORIGIN/timemory/libunwind:\$ORIGIN/dyninst-tpls/libs")
install(
TARGETS omnitrace-library
DESTINATION ${CMAKE_INSTALL_LIBDIR}
OPTIONAL)
Переглянути файл
File renamed without changes.
+8
Переглянути файл
@@ -51,6 +51,12 @@ extern "C"
/// stops an instrumentation region
void omnitrace_pop_trace(const char* name) OMNITRACE_PUBLIC_API;
/// starts an instrumentation region (user-defined)
void omnitrace_push_region(const char* name) OMNITRACE_PUBLIC_API;
/// stops an instrumentation region (user-defined)
void omnitrace_pop_region(const char* name) OMNITRACE_PUBLIC_API;
// these are the real implementations for internal calling convention
void omnitrace_init_library_hidden(void) OMNITRACE_HIDDEN_API;
void omnitrace_init_hidden(const char*, bool, const char*) OMNITRACE_HIDDEN_API;
@@ -60,4 +66,6 @@ extern "C"
void omnitrace_set_mpi_hidden(bool use, bool attached) OMNITRACE_HIDDEN_API;
void omnitrace_push_trace_hidden(const char* name) OMNITRACE_HIDDEN_API;
void omnitrace_pop_trace_hidden(const char* name) OMNITRACE_HIDDEN_API;
void omnitrace_push_region_hidden(const char* name) OMNITRACE_HIDDEN_API;
void omnitrace_pop_region_hidden(const char* name) OMNITRACE_HIDDEN_API;
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -68,6 +68,7 @@ using functor_t = std::function<void(Tp...)>;
using default_functor_t = functor_t<const char*>;
struct omnitrace;
struct user_region;
struct backtrace;
struct backtrace_wall_clock
{};
@@ -126,6 +127,8 @@ TIMEMORY_DEFINE_CONCRETE_TRAIT(is_available, omnitrace::component::sampling_gpu_
TIMEMORY_SET_COMPONENT_API(omnitrace::component::omnitrace, project::omnitrace,
category::dynamic_instrumentation, os::supports_linux)
TIMEMORY_SET_COMPONENT_API(omnitrace::component::user_region, project::omnitrace,
os::supports_linux)
TIMEMORY_SET_COMPONENT_API(omnitrace::component::roctracer, project::omnitrace,
tpls::rocm, device::gpu, os::supports_linux,
category::external)
@@ -154,6 +157,8 @@ TIMEMORY_SET_COMPONENT_API(omnitrace::component::sampling_gpu_temp, project::omn
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::omnitrace, OMNITRACE_COMPONENT,
"omnitrace", "omnitrace_component")
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::user_region, OMNITRACE_USER_REGION,
"user_region", "omnitrace_user_region")
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::roctracer, OMNITRACE_ROCTRACER,
"roctracer", "omnitrace_roctracer")
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::sampling_wall_clock,
@@ -173,6 +178,15 @@ TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::sampling_gpu_power,
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::sampling_gpu_temp,
OMNITRACE_SAMPLING_GPU_TEMP, "sampling_gpu_temp", "")
TIMEMORY_METADATA_SPECIALIZATION(
omnitrace::component::omnitrace, "omnitrace",
"Invokes instrumentation functions 'omnitrace_push_trace' and 'omnitrace_pop_trace'",
"Used by gotcha wrappers")
TIMEMORY_METADATA_SPECIALIZATION(
omnitrace::component::user_region, "user_region",
"Invokes instrumentation functions 'omnitrace_user_push_region' and "
"'omnitrace_user_pop_region'",
"Used by OMPT")
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::roctracer, "roctracer",
"High-precision ROCm API and kernel tracing", "")
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::sampling_wall_clock,
File renamed without changes.
@@ -43,8 +43,3 @@ private:
};
} // namespace component
} // namespace omnitrace
TIMEMORY_METADATA_SPECIALIZATION(
omnitrace::component::omnitrace, "omnitrace",
"Invokes instrumentation functions 'omnitrace_push_trace' and 'omnitrace_pop_trace'",
"Used by gotcha wrappers")
File renamed without changes.
File renamed without changes.
File renamed without changes.
+56
Переглянути файл
@@ -0,0 +1,56 @@
// 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 "library/defines.hpp"
#include "library/timemory.hpp"
namespace omnitrace
{
namespace component
{
// timemory component which calls omnitrace functions
// (used in gotcha wrappers)
struct user_region : comp::base<user_region, void>
{
static std::string label() { return "user_region"; }
void start();
void stop();
void set_prefix(const char*);
private:
const char* m_prefix = nullptr;
};
} // namespace component
} // namespace omnitrace
TIMEMORY_COMPONENT_ALIAS(omnitrace_user_region, omnitrace::component::user_region)
#if !defined(OMNITRACE_EXTERN_COMPONENTS) || \
(defined(OMNITRACE_EXTERN_COMPONENTS) && OMNITRACE_EXTERN_COMPONENTS > 0)
# include <timemory/operations.hpp>
TIMEMORY_DECLARE_EXTERN_COMPONENT(omnitrace_user_region, false, void)
#endif
@@ -171,6 +171,9 @@ get_use_critical_trace();
bool
get_use_kokkosp();
bool
get_use_ompt();
bool
get_timeline_sampling();
@@ -245,6 +248,9 @@ get_critical_trace_per_row();
State&
get_state();
/// returns old state
State set_state(State);
std::unique_ptr<main_bundle_t>&
get_main_bundle();
File renamed without changes.
File renamed without changes.
+60 -4
Переглянути файл
@@ -30,6 +30,9 @@
#include <timemory/utility/utility.hpp>
#include <cstdio>
#include <cstring>
#include <string_view>
#include <utility>
namespace omnitrace
{
@@ -47,8 +50,32 @@ get_debug_pid();
bool
get_critical_trace_debug();
} // namespace config
namespace debug
{
namespace
{
template <typename T, size_t... Idx>
auto get_chars(std::index_sequence<Idx...>)
{
static const char _v[sizeof...(Idx) + 1] = { T::get()[Idx]..., '\0' };
return _v;
}
template <typename T>
auto
get_chars()
{
return get_chars<T>(typename T::sequence{});
}
} // namespace
} // namespace debug
} // namespace omnitrace
#define OMNITRACE_VAR_NAME_COMBINE(X, Y) X##Y
#define OMNITRACE_LINESTR TIMEMORY_STRINGIZE(__LINE__)
#define OMNITRACE_VARIABLE(LABEL) OMNITRACE_VAR_NAME_COMBINE(_omni_var_, LABEL)
#if defined(TIMEMORY_USE_MPI)
# define OMNITRACE_PROCESS_IDENTIFIER static_cast<int>(::tim::dmp::rank())
#elif defined(TIMEMORY_USE_MPI_HEADERS)
@@ -59,6 +86,26 @@ get_critical_trace_debug();
# define OMNITRACE_PROCESS_IDENTIFIER static_cast<int>(::tim::process::get_id())
#endif
#define OMNITRACE_FUNCTION \
std::string{ __FUNCTION__ } \
.substr(0, std::string_view{ __FUNCTION__ }.find("_hidden")) \
.c_str()
#define OMNITRACE_CT_FUNCTION(VAR, STR) \
static constexpr auto OMNITRACE_VARIABLE(__LINE__) = std::string_view{ STR }; \
VAR = OMNITRACE_CT_FUNCTION_IMPL(OMNITRACE_VARIABLE(__LINE__));
#define OMNITRACE_CT_FUNCTION_IMPL(STR) \
[]() { \
struct wrapper \
{ \
static constexpr const char* get() { return STR.data(); } \
using sequence = \
std::make_index_sequence<std::min(STR.find("_hidden"), STR.length())>; \
}; \
return ::omnitrace::debug::get_chars<wrapper>(); \
}();
#define OMNITRACE_CONDITIONAL_PRINT(COND, ...) \
if((COND) && ::omnitrace::config::get_debug_tid() && \
::omnitrace::config::get_debug_pid()) \
@@ -89,7 +136,7 @@ get_critical_trace_debug();
fflush(stderr); \
tim::auto_lock_t _lk{ tim::type_mutex<decltype(std::cerr)>() }; \
fprintf(stderr, "[omnitrace][%i][%li][%s] ", OMNITRACE_PROCESS_IDENTIFIER, \
tim::threading::get_id(), __FUNCTION__); \
tim::threading::get_id(), OMNITRACE_FUNCTION); \
fprintf(stderr, __VA_ARGS__); \
fflush(stderr); \
}
@@ -100,7 +147,7 @@ get_critical_trace_debug();
{ \
fflush(stderr); \
tim::auto_lock_t _lk{ tim::type_mutex<decltype(std::cerr)>() }; \
fprintf(stderr, "[omnitrace][%s] ", __FUNCTION__); \
fprintf(stderr, "[omnitrace][%s] ", OMNITRACE_FUNCTION); \
fprintf(stderr, __VA_ARGS__); \
fflush(stderr); \
}
@@ -110,7 +157,8 @@ get_critical_trace_debug();
{ \
char _msg_buffer[2048]; \
snprintf(_msg_buffer, 2048, "[omnitrace][%i][%li][%s] ", \
OMNITRACE_PROCESS_IDENTIFIER, tim::threading::get_id(), __FUNCTION__); \
OMNITRACE_PROCESS_IDENTIFIER, tim::threading::get_id(), \
OMNITRACE_FUNCTION); \
auto len = strlen(_msg_buffer); \
snprintf(_msg_buffer + len, 2048 - len, __VA_ARGS__); \
throw std::runtime_error(_msg_buffer); \
@@ -120,12 +168,20 @@ get_critical_trace_debug();
if(COND) \
{ \
char _msg_buffer[2048]; \
snprintf(_msg_buffer, 2048, "[omnitrace][%s] ", __FUNCTION__); \
snprintf(_msg_buffer, 2048, "[omnitrace][%s] ", OMNITRACE_FUNCTION); \
auto len = strlen(_msg_buffer); \
snprintf(_msg_buffer + len, 2048 - len, __VA_ARGS__); \
throw std::runtime_error(_msg_buffer); \
}
#define OMNITRACE_CI_THROW(COND, ...) \
OMNITRACE_CONDITIONAL_THROW(::omnitrace::get_is_continuous_integration() && (COND), \
__VA_ARGS__)
#define OMNITRACE_CI_BASIC_THROW(COND, ...) \
OMNITRACE_CONDITIONAL_BASIC_THROW( \
::omnitrace::get_is_continuous_integration() && (COND), __VA_ARGS__)
#define OMNITRACE_STRINGIZE(...) #__VA_ARGS__
#define OMNITRACE_ESC(...) __VA_ARGS__
@@ -36,12 +36,14 @@
// clang-format on
#define TIMEMORY_USER_COMPONENT_ENUM \
OMNITRACE_COMPONENT_idx, OMNITRACE_ROCTRACER_idx, OMNITRACE_SAMPLING_WALL_CLOCK_idx, \
OMNITRACE_SAMPLING_CPU_CLOCK_idx, OMNITRACE_SAMPLING_PERCENT_idx, \
OMNITRACE_SAMPLING_GPU_POWER_idx, OMNITRACE_SAMPLING_GPU_TEMP_idx, \
OMNITRACE_SAMPLING_GPU_BUSY_idx, OMNITRACE_SAMPLING_GPU_MEMORY_USAGE_idx,
OMNITRACE_COMPONENT_idx, OMNITRACE_USER_REGION_idx, OMNITRACE_ROCTRACER_idx, \
OMNITRACE_SAMPLING_WALL_CLOCK_idx, OMNITRACE_SAMPLING_CPU_CLOCK_idx, \
OMNITRACE_SAMPLING_PERCENT_idx, OMNITRACE_SAMPLING_GPU_POWER_idx, \
OMNITRACE_SAMPLING_GPU_TEMP_idx, OMNITRACE_SAMPLING_GPU_BUSY_idx, \
OMNITRACE_SAMPLING_GPU_MEMORY_USAGE_idx,
#define OMNITRACE_COMPONENT OMNITRACE_COMPONENT_idx
#define OMNITRACE_USER_REGION OMNITRACE_USER_REGION_idx
#define OMNITRACE_ROCTRACER OMNITRACE_ROCTRACER_idx
#define OMNITRACE_SAMPLING_WALL_CLOCK OMNITRACE_SAMPLING_WALL_CLOCK_idx
#define OMNITRACE_SAMPLING_CPU_CLOCK OMNITRACE_SAMPLING_CPU_CLOCK_idx
File renamed without changes.
Переглянути файл
File renamed without changes.
+35
Переглянути файл
@@ -0,0 +1,35 @@
// 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
namespace omnitrace
{
namespace ompt
{
void
setup();
void
shutdown();
} // namespace ompt
} // namespace omnitrace
@@ -33,6 +33,7 @@
# define PERFETTO_CATEGORIES \
perfetto::Category("host").SetDescription("Host-side function tracing"), \
perfetto::Category("device").SetDescription("Device-side function tracing"), \
perfetto::Category("user").SetDescription("User-defined regions"), \
perfetto::Category("rocm_smi").SetDescription("Device-level metrics"), \
perfetto::Category("sampling") \
.SetDescription("Metrics derived from sampling"), \
@@ -46,6 +47,7 @@
# define PERFETTO_CATEGORIES \
perfetto::Category("host").SetDescription("Host-side function tracing"), \
perfetto::Category("device").SetDescription("Device-side function tracing"), \
perfetto::Category("user").SetDescription("User-defined regions"), \
perfetto::Category("rocm_smi").SetDescription("Device-level metrics"), \
perfetto::Category("sampling") \
.SetDescription("Metrics derived from sampling"), \
Переглянути файл
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+191 -46
Переглянути файл
@@ -32,6 +32,7 @@
#include "library/debug.hpp"
#include "library/defines.hpp"
#include "library/gpu.hpp"
#include "library/ompt.hpp"
#include "library/ptl.hpp"
#include "library/sampling.hpp"
#include "library/thread_data.hpp"
@@ -46,10 +47,22 @@ using namespace omnitrace;
//======================================================================================//
using library_functors = omnitrace::component::functors<omnitrace::api::omnitrace>;
namespace
{
struct omni_regions
{};
struct user_regions
{};
} // namespace
TIMEMORY_DEFINE_NAME_TRAIT("cpu_instrumentation", library_functors);
TIMEMORY_INVOKE_PREINIT(library_functors)
using omni_functors = omnitrace::component::functors<omni_regions>;
using user_functors = omnitrace::component::functors<user_regions>;
// TIMEMORY_DEFINE_NAME_TRAIT("host", omni_functors);
// TIMEMORY_DEFINE_NAME_TRAIT("user", user_functors);
TIMEMORY_INVOKE_PREINIT(omni_functors)
TIMEMORY_INVOKE_PREINIT(user_functors)
//======================================================================================//
@@ -159,6 +172,9 @@ pop_count()
}
auto _debug_push = tim::get_env("OMNITRACE_DEBUG_PUSH", false) && !get_debug_env();
auto _debug_pop = tim::get_env("OMNITRACE_DEBUG_POP", false) && !get_debug_env();
auto _debug_user =
tim::get_env("OMNITRACE_DEBUG_USER_REGIONS", false) && !get_debug_env();
} // namespace
//======================================================================================//
@@ -172,11 +188,11 @@ omnitrace_push_trace_hidden(const char* name)
if(get_state() == State::Finalized)
{
OMNITRACE_CONDITIONAL_BASIC_PRINT(
_debug_push, "%s(%s) called during finalization\n", __FUNCTION__, name);
_debug_push, "omnitrace_push_trace(%s) called during finalization\n", name);
return;
}
OMNITRACE_CONDITIONAL_BASIC_PRINT(_debug_push, "%s(%s)\n", __FUNCTION__, name);
OMNITRACE_CONDITIONAL_BASIC_PRINT(_debug_push, "omnitrace_push_trace(%s)\n", name);
// the expectation here is that if the state is not active then the call
// to omnitrace_init_tooling_hidden will activate all the appropriate
@@ -184,12 +200,13 @@ omnitrace_push_trace_hidden(const char* name)
if(get_state() != State::Active && !omnitrace_init_tooling_hidden())
{
static auto _debug = get_debug_env() || get_debug_init();
OMNITRACE_CONDITIONAL_BASIC_PRINT_F(_debug, "%s :: not active. state = %s\n",
name, std::to_string(get_state()).c_str());
OMNITRACE_CONDITIONAL_BASIC_PRINT(
_debug, "omnitrace_push_trace(%s) ignored :: not active. state = %s\n", name,
std::to_string(get_state()).c_str());
return;
}
OMNITRACE_DEBUG_F("%s\n", name);
OMNITRACE_DEBUG("omnitrace_push_trace(%s)\n", name);
static auto _sample_rate = std::max<size_t>(get_instrumentation_interval(), 1);
static thread_local size_t _sample_idx = 0;
@@ -197,7 +214,7 @@ omnitrace_push_trace_hidden(const char* name)
auto _enabled = (_sample_idx++ % _sample_rate == 0);
_interval->emplace_back(_enabled);
if(_enabled) library_functors::start(name);
if(_enabled) omni_functors::start(name);
if(get_use_critical_trace())
{
uint64_t _cid = 0;
@@ -222,15 +239,17 @@ omnitrace_pop_trace_hidden(const char* name)
{
++pop_count();
OMNITRACE_CONDITIONAL_BASIC_PRINT(_debug_pop, "omnitrace_pop_trace(%s)\n", name);
// only execute when active
if(get_state() == State::Active)
{
OMNITRACE_DEBUG_F("%s\n", name);
OMNITRACE_DEBUG("omnitrace_pop_trace(%s)\n", name);
auto& _interval_data = get_interval_data();
if(!_interval_data->empty())
{
if(_interval_data->back()) library_functors::stop(name);
if(_interval_data->back()) omni_functors::stop(name);
_interval_data->pop_back();
}
@@ -255,9 +274,64 @@ omnitrace_pop_trace_hidden(const char* name)
else
{
static auto _debug = get_debug_env();
OMNITRACE_CONDITIONAL_BASIC_PRINT(_debug, "[%s] %s ignored :: state = %s\n",
__FUNCTION__, name,
std::to_string(get_state()).c_str());
OMNITRACE_CONDITIONAL_BASIC_PRINT(
_debug, "omnitrace_pop_trace(%s) ignored :: state = %s\n", name,
std::to_string(get_state()).c_str());
}
}
//======================================================================================//
///
///
///
//======================================================================================//
extern "C" void
omnitrace_push_region_hidden(const char* name)
{
// unconditionally return if finalized
if(get_state() == State::Finalized)
{
OMNITRACE_CONDITIONAL_BASIC_PRINT(
_debug_user, "omnitrace_push_region(%s) called during finalization\n", name);
return;
}
OMNITRACE_CONDITIONAL_BASIC_PRINT(_debug_push, "omnitrace_push_region(%s)\n", name);
// the expectation here is that if the state is not active then the call
// to omnitrace_init_tooling_hidden will activate all the appropriate
// tooling one time and as it exits set it to active and return true.
if(get_state() != State::Active && !omnitrace_init_tooling_hidden())
{
static auto _debug = get_debug_env() || get_debug_init();
OMNITRACE_CONDITIONAL_BASIC_PRINT(
_debug, "omnitrace_push_region(%s) ignored :: not active. state = %s\n", name,
std::to_string(get_state()).c_str());
return;
}
OMNITRACE_DEBUG("omnitrace_push_region(%s)\n", name);
user_functors::start(name);
}
//======================================================================================//
extern "C" void
omnitrace_pop_region_hidden(const char* name)
{
// only execute when active
if(get_state() == State::Active)
{
OMNITRACE_DEBUG("omnitrace_pop_region(%s)\n", name);
user_functors::stop(name);
}
else
{
static auto _debug = get_debug_env();
OMNITRACE_CONDITIONAL_BASIC_PRINT(
_debug, "omnitrace_pop_region(%s) ignored :: state = %s\n", name,
std::to_string(get_state()).c_str());
}
}
@@ -271,7 +345,7 @@ extern "C" void
omnitrace_set_env_hidden(const char* env_name, const char* env_val)
{
// just search env to avoid initializing the settings
OMNITRACE_CONDITIONAL_PRINT(get_debug_env() || get_verbose_env() > 2,
OMNITRACE_CONDITIONAL_PRINT(get_debug_init() || get_verbose_env() > 2,
"[%s] Setting env: %s=%s\n", __FUNCTION__, env_name,
env_val);
@@ -279,9 +353,10 @@ omnitrace_set_env_hidden(const char* env_name, const char* env_val)
OMNITRACE_CONDITIONAL_THROW(
get_state() >= State::Init &&
(config::get_is_continuous_integration() || get_debug_env()),
"%s(\"%s\", \"%s\") called after omnitrace was initialized. state = %s",
__FUNCTION__, env_name, env_val, std::to_string(get_state()).c_str());
(config::get_is_continuous_integration() || get_debug_init()),
"omnitrace_set_env(\"%s\", \"%s\") called after omnitrace was initialized. state "
"= %s",
env_name, env_val, std::to_string(get_state()).c_str());
}
//======================================================================================//
@@ -300,7 +375,7 @@ extern "C" void
omnitrace_set_mpi_hidden(bool use, bool attached)
{
// just search env to avoid initializing the settings
OMNITRACE_CONDITIONAL_PRINT(get_debug_env() || get_verbose_env() > 2,
OMNITRACE_CONDITIONAL_PRINT(get_debug_init() || get_verbose_env() > 2,
"[%s] use: %s, attached: %s\n", __FUNCTION__,
(use) ? "y" : "n", (attached) ? "y" : "n");
@@ -319,9 +394,10 @@ omnitrace_set_mpi_hidden(bool use, bool attached)
OMNITRACE_CONDITIONAL_THROW(
get_state() >= State::Init &&
(config::get_is_continuous_integration() || get_debug_env()),
"%s(use=%s, attached=%s) called after omnitrace was initialized. state = %s",
__FUNCTION__, std::to_string(use).c_str(), std::to_string(attached).c_str(),
(config::get_is_continuous_integration() || get_debug_init()),
"omnitrace_set_mpi(use=%s, attached=%s) called after omnitrace was initialized. "
"state = %s",
std::to_string(use).c_str(), std::to_string(attached).c_str(),
std::to_string(get_state()).c_str());
_start_gotcha_callback();
@@ -335,23 +411,37 @@ omnitrace_init_library_hidden()
auto _tid = threading::get_id();
(void) _tid;
auto _mode = get_mode();
auto _debug_init = get_debug_init();
static bool _once = false;
auto _mode = get_mode();
auto _debug_init = get_debug_init();
OMNITRACE_CONDITIONAL_BASIC_PRINT_F(_debug_init, "State is %s...\n",
std::to_string(get_state()).c_str());
OMNITRACE_CI_THROW(get_state() != State::PreInit, "State is not PreInit :: %s",
std::to_string(get_state()).c_str());
if(get_state() != State::PreInit || get_state() == State::Init || _once) return;
_once = true;
OMNITRACE_CONDITIONAL_BASIC_PRINT_F(_debug_init, "State is %s. Setting to %s...\n",
std::to_string(get_state()).c_str(),
std::to_string(State::Init).c_str());
OMNITRACE_CONDITIONAL_BASIC_PRINT_F(
_debug_init, "Calling backtrace once so that the one-time call of malloc in "
"glibc's backtrace() occurs...\n");
{
OMNITRACE_CONDITIONAL_BASIC_PRINT_F(
_debug_init, "Calling backtrace once so that the one-time call of malloc in "
"glibc's backtrace() occurs...\n");
std::stringstream _ss{};
tim::print_backtrace<64>(_ss);
(void) _ss;
}
get_state() = State::Init;
set_state(State::Init);
OMNITRACE_CI_THROW(get_state() != State::Init,
"set_state(State::Init) failed. state is %s",
std::to_string(get_state()).c_str());
OMNITRACE_CONDITIONAL_BASIC_PRINT_F(_debug_init, "Configuring settings...\n");
@@ -395,8 +485,9 @@ omnitrace_init_library_hidden()
if(get_use_kokkosp())
{
auto _force = 0;
if(tim::get_env<std::string>("KOKKOS_PROFILE_LIBRARY") == "libtimemory.so")
auto _force = 0;
auto _current_kokkosp_lib = tim::get_env<std::string>("KOKKOS_PROFILE_LIBRARY");
if(std::regex_search(_current_kokkosp_lib, std::regex{ "libtimemory\\." }))
_force = 1;
tim::set_env("KOKKOS_PROFILE_LIBRARY", "libomnitrace.so", _force);
}
@@ -537,8 +628,12 @@ omnitrace_init_tooling_hidden()
return true;
}();
static thread_local auto _dtor = scope::destructor{ []() {
if(get_use_sampling()) sampling::shutdown();
thread_data<omnitrace_thread_bundle_t>::instance()->stop();
if(get_state() != State::Finalized)
{
if(get_use_sampling()) sampling::shutdown();
if(thread_data<omnitrace_thread_bundle_t>::instance())
thread_data<omnitrace_thread_bundle_t>::instance()->stop();
}
} };
(void) _thread_setup;
(void) _dtor;
@@ -555,7 +650,7 @@ omnitrace_init_tooling_hidden()
(void) _v;
};
// functors for starting and stopping timemory
// functors for starting and stopping timemory omni functors
auto _push_timemory = [](const char* name) {
auto& _data = get_instrumentation_bundles();
// this generates a hash for the raw string array
@@ -566,11 +661,6 @@ omnitrace_init_tooling_hidden()
_bundle->start();
};
auto _push_perfetto = [](const char* name) {
uint64_t _ts = comp::wall_clock::record();
TRACE_EVENT_BEGIN("host", perfetto::StaticString(name), _ts);
};
auto _pop_timemory = [](const char* name) {
auto _hash = tim::hash::get_hash_id(tim::string_view_t{ name });
auto& _data = get_instrumentation_bundles();
@@ -593,14 +683,33 @@ omnitrace_init_tooling_hidden()
}
};
// functors for starting and stopping perfetto omni functors
auto _push_perfetto = [](const char* name) {
uint64_t _ts = comp::wall_clock::record();
TRACE_EVENT_BEGIN("host", perfetto::StaticString(name), _ts);
};
auto _pop_perfetto = [](const char*) {
uint64_t _ts = comp::wall_clock::record();
TRACE_EVENT_END("host", _ts);
};
// functors for starting and stopping perfetto user functors
auto _push_user_perfetto = [](const char* name) {
uint64_t _ts = comp::wall_clock::record();
TRACE_EVENT_BEGIN("user", nullptr, _ts, [name](perfetto::EventContext& _ctx) {
_ctx.event()->set_name(name);
});
};
auto _pop_user_perfetto = [](const char*) {
uint64_t _ts = comp::wall_clock::record();
TRACE_EVENT_END("user", _ts);
};
if(get_use_perfetto() && get_use_timemory())
{
library_functors::configure(
omni_functors::configure(
[=](const char* name) {
_thread_init();
_push_perfetto(name);
@@ -611,20 +720,44 @@ omnitrace_init_tooling_hidden()
_pop_timemory(name);
_pop_perfetto(name);
});
user_functors::configure(
[=](const char* name) {
_thread_init();
_push_user_perfetto(name);
_push_timemory(name);
},
[=](const char* name) {
_pop_timemory(name);
_pop_user_perfetto(name);
});
}
else if(get_use_perfetto())
{
library_functors::configure(
omni_functors::configure(
[=](const char* name) {
_thread_init();
_push_perfetto(name);
_setup_thread_sampling();
},
[=](const char* name) { _pop_perfetto(name); });
user_functors::configure(
[=](const char* name) {
_thread_init();
_push_user_perfetto(name);
_setup_thread_sampling();
},
[=](const char* name) { _pop_user_perfetto(name); });
}
else if(get_use_timemory())
{
library_functors::configure(
omni_functors::configure(
[=](const char* name) {
_thread_init();
_push_timemory(name);
_setup_thread_sampling();
},
[=](const char* name) { _pop_timemory(name); });
user_functors::configure(
[=](const char* name) {
_thread_init();
_push_timemory(name);
@@ -633,6 +766,8 @@ omnitrace_init_tooling_hidden()
[=](const char* name) { _pop_timemory(name); });
}
ompt::setup();
if(get_use_perfetto() && !is_system_backend())
{
#if defined(CUSTOM_DATA_SOURCE)
@@ -676,9 +811,16 @@ omnitrace_init_hidden(const char* _mode, bool _is_binary_rewrite, const char* _a
(void) pop_count();
get_finalization_functions().emplace_back([_argv0]() {
// if main hasn't been popped yet, pop it
OMNITRACE_BASIC_PRINT("Running omnitrace_pop_trace(%s)...\n", _argv0);
omnitrace_pop_trace_hidden(_argv0);
OMNITRACE_CI_THROW(get_state() != State::Active,
"Finalizer function for popping main invoked in non-active "
"state :: state = %s\n",
std::to_string(get_state()).c_str());
if(get_state() == State::Active)
{
// if main hasn't been popped yet, pop it
OMNITRACE_BASIC_VERBOSE(2, "Running omnitrace_pop_trace(%s)...\n", _argv0);
omnitrace_pop_trace_hidden(_argv0);
}
});
std::atexit([]() {
@@ -740,9 +882,10 @@ omnitrace_finalize_hidden(void)
}
}
get_state() = State::Finalized;
set_state(State::Finalized);
library_functors::configure([](const char*) {}, [](const char*) {});
omni_functors::configure([](const char*) {}, [](const char*) {});
user_functors::configure([](const char*) {}, [](const char*) {});
pthread_gotcha::push_enable_sampling_on_child_threads(false);
pthread_gotcha::set_sampling_on_all_future_threads(false);
@@ -785,6 +928,8 @@ omnitrace_finalize_hidden(void)
}
}
ompt::shutdown();
OMNITRACE_DEBUG_F("Stopping and destroying instrumentation bundles...\n");
for(auto& itr : instrumentation_bundles::instances())
{
+12
Переглянути файл
@@ -34,6 +34,18 @@ omnitrace_pop_trace(const char* _name)
omnitrace_pop_trace_hidden(_name);
}
extern "C" void
omnitrace_push_region(const char* _name)
{
omnitrace_push_region_hidden(_name);
}
extern "C" void
omnitrace_pop_region(const char* _name)
{
omnitrace_pop_region_hidden(_name);
}
extern "C" void
omnitrace_init_library(void)
{
@@ -231,7 +231,7 @@ backtrace::get_thread_cpu_timestamp() const
void
backtrace::sample(int signum)
{
if(get_state() != State::Active)
if(signum != -1 && get_state() != State::Active)
{
OMNITRACE_CONDITIONAL_PRINT(
get_debug_sampling(),
@@ -341,7 +341,6 @@ backtrace::configure(bool _setup, int64_t _tid)
OMNITRACE_DEBUG("Configuring sampler for thread %lu...\n", _tid);
sampler_running_instances::construct(true);
backtrace_init_instances::construct();
sampling::sampler_instances::construct("omnitrace", _tid, *_signal_types);
_sampler->set_signals(*_signal_types);
_sampler->set_flags(SA_RESTART);
@@ -363,6 +362,7 @@ backtrace::configure(bool _setup, int64_t _tid)
_sampler->get_rate(units::sec));
// (void) sampling::sampler_t::get_samplers(_tid);
backtrace_init_instances::construct();
get_backtrace_init(_tid)->sample();
_sampler->configure(false);
_sampler->start();
@@ -617,6 +617,8 @@ backtrace::post_process(int64_t _tid)
auto* _bt = ditr->get<backtrace>();
if(_bt->m_ts < _last_wall_ts) continue;
double _elapsed_wc = (_bt->m_ts - _last_wall_ts).count();
double _elapsed_cc = (_bt->m_thr_cpu_ts - _last_cpu_ts);
File renamed without changes.
@@ -86,8 +86,7 @@ mpi_gotcha::audit(const gotcha_data_t& _data, audit::incoming, int*, char***)
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug_env(), "[%s] %s(int*, char***)\n",
__FUNCTION__, _data.tool_id.c_str());
if(get_state() == ::omnitrace::State::DelayedInit)
get_state() = ::omnitrace::State::PreInit;
if(get_state() < ::omnitrace::State::Init) set_state(::omnitrace::State::PreInit);
omnitrace_push_trace_hidden(_data.tool_id.c_str());
#if !defined(TIMEMORY_USE_MPI) && defined(TIMEMORY_USE_MPI_HEADERS)
@@ -102,8 +101,8 @@ mpi_gotcha::audit(const gotcha_data_t& _data, audit::incoming, int*, char***, in
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug_env(),
"[%s] %s(int*, char***, int, int*)\n", __FUNCTION__,
_data.tool_id.c_str());
if(get_state() == ::omnitrace::State::DelayedInit)
get_state() = ::omnitrace::State::PreInit;
if(get_state() < ::omnitrace::State::Init) set_state(::omnitrace::State::PreInit);
omnitrace_push_trace_hidden(_data.tool_id.c_str());
#if !defined(TIMEMORY_USE_MPI) && defined(TIMEMORY_USE_MPI_HEADERS)
File renamed without changes.
@@ -140,6 +140,8 @@ pthread_gotcha::wrapper::operator()() const
{
_tid = threading::get_id();
threading::set_thread_name(TIMEMORY_JOIN(" ", "Thread", _tid).c_str());
// initialize thread-local statics
(void) tim::get_unw_backtrace<12, 1, false>();
{
std::unique_lock<std::mutex> _lk{ bundles_mutex };
if(comp::roctracer::is_setup())
@@ -86,7 +86,7 @@ check_error(rsmi_status_t ec)
}
std::atomic<State>&
get_rocm_smi_state()
get_state()
{
static std::atomic<State> _v{ State::PreInit };
return _v;
@@ -151,7 +151,7 @@ config()
void
sample()
{
if(get_rocm_smi_state() != State::Active) return;
if(rocm_smi::get_state() != State::Active) return;
for(auto itr : data::device_list)
{
@@ -168,63 +168,9 @@ sample()
void
set_state(State _v)
{
get_rocm_smi_state().store(_v);
rocm_smi::get_state().store(_v);
}
/*
void
data::poll(std::atomic<State>* _state, nsec_t _interval, promise_t* _ready)
{
threading::set_thread_name("omni.rocm_smi");
// notify thread started
if(_ready) _ready->set_value();
std::vector<std::unique_ptr<bundle_t>*> _bundle_data{};
_bundle_data.resize(device_count, nullptr);
for(size_t i = 0; i < device_count; ++i)
{
if(device_list.count(i) > 0)
{
_bundle_data.at(i) = &sampler_instances::instances().at(i);
if(!*_bundle_data.at(i)) *_bundle_data.at(i) = std::make_unique<bundle_t>();
}
}
OMNITRACE_CONDITIONAL_BASIC_PRINT(
get_verbose() > 0 || get_debug(),
"Polling rocm-smi for %zu device(s) at an interval of %f seconds...\n",
device_list.size(),
std::chrono::duration_cast<std::chrono::duration<double>>(_interval).count());
get_initial().resize(device_count);
for(auto itr : device_list)
get_initial().at(itr).sample(itr);
auto _now = std::chrono::steady_clock::now();
while(_state && _state->load() != State::Finalized && get_state() != State::Finalized)
{
std::this_thread::sleep_until(_now);
if(_state->load() != State::Active) continue;
for(auto itr : device_list)
{
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug(),
"Polling rocm-smi for device %u...\n", itr);
auto& _data = *_bundle_data.at(itr);
if(!_data) continue;
_data->emplace_back(data{ itr });
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug(), " %s\n",
TIMEMORY_JOIN("", _data->back()).c_str());
}
while(_now < std::chrono::steady_clock::now())
_now += _interval;
}
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug(), "Polling rocm-smi completed...\n");
if(polling_finished) polling_finished->set_value();
}
*/
std::vector<data>&
data::get_initial()
{
@@ -236,7 +182,7 @@ bool
data::setup()
{
perfetto_counter_track<data>::init();
set_state(State::PreInit);
rocm_smi::set_state(State::PreInit);
return true;
}
@@ -244,7 +190,7 @@ bool
data::shutdown()
{
OMNITRACE_DEBUG("Shutting down rocm-smi...\n");
set_state(State::Finalized);
rocm_smi::set_state(State::Finalized);
return true;
}
File renamed without changes.
File renamed without changes.
+52
Переглянути файл
@@ -0,0 +1,52 @@
// 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 "library/components/user_region.hpp"
#include "library/api.hpp"
#include "library/components/fwd.hpp"
namespace omnitrace
{
namespace component
{
void
user_region::start()
{
if(m_prefix) omnitrace_push_region_hidden(m_prefix);
}
void
user_region::stop()
{
if(m_prefix) omnitrace_pop_region_hidden(m_prefix);
}
void
user_region::set_prefix(const char* _prefix)
{
m_prefix = _prefix;
}
} // namespace component
} // namespace omnitrace
TIMEMORY_INITIALIZE_STORAGE(omnitrace::component::user_region)
TIMEMORY_INSTANTIATE_EXTERN_COMPONENT(omnitrace_user_region, false, void)
+31
Переглянути файл
@@ -150,6 +150,12 @@ configure_settings()
"Enable support for Kokkos Tools", false, "kokkos",
"backend");
#if defined(TIMEMORY_USE_OMPT)
OMNITRACE_CONFIG_SETTING(bool, "OMNITRACE_USE_OMPT",
"Enable support for OpenMP-Tools", true, "openmp", "ompt",
"backend");
#endif
OMNITRACE_CONFIG_SETTING(size_t, "OMNITRACE_INSTRUMENTATION_INTERVAL",
"Instrumentation only takes measurements once every N "
"function calls (not statistical)",
@@ -736,6 +742,17 @@ get_use_kokkosp()
return static_cast<tim::tsettings<bool>&>(*_v->second).get();
}
bool
get_use_ompt()
{
#if defined(TIMEMORY_USE_OMPT)
static auto _v = get_config()->find("OMNITRACE_USE_OMPT");
return static_cast<tim::tsettings<bool>&>(*_v->second).get();
#else
return false;
#endif
}
bool
get_critical_trace_debug()
{
@@ -956,6 +973,20 @@ get_state()
return _v;
}
State
set_state(State _n)
{
auto _o = get_state();
OMNITRACE_CONDITIONAL_PRINT_F(get_debug_init(), "Setting state :: %s -> %s\n",
std::to_string(_o).c_str(), std::to_string(_n).c_str());
// state should always be increased, not decreased
OMNITRACE_CI_BASIC_THROW(_n < _o,
"State is being assigned to a lesser value :: %s -> %s",
std::to_string(_o).c_str(), std::to_string(_n).c_str());
get_state() = _n;
return _o;
}
std::atomic<uint64_t>&
get_cpu_cid()
{
File renamed without changes.
File renamed without changes.
Переглянути файл
File renamed without changes.
+3 -4
Переглянути файл
@@ -22,10 +22,9 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// used by Kokkos decls
#if !defined(TIMEMORY_LIBRARY_SOURCE)
# define TIMEMORY_LIBRARY_SOURCE 1
#endif
#include "library/defines.hpp"
#define TIMEMORY_KOKKOSP_POSTFIX OMNITRACE_PUBLIC_API
#include "library/components/omnitrace.hpp"
#include "library/config.hpp"
+114
Переглянути файл
@@ -0,0 +1,114 @@
// 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 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 "library/defines.hpp"
#include <timemory/defines.h>
#if defined(TIMEMORY_USE_OMPT)
# include "library/components/fwd.hpp"
# include "library/components/user_region.hpp"
# include "library/config.hpp"
# include "library/debug.hpp"
# include <timemory/components/ompt.hpp>
# include <timemory/components/ompt/extern.hpp>
# include <timemory/timemory.hpp>
# include <memory>
using api_t = TIMEMORY_API;
using ompt_handle_t = tim::component::ompt_handle<api_t>;
using ompt_context_t = tim::openmp::context_handler<api_t>;
using ompt_toolset_t = typename ompt_handle_t::toolset_type;
using ompt_bundle_t = tim::component_tuple<ompt_handle_t>;
extern "C"
{
ompt_start_tool_result_t* ompt_start_tool(unsigned int,
const char*) OMNITRACE_PUBLIC_API;
}
namespace omnitrace
{
namespace ompt
{
namespace
{
std::unique_ptr<ompt_bundle_t> f_bundle = {};
bool _init_toolset_off = (trait::runtime_enabled<ompt_toolset_t>::set(false), true);
} // namespace
void
setup()
{
OMNITRACE_VERBOSE(1, "Setting up OMPT...\n");
trait::runtime_enabled<ompt_toolset_t>::set(config::get_use_ompt());
comp::user_ompt_bundle::global_init();
comp::user_ompt_bundle::reset();
// provide environment variable for enabling/disabling
if(config::get_use_ompt())
{
tim::auto_lock_t lk{ tim::type_mutex<ompt_handle_t>() };
comp::user_ompt_bundle::configure<omnitrace::component::user_region>();
f_bundle =
std::make_unique<ompt_bundle_t>("ompt", quirk::config<quirk::auto_start>{});
}
}
void
shutdown()
{
OMNITRACE_VERBOSE(1, "Shutting down OMPT...\n");
if(f_bundle)
{
f_bundle->stop();
ompt_context_t::cleanup();
trait::runtime_enabled<ompt_toolset_t>::set(false);
}
f_bundle.reset();
}
} // namespace ompt
} // namespace omnitrace
// include the ompt_start_tool definition
# include <timemory/components/ompt/start_tool.hpp>
#else
namespace omnitrace
{
namespace ompt
{
void
setup()
{}
void
shutdown()
{}
} // namespace ompt
} // namespace omnitrace
#endif
File renamed without changes.
Переглянути файл
File renamed without changes.
File renamed without changes.
Переглянути файл
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.