rocr: Add logic to track the age of events
Some KFD versions can return from hsaKmtWaitOnMultipleEvents_Ext without any wait and require the second call without age array init. Change-Id: I8358c33080084d47c273c2a2827085d0570c8201
This commit is contained in:
@@ -1565,12 +1565,15 @@ void Runtime::AsyncEventsLoop(void* _eventsInfo) {
|
|||||||
uint32_t unique_evts = 0;
|
uint32_t unique_evts = 0;
|
||||||
auto hsa_signals = reinterpret_cast<hsa_signal_handle*>(&async_events_.signal_[0]);
|
auto hsa_signals = reinterpret_cast<hsa_signal_handle*>(&async_events_.signal_[0]);
|
||||||
|
|
||||||
auto processEvent = [&](size_t index, hsa_signal_value_t value) {
|
auto processEvent = [&](size_t index, hsa_signal_value_t value, bool wait_any) {
|
||||||
// No error or timeout occured, process the handlers
|
// No error or timeout occured, process the handlers
|
||||||
// Call handler for the known satisfied signal.
|
// Call handler for the known satisfied signal.
|
||||||
assert(async_events_.handler_[index] != nullptr);
|
assert(async_events_.handler_[index] != nullptr);
|
||||||
bool keep = async_events_.handler_[index](value, async_events_.arg_[index]);
|
bool keep = async_events_.handler_[index](value, async_events_.arg_[index]);
|
||||||
if (!keep) {
|
if (!keep) {
|
||||||
|
if (!wait_any) {
|
||||||
|
hsa_signals[index]->WaitingDec();
|
||||||
|
}
|
||||||
hsa_signal_handle(async_events_.signal_[index])->Release();
|
hsa_signal_handle(async_events_.signal_[index])->Release();
|
||||||
async_events_.CopyIndex(index, async_events_.Size() - 1);
|
async_events_.CopyIndex(index, async_events_.Size() - 1);
|
||||||
async_events_.PopBack();
|
async_events_.PopBack();
|
||||||
@@ -1590,24 +1593,21 @@ void Runtime::AsyncEventsLoop(void* _eventsInfo) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Prepares a list of events for a wait inside KFD
|
// Prepares a list of events for a wait inside KFD
|
||||||
auto PrepareInterrupt = [&](size_t idx) {
|
auto PrepareInterrupt = [&](size_t idx, bool init_age) {
|
||||||
HsaEvent* hsa_event = hsa_signals[idx]->EopEvent();
|
HsaEvent* hsa_event = hsa_signals[idx]->EopEvent();
|
||||||
// If any signal doesn't have an interrupt, then switch to polling
|
// If any signal doesn't have an interrupt, then switch to polling
|
||||||
if (hsa_event == nullptr) {
|
if (hsa_event == nullptr) {
|
||||||
// Remove decrement from all previous events
|
|
||||||
for (int e = 0; e < idx; ++e) {
|
|
||||||
hsa_signals[e]->WaitingDec();
|
|
||||||
}
|
|
||||||
unique_evts = 0;
|
unique_evts = 0;
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
hsa_signals[idx]->WaitingInc();
|
|
||||||
if (hsa_events.size() <= unique_evts) {
|
if (hsa_events.size() <= unique_evts) {
|
||||||
hsa_events.resize(unique_evts + 10);
|
hsa_events.resize(unique_evts + 10);
|
||||||
event_age.resize(unique_evts + 10);
|
event_age.resize(unique_evts + 10);
|
||||||
}
|
}
|
||||||
hsa_events[unique_evts] = hsa_event;
|
hsa_events[unique_evts] = hsa_event;
|
||||||
event_age[unique_evts] = runtime_singleton_->KfdVersion().supports_event_age ? 1 : 0;
|
if (init_age) {
|
||||||
|
event_age[unique_evts] = runtime_singleton_->KfdVersion().supports_event_age ? 1 : 0;
|
||||||
|
}
|
||||||
unique_evts++;
|
unique_evts++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1620,9 +1620,6 @@ void Runtime::AsyncEventsLoop(void* _eventsInfo) {
|
|||||||
HsaEvent** end = std::unique(&hsa_events[0], &hsa_events[0] + unique_evts);
|
HsaEvent** end = std::unique(&hsa_events[0], &hsa_events[0] + unique_evts);
|
||||||
unique_evts = uint32_t(end - &hsa_events[0]);
|
unique_evts = uint32_t(end - &hsa_events[0]);
|
||||||
hsaKmtWaitOnMultipleEvents_Ext(&hsa_events[0], unique_evts, false, wait_ms, &event_age[0]);
|
hsaKmtWaitOnMultipleEvents_Ext(&hsa_events[0], unique_evts, false, wait_ms, &event_age[0]);
|
||||||
for (size_t i = 0; i < async_events_.Size(); i++) {
|
|
||||||
hsa_signals[i]->WaitingDec();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
while (!async_events_control_.exit) {
|
while (!async_events_control_.exit) {
|
||||||
@@ -1661,13 +1658,23 @@ void Runtime::AsyncEventsLoop(void* _eventsInfo) {
|
|||||||
hsa_signal_handle(async_events_control_.wake)->StoreRelaxed(0);
|
hsa_signal_handle(async_events_control_.wake)->StoreRelaxed(0);
|
||||||
} else if (index != -1) {
|
} else if (index != -1) {
|
||||||
if (wait_any) {
|
if (wait_any) {
|
||||||
processEvent(index, value);
|
processEvent(index, value, wait_any);
|
||||||
} else {
|
} else {
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
// Process all signals on the CPU first
|
// Process all signals on the CPU first
|
||||||
bool finish = false;
|
bool finish = false;
|
||||||
bool polling = false;
|
bool polling = false;
|
||||||
|
bool init_age = true;
|
||||||
|
|
||||||
|
// Mark all signals with a waiting tag
|
||||||
|
// @note: Waiting tag must be marked before the signal state check on CPU to
|
||||||
|
// avoid a possible race condition between KFD sleep and rocr's awake call
|
||||||
|
if (!wait_any) {
|
||||||
|
for (size_t e = 0; e < async_events_.Size(); e++) {
|
||||||
|
hsa_signals[e]->WaitingInc();
|
||||||
|
}
|
||||||
|
}
|
||||||
while (!finish) {
|
while (!finish) {
|
||||||
// If exception or WaitAny(), then finish with just one iterration
|
// If exception or WaitAny(), then finish with just one iterration
|
||||||
if (wait_any) {
|
if (wait_any) {
|
||||||
@@ -1684,28 +1691,25 @@ void Runtime::AsyncEventsLoop(void* _eventsInfo) {
|
|||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
hsa_signal_handle(async_events_control_.wake)->StoreRelaxed(0);
|
hsa_signal_handle(async_events_control_.wake)->StoreRelaxed(0);
|
||||||
} else {
|
} else {
|
||||||
if (!processEvent(i, value)) {
|
if (!processEvent(i, value, wait_any)) {
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!wait_any) {
|
if (!wait_any) {
|
||||||
finish = true;
|
finish = true;
|
||||||
|
init_age = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the current signal isn't complete and polling is disabled, then prepare KFD wait for an interrupt
|
// If the current signal isn't complete and polling is disabled, then prepare KFD wait for an interrupt
|
||||||
if (!finish && !polling) {
|
if (!finish && !polling) {
|
||||||
interrupt_wait = PrepareInterrupt(i);
|
interrupt_wait = PrepareInterrupt(i, init_age);
|
||||||
// If the interrupt was disabled, then force polling
|
// If the interrupt was disabled, then force polling
|
||||||
if (!interrupt_wait) {
|
if (!interrupt_wait) {
|
||||||
polling = true;
|
polling = true;
|
||||||
finish = false;
|
finish = false;
|
||||||
}
|
}
|
||||||
} else if (unique_evts > 0) {
|
} else if (unique_evts > 0) {
|
||||||
// Remove the waiting tag from events if we found a complete event
|
|
||||||
for (int e = 0; e < i; ++e) {
|
|
||||||
hsa_signals[e]->WaitingDec();
|
|
||||||
}
|
|
||||||
unique_evts = 0;
|
unique_evts = 0;
|
||||||
interrupt_wait = false;
|
interrupt_wait = false;
|
||||||
}
|
}
|
||||||
@@ -1713,10 +1717,18 @@ void Runtime::AsyncEventsLoop(void* _eventsInfo) {
|
|||||||
// If nothing was complete and an interrupt wait was requested, then call KFD
|
// If nothing was complete and an interrupt wait was requested, then call KFD
|
||||||
if (interrupt_wait) {
|
if (interrupt_wait) {
|
||||||
WaitForInterrupt();
|
WaitForInterrupt();
|
||||||
|
init_age = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!wait_any) {
|
||||||
|
// Remove the waiting tags from events
|
||||||
|
for (size_t e = 0; e < async_events_.Size(); e++) {
|
||||||
|
hsa_signals[e]->WaitingDec();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Insert new signals and find plain functions
|
// Insert new signals and find plain functions
|
||||||
typedef std::pair<void (*)(void*), void*> func_arg_t;
|
typedef std::pair<void (*)(void*), void*> func_arg_t;
|
||||||
std::vector<func_arg_t> functions;
|
std::vector<func_arg_t> functions;
|
||||||
|
|||||||
Reference in New Issue
Block a user