Minor fix of sys_ppu_thread_yield return value

Account for a special case where threads were rotated but no context
switch was made.
This commit is contained in:
Eladash 2020-03-18 21:44:58 +02:00 committed by Ivan
parent 7be35315da
commit b11e8f8b8d
3 changed files with 27 additions and 9 deletions

View File

@ -1162,16 +1162,34 @@ bool lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio)
if (const auto ppu = g_ppu[i]; ppu == cpu)
{
if (g_ppu[i + 1]->prio != ppu->prio)
std::size_t j = i + 1;
for (; j < g_ppu.size(); j++)
{
if (g_ppu[j]->prio != ppu->prio)
{
break;
}
}
if (j == i + 1)
{
// Empty 'same prio' threads list
return false;
}
else
// Rotate current thread to the last position of the 'same prio' threads list
std::rotate(g_ppu.begin() + i, g_ppu.begin() + i + 1, g_ppu.begin() + j);
if (j <= g_cfg.core.ppu_threads + 0u)
{
g_ppu.erase(g_ppu.cbegin() + i);
ppu->start_time = get_guest_system_time();
break;
// Threads were rotated, but no context switch was made
return false;
}
ppu->start_time = get_guest_system_time();
cpu = nullptr; // Disable current thread enqueing, also enable threads list enqueing
break;
}
}
}
@ -1227,9 +1245,9 @@ bool lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio)
}
// Remove pending if necessary
if (!g_pending.empty() && cpu && cpu == get_current_cpu_thread())
if (!g_pending.empty() && ((cpu && cpu == get_current_cpu_thread()) || prio == yield_cmd))
{
unqueue(g_pending, cpu);
unqueue(g_pending, get_current_cpu_thread());
}
// Suspend threads if necessary

View File

@ -82,7 +82,7 @@ s32 sys_ppu_thread_yield(ppu_thread& ppu)
{
sys_ppu_thread.trace("sys_ppu_thread_yield()");
// Return 1 on no-op, 0 on successful context switch
// Return 0 on successful context switch, 1 otherwise
return +!lv2_obj::yield(ppu);
}

View File

@ -159,7 +159,7 @@ public:
return awake_unlocked(thread, prio);
}
// Returns true and success, false if did nothing
// Returns true on successful context switch, false otherwise
static bool yield(cpu_thread& thread)
{
vm::temporary_unlock(thread);