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