Permalink
Browse files

PPU thread scheduler

  • Loading branch information...
1 parent e496205 commit 598c90f3762e3942d7924978887d1b2d8ca3ea89 @Nekotekina Nekotekina committed Feb 6, 2017
Showing with 694 additions and 254 deletions.
  1. +14 −6 rpcs3/Emu/CPU/CPUThread.cpp
  2. +4 −7 rpcs3/Emu/CPU/CPUThread.h
  3. +4 −0 rpcs3/Emu/Cell/Modules/cellAdec.cpp
  4. +7 −0 rpcs3/Emu/Cell/Modules/cellDmux.cpp
  5. +2 −0 rpcs3/Emu/Cell/Modules/cellFs.cpp
  6. +24 −24 rpcs3/Emu/Cell/Modules/cellSpurs.cpp
  7. +9 −5 rpcs3/Emu/Cell/Modules/cellVdec.cpp
  8. +2 −0 rpcs3/Emu/Cell/Modules/libmixer.cpp
  9. +9 −9 rpcs3/Emu/Cell/Modules/sys_lwcond_.cpp
  10. +1 −1 rpcs3/Emu/Cell/Modules/sys_lwmutex_.cpp
  11. +4 −2 rpcs3/Emu/Cell/Modules/sys_ppu_thread_.cpp
  12. +11 −2 rpcs3/Emu/Cell/PPUThread.cpp
  13. +3 −1 rpcs3/Emu/Cell/PPUThread.h
  14. +176 −0 rpcs3/Emu/Cell/lv2/lv2.cpp
  15. +12 −8 rpcs3/Emu/Cell/lv2/sys_cond.cpp
  16. +3 −3 rpcs3/Emu/Cell/lv2/sys_cond.h
  17. +16 −8 rpcs3/Emu/Cell/lv2/sys_event.cpp
  18. +2 −2 rpcs3/Emu/Cell/lv2/sys_event.h
  19. +79 −50 rpcs3/Emu/Cell/lv2/sys_event_flag.cpp
  20. +1 −1 rpcs3/Emu/Cell/lv2/sys_event_flag.h
  21. +1 −0 rpcs3/Emu/Cell/lv2/sys_interrupt.cpp
  22. +27 −12 rpcs3/Emu/Cell/lv2/sys_lwcond.cpp
  23. +2 −2 rpcs3/Emu/Cell/lv2/sys_lwcond.h
  24. +12 −5 rpcs3/Emu/Cell/lv2/sys_lwmutex.cpp
  25. +1 −1 rpcs3/Emu/Cell/lv2/sys_lwmutex.h
  26. +25 −6 rpcs3/Emu/Cell/lv2/sys_mutex.cpp
  27. +1 −18 rpcs3/Emu/Cell/lv2/sys_mutex.h
  28. +148 −53 rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp
  29. +3 −3 rpcs3/Emu/Cell/lv2/sys_ppu_thread.h
  30. +26 −11 rpcs3/Emu/Cell/lv2/sys_rwlock.cpp
  31. +1 −1 rpcs3/Emu/Cell/lv2/sys_rwlock.h
  32. +12 −5 rpcs3/Emu/Cell/lv2/sys_semaphore.cpp
  33. +1 −1 rpcs3/Emu/Cell/lv2/sys_semaphore.h
  34. +4 −1 rpcs3/Emu/Cell/lv2/sys_spu.cpp
  35. +1 −1 rpcs3/Emu/Cell/lv2/sys_spu.h
  36. +35 −0 rpcs3/Emu/Cell/lv2/sys_sync.h
  37. +5 −5 rpcs3/Emu/Cell/lv2/sys_timer.cpp
  38. +2 −0 rpcs3/Emu/PSP2/ARMv7Thread.h
  39. +1 −0 rpcs3/Emu/RSX/RSXThread.cpp
  40. +2 −0 rpcs3/Emu/RSX/rsx_methods.cpp
  41. +1 −0 rpcs3/Emu/System.cpp
@@ -89,18 +89,32 @@ cpu_thread::cpu_thread(u32 id)
bool cpu_thread::check_state()
{
+ bool cpu_sleep_called = false;
+
while (true)
{
if (test(state & cpu_flag::exit))
{
return true;
}
+ if (test(state & cpu_flag::signal) && state.test_and_reset(cpu_flag::signal))
+ {
+ cpu_sleep_called = false;
+ }
+
if (!test(state & (cpu_state_pause + cpu_flag::dbg_global_stop)))
{
break;
}
+ if (test(state & cpu_flag::suspend) && !cpu_sleep_called)
+ {
+ cpu_sleep();
+ cpu_sleep_called = true;
+ continue;
+ }
+
thread_ctrl::wait();
}
@@ -126,12 +140,6 @@ void cpu_thread::run()
notify();
}
-void cpu_thread::set_signal()
-{
- verify("cpu_flag::signal" HERE), !state.test_and_set(cpu_flag::signal);
- notify();
-}
-
std::string cpu_thread::dump() const
{
return fmt::format("Type: %s\n" "State: %s\n", typeid(*this).name(), state.load());
@@ -8,7 +8,7 @@ enum class cpu_flag : u32
{
stop, // Thread not running (HLE, initial state)
exit, // Irreversible exit
- suspend, // Thread paused
+ suspend, // Thread suspended
ret, // Callback return requested
signal, // Thread received a signal (HLE)
@@ -38,18 +38,12 @@ class cpu_thread : public named_thread
// Public thread state
atomic_t<bs_t<cpu_flag>> state{+cpu_flag::stop};
- // Object associated with sleep state, possibly synchronization primitive (mutex, semaphore, etc.)
- atomic_t<void*> owner{};
-
// Process thread state, return true if the checker must return
bool check_state();
// Run thread
void run();
- // Set cpu_flag::signal
- void set_signal();
-
// Check thread type
u32 id_type()
{
@@ -64,6 +58,9 @@ class cpu_thread : public named_thread
// Thread entry point function
virtual void cpu_task() = 0;
+
+ // Callback for cpu_flag::suspend
+ virtual void cpu_sleep() {}
};
inline cpu_thread* get_current_cpu_thread() noexcept
@@ -2,6 +2,7 @@
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Emu/Cell/PPUModule.h"
+#include "Emu/Cell/lv2/sys_sync.h"
extern "C"
{
@@ -199,6 +200,7 @@ class AudioDecoder : public ppu_thread
// TODO: finalize
cellAdec.warning("adecEndSeq:");
cbFunc(*this, id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, cbArg);
+ lv2_obj::sleep(*this, -1);
just_finished = true;
break;
@@ -375,11 +377,13 @@ class AudioDecoder : public ppu_thread
{
frame.data = nullptr; // to prevent destruction
cbFunc(*this, id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, cbArg);
+ lv2_obj::sleep(*this, -1);
}
}
}
cbFunc(*this, id, CELL_ADEC_MSG_TYPE_AUDONE, task.au.auInfo_addr, cbArg);
+ lv2_obj::sleep(*this, -1);
break;
}
@@ -2,6 +2,7 @@
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Emu/Cell/PPUModule.h"
+#include "Emu/Cell/lv2/sys_sync.h"
#include "cellPamf.h"
#include "cellDmux.h"
@@ -242,6 +243,7 @@ class Demuxer : public ppu_thread
dmuxMsg->msgType = CELL_DMUX_MSG_TYPE_DEMUX_DONE;
dmuxMsg->supplementalInfo = stream.userdata;
cbFunc(*this, id, dmuxMsg, cbArg);
+ lv2_obj::sleep(*this, -1);
is_working = false;
@@ -395,6 +397,7 @@ class Demuxer : public ppu_thread
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND;
esMsg->supplementalInfo = stream.userdata;
es.cbFunc(*this, id, es.id, esMsg, es.cbArg);
+ lv2_obj::sleep(*this, -1);
}
}
else
@@ -460,6 +463,7 @@ class Demuxer : public ppu_thread
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND;
esMsg->supplementalInfo = stream.userdata;
es.cbFunc(*this, id, es.id, esMsg, es.cbArg);
+ lv2_obj::sleep(*this, -1);
}
if (pes.has_ts)
@@ -536,6 +540,7 @@ class Demuxer : public ppu_thread
dmuxMsg->msgType = CELL_DMUX_MSG_TYPE_DEMUX_DONE;
dmuxMsg->supplementalInfo = stream.userdata;
cbFunc(*this, id, dmuxMsg, cbArg);
+ lv2_obj::sleep(*this, -1);
stream = {};
@@ -624,6 +629,7 @@ class Demuxer : public ppu_thread
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND;
esMsg->supplementalInfo = stream.userdata;
es.cbFunc(*this, id, es.id, esMsg, es.cbArg);
+ lv2_obj::sleep(*this, -1);
}
if (es.raw_data.size())
@@ -636,6 +642,7 @@ class Demuxer : public ppu_thread
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_FLUSH_DONE;
esMsg->supplementalInfo = stream.userdata;
es.cbFunc(*this, id, es.id, esMsg, es.cbArg);
+ lv2_obj::sleep(*this, -1);
break;
}
@@ -4,6 +4,7 @@
#include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/lv2/sys_fs.h"
+#include "Emu/Cell/lv2/sys_sync.h"
#include "cellFs.h"
#include "Utilities/StrUtil.h"
@@ -742,6 +743,7 @@ struct fs_aio_thread : ppu_thread
}
func(*this, aio, error, xid, result);
+ lv2_obj::sleep(*this, -1);
}
}
};
@@ -84,7 +84,7 @@ namespace _spurs
s32 add_default_syswkl(vm::ptr<CellSpurs> spurs, vm::cptr<u8> swlPriority, u32 swlMaxSpu, u32 swlIsPreem);
// Destroy the SPURS SPU threads and thread group
- s32 finalize_spu(vm::ptr<CellSpurs> spurs);
+ s32 finalize_spu(ppu_thread&, vm::ptr<CellSpurs> spurs);
// Stop the event helper thread
s32 stop_event_helper(ppu_thread& ppu, vm::ptr<CellSpurs> spurs);
@@ -276,7 +276,7 @@ namespace _spurs
//s32 cellSpursEventFlagWait(ppu_thread& ppu, vm::ptr<CellSpursEventFlag> eventFlag, vm::ptr<u16> mask, u32 mode);
//s32 cellSpursEventFlagTryWait(ppu_thread& ppu, vm::ptr<CellSpursEventFlag> eventFlag, vm::ptr<u16> mask, u32 mode);
//s32 cellSpursEventFlagAttachLv2EventQueue(ppu_thread& ppu, vm::ptr<CellSpursEventFlag> eventFlag);
-//s32 cellSpursEventFlagDetachLv2EventQueue(vm::ptr<CellSpursEventFlag> eventFlag);
+//s32 cellSpursEventFlagDetachLv2EventQueue(ppu_thread& ppu, vm::ptr<CellSpursEventFlag> eventFlag);
//s32 cellSpursEventFlagGetDirection(vm::ptr<CellSpursEventFlag> eventFlag, vm::ptr<u32> direction);
//s32 cellSpursEventFlagGetClearMode(vm::ptr<CellSpursEventFlag> eventFlag, vm::ptr<u32> clear_mode);
//s32 cellSpursEventFlagGetTasksetAddress(vm::ptr<CellSpursEventFlag> eventFlag, vm::pptr<CellSpursTaskset> taskset);
@@ -380,7 +380,7 @@ s32 _spurs::create_lv2_eq(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<u32
if (s32 rc = _spurs::attach_lv2_eq(ppu, spurs, *queueId, port, 1, true))
{
- sys_event_queue_destroy(*queueId, SYS_EVENT_QUEUE_DESTROY_FORCE);
+ sys_event_queue_destroy(ppu, *queueId, SYS_EVENT_QUEUE_DESTROY_FORCE);
}
return CELL_OK;
@@ -574,7 +574,7 @@ void _spurs::handler_entry(ppu_thread& ppu, vm::ptr<CellSpurs> spurs)
CHECK_SUCCESS(sys_spu_thread_group_start(spurs->spuTG));
- if (s32 rc = sys_spu_thread_group_join(spurs->spuTG, vm::null, vm::null))
+ if (s32 rc = sys_spu_thread_group_join(ppu, spurs->spuTG, vm::null, vm::null))
{
if (rc == CELL_ESTAT)
{
@@ -674,7 +674,7 @@ s32 _spurs::wakeup_shutdown_completion_waiter(ppu_thread& ppu, vm::ptr<CellSpurs
if (!wklF->hook || wklEvent->load() & 0x10)
{
verify(HERE), (wklF->x28 == 2);
- rc = sys_semaphore_post((u32)wklF->sem, 1);
+ rc = sys_semaphore_post(ppu, (u32)wklF->sem, 1);
}
return rc;
@@ -712,11 +712,11 @@ void _spurs::event_helper_entry(ppu_thread& ppu, vm::ptr<CellSpurs> spurs)
for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++)
{
- sys_semaphore_post((u32)spurs->wklF1[i].sem, 1);
+ sys_semaphore_post(ppu, (u32)spurs->wklF1[i].sem, 1);
if (spurs->flags1 & SF1_32_WORKLOADS)
{
- sys_semaphore_post((u32)spurs->wklF2[i].sem, 1);
+ sys_semaphore_post(ppu, (u32)spurs->wklF2[i].sem, 1);
}
}
}
@@ -747,7 +747,7 @@ void _spurs::event_helper_entry(ppu_thread& ppu, vm::ptr<CellSpurs> spurs)
}
else if (data0 == 2)
{
- CHECK_SUCCESS(sys_semaphore_post((u32)spurs->semPrv, 1));
+ CHECK_SUCCESS(sys_semaphore_post(ppu, (u32)spurs->semPrv, 1));
}
else if (data0 == 3)
{
@@ -775,7 +775,7 @@ s32 _spurs::create_event_helper(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 p
return CELL_SPURS_CORE_ERROR_AGAIN;
}
- sys_event_queue_destroy(spurs->eventQueue, SYS_EVENT_QUEUE_DESTROY_FORCE);
+ sys_event_queue_destroy(ppu, spurs->eventQueue, SYS_EVENT_QUEUE_DESTROY_FORCE);
return CELL_SPURS_CORE_ERROR_AGAIN;
}
@@ -788,7 +788,7 @@ s32 _spurs::create_event_helper(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 p
return CELL_SPURS_CORE_ERROR_STAT;
}
- sys_event_queue_destroy(spurs->eventQueue, SYS_EVENT_QUEUE_DESTROY_FORCE);
+ sys_event_queue_destroy(ppu, spurs->eventQueue, SYS_EVENT_QUEUE_DESTROY_FORCE);
return CELL_SPURS_CORE_ERROR_STAT;
}
@@ -814,7 +814,7 @@ s32 _spurs::create_event_helper(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 p
return CELL_SPURS_CORE_ERROR_STAT;
}
- sys_event_queue_destroy(spurs->eventQueue, SYS_EVENT_QUEUE_DESTROY_FORCE);
+ sys_event_queue_destroy(ppu, spurs->eventQueue, SYS_EVENT_QUEUE_DESTROY_FORCE);
return CELL_SPURS_CORE_ERROR_STAT;
}
@@ -839,13 +839,13 @@ s32 _spurs::add_default_syswkl(vm::ptr<CellSpurs> spurs, vm::cptr<u8> swlPriorit
return CELL_OK;
}
-s32 _spurs::finalize_spu(vm::ptr<CellSpurs> spurs)
+s32 _spurs::finalize_spu(ppu_thread& ppu, vm::ptr<CellSpurs> spurs)
{
if (spurs->flags & SAF_UNKNOWN_FLAG_7 || spurs->flags & SAF_UNKNOWN_FLAG_8)
{
while (true)
{
- CHECK_SUCCESS(sys_spu_thread_group_join(spurs->spuTG, vm::null, vm::null));
+ CHECK_SUCCESS(sys_spu_thread_group_join(ppu, spurs->spuTG, vm::null, vm::null));
if (s32 rc = sys_spu_thread_group_destroy(spurs->spuTG))
{
@@ -880,7 +880,7 @@ s32 _spurs::stop_event_helper(ppu_thread& ppu, vm::ptr<CellSpurs> spurs)
return CELL_SPURS_CORE_ERROR_STAT;
}
- if (sys_event_port_send(spurs->eventPort, 0, 1, 0) != CELL_OK)
+ if (sys_event_port_send(ppu, spurs->eventPort, 0, 1, 0) != CELL_OK)
{
return CELL_SPURS_CORE_ERROR_STAT;
}
@@ -895,7 +895,7 @@ s32 _spurs::stop_event_helper(ppu_thread& ppu, vm::ptr<CellSpurs> spurs)
CHECK_SUCCESS(sys_event_port_disconnect(spurs->eventPort));
CHECK_SUCCESS(sys_event_port_destroy(spurs->eventPort));
CHECK_SUCCESS(_spurs::detach_lv2_eq(spurs, spurs->spuPort, true));
- CHECK_SUCCESS(sys_event_queue_destroy(spurs->eventQueue, SYS_EVENT_QUEUE_DESTROY_FORCE));
+ CHECK_SUCCESS(sys_event_queue_destroy(ppu, spurs->eventQueue, SYS_EVENT_QUEUE_DESTROY_FORCE));
return CELL_OK;
}
@@ -1141,15 +1141,15 @@ s32 _spurs::initialize(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 revision,
// Create a mutex to protect access to SPURS handler thread data
if (s32 rc = sys_lwmutex_create(lwMutex, vm::make_var(sys_lwmutex_attribute_t{ SYS_SYNC_PRIORITY, SYS_SYNC_NOT_RECURSIVE, "_spuPrv" })))
{
- _spurs::finalize_spu(spurs);
+ _spurs::finalize_spu(ppu, spurs);
return rollback(), rc;
}
// Create condition variable to signal the SPURS handler thread
if (s32 rc = sys_lwcond_create(lwCond, lwMutex, vm::make_var(sys_lwcond_attribute_t{ "_spuPrv" })))
{
sys_lwmutex_destroy(ppu, lwMutex);
- _spurs::finalize_spu(spurs);
+ _spurs::finalize_spu(ppu, spurs);
return rollback(), rc;
}
@@ -1166,7 +1166,7 @@ s32 _spurs::initialize(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 revision,
{
sys_lwcond_destroy(lwCond);
sys_lwmutex_destroy(ppu, lwMutex);
- _spurs::finalize_spu(spurs);
+ _spurs::finalize_spu(ppu, spurs);
return rollback(), rc;
}
@@ -1176,7 +1176,7 @@ s32 _spurs::initialize(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 revision,
_spurs::stop_event_helper(ppu, spurs);
sys_lwcond_destroy(lwCond);
sys_lwmutex_destroy(ppu, lwMutex);
- _spurs::finalize_spu(spurs);
+ _spurs::finalize_spu(ppu, spurs);
return rollback(), rc;
}
@@ -1188,7 +1188,7 @@ s32 _spurs::initialize(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 revision,
_spurs::stop_event_helper(ppu, spurs);
sys_lwcond_destroy(lwCond);
sys_lwmutex_destroy(ppu, lwMutex);
- _spurs::finalize_spu(spurs);
+ _spurs::finalize_spu(ppu, spurs);
return rollback(), rc;
}
@@ -2787,7 +2787,7 @@ s32 cellSpursEventFlagSet(ppu_thread& ppu, vm::ptr<CellSpursEventFlag> eventFlag
// Signal the PPU thread to be woken up
eventFlag->pendingRecvTaskEvents[ppuWaitSlot] = ppuEvents;
- CHECK_SUCCESS(sys_event_port_send(eventFlag->eventPortId, 0, 0, 0));
+ CHECK_SUCCESS(sys_event_port_send(ppu, eventFlag->eventPortId, 0, 0, 0));
}
if (pendingRecv)
@@ -3067,7 +3067,7 @@ s32 cellSpursEventFlagAttachLv2EventQueue(ppu_thread& ppu, vm::ptr<CellSpursEven
if (_spurs::detach_lv2_eq(spurs, *port, true) == CELL_OK)
{
- sys_event_queue_destroy(*eventQueueId, SYS_EVENT_QUEUE_DESTROY_FORCE);
+ sys_event_queue_destroy(ppu, *eventQueueId, SYS_EVENT_QUEUE_DESTROY_FORCE);
}
return failure(rc);
@@ -3077,7 +3077,7 @@ s32 cellSpursEventFlagAttachLv2EventQueue(ppu_thread& ppu, vm::ptr<CellSpursEven
}
/// Detach an LV2 event queue from SPURS event flag
-s32 cellSpursEventFlagDetachLv2EventQueue(vm::ptr<CellSpursEventFlag> eventFlag)
+s32 cellSpursEventFlagDetachLv2EventQueue(ppu_thread& ppu, vm::ptr<CellSpursEventFlag> eventFlag)
{
cellSpurs.warning("cellSpursEventFlagDetachLv2EventQueue(eventFlag=*0x%x)", eventFlag);
@@ -3131,7 +3131,7 @@ s32 cellSpursEventFlagDetachLv2EventQueue(vm::ptr<CellSpursEventFlag> eventFlag)
if (rc == CELL_OK)
{
- rc = sys_event_queue_destroy(eventFlag->eventQueueId, SYS_EVENT_QUEUE_DESTROY_FORCE);
+ rc = sys_event_queue_destroy(ppu, eventFlag->eventQueueId, SYS_EVENT_QUEUE_DESTROY_FORCE);
}
return CELL_OK;
Oops, something went wrong.

0 comments on commit 598c90f

Please sign in to comment.