Add callback exception forwarding.
Modified callbacks for intercept queue, queue error, iterate agent and iterate region. Change-Id: I8bdd67f2312510ea7eb9caec93babca244938b40
This commit is contained in:
@@ -379,7 +379,7 @@ class AqlQueue : public core::Queue, private core::LocalSignal, public core::Sig
|
||||
// Handle of scratch memory descriptor
|
||||
ScratchInfo queue_scratch_;
|
||||
|
||||
core::HsaEventCallback errors_callback_;
|
||||
AMD::callback_t<core::HsaEventCallback> errors_callback_;
|
||||
|
||||
void* errors_data_;
|
||||
|
||||
|
||||
@@ -62,6 +62,36 @@ class hsa_exception : public std::exception {
|
||||
std::string desc_;
|
||||
};
|
||||
|
||||
/// @brief Holds and invokes callbacks, capturing any execptions and forwarding those to the user
|
||||
/// after unwinding the runtime stack.
|
||||
template <class F> class callback_t;
|
||||
template <class R, class... Args> class callback_t<R (*)(Args...)> {
|
||||
public:
|
||||
typedef R (*func_t)(Args...);
|
||||
|
||||
callback_t() : function(nullptr) {}
|
||||
|
||||
// Should not be marked explicit.
|
||||
callback_t(func_t function_ptr) : function(function_ptr) {}
|
||||
callback_t& operator=(func_t function_ptr) { function = function_ptr; }
|
||||
|
||||
// Allows common function pointer idioms, such as if( func != nullptr )...
|
||||
// without allowing silent reversion to the original function pointer type.
|
||||
operator void*() { return reinterpret_cast<void*>(function); }
|
||||
|
||||
R operator()(Args... args) {
|
||||
try {
|
||||
return function(args...);
|
||||
} catch (...) {
|
||||
throw std::nested_exception();
|
||||
return R();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
func_t function;
|
||||
};
|
||||
|
||||
} // namespace AMD
|
||||
|
||||
#endif // HSA_RUNTIME_CORE_INC_EXCEPTIONS_H
|
||||
|
||||
@@ -184,16 +184,11 @@ class QueueProxy : public QueueWrapper {
|
||||
// Device-side dispatches are processed as an asynchronous signal event.
|
||||
class InterceptQueue : public QueueProxy, private LocalSignal, public Signal {
|
||||
public:
|
||||
// typedef void(*intercept_packet_writer)(const AqlPacket* pkts, uint64_t pkt_count);
|
||||
// typedef void(*intercept_handler)(const AqlPacket* pkts, uint64_t pkt_count, uint64_t
|
||||
// user_pkt_index, void* data, intercept_packet_writer writer);
|
||||
|
||||
std::vector<std::pair<hsa_amd_queue_intercept_handler, void*>> interceptors;
|
||||
|
||||
explicit InterceptQueue(std::unique_ptr<Queue> queue);
|
||||
~InterceptQueue();
|
||||
|
||||
void AddInterceptor(hsa_amd_queue_intercept_handler interceptor, void* data) {
|
||||
assert(interceptor != nullptr && "Packet intercept callback was nullptr.");
|
||||
interceptors.push_back(std::make_pair(interceptor, data));
|
||||
}
|
||||
|
||||
@@ -225,6 +220,9 @@ class InterceptQueue : public QueueProxy, private LocalSignal, public Signal {
|
||||
// Proxy packet buffer
|
||||
SharedArray<AqlPacket, 4096> buffer_;
|
||||
|
||||
// Packet transform callbacks
|
||||
std::vector<std::pair<AMD::callback_t<hsa_amd_queue_intercept_handler>, void*>> interceptors;
|
||||
|
||||
static const hsa_signal_value_t DOORBELL_MAX = 0xFFFFFFFFFFFFFFFFull;
|
||||
|
||||
static bool HandleAsyncDoorbell(hsa_signal_value_t value, void* arg);
|
||||
|
||||
@@ -451,8 +451,9 @@ hsa_status_t GpuAgent::IterateRegion(
|
||||
|
||||
hsa_status_t GpuAgent::IterateCache(hsa_status_t (*callback)(hsa_cache_t cache, void* data),
|
||||
void* data) const {
|
||||
AMD::callback_t<decltype(callback)> call(callback);
|
||||
for (size_t i = 0; i < caches_.size(); i++) {
|
||||
hsa_status_t stat = callback(core::Cache::Convert(caches_[i].get()), data);
|
||||
hsa_status_t stat = call(core::Cache::Convert(caches_[i].get()), data);
|
||||
if (stat != HSA_STATUS_SUCCESS) return stat;
|
||||
}
|
||||
return HSA_STATUS_SUCCESS;
|
||||
@@ -493,6 +494,7 @@ hsa_status_t GpuAgent::VisitRegion(
|
||||
const std::vector<const core::MemoryRegion*>& regions,
|
||||
hsa_status_t (*callback)(hsa_region_t region, void* data),
|
||||
void* data) const {
|
||||
AMD::callback_t<decltype(callback)> call(callback);
|
||||
for (const core::MemoryRegion* region : regions) {
|
||||
const amd::MemoryRegion* amd_region =
|
||||
reinterpret_cast<const amd::MemoryRegion*>(region);
|
||||
@@ -501,7 +503,7 @@ hsa_status_t GpuAgent::VisitRegion(
|
||||
if (amd_region->IsSystem() || amd_region->IsLocalMemory() ||
|
||||
amd_region->IsLDS()) {
|
||||
hsa_region_t region_handle = core::MemoryRegion::Convert(region);
|
||||
hsa_status_t status = callback(region_handle, data);
|
||||
hsa_status_t status = call(region_handle, data);
|
||||
if (status != HSA_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -128,17 +128,19 @@ hsa_status_t handleException() {
|
||||
try {
|
||||
throw;
|
||||
} catch (const std::bad_alloc& e) {
|
||||
debug_print("HSA exception: BadAlloc\n");
|
||||
return HSA_STATUS_ERROR_OUT_OF_RESOURCES;
|
||||
} catch (const hsa_exception& e) {
|
||||
debug_print("HSA exception: %s\n", e.what());
|
||||
return e.error_code();
|
||||
// } catch (std::nested_exception& e) { // Rethrow exceptions from callbacks
|
||||
// e.rethrow_nested();
|
||||
// return HSA_STATUS_ERROR;
|
||||
} catch (const std::exception& e) {
|
||||
debug_print("Unhandled exception: %s\n", e.what());
|
||||
assert(false && "Unhandled exception.");
|
||||
return HSA_STATUS_ERROR;
|
||||
} catch (const std::nested_exception& e) {
|
||||
debug_print("Callback threw, forwarding.\n");
|
||||
e.rethrow_nested();
|
||||
return HSA_STATUS_ERROR;
|
||||
} catch (...) {
|
||||
assert(false && "Unhandled exception.");
|
||||
abort();
|
||||
|
||||
@@ -287,15 +287,13 @@ uint32_t Runtime::GetIndexLinkInfo(uint32_t node_id_from, uint32_t node_id_to) {
|
||||
hsa_status_t Runtime::IterateAgent(hsa_status_t (*callback)(hsa_agent_t agent,
|
||||
void* data),
|
||||
void* data) {
|
||||
if (!IsOpen()) {
|
||||
return HSA_STATUS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
AMD::callback_t<decltype(callback)> call(callback);
|
||||
|
||||
std::vector<core::Agent*>* agent_lists[2] = {&cpu_agents_, &gpu_agents_};
|
||||
for (std::vector<core::Agent*>* agent_list : agent_lists) {
|
||||
for (size_t i = 0; i < agent_list->size(); ++i) {
|
||||
hsa_agent_t agent = Agent::Convert(agent_list->at(i));
|
||||
hsa_status_t status = callback(agent, data);
|
||||
hsa_status_t status = call(agent, data);
|
||||
|
||||
if (status != HSA_STATUS_SUCCESS) {
|
||||
return status;
|
||||
@@ -768,7 +766,8 @@ hsa_status_t Runtime::PtrInfo(void* ptr, hsa_amd_pointer_info_t* info, void* (*a
|
||||
count += agents_by_node_[mappedNodes[i]].size();
|
||||
}
|
||||
|
||||
*accessible = (hsa_agent_t*)alloc(sizeof(hsa_agent_t) * count);
|
||||
AMD::callback_t<decltype(alloc)> Alloc(alloc);
|
||||
*accessible = (hsa_agent_t*)Alloc(sizeof(hsa_agent_t) * count);
|
||||
if ((*accessible) == nullptr) return HSA_STATUS_ERROR_OUT_OF_RESOURCES;
|
||||
*num_agents_accessible = count;
|
||||
|
||||
|
||||
Referens i nytt ärende
Block a user