Add return value of sys_ppu_thread_yield

This commit is contained in:
Eladash 2020-03-16 16:55:08 +02:00 committed by Ivan
parent 00d25a191b
commit 664d606123
4 changed files with 35 additions and 27 deletions

View File

@ -1133,7 +1133,7 @@ void lv2_obj::sleep_unlocked(cpu_thread& thread, u64 timeout)
}
}
void lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio)
bool lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio)
{
// Check thread type
AUDIT(!cpu || cpu->id_type() == 1);
@ -1145,7 +1145,7 @@ void lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio)
// Priority set
if (static_cast<ppu_thread*>(cpu)->prio.exchange(prio) == prio || !unqueue(g_ppu, cpu))
{
return;
return true;
}
break;
@ -1153,25 +1153,27 @@ void lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio)
case yield_cmd:
{
// Yield command
const u64 start_time = get_guest_system_time();
for (std::size_t i = 0, pos = -1; i < g_ppu.size(); i++)
for (std::size_t i = 0;; i++)
{
if (g_ppu[i] == cpu)
if (i + 1 >= g_ppu.size())
{
pos = i;
prio = g_ppu[i]->prio;
return false;
}
else if (i == pos + 1 && prio != -4 && g_ppu[i]->prio != prio)
if (const auto ppu = g_ppu[i]; ppu == cpu)
{
return;
if (g_ppu[i + 1]->prio != ppu->prio)
{
return false;
}
else
{
g_ppu.erase(g_ppu.cbegin() + i);
ppu->start_time = get_guest_system_time();
break;
}
}
}
unqueue(g_ppu, cpu);
unqueue(g_pending, cpu);
static_cast<ppu_thread*>(cpu)->start_time = start_time;
}
case enqueue_cmd:
{
@ -1186,7 +1188,7 @@ void lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio)
if (it != end && *it == cpu)
{
ppu_log.trace("sleep() - suspended (p=%zu)", g_pending.size());
return;
return false;
}
// Use priority, also preserve FIFO order
@ -1208,17 +1210,20 @@ void lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio)
}
ppu_log.trace("awake(): %s", cpu->id);
return true;
};
bool changed_queue = false;
if (cpu)
{
// Emplace current thread
emplace_thread(cpu);
changed_queue = emplace_thread(cpu);
}
else for (const auto _cpu : g_to_awake)
{
// Emplace threads from list
emplace_thread(_cpu);
changed_queue |= emplace_thread(_cpu);
}
// Remove pending if necessary
@ -1228,7 +1233,7 @@ void lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio)
}
// Suspend threads if necessary
for (std::size_t i = g_cfg.core.ppu_threads; i < g_ppu.size(); i++)
for (std::size_t i = g_cfg.core.ppu_threads; changed_queue && i < g_ppu.size(); i++)
{
const auto target = g_ppu[i];
@ -1240,6 +1245,7 @@ void lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio)
}
schedule_all();
return changed_queue;
}
void lv2_obj::cleanup()

View File

@ -78,11 +78,12 @@ void _sys_ppu_thread_exit(ppu_thread& ppu, u64 errorcode)
}
}
void sys_ppu_thread_yield(ppu_thread& ppu)
s32 sys_ppu_thread_yield(ppu_thread& ppu)
{
sys_ppu_thread.trace("sys_ppu_thread_yield()");
lv2_obj::yield(ppu);
// Return 1 on no-op, 0 on successful context switch
return +!lv2_obj::yield(ppu);
}
error_code sys_ppu_thread_join(ppu_thread& ppu, u32 thread_id, vm::ptr<u64> vptr)

View File

@ -56,7 +56,7 @@ enum : u32
// Syscalls
void _sys_ppu_thread_exit(ppu_thread& ppu, u64 errorcode);
void sys_ppu_thread_yield(ppu_thread& ppu);
s32 sys_ppu_thread_yield(ppu_thread& ppu); // Return value is ignored by the library
error_code sys_ppu_thread_join(ppu_thread& ppu, u32 thread_id, vm::ptr<u64> vptr);
error_code sys_ppu_thread_detach(u32 thread_id);
error_code sys_ppu_thread_get_join_state(ppu_thread& ppu, vm::ptr<s32> isjoinable); // Error code is ignored by the library

View File

@ -130,7 +130,7 @@ private:
static void sleep_unlocked(cpu_thread&, u64 timeout);
// Schedule the thread
static void awake_unlocked(cpu_thread*, s32 prio = enqueue_cmd);
static bool awake_unlocked(cpu_thread*, s32 prio = enqueue_cmd);
public:
static void sleep(cpu_thread& cpu, const u64 timeout = 0)
@ -140,16 +140,17 @@ public:
g_to_awake.clear();
}
static inline void awake(cpu_thread* const thread, s32 prio = enqueue_cmd)
static inline bool awake(cpu_thread* const thread, s32 prio = enqueue_cmd)
{
std::lock_guard lock(g_mutex);
awake_unlocked(thread, prio);
return awake_unlocked(thread, prio);
}
static void yield(cpu_thread& thread)
// Returns true and success, false if did nothing
static bool yield(cpu_thread& thread)
{
vm::temporary_unlock(thread);
awake(&thread, yield_cmd);
return awake(&thread, yield_cmd);
}
static void set_priority(cpu_thread& thread, s32 prio)