Add callback exception forwarding.

Modified callbacks for intercept queue, queue error, iterate agent and
iterate region.

Change-Id: I8bdd67f2312510ea7eb9caec93babca244938b40
This commit is contained in:
Sean Keely
2017-10-21 10:35:27 -05:00
förälder f312a7386e
incheckning a6d8a48cbc
6 ändrade filer med 48 tillägg och 17 borttagningar
+1 -1
Visa fil
@@ -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_;
+30
Visa fil
@@ -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();
+4 -5
Visa fil
@@ -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;