2021-07-02 16:46:49 -07:00
|
|
|
/* Copyright (c) 2019 - 2021 Advanced Micro Devices, Inc.
|
2019-10-07 11:55:30 -04:00
|
|
|
|
2020-02-04 08:45:01 -08:00
|
|
|
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:
|
2019-10-07 11:55:30 -04:00
|
|
|
|
2020-02-04 08:45:01 -08:00
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
|
all copies or substantial portions of the Software.
|
2019-10-07 11:55:30 -04:00
|
|
|
|
2020-02-04 08:45:01 -08:00
|
|
|
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. */
|
2019-10-07 11:55:30 -04:00
|
|
|
|
|
|
|
|
#ifndef HIP_SRC_HIP_PROF_API_H
|
|
|
|
|
#define HIP_SRC_HIP_PROF_API_H
|
|
|
|
|
|
|
|
|
|
#include <atomic>
|
2022-07-29 14:44:49 -07:00
|
|
|
#include <cassert>
|
2019-10-07 11:55:30 -04:00
|
|
|
#include <iostream>
|
2022-08-10 00:36:49 -07:00
|
|
|
#include <shared_mutex>
|
2022-07-29 14:44:49 -07:00
|
|
|
#include <utility>
|
2019-10-07 11:55:30 -04:00
|
|
|
|
2019-10-08 12:46:05 -04:00
|
|
|
#if USE_PROF_API
|
2020-12-15 17:38:08 -05:00
|
|
|
#include "hip/amd_detail/hip_prof_str.h"
|
2019-10-22 12:38:12 -04:00
|
|
|
#include "platform/prof_protocol.h"
|
2019-10-08 12:46:05 -04:00
|
|
|
|
|
|
|
|
// HIP API callbacks spawner object macro
|
|
|
|
|
#define HIP_CB_SPAWNER_OBJECT(CB_ID) \
|
2022-08-04 10:19:31 -07:00
|
|
|
api_callbacks_spawner_t<HIP_API_ID_##CB_ID> \
|
|
|
|
|
__api_tracer([=](auto &api_data) constexpr { INIT_CB_ARGS_DATA(CB_ID, api_data); });
|
2019-10-08 12:46:05 -04:00
|
|
|
|
|
|
|
|
class api_callbacks_table_t {
|
2019-10-07 11:55:30 -04:00
|
|
|
public:
|
2022-07-29 14:44:49 -07:00
|
|
|
api_callbacks_table_t() = default;
|
2019-10-07 11:55:30 -04:00
|
|
|
|
2022-07-29 14:44:49 -07:00
|
|
|
bool set_activity(hip_api_id_t id, activity_sync_callback_t function, void* arg) {
|
|
|
|
|
if (id < HIP_API_ID_FIRST || id > HIP_API_ID_LAST)
|
|
|
|
|
return false;
|
2019-10-07 11:55:30 -04:00
|
|
|
|
2022-08-26 22:45:00 -07:00
|
|
|
auto& entry = callbacks_table_[id];
|
|
|
|
|
std::unique_lock lock(entry.mutex);
|
|
|
|
|
|
2022-07-29 14:44:49 -07:00
|
|
|
/* 'function != nullptr' indicates it is activity register call,
|
|
|
|
|
increment should happen only once but client is free to call
|
|
|
|
|
register CB multiple times for same API id hence the check
|
2019-10-07 11:55:30 -04:00
|
|
|
|
2022-07-29 14:44:49 -07:00
|
|
|
'function == nullptr' indicates it is de-register call and
|
|
|
|
|
decrement should happen only once hence the check. */
|
|
|
|
|
|
|
|
|
|
if (function != nullptr) {
|
2022-08-26 22:45:00 -07:00
|
|
|
if (entry.activity.first == nullptr)
|
|
|
|
|
enabled_api_count_.fetch_add(1, std::memory_order_relaxed);
|
2019-10-07 11:55:30 -04:00
|
|
|
} else {
|
2022-08-26 22:45:00 -07:00
|
|
|
if (entry.activity.first != nullptr)
|
|
|
|
|
enabled_api_count_.fetch_sub(1, std::memory_order_relaxed);
|
2019-10-07 11:55:30 -04:00
|
|
|
}
|
2022-08-26 22:45:00 -07:00
|
|
|
entry.activity = {function, arg};
|
2022-07-29 14:44:49 -07:00
|
|
|
|
|
|
|
|
return true;
|
2019-10-07 11:55:30 -04:00
|
|
|
}
|
|
|
|
|
|
2022-07-29 14:44:49 -07:00
|
|
|
bool set_callback(hip_api_id_t id, activity_rtapi_callback_t function, void* arg) {
|
|
|
|
|
if (id < HIP_API_ID_FIRST || id > HIP_API_ID_LAST)
|
|
|
|
|
return false;
|
2019-10-10 20:23:33 -04:00
|
|
|
|
2022-08-26 22:45:00 -07:00
|
|
|
auto& entry = callbacks_table_[id];
|
|
|
|
|
std::unique_lock lock(entry.mutex);
|
|
|
|
|
entry.user_callback = {function, arg};
|
2019-10-07 11:55:30 -04:00
|
|
|
|
2022-07-29 14:44:49 -07:00
|
|
|
return true;
|
2019-10-07 11:55:30 -04:00
|
|
|
}
|
|
|
|
|
|
2022-08-04 10:19:31 -07:00
|
|
|
auto get(hip_api_id_t id) {
|
2022-07-29 14:44:49 -07:00
|
|
|
assert(id >= HIP_API_ID_FIRST && id <= HIP_API_ID_LAST && "invalid callback id");
|
2019-10-07 11:55:30 -04:00
|
|
|
|
2022-08-26 22:45:00 -07:00
|
|
|
auto& entry = callbacks_table_[id];
|
|
|
|
|
std::shared_lock lock(entry.mutex);
|
|
|
|
|
return std::make_pair(entry.user_callback, entry.activity);
|
2019-10-07 11:55:30 -04:00
|
|
|
}
|
|
|
|
|
|
2022-07-29 14:44:49 -07:00
|
|
|
bool is_enabled() const {
|
2022-08-26 22:45:00 -07:00
|
|
|
return enabled_api_count_.load(std::memory_order_relaxed) > 0;
|
2019-10-07 11:55:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
2022-08-26 22:45:00 -07:00
|
|
|
std::atomic<uint32_t> enabled_api_count_{0};
|
2022-07-29 14:44:49 -07:00
|
|
|
|
|
|
|
|
// HIP API callbacks table
|
2022-08-10 00:36:49 -07:00
|
|
|
struct {
|
|
|
|
|
std::shared_mutex mutex;
|
2022-07-29 14:44:49 -07:00
|
|
|
std::pair<activity_sync_callback_t, void*> activity;
|
|
|
|
|
std::pair<activity_rtapi_callback_t, void*> user_callback;
|
|
|
|
|
} callbacks_table_[HIP_API_ID_LAST + 1]{};
|
2019-10-07 11:55:30 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
extern api_callbacks_table_t callbacks_table;
|
|
|
|
|
|
2022-07-29 14:44:49 -07:00
|
|
|
template <hip_api_id_t ID>
|
2019-10-07 11:55:30 -04:00
|
|
|
class api_callbacks_spawner_t {
|
|
|
|
|
public:
|
2022-08-04 10:19:31 -07:00
|
|
|
template <typename Functor>
|
|
|
|
|
constexpr api_callbacks_spawner_t(Functor init_cb_args_data) : record_()
|
2019-10-07 11:55:30 -04:00
|
|
|
{
|
2022-07-29 14:44:49 -07:00
|
|
|
static_assert(ID >= HIP_API_ID_FIRST && ID <= HIP_API_ID_LAST, "invalid callback id");
|
|
|
|
|
if (!callbacks_table.is_enabled()) return;
|
2019-10-07 11:55:30 -04:00
|
|
|
|
2022-08-04 10:19:31 -07:00
|
|
|
std::tie(user_callback_, activity_) = callbacks_table.get(ID);
|
|
|
|
|
if (activity_.first == nullptr)
|
|
|
|
|
return;
|
2019-10-07 11:55:30 -04:00
|
|
|
|
2022-08-04 10:19:31 -07:00
|
|
|
api_data_.phase = ACTIVITY_API_PHASE_ENTER;
|
|
|
|
|
activity_.first(ID, &record_, &api_data_, activity_.second);
|
2022-08-26 22:45:00 -07:00
|
|
|
activity_prof::correlation_id = api_data_.correlation_id;
|
2019-10-07 11:55:30 -04:00
|
|
|
|
2022-08-04 10:19:31 -07:00
|
|
|
if (user_callback_.first) {
|
|
|
|
|
init_cb_args_data(api_data_);
|
|
|
|
|
user_callback_.first(ACTIVITY_DOMAIN_HIP_API, ID, &api_data_, user_callback_.second);
|
|
|
|
|
}
|
2019-10-07 11:55:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~api_callbacks_spawner_t() {
|
2022-08-04 10:19:31 -07:00
|
|
|
if (activity_.first == nullptr)
|
2022-07-29 14:44:49 -07:00
|
|
|
return;
|
2019-10-07 11:55:30 -04:00
|
|
|
|
2022-08-04 10:19:31 -07:00
|
|
|
api_data_.phase = ACTIVITY_API_PHASE_EXIT;
|
|
|
|
|
if (user_callback_.first != nullptr)
|
|
|
|
|
user_callback_.first(ACTIVITY_DOMAIN_HIP_API, ID, &api_data_, user_callback_.second);
|
2019-10-07 11:55:30 -04:00
|
|
|
|
2022-08-26 22:45:00 -07:00
|
|
|
activity_prof::correlation_id = 0;
|
2022-08-04 10:19:31 -07:00
|
|
|
activity_.first(ID, &record_, &api_data_, activity_.second);
|
2019-10-07 11:55:30 -04:00
|
|
|
}
|
|
|
|
|
|
2022-07-29 14:44:49 -07:00
|
|
|
private:
|
|
|
|
|
std::pair<activity_rtapi_callback_t /* function */, void * /* arg */> user_callback_;
|
|
|
|
|
std::pair<activity_sync_callback_t /* function */, void * /* arg */> activity_;
|
2022-08-04 10:19:31 -07:00
|
|
|
activity_record_t record_;
|
|
|
|
|
union {
|
|
|
|
|
hip_api_data_t api_data_;
|
|
|
|
|
};
|
2019-10-07 11:55:30 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <>
|
2021-06-18 22:53:35 -07:00
|
|
|
class api_callbacks_spawner_t<HIP_API_ID_NONE> {
|
2019-10-07 11:55:30 -04:00
|
|
|
public:
|
2022-08-04 10:19:31 -07:00
|
|
|
template <typename Functor>
|
|
|
|
|
api_callbacks_spawner_t(Functor) {}
|
2019-10-07 11:55:30 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
2022-08-04 10:19:31 -07:00
|
|
|
#define HIP_CB_SPAWNER_OBJECT(x) do {} while(false)
|
2019-10-07 11:55:30 -04:00
|
|
|
|
|
|
|
|
class api_callbacks_table_t {
|
|
|
|
|
public:
|
2022-07-29 14:44:49 -07:00
|
|
|
bool set_activity(hip_api_id_t, activity_sync_callback_t, void*) { return false; }
|
|
|
|
|
bool set_callback(hip_api_id_t, activity_rtapi_callback_t, void*) { return false; }
|
2019-10-07 11:55:30 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#endif // HIP_SRC_HIP_PROF_API_H
|