Implement priorities for cpu_thread::suspend_all tasks

Give PUTLLUC increased priority.
This commit is contained in:
Nekotekina 2020-10-17 14:30:24 +03:00
parent a90801e2aa
commit f5c575961f
3 changed files with 25 additions and 6 deletions

View File

@ -811,6 +811,9 @@ void cpu_thread::suspend_work::push(cpu_thread* _this) noexcept
// Extract queue and reverse element order (FILO to FIFO) (TODO: maybe leave order as is?) // Extract queue and reverse element order (FILO to FIFO) (TODO: maybe leave order as is?)
auto* head = queue.exchange(nullptr); auto* head = queue.exchange(nullptr);
s8 min_prio = head->prio;
s8 max_prio = head->prio;
if (auto* prev = head->next) if (auto* prev = head->next)
{ {
head->next = nullptr; head->next = nullptr;
@ -821,14 +824,26 @@ void cpu_thread::suspend_work::push(cpu_thread* _this) noexcept
prev->next = head; prev->next = head;
head = std::exchange(prev, pre2); head = std::exchange(prev, pre2);
// Fill priority range
min_prio = std::min<s8>(min_prio, head->prio);
max_prio = std::max<s8>(max_prio, head->prio);
} }
while (prev); while (prev);
} }
// Execute all stored workload // Execute all stored workload
for (; head; head = head->next) for (s32 prio = max_prio; prio >= min_prio; prio--)
{ {
head->exec(head->func_ptr, head->res_buf); // ... according to priorities
for (auto work = head; work; work = work->next)
{
// Properly sorting single-linked list may require to optimize the loop
if (work->prio == prio)
{
work->exec(work->func_ptr, work->res_buf);
}
}
} }
// Finalization // Finalization

View File

@ -123,6 +123,9 @@ public:
// For internal use // For internal use
struct suspend_work struct suspend_work
{ {
// Task priority
s8 prio;
void* func_ptr; void* func_ptr;
void* res_buf; void* res_buf;
@ -137,12 +140,12 @@ public:
}; };
// Suspend all threads and execute op (may be executed by other thread than caller!) // Suspend all threads and execute op (may be executed by other thread than caller!)
template <typename F> template <s8 Prio = 0, typename F>
static auto suspend_all(cpu_thread* _this, F op) static auto suspend_all(cpu_thread* _this, F op)
{ {
if constexpr (std::is_void_v<std::invoke_result_t<F>>) if constexpr (std::is_void_v<std::invoke_result_t<F>>)
{ {
suspend_work work{&op, nullptr, [](void* func, void*) suspend_work work{Prio, &op, nullptr, [](void* func, void*)
{ {
std::invoke(*static_cast<F*>(func)); std::invoke(*static_cast<F*>(func));
}}; }};
@ -154,7 +157,7 @@ public:
{ {
std::invoke_result_t<F> result; std::invoke_result_t<F> result;
suspend_work work{&op, &result, [](void* func, void* res_buf) suspend_work work{Prio, &op, &result, [](void* func, void* res_buf)
{ {
*static_cast<std::invoke_result_t<F>*>(res_buf) = std::invoke(*static_cast<F*>(func)); *static_cast<std::invoke_result_t<F>*>(res_buf) = std::invoke(*static_cast<F*>(func));
}}; }};

View File

@ -2200,7 +2200,8 @@ void do_cell_atomic_128_store(u32 addr, const void* to_write)
if (result == 0) if (result == 0)
{ {
cpu_thread::suspend_all(cpu, [&] // Execute with increased priority
cpu_thread::suspend_all<+1>(cpu, [&]
{ {
mov_rdata(vm::_ref<spu_rdata_t>(addr), *static_cast<const spu_rdata_t*>(to_write)); mov_rdata(vm::_ref<spu_rdata_t>(addr), *static_cast<const spu_rdata_t*>(to_write));
vm::reservation_acquire(addr, 128) += 127; vm::reservation_acquire(addr, 128) += 127;