Iterates over all the arguments for the traced function (when available). This is particularly useful when tools want to annotate traces with the function arguments. See for a usage example.
Iterates over all the arguments for the traced function (when available). This is particularly useful when tools want to annotate traces with the function arguments. See for a usage example. It is recommended to use this function when the record phase is ROCPROFILER_CALLBACK_PHASE_EXIT or ROCPROFILER_CALLBACK_PHASE_NONE. When the phase is ROCPROFILER_CALLBACK_PHASE_ENTER, the function may have output parameters which have not set. In the case of an output parameter with one level of indirection, e.g. int* output_len
, this is considered safe since the output parameter is either null or, in the worst case scenario, pointing to an uninitialized value which will result in garbage values to be stringified. However, if the output parameter has more than one level of indirection, e.g. const char** output_name
, this can result in a segmentation fault because the dereferenced output parameter may be uninitialized and point to an invalid address. E.g.:
#ifdef NDEBUG
# undef NDEBUG
#endif
#include "client.hpp"
#include "common/call_stack.hpp"
#include "common/defines.hpp"
#include "common/filesystem.hpp"
#include "common/name_info.hpp"
#include <cassert>
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <mutex>
#include <ratio>
#include <string>
#include <string_view>
#include <unordered_set>
#include <vector>
namespace client
{
namespace
{
using common::call_stack_t;
using common::callback_name_info;
using common::source_location;
void
print_call_stack(const call_stack_t& _call_stack)
{
common::print_call_stack("api_callback_trace.log", _call_stack);
}
void
void* client_data)
{
{
}
{
}
}
void
void* callback_data)
{
assert(callback_data != nullptr);
auto now = std::chrono::steady_clock::now().time_since_epoch().count();
uint64_t dt = 0;
else
dt = (now - user_data->
value);
auto info = std::stringstream{};
info << std::left <<
"tid=" << record.
thread_id <<
", cid=" << std::setw(3)
<<
", operation=" << std::setw(3) << record.
operation <<
", phase=" << record.
phase
<< ", dt_nsec=" << std::setw(6) << dt;
uint32_t arg_num,
const void* const arg_value_addr,
int32_t indirection_count,
const char* arg_type,
const char* arg_name,
const char* arg_value_str,
int32_t dereference_count,
void* cb_data) -> int {
auto& dss = *static_cast<std::stringstream*>(cb_data);
dss << ((arg_num == 0) ? "(" : ", ");
dss << arg_num << ": " << arg_name << "=" << arg_value_str;
(void) arg_value_addr;
(void) arg_type;
(void) indirection_count;
(void) dereference_count;
return 0;
};
auto info_data = std::stringstream{};
record, info_data_cb, max_deref, static_cast<void*>(&info_data)),
"Failure iterating trace operation args");
auto info_data_str = info_data.str();
if(!info_data_str.empty()) info << " " << info_data_str << ")";
static auto _mutex = std::mutex{};
_mutex.lock();
static_cast<call_stack_t*>(callback_data)
->emplace_back(source_location{__FUNCTION__, __FILE__, __LINE__, info.str()});
_mutex.unlock();
}
void
{
cntrl_ctx,
nullptr,
0,
tool_tracing_ctrl_callback,
&primary_ctx),
"callback tracing service failed to configure");
}
int
{
assert(tool_data != nullptr);
auto* call_stack_v = static_cast<call_stack_t*>(tool_data);
call_stack_v->emplace_back(source_location{__FUNCTION__, __FILE__, __LINE__, ""});
callback_name_info name_info = common::get_callback_id_names();
for(const auto& itr : name_info)
{
auto name_idx = std::stringstream{};
name_idx << " [" << std::setw(3) << itr.value << "]";
call_stack_v->emplace_back(
source_location{"rocprofiler_callback_tracing_kind_names " + name_idx.str(),
__FILE__,
__LINE__,
std::string{itr.name}});
for(auto [didx, ditr] : itr.items())
{
auto operation_idx = std::stringstream{};
operation_idx << " [" << std::setw(3) << didx << "]";
call_stack_v->emplace_back(source_location{
"rocprofiler_callback_tracing_kind_operation_names" + operation_idx.str(),
__FILE__,
__LINE__,
std::string{"- "} + std::string{*ditr}});
}
}
client_fini_func = fini_func;
tool_control_init(client_ctx);
{
client_ctx, itr, nullptr, 0, tool_tracing_callback, tool_data),
"callback tracing service failed to configure");
}
ROCPROFILER_CALL(
nullptr,
0,
tool_tracing_callback,
tool_data),
"callback tracing service failed to configure");
ROCPROFILER_CALL(
nullptr,
0,
tool_tracing_callback,
tool_data),
"callback tracing service failed to configure");
ROCPROFILER_CALL(
nullptr,
0,
tool_tracing_callback,
tool_data),
"callback tracing service failed to configure");
int valid_ctx = 0;
"failure checking context validity");
if(valid_ctx == 0)
{
return -1;
}
return 0;
}
void
tool_fini(void* tool_data)
{
assert(tool_data != nullptr);
auto* _call_stack = static_cast<call_stack_t*>(tool_data);
_call_stack->emplace_back(source_location{__FUNCTION__, __FILE__, __LINE__, ""});
print_call_stack(*_call_stack);
delete _call_stack;
}
}
void
setup()
{}
void
shutdown()
{
if(client_id) client_fini_func(*client_id);
}
void
start()
{
}
void
stop()
{
int status = 0;
if(status != 0)
{
}
}
}
const char* runtime_version,
uint32_t priority,
{
id->name = "ExampleTool";
client::client_id = id;
uint32_t major = version / 10000;
uint32_t minor = (version % 10000) / 100;
uint32_t patch = version % 100;
auto info = std::stringstream{};
info <<
id->
name <<
" (priority=" << priority <<
") is using rocprofiler-sdk v" << major <<
"."
<< minor << "." << patch << " (" << runtime_version << ")";
std::clog << info.str() << std::endl;
{
auto version_info = std::array<uint32_t, 3>{};
ROCPROFILER_CALL(
"failed to get version info");
if(std::array<uint32_t, 3>{major, minor, patch} != version_info)
{
throw std::runtime_error{"version info mismatch"};
}
}
auto* client_tool_data = new std::vector<client::source_location>{};
client_tool_data->emplace_back(
client::source_location{__FUNCTION__, __FILE__, __LINE__, info.str()});
static auto cfg =
&client::tool_init,
&client::tool_fini,
static_cast<void*>(client_tool_data)};
return &cfg;
}
uint64_t value
usage example: set to process id, thread id, etc.
rocprofiler_callback_phase_t phase
rocprofiler_callback_tracing_kind_t kind
rocprofiler_thread_id_t thread_id
rocprofiler_tracing_operation_t operation
rocprofiler_correlation_id_t correlation_id
int32_t rocprofiler_tracing_operation_t
Tracing Operation ID. Depending on the kind, operations can be determined. If the value is equal to z...
rocprofiler_callback_tracing_kind_t
Service Callback Tracing Kind.
@ ROCPROFILER_CALLBACK_PHASE_EXIT
Callback invoked after to function execution.
@ ROCPROFILER_CALLBACK_PHASE_ENTER
Callback invoked prior to function execution.
@ ROCPROFILER_CALLBACK_TRACING_MARKER_CONTROL_API
@ ROCPROFILER_CALLBACK_TRACING_HSA_AMD_EXT_API
@ ROCPROFILER_CALLBACK_TRACING_MARKER_NAME_API
@ ROCPROFILER_CALLBACK_TRACING_HSA_CORE_API
@ ROCPROFILER_CALLBACK_TRACING_HIP_RUNTIME_API
@ ROCPROFILER_CALLBACK_TRACING_HSA_IMAGE_EXT_API
@ ROCPROFILER_CALLBACK_TRACING_MARKER_CORE_API
@ ROCPROFILER_CALLBACK_TRACING_HSA_FINALIZE_EXT_API
User-assignable data type.
rocprofiler_status_t rocprofiler_iterate_callback_tracing_kind_operation_args(rocprofiler_callback_tracing_record_t record, rocprofiler_callback_tracing_operation_args_cb_t callback, int32_t max_dereference_count, void *user_data)
rocprofiler_status_t rocprofiler_configure_callback_tracing_service(rocprofiler_context_id_t context_id, rocprofiler_callback_tracing_kind_t kind, const rocprofiler_tracing_operation_t *operations, unsigned long operations_count, rocprofiler_callback_tracing_cb_t callback, void *callback_args)
Configure Callback Tracing Service. The callback tracing service provides two synchronous callbacks a...
rocprofiler_status_t rocprofiler_start_context(rocprofiler_context_id_t context_id)
Start context.
rocprofiler_status_t rocprofiler_create_context(rocprofiler_context_id_t *context_id)
Create context.
rocprofiler_status_t rocprofiler_context_is_valid(rocprofiler_context_id_t context_id, int *status)
Query whether the context is valid.
rocprofiler_status_t rocprofiler_stop_context(rocprofiler_context_id_t context_id)
Stop context.
const char * name
clients should set this value for debugging
void(* rocprofiler_client_finalize_t)(rocprofiler_client_id_t)
Prototype for the function pointer provided to tool in rocprofiler_tool_initialize_t....
rocprofiler_tool_configure_result_t * rocprofiler_configure(uint32_t version, const char *runtime_version, uint32_t priority, rocprofiler_client_id_t *client_id)
This is the special function that tools define to enable rocprofiler support. The tool should return ...
rocprofiler_status_t rocprofiler_is_initialized(int *status)
Query whether rocprofiler has already scanned the binary for all the instances of rocprofiler_configu...
A client refers to an individual or entity engaged in the configuration of ROCprofiler services....
rocprofiler_status_t rocprofiler_get_version(uint32_t *major, uint32_t *minor, uint32_t *patch)
Query the version of the installed library.
@ ROCPROFILER_MARKER_CONTROL_API_ID_roctxProfilerPause
@ ROCPROFILER_MARKER_CONTROL_API_ID_roctxProfilerResume