Update HSA copy table (#687)

- two copies of HSA table: internal and tracing
- internal is used to invoke HSA function without any possibility of triggering tracing, etc.
This commit is contained in:
Jonathan R. Madsen
2024-03-26 17:11:34 -05:00
committed by GitHub
parent 1addfed9f6
commit bc9f86ec62
4 changed files with 106 additions and 47 deletions
+15 -9
View File
@@ -39,8 +39,6 @@
using this_type = hsa_api_meta<table_idx, operation_idx>; \
using function_type = hsa_api_func<decltype(::HSA_FUNC)*>::function_type; \
\
static auto& get_table() { return hsa_table_lookup<table_idx>{}(); } \
\
template <typename TableT> \
static auto& get_table(TableT& _v) \
{ \
@@ -60,8 +58,6 @@
return _table.HSA_FUNC_PTR; \
} \
} \
\
static auto& get_table_func() { return get_table_func(get_table()); } \
}; \
} \
}
@@ -90,7 +86,10 @@
return offsetof(hsa_table_lookup<table_idx>::type, HSA_FUNC_PTR); \
} \
\
static auto& get_table() { return hsa_table_lookup<table_idx>{}(); } \
static auto& get_table(tracing_table) \
{ \
return hsa_table_lookup<table_idx>{}(tracing_table{}); \
} \
\
template <typename TableT> \
static auto& get_table(TableT& _v) \
@@ -112,7 +111,7 @@
} \
} \
\
static auto& get_table_func() { return get_table_func(get_table()); } \
static auto& get_table_func() { return get_table_func(get_table(tracing_table{})); } \
\
template <typename DataT> \
static auto& get_api_data_args(DataT& _data) \
@@ -165,7 +164,10 @@
return offsetof(hsa_table_lookup<table_idx>::type, HSA_FUNC_PTR); \
} \
\
static auto& get_table() { return hsa_table_lookup<table_idx>{}(); } \
static auto& get_table(tracing_table) \
{ \
return hsa_table_lookup<table_idx>{}(tracing_table{}); \
} \
\
template <typename TableT> \
static auto& get_table(TableT& _v) \
@@ -187,7 +189,7 @@
} \
} \
\
static auto& get_table_func() { return get_table_func(get_table()); } \
static auto& get_table_func() { return get_table_func(get_table(tracing_table{})); } \
\
template <typename DataT> \
static auto& get_api_data_args(DataT& _data) \
@@ -224,13 +226,17 @@
{ \
namespace hsa \
{ \
struct tracing_table; \
struct internal_table; \
\
template <> \
struct hsa_table_lookup<TABLE_ID> \
{ \
using type = TYPE; \
auto& operator()(type& _v) const { return _v; } \
auto& operator()(type* _v) const { return *_v; } \
auto& operator()() const { return (*this)(get_##NAME##_table()); } \
auto& operator()(tracing_table) const { return (*this)(get_tracing_##NAME##_table()); } \
auto& operator()(internal_table) const { return (*this)(get_##NAME##_table()); } \
}; \
\
template <> \
+61 -25
View File
@@ -108,53 +108,82 @@ DEFINE_TABLE_VERSION(img_ext, IMAGE_API)
#undef DEFINE_TABLE_VERSION
#undef DEFINE_TABLE_VERSION_IMPL
template <typename Tp>
// helper to ensure that table type is paired with the correct table version
#define GET_TABLE_IMPL(ALIAS, TYPE) \
get_table_impl<hsa_##ALIAS##_table_t, TYPE>(hsa_##ALIAS##_table_version);
template <typename Tp, typename TableT>
Tp*&
get_table_impl(hsa_table_version_t _version)
{
static_assert(common::static_object<Tp>::is_trivial_standard_layout(),
static_assert(common::static_object<Tp, TableT>::is_trivial_standard_layout(),
"This HSA API table is not a trivial, standard layout type as it should be");
auto*& val = common::static_object<Tp>::construct();
auto*& val = common::static_object<Tp, TableT>::construct();
val->version = _version;
return val;
}
} // namespace
hsa_core_table_t*
get_tracing_core_table()
{
static auto*& val = GET_TABLE_IMPL(core, tracing_table);
return val;
}
hsa_amd_ext_table_t*
get_tracing_amd_ext_table()
{
static auto*& val = GET_TABLE_IMPL(amd_ext, tracing_table);
return val;
}
hsa_fini_ext_table_t*
get_tracing_fini_ext_table()
{
static auto*& val = GET_TABLE_IMPL(fini_ext, tracing_table);
return val;
}
hsa_img_ext_table_t*
get_tracing_img_ext_table()
{
static auto*& val = GET_TABLE_IMPL(img_ext, tracing_table);
return val;
}
hsa_table_version_t
get_table_version()
{
return hsa_api_table_version;
}
// helper to ensure that table type is paired with the correct table version
#define GET_TABLE_IMPL(ALIAS) get_table_impl<hsa_##ALIAS##_table_t>(hsa_##ALIAS##_table_version);
hsa_core_table_t*
get_core_table()
{
static auto*& val = GET_TABLE_IMPL(core);
static auto*& val = GET_TABLE_IMPL(core, internal_table);
return val;
}
hsa_amd_ext_table_t*
get_amd_ext_table()
{
static auto*& val = GET_TABLE_IMPL(amd_ext);
static auto*& val = GET_TABLE_IMPL(amd_ext, internal_table);
return val;
}
hsa_fini_ext_table_t*
get_fini_ext_table()
{
static auto*& val = GET_TABLE_IMPL(fini_ext);
static auto*& val = GET_TABLE_IMPL(fini_ext, internal_table);
return val;
}
hsa_img_ext_table_t*
get_img_ext_table()
{
static auto*& val = GET_TABLE_IMPL(img_ext);
static auto*& val = GET_TABLE_IMPL(img_ext, internal_table);
return val;
}
@@ -547,7 +576,7 @@ should_wrap_functor(const context::context_array_t& _contexts,
return false;
}
template <size_t TableIdx, typename Tp, size_t OpIdx>
template <size_t TableIdx, typename LookupT = internal_table, typename Tp, size_t OpIdx>
void
copy_table(Tp* _orig, uint64_t _tbl_instance, std::integral_constant<size_t, OpIdx>)
{
@@ -567,7 +596,7 @@ copy_table(Tp* _orig, uint64_t _tbl_instance, std::integral_constant<size_t, OpI
// 3. get the sub-table containing the function pointer in saved table
// 4. get reference to function pointer in sub-table in saved table
// 5. save the original function in the saved table
auto& _copy_table = _info.get_table(hsa_table_lookup<TableIdx>{}());
auto& _copy_table = _info.get_table(hsa_table_lookup<TableIdx>{}(LookupT{}));
auto& _copy_func = _info.get_table_func(_copy_table);
LOG_IF(FATAL, _copy_func && _tbl_instance == 0)
@@ -621,13 +650,17 @@ update_table(const context::context_array_t& _contexts,
}
}
template <size_t TableIdx, typename Tp, size_t OpIdx, size_t... OpIdxTail>
template <size_t TableIdx,
typename LookupT = internal_table,
typename Tp,
size_t OpIdx,
size_t... OpIdxTail>
void
copy_table(Tp* _orig, uint64_t _tbl_instance, std::index_sequence<OpIdx, OpIdxTail...>)
{
copy_table<TableIdx>(_orig, _tbl_instance, std::integral_constant<size_t, OpIdx>{});
copy_table<TableIdx, LookupT>(_orig, _tbl_instance, std::integral_constant<size_t, OpIdx>{});
if constexpr(sizeof...(OpIdxTail) > 0)
copy_table<TableIdx>(_orig, _tbl_instance, std::index_sequence<OpIdxTail...>{});
copy_table<TableIdx, LookupT>(_orig, _tbl_instance, std::index_sequence<OpIdxTail...>{});
}
template <size_t TableIdx, typename Tp, size_t OpIdx, size_t... OpIdxTail>
@@ -702,17 +735,20 @@ copy_table(TableT* _orig, uint64_t _tbl_instance)
{
constexpr auto TableIdx = hsa_table_id_lookup<TableT>::value;
if(_orig)
copy_table<TableIdx>(
copy_table<TableIdx, internal_table>(
_orig, _tbl_instance, std::make_index_sequence<hsa_domain_info<TableIdx>::last>{});
}
template <typename TableT>
void
update_table(TableT* _orig)
update_table(TableT* _orig, uint64_t _tbl_instance)
{
constexpr auto TableIdx = hsa_table_id_lookup<TableT>::value;
if(_orig)
{
copy_table<TableIdx, tracing_table>(
_orig, _tbl_instance, std::make_index_sequence<hsa_domain_info<TableIdx>::last>{});
auto _contexts = context::get_registered_contexts();
update_table<TableIdx>(
_contexts, _orig, std::make_index_sequence<hsa_domain_info<TableIdx>::last>{});
@@ -722,14 +758,14 @@ update_table(TableT* _orig)
using iterate_args_data_t = rocprofiler_callback_tracing_hsa_api_data_t;
using iterate_args_cb_t = rocprofiler_callback_tracing_operation_args_cb_t;
#define INSTANTIATE_HSA_TABLE_FUNC(TABLE_TYPE, TABLE_IDX) \
template void copy_table<TABLE_TYPE>(TABLE_TYPE * _tbl, uint64_t _instv); \
template void update_table<TABLE_TYPE>(TABLE_TYPE * _tbl); \
template const char* name_by_id<TABLE_IDX>(uint32_t); \
template uint32_t id_by_name<TABLE_IDX>(const char*); \
template std::vector<uint32_t> get_ids<TABLE_IDX>(); \
template std::vector<const char*> get_names<TABLE_IDX>(); \
template void iterate_args<TABLE_IDX>( \
#define INSTANTIATE_HSA_TABLE_FUNC(TABLE_TYPE, TABLE_IDX) \
template void copy_table<TABLE_TYPE>(TABLE_TYPE * _tbl, uint64_t _instv); \
template void update_table<TABLE_TYPE>(TABLE_TYPE * _tbl, uint64_t _instv); \
template const char* name_by_id<TABLE_IDX>(uint32_t); \
template uint32_t id_by_name<TABLE_IDX>(const char*); \
template std::vector<uint32_t> get_ids<TABLE_IDX>(); \
template std::vector<const char*> get_names<TABLE_IDX>(); \
template void iterate_args<TABLE_IDX>( \
uint32_t, const iterate_args_data_t&, iterate_args_cb_t, int32_t, void*);
INSTANTIATE_HSA_TABLE_FUNC(hsa_core_table_t, ROCPROFILER_HSA_TABLE_ID_Core)
+19 -1
View File
@@ -32,6 +32,12 @@ namespace rocprofiler
{
namespace hsa
{
struct tracing_table
{};
struct internal_table
{};
using hsa_api_table_t = ::HsaApiTable;
using hsa_table_version_t = ::ApiTableVersion;
using hsa_core_table_t = ::CoreApiTable;
@@ -57,6 +63,18 @@ get_fini_ext_table();
hsa_img_ext_table_t*
get_img_ext_table();
hsa_core_table_t*
get_tracing_core_table();
hsa_amd_ext_table_t*
get_tracing_amd_ext_table();
hsa_fini_ext_table_t*
get_tracing_fini_ext_table();
hsa_img_ext_table_t*
get_tracing_img_ext_table();
template <size_t Idx>
struct hsa_table_lookup;
@@ -130,6 +148,6 @@ copy_table(TableT* _orig, uint64_t _tbl_instance);
template <typename TableT>
void
update_table(TableT* _orig);
update_table(TableT* _orig, uint64_t _tbl_instance);
} // namespace hsa
} // namespace rocprofiler
+11 -12
View File
@@ -718,25 +718,24 @@ rocprofiler_set_api_table(const char* name,
auto* hsa_api_table = static_cast<HsaApiTable*>(*tables);
// store a reference of the HsaApiTable implementations for invoking these functions
// without going through tracing wrappers
rocprofiler::hsa::copy_table(hsa_api_table->core_, lib_instance);
rocprofiler::hsa::copy_table(hsa_api_table->amd_ext_, lib_instance);
rocprofiler::hsa::copy_table(hsa_api_table->image_ext_, lib_instance);
rocprofiler::hsa::copy_table(hsa_api_table->finalizer_ext_, lib_instance);
// need to construct agent mappings before initializing the queue controller
rocprofiler::agent::construct_agent_cache(hsa_api_table);
rocprofiler::hsa::queue_controller_init(hsa_api_table);
rocprofiler::hsa::code_object_init(hsa_api_table);
rocprofiler::hsa::async_copy_init(hsa_api_table, lib_instance);
// any internal modifications to the HsaApiTable need to be done before we make the
// copy or else those modifications will be lost when HSA API tracing is enabled
// because the HSA API tracing invokes the function pointers from the copy below
rocprofiler::hsa::copy_table(hsa_api_table->core_, lib_instance);
rocprofiler::hsa::copy_table(hsa_api_table->amd_ext_, lib_instance);
rocprofiler::hsa::copy_table(hsa_api_table->image_ext_, lib_instance);
rocprofiler::hsa::copy_table(hsa_api_table->finalizer_ext_, lib_instance);
// install rocprofiler API wrappers
rocprofiler::hsa::update_table(hsa_api_table->core_);
rocprofiler::hsa::update_table(hsa_api_table->amd_ext_);
rocprofiler::hsa::update_table(hsa_api_table->image_ext_);
rocprofiler::hsa::update_table(hsa_api_table->finalizer_ext_);
rocprofiler::hsa::update_table(hsa_api_table->core_, lib_instance);
rocprofiler::hsa::update_table(hsa_api_table->amd_ext_, lib_instance);
rocprofiler::hsa::update_table(hsa_api_table->image_ext_, lib_instance);
rocprofiler::hsa::update_table(hsa_api_table->finalizer_ext_, lib_instance);
// allow tools to install API wrappers
rocprofiler::intercept_table::notify_intercept_table_registration(