mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-04 22:11:26 +12:00
Partial commit: Emu (the rest)
This commit is contained in:
parent
c7738b8b37
commit
f8f067ca7c
28 changed files with 1043 additions and 4765 deletions
|
@ -1,14 +1,16 @@
|
|||
#include "stdafx.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
|
||||
#include "CPUDecoder.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "Emu/Cell/SPUThread.h"
|
||||
#include "Emu/Cell/RawSPUThread.h"
|
||||
#include "Emu/ARMv7/ARMv7Thread.h"
|
||||
#include "CPUThread.h"
|
||||
|
||||
thread_local CPUThread* g_tls_current_cpu_thread = nullptr;
|
||||
thread_local cpu_thread* g_tls_current_cpu_thread = nullptr;
|
||||
|
||||
void CPUThread::on_task()
|
||||
void cpu_thread::on_task()
|
||||
{
|
||||
g_tls_current_cpu_thread = this;
|
||||
|
||||
|
@ -16,13 +18,13 @@ void CPUThread::on_task()
|
|||
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
|
||||
// check thread status
|
||||
while (is_alive())
|
||||
// Check thread status
|
||||
while (!(state & cpu_state::exit))
|
||||
{
|
||||
CHECK_EMU_STATUS;
|
||||
|
||||
// check stop status
|
||||
if (!is_stopped())
|
||||
if (!(state & cpu_state::stop))
|
||||
{
|
||||
if (lock) lock.unlock();
|
||||
|
||||
|
@ -30,26 +32,17 @@ void CPUThread::on_task()
|
|||
{
|
||||
cpu_task();
|
||||
}
|
||||
catch (CPUThreadReturn)
|
||||
catch (cpu_state _s)
|
||||
{
|
||||
;
|
||||
state += _s;
|
||||
}
|
||||
catch (CPUThreadStop)
|
||||
catch (const std::exception&)
|
||||
{
|
||||
m_state |= CPU_STATE_STOPPED;
|
||||
}
|
||||
catch (CPUThreadExit)
|
||||
{
|
||||
m_state |= CPU_STATE_DEAD;
|
||||
break;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
dump_info();
|
||||
LOG_NOTICE(GENERAL, "\n%s", dump());
|
||||
throw;
|
||||
}
|
||||
|
||||
m_state &= ~CPU_STATE_RETURN;
|
||||
state -= cpu_state::ret;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -63,201 +56,7 @@ void CPUThread::on_task()
|
|||
}
|
||||
}
|
||||
|
||||
CPUThread::CPUThread(CPUThreadType type, const std::string& name)
|
||||
: m_id(idm::get_last_id())
|
||||
, m_type(type)
|
||||
, m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
CPUThread::~CPUThread()
|
||||
{
|
||||
Emu.SendDbgCommand(DID_REMOVE_THREAD, this);
|
||||
}
|
||||
|
||||
std::string CPUThread::get_name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
bool CPUThread::is_paused() const
|
||||
{
|
||||
return (m_state & CPU_STATE_PAUSED) != 0 || Emu.IsPaused();
|
||||
}
|
||||
|
||||
void CPUThread::dump_info() const
|
||||
{
|
||||
if (!Emu.IsStopped())
|
||||
{
|
||||
LOG_NOTICE(GENERAL, "%s", RegsToString());
|
||||
}
|
||||
}
|
||||
|
||||
void CPUThread::run()
|
||||
{
|
||||
Emu.SendDbgCommand(DID_START_THREAD, this);
|
||||
|
||||
init_stack();
|
||||
init_regs();
|
||||
do_run();
|
||||
|
||||
Emu.SendDbgCommand(DID_STARTED_THREAD, this);
|
||||
}
|
||||
|
||||
void CPUThread::pause()
|
||||
{
|
||||
Emu.SendDbgCommand(DID_PAUSE_THREAD, this);
|
||||
|
||||
m_state |= CPU_STATE_PAUSED;
|
||||
|
||||
Emu.SendDbgCommand(DID_PAUSED_THREAD, this);
|
||||
}
|
||||
|
||||
void CPUThread::resume()
|
||||
{
|
||||
Emu.SendDbgCommand(DID_RESUME_THREAD, this);
|
||||
|
||||
{
|
||||
// lock for reliable notification
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
|
||||
m_state &= ~CPU_STATE_PAUSED;
|
||||
|
||||
cv.notify_one();
|
||||
}
|
||||
|
||||
Emu.SendDbgCommand(DID_RESUMED_THREAD, this);
|
||||
}
|
||||
|
||||
void CPUThread::stop()
|
||||
{
|
||||
Emu.SendDbgCommand(DID_STOP_THREAD, this);
|
||||
|
||||
if (is_current())
|
||||
{
|
||||
throw CPUThreadStop{};
|
||||
}
|
||||
else
|
||||
{
|
||||
// lock for reliable notification
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
|
||||
m_state |= CPU_STATE_STOPPED;
|
||||
|
||||
cv.notify_one();
|
||||
}
|
||||
|
||||
Emu.SendDbgCommand(DID_STOPED_THREAD, this);
|
||||
}
|
||||
|
||||
void CPUThread::exec()
|
||||
{
|
||||
Emu.SendDbgCommand(DID_EXEC_THREAD, this);
|
||||
|
||||
m_state &= ~CPU_STATE_STOPPED;
|
||||
|
||||
{
|
||||
// lock for reliable notification
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
|
||||
cv.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
void CPUThread::exit()
|
||||
{
|
||||
m_state |= CPU_STATE_DEAD;
|
||||
|
||||
if (!is_current())
|
||||
{
|
||||
// lock for reliable notification
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
|
||||
cv.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
void CPUThread::step()
|
||||
{
|
||||
if (m_state.atomic_op([](u64& state) -> bool
|
||||
{
|
||||
const bool was_paused = (state & CPU_STATE_PAUSED) != 0;
|
||||
|
||||
state |= CPU_STATE_STEP;
|
||||
state &= ~CPU_STATE_PAUSED;
|
||||
|
||||
return was_paused;
|
||||
}))
|
||||
{
|
||||
if (is_current()) return;
|
||||
|
||||
// lock for reliable notification (only if PAUSE was removed)
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
|
||||
cv.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
void CPUThread::sleep()
|
||||
{
|
||||
m_state += CPU_STATE_MAX;
|
||||
m_state |= CPU_STATE_SLEEP;
|
||||
}
|
||||
|
||||
void CPUThread::awake()
|
||||
{
|
||||
// must be called after the balanced sleep() call
|
||||
|
||||
if (m_state.atomic_op([](u64& state) -> bool
|
||||
{
|
||||
if (state < CPU_STATE_MAX)
|
||||
{
|
||||
throw EXCEPTION("sleep()/awake() inconsistency");
|
||||
}
|
||||
|
||||
if ((state -= CPU_STATE_MAX) < CPU_STATE_MAX)
|
||||
{
|
||||
state &= ~CPU_STATE_SLEEP;
|
||||
|
||||
// notify the condition variable as well
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}))
|
||||
{
|
||||
if (is_current()) return;
|
||||
|
||||
// lock for reliable notification; the condition being checked is probably externally set
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
|
||||
cv.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
bool CPUThread::signal()
|
||||
{
|
||||
// try to set SIGNAL
|
||||
if (m_state._or(CPU_STATE_SIGNAL) & CPU_STATE_SIGNAL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// not truly responsible for signal delivery, requires additional measures like LV2_LOCK
|
||||
cv.notify_one();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool CPUThread::unsignal()
|
||||
{
|
||||
// remove SIGNAL and return its old value
|
||||
return (m_state._and_not(CPU_STATE_SIGNAL) & CPU_STATE_SIGNAL) != 0;
|
||||
}
|
||||
|
||||
bool CPUThread::check_status()
|
||||
bool cpu_thread::check_status()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex, std::defer_lock);
|
||||
|
||||
|
@ -265,12 +64,12 @@ bool CPUThread::check_status()
|
|||
{
|
||||
CHECK_EMU_STATUS; // check at least once
|
||||
|
||||
if (!is_alive())
|
||||
if (state & cpu_state::exit)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!is_paused() && (m_state & CPU_STATE_INTR) == 0)
|
||||
if (!state.test(cpu_state_pause) && !state.test(cpu_state::interrupt))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -281,7 +80,7 @@ bool CPUThread::check_status()
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!is_paused() && (m_state & CPU_STATE_INTR) != 0 && handle_interrupt())
|
||||
if (!state.test(cpu_state_pause) && state & cpu_state::interrupt && handle_interrupt())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -289,17 +88,45 @@ bool CPUThread::check_status()
|
|||
cv.wait(lock);
|
||||
}
|
||||
|
||||
if (m_state & CPU_STATE_RETURN || is_stopped())
|
||||
const auto state_ = state.load();
|
||||
|
||||
if (state_ & to_mset(cpu_state::ret, cpu_state::stop))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_state & CPU_STATE_STEP)
|
||||
if (state_ & cpu_state::dbg_step)
|
||||
{
|
||||
// set PAUSE, but allow to execute once
|
||||
m_state |= CPU_STATE_PAUSED;
|
||||
m_state &= ~CPU_STATE_STEP;
|
||||
state += cpu_state::dbg_pause;
|
||||
state -= cpu_state::dbg_step;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<cpu_thread>> get_all_cpu_threads()
|
||||
{
|
||||
std::vector<std::shared_ptr<cpu_thread>> result;
|
||||
|
||||
for (auto& t : idm::get_all<PPUThread>())
|
||||
{
|
||||
result.emplace_back(t);
|
||||
}
|
||||
|
||||
for (auto& t : idm::get_all<SPUThread>())
|
||||
{
|
||||
result.emplace_back(t);
|
||||
}
|
||||
|
||||
for (auto& t : idm::get_all<RawSPUThread>())
|
||||
{
|
||||
result.emplace_back(t);
|
||||
}
|
||||
|
||||
for (auto& t : idm::get_all<ARMv7Thread>())
|
||||
{
|
||||
result.emplace_back(t);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue