mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-04 05:51:27 +12:00
SPU: cleanup former OOM handling
Remove cpu_flag::jit_return. It's obsolete now, and worked only in SPU ASMJIT anyway.
This commit is contained in:
parent
7a32af7a57
commit
9ac6ef6494
7 changed files with 46 additions and 192 deletions
|
@ -30,7 +30,6 @@ void fmt_class_string<cpu_flag>::format(std::string& out, u64 arg)
|
||||||
case cpu_flag::ret: return "ret";
|
case cpu_flag::ret: return "ret";
|
||||||
case cpu_flag::signal: return "sig";
|
case cpu_flag::signal: return "sig";
|
||||||
case cpu_flag::memory: return "mem";
|
case cpu_flag::memory: return "mem";
|
||||||
case cpu_flag::jit_return: return "JIT";
|
|
||||||
case cpu_flag::dbg_global_pause: return "G-PAUSE";
|
case cpu_flag::dbg_global_pause: return "G-PAUSE";
|
||||||
case cpu_flag::dbg_global_stop: return "G-EXIT";
|
case cpu_flag::dbg_global_stop: return "G-EXIT";
|
||||||
case cpu_flag::dbg_pause: return "PAUSE";
|
case cpu_flag::dbg_pause: return "PAUSE";
|
||||||
|
@ -423,7 +422,7 @@ bool cpu_thread::check_state() noexcept
|
||||||
state -= cpu_flag::memory;
|
state -= cpu_flag::memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state & (cpu_flag::exit + cpu_flag::jit_return + cpu_flag::dbg_global_stop))
|
if (state & (cpu_flag::exit + cpu_flag::dbg_global_stop))
|
||||||
{
|
{
|
||||||
state += cpu_flag::wait;
|
state += cpu_flag::wait;
|
||||||
return true;
|
return true;
|
||||||
|
@ -432,7 +431,7 @@ bool cpu_thread::check_state() noexcept
|
||||||
const auto [state0, escape] = state.fetch_op([&](bs_t<cpu_flag>& flags)
|
const auto [state0, escape] = state.fetch_op([&](bs_t<cpu_flag>& flags)
|
||||||
{
|
{
|
||||||
// Atomically clean wait flag and escape
|
// Atomically clean wait flag and escape
|
||||||
if (!(flags & (cpu_flag::exit + cpu_flag::jit_return + cpu_flag::dbg_global_stop + cpu_flag::ret + cpu_flag::stop)))
|
if (!(flags & (cpu_flag::exit + cpu_flag::dbg_global_stop + cpu_flag::ret + cpu_flag::stop)))
|
||||||
{
|
{
|
||||||
// Check pause flags which hold thread inside check_state
|
// Check pause flags which hold thread inside check_state
|
||||||
if (flags & (cpu_flag::pause + cpu_flag::suspend + cpu_flag::dbg_global_pause + cpu_flag::dbg_pause))
|
if (flags & (cpu_flag::pause + cpu_flag::suspend + cpu_flag::dbg_global_pause + cpu_flag::dbg_pause))
|
||||||
|
|
|
@ -15,7 +15,6 @@ enum class cpu_flag : u32
|
||||||
signal, // Thread received a signal (HLE)
|
signal, // Thread received a signal (HLE)
|
||||||
memory, // Thread must unlock memory mutex
|
memory, // Thread must unlock memory mutex
|
||||||
|
|
||||||
jit_return, // JIT compiler event (forced return)
|
|
||||||
dbg_global_pause, // Emulation paused
|
dbg_global_pause, // Emulation paused
|
||||||
dbg_global_stop, // Emulation stopped
|
dbg_global_stop, // Emulation stopped
|
||||||
dbg_pause, // Thread paused
|
dbg_pause, // Thread paused
|
||||||
|
@ -66,7 +65,7 @@ public:
|
||||||
// Test stopped state
|
// Test stopped state
|
||||||
bool is_stopped() const
|
bool is_stopped() const
|
||||||
{
|
{
|
||||||
return !!(state & (cpu_flag::stop + cpu_flag::exit + cpu_flag::jit_return + cpu_flag::dbg_global_stop));
|
return !!(state & (cpu_flag::stop + cpu_flag::exit + cpu_flag::dbg_global_stop));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test paused state
|
// Test paused state
|
||||||
|
|
|
@ -45,11 +45,11 @@ void spu_recompiler::init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spu_function_t spu_recompiler::compile(u64 last_reset_count, const std::vector<u32>& func, void* fn_location)
|
spu_function_t spu_recompiler::compile(const std::vector<u32>& func, void* fn_location)
|
||||||
{
|
{
|
||||||
if (!fn_location)
|
if (!fn_location)
|
||||||
{
|
{
|
||||||
fn_location = m_spurt->find(last_reset_count, func);
|
fn_location = m_spurt->find(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fn_location == spu_runtime::g_dispatcher)
|
if (fn_location == spu_runtime::g_dispatcher)
|
||||||
|
@ -892,7 +892,7 @@ spu_function_t spu_recompiler::compile(u64 last_reset_count, const std::vector<u
|
||||||
LOG_FATAL(SPU, "Failed to build a function");
|
LOG_FATAL(SPU, "Failed to build a function");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_spurt->add(last_reset_count, fn_location, fn))
|
if (!m_spurt->add(fn_location, fn))
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ public:
|
||||||
|
|
||||||
virtual void init() override;
|
virtual void init() override;
|
||||||
|
|
||||||
virtual spu_function_t compile(u64 last_reset_count, const std::vector<u32>&, void*) override;
|
virtual spu_function_t compile(const std::vector<u32>&, void*) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ASMJIT runtime
|
// ASMJIT runtime
|
||||||
|
|
|
@ -400,7 +400,7 @@ void spu_cache::initialize()
|
||||||
{
|
{
|
||||||
compiler->init();
|
compiler->init();
|
||||||
|
|
||||||
if (compiler->compile(0, {}, nullptr) && spu_runtime::g_interpreter)
|
if (compiler->compile({}, nullptr) && spu_runtime::g_interpreter)
|
||||||
{
|
{
|
||||||
LOG_SUCCESS(SPU, "SPU Runtime: built interpreter.");
|
LOG_SUCCESS(SPU, "SPU Runtime: built interpreter.");
|
||||||
|
|
||||||
|
@ -447,9 +447,6 @@ void spu_cache::initialize()
|
||||||
|
|
||||||
for (std::size_t i = 0; i < compilers.size(); i++) thread_queue.emplace_back("Worker " + std::to_string(i), [&, compiler = compilers[i].get()]()
|
for (std::size_t i = 0; i < compilers.size(); i++) thread_queue.emplace_back("Worker " + std::to_string(i), [&, compiler = compilers[i].get()]()
|
||||||
{
|
{
|
||||||
// Register SPU runtime user
|
|
||||||
spu_runtime::passive_lock _passive_lock(compiler->get_runtime());
|
|
||||||
|
|
||||||
// Fake LS
|
// Fake LS
|
||||||
std::vector<be_t<u32>> ls(0x10000);
|
std::vector<be_t<u32>> ls(0x10000);
|
||||||
|
|
||||||
|
@ -482,7 +479,7 @@ void spu_cache::initialize()
|
||||||
LOG_ERROR(SPU, "[0x%05x] SPU Analyser failed, %u vs %u", func2[0], func2.size() - 1, size0 - 1);
|
LOG_ERROR(SPU, "[0x%05x] SPU Analyser failed, %u vs %u", func2[0], func2.size() - 1, size0 - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!compiler->compile(0, func, nullptr))
|
if (!compiler->compile(func, nullptr))
|
||||||
{
|
{
|
||||||
// Likely, out of JIT memory. Signal to prevent further building.
|
// Likely, out of JIT memory. Signal to prevent further building.
|
||||||
fail_flag |= 1;
|
fail_flag |= 1;
|
||||||
|
@ -523,8 +520,6 @@ void spu_cache::initialize()
|
||||||
if (fail_flag)
|
if (fail_flag)
|
||||||
{
|
{
|
||||||
LOG_ERROR(SPU, "SPU Runtime: Cache building failed (too much data). SPU Cache will be disabled.");
|
LOG_ERROR(SPU, "SPU Runtime: Cache building failed (too much data). SPU Cache will be disabled.");
|
||||||
spu_runtime::passive_lock _passive_lock(compilers[0]->get_runtime());
|
|
||||||
compilers[0]->get_runtime().reset(0);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -607,12 +602,11 @@ spu_runtime::spu_runtime()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool spu_runtime::add(u64 last_reset_count, void* _where, spu_function_t compiled)
|
bool spu_runtime::add(void* _where, spu_function_t compiled)
|
||||||
{
|
{
|
||||||
writer_lock lock(*this);
|
writer_lock lock(*this);
|
||||||
|
|
||||||
// Check reset count (makes where invalid)
|
if (!_where)
|
||||||
if (!_where || last_reset_count != m_reset_count)
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -957,16 +951,10 @@ spu_function_t spu_runtime::rebuild_ubertrampoline(u32 id_inst)
|
||||||
return beg->second;
|
return beg->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* spu_runtime::find(u64 last_reset_count, const std::vector<u32>& func)
|
void* spu_runtime::find(const std::vector<u32>& func)
|
||||||
{
|
{
|
||||||
writer_lock lock(*this);
|
writer_lock lock(*this);
|
||||||
|
|
||||||
// Check reset count
|
|
||||||
if (last_reset_count != m_reset_count)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
const u32 _off = 1 + (func[0] / 4) * (false);
|
const u32 _off = 1 + (func[0] / 4) * (false);
|
||||||
|
|
||||||
|
@ -979,11 +967,6 @@ void* spu_runtime::find(u64 last_reset_count, const std::vector<u32>& func)
|
||||||
while (!found->second)
|
while (!found->second)
|
||||||
{
|
{
|
||||||
m_cond.wait(m_mutex);
|
m_cond.wait(m_mutex);
|
||||||
|
|
||||||
if (last_reset_count != m_reset_count)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Already compiled
|
// Already compiled
|
||||||
|
@ -1010,12 +993,6 @@ void* spu_runtime::find(u64 last_reset_count, const std::vector<u32>& func)
|
||||||
while (!fn_location->second)
|
while (!fn_location->second)
|
||||||
{
|
{
|
||||||
m_cond.wait(m_mutex);
|
m_cond.wait(m_mutex);
|
||||||
|
|
||||||
// If reset count changed, fn_location is invalidated; also requires return
|
|
||||||
if (last_reset_count != m_reset_count)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return g_dispatcher;
|
return g_dispatcher;
|
||||||
|
@ -1027,14 +1004,7 @@ void* spu_runtime::find(u64 last_reset_count, const std::vector<u32>& func)
|
||||||
|
|
||||||
spu_function_t spu_runtime::find(const u32* ls, u32 addr) const
|
spu_function_t spu_runtime::find(const u32* ls, u32 addr) const
|
||||||
{
|
{
|
||||||
const u64 reset_count = m_reset_count;
|
reader_lock lock(this->m_mutex);
|
||||||
|
|
||||||
reader_lock lock(*this);
|
|
||||||
|
|
||||||
if (reset_count != m_reset_count)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto upper = m_pic_map.upper_bound({ls + addr / 4, (0x40000 - addr) / 4});
|
const auto upper = m_pic_map.upper_bound({ls + addr / 4, (0x40000 - addr) / 4});
|
||||||
|
|
||||||
|
@ -1083,53 +1053,6 @@ spu_function_t spu_runtime::make_branch_patchpoint() const
|
||||||
return reinterpret_cast<spu_function_t>(raw);
|
return reinterpret_cast<spu_function_t>(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 spu_runtime::reset(std::size_t last_reset_count)
|
|
||||||
{
|
|
||||||
writer_lock lock(*this);
|
|
||||||
|
|
||||||
if (last_reset_count != m_reset_count || !m_reset_count.compare_and_swap_test(last_reset_count, last_reset_count + 1))
|
|
||||||
{
|
|
||||||
// Probably already reset
|
|
||||||
return m_reset_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify SPU threads
|
|
||||||
idm::select<named_thread<spu_thread>>([](u32, cpu_thread& cpu)
|
|
||||||
{
|
|
||||||
if (!cpu.state.test_and_set(cpu_flag::jit_return))
|
|
||||||
{
|
|
||||||
cpu.notify();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Reset function map (may take some time)
|
|
||||||
m_map.clear();
|
|
||||||
m_pic_map.clear();
|
|
||||||
|
|
||||||
// Wait for threads to catch on jit_return flag
|
|
||||||
while (m_passive_locks)
|
|
||||||
{
|
|
||||||
busy_wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reinitialize (TODO)
|
|
||||||
jit_runtime::finalize();
|
|
||||||
jit_runtime::initialize();
|
|
||||||
return ++m_reset_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void spu_runtime::handle_return(spu_thread* _spu)
|
|
||||||
{
|
|
||||||
// Wait until the runtime becomes available
|
|
||||||
writer_lock lock(*this);
|
|
||||||
|
|
||||||
// Reset stack mirror
|
|
||||||
std::memset(_spu->stack_mirror.data(), 0xff, sizeof(spu_thread::stack_mirror));
|
|
||||||
|
|
||||||
// Reset the flag
|
|
||||||
_spu->state -= cpu_flag::jit_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
spu_recompiler_base::spu_recompiler_base()
|
spu_recompiler_base::spu_recompiler_base()
|
||||||
{
|
{
|
||||||
result.reserve(8192);
|
result.reserve(8192);
|
||||||
|
@ -1141,15 +1064,7 @@ spu_recompiler_base::~spu_recompiler_base()
|
||||||
|
|
||||||
void spu_recompiler_base::make_function(const std::vector<u32>& data)
|
void spu_recompiler_base::make_function(const std::vector<u32>& data)
|
||||||
{
|
{
|
||||||
for (u64 reset_count = m_spurt->get_reset_count();;)
|
compile(data, nullptr);
|
||||||
{
|
|
||||||
if (LIKELY(compile(reset_count, data, nullptr)))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
reset_count = m_spurt->reset(reset_count);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void spu_recompiler_base::dispatch(spu_thread& spu, void*, u8* rip)
|
void spu_recompiler_base::dispatch(spu_thread& spu, void*, u8* rip)
|
||||||
|
@ -4238,16 +4153,16 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual spu_function_t compile(u64 last_reset_count, const std::vector<u32>& func, void* fn_location) override
|
virtual spu_function_t compile(const std::vector<u32>& func, void* fn_location) override
|
||||||
{
|
{
|
||||||
if (func.empty() && last_reset_count == 0 && m_interp_magn)
|
if (func.empty() && m_interp_magn)
|
||||||
{
|
{
|
||||||
return compile_interpreter();
|
return compile_interpreter();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fn_location)
|
if (!fn_location)
|
||||||
{
|
{
|
||||||
fn_location = m_spurt->find(last_reset_count, func);
|
fn_location = m_spurt->find(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fn_location == spu_runtime::g_dispatcher)
|
if (fn_location == spu_runtime::g_dispatcher)
|
||||||
|
@ -4830,7 +4745,7 @@ public:
|
||||||
// Register function pointer
|
// Register function pointer
|
||||||
const spu_function_t fn = reinterpret_cast<spu_function_t>(m_jit.get_engine().getPointerToFunction(main_func));
|
const spu_function_t fn = reinterpret_cast<spu_function_t>(m_jit.get_engine().getPointerToFunction(main_func));
|
||||||
|
|
||||||
if (!m_spurt->add(last_reset_count, fn_location, fn))
|
if (!m_spurt->add(fn_location, fn))
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -8364,9 +8279,9 @@ struct spu_llvm
|
||||||
LOG_ERROR(SPU, "[0x%05x] SPU Analyser failed, %u vs %u", func2[0], func2.size() - 1, size0 - 1);
|
LOG_ERROR(SPU, "[0x%05x] SPU Analyser failed, %u vs %u", func2[0], func2.size() - 1, size0 - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const auto target = compiler->compile(0, func, parg->first))
|
if (const auto target = compiler->compile(func, parg->first))
|
||||||
{
|
{
|
||||||
// Redirect old function
|
// Redirect old function (TODO: patch in multiple places)
|
||||||
const s64 rel = reinterpret_cast<u64>(target) - reinterpret_cast<u64>(parg->second) - 5;
|
const s64 rel = reinterpret_cast<u64>(target) - reinterpret_cast<u64>(parg->second) - 5;
|
||||||
|
|
||||||
union
|
union
|
||||||
|
@ -8421,11 +8336,11 @@ struct spu_fast : public spu_recompiler_base
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual spu_function_t compile(u64 last_reset_count, const std::vector<u32>& func, void* fn_location) override
|
virtual spu_function_t compile(const std::vector<u32>& func, void* fn_location) override
|
||||||
{
|
{
|
||||||
if (!fn_location)
|
if (!fn_location)
|
||||||
{
|
{
|
||||||
fn_location = m_spurt->find(last_reset_count, func);
|
fn_location = m_spurt->find(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fn_location == spu_runtime::g_dispatcher)
|
if (fn_location == spu_runtime::g_dispatcher)
|
||||||
|
@ -8446,7 +8361,7 @@ struct spu_fast : public spu_recompiler_base
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate executable area with necessary size
|
// Allocate executable area with necessary size
|
||||||
const auto result = jit_runtime::alloc(8 + 1 + 9 + (::size32(func) - 1) * (16 + 16) + 36 + 47, 16);
|
const auto result = jit_runtime::alloc(16 + 1 + 9 + (::size32(func) - 1) * (16 + 16) + 36 + 47, 16);
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
|
@ -8458,13 +8373,14 @@ struct spu_fast : public spu_recompiler_base
|
||||||
|
|
||||||
u8* raw = result;
|
u8* raw = result;
|
||||||
|
|
||||||
// 8-byte NOP for patching
|
// 8-byte intruction for patching
|
||||||
*raw++ = 0x0f;
|
// Update block_hash: mov [r13 + spu_thread::m_block_hash], 0xffff
|
||||||
*raw++ = 0x1f;
|
*raw++ = 0x49;
|
||||||
*raw++ = 0x84;
|
*raw++ = 0xc7;
|
||||||
*raw++ = 0x00;
|
*raw++ = 0x45;
|
||||||
*raw++ = 0x00;
|
*raw++ = ::narrow<s8>(::offset32(&spu_thread::block_hash));
|
||||||
*raw++ = 0x00;
|
*raw++ = 0xff;
|
||||||
|
*raw++ = 0xff;
|
||||||
*raw++ = 0x00;
|
*raw++ = 0x00;
|
||||||
*raw++ = 0x00;
|
*raw++ = 0x00;
|
||||||
|
|
||||||
|
@ -8509,6 +8425,16 @@ struct spu_fast : public spu_recompiler_base
|
||||||
// trap
|
// trap
|
||||||
//*raw++ = 0xcc;
|
//*raw++ = 0xcc;
|
||||||
|
|
||||||
|
// Update block_hash: mov [r13 + spu_thread::m_block_hash], 0xfffe
|
||||||
|
*raw++ = 0x49;
|
||||||
|
*raw++ = 0xc7;
|
||||||
|
*raw++ = 0x45;
|
||||||
|
*raw++ = ::narrow<s8>(::offset32(&spu_thread::block_hash));
|
||||||
|
*raw++ = 0xfe;
|
||||||
|
*raw++ = 0xff;
|
||||||
|
*raw++ = 0x00;
|
||||||
|
*raw++ = 0x00;
|
||||||
|
|
||||||
// Secondary prologue: sub rsp,0x28
|
// Secondary prologue: sub rsp,0x28
|
||||||
*raw++ = 0x48;
|
*raw++ = 0x48;
|
||||||
*raw++ = 0x83;
|
*raw++ = 0x83;
|
||||||
|
@ -8713,7 +8639,7 @@ struct spu_fast : public spu_recompiler_base
|
||||||
*raw++ = 0x28;
|
*raw++ = 0x28;
|
||||||
*raw++ = 0xc3;
|
*raw++ = 0xc3;
|
||||||
|
|
||||||
if (!m_spurt->add(last_reset_count, fn_location, reinterpret_cast<spu_function_t>(result)))
|
if (!m_spurt->add(fn_location, reinterpret_cast<spu_function_t>(result)))
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,10 +44,6 @@ class spu_runtime
|
||||||
|
|
||||||
mutable cond_variable m_cond;
|
mutable cond_variable m_cond;
|
||||||
|
|
||||||
mutable atomic_t<u64> m_passive_locks{0};
|
|
||||||
|
|
||||||
atomic_t<u64> m_reset_count{0};
|
|
||||||
|
|
||||||
struct func_compare
|
struct func_compare
|
||||||
{
|
{
|
||||||
// Comparison function for SPU programs
|
// Comparison function for SPU programs
|
||||||
|
@ -93,7 +89,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add compiled function and generate trampoline if necessary
|
// Add compiled function and generate trampoline if necessary
|
||||||
bool add(u64 last_reset_count, void* where, spu_function_t compiled);
|
bool add(void* where, spu_function_t compiled);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
spu_function_t rebuild_ubertrampoline(u32 id_inst);
|
spu_function_t rebuild_ubertrampoline(u32 id_inst);
|
||||||
|
@ -102,7 +98,7 @@ private:
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Return opaque pointer for add()
|
// Return opaque pointer for add()
|
||||||
void* find(u64 last_reset_count, const std::vector<u32>&);
|
void* find(const std::vector<u32>&);
|
||||||
|
|
||||||
// Get func from opaque ptr
|
// Get func from opaque ptr
|
||||||
static inline const std::vector<u32>& get_func(void* _where)
|
static inline const std::vector<u32>& get_func(void* _where)
|
||||||
|
@ -116,18 +112,6 @@ public:
|
||||||
// Generate a patchable trampoline to spu_recompiler_base::branch
|
// Generate a patchable trampoline to spu_recompiler_base::branch
|
||||||
spu_function_t make_branch_patchpoint() const;
|
spu_function_t make_branch_patchpoint() const;
|
||||||
|
|
||||||
// reset() arg retriever, for race avoidance (can result in double reset)
|
|
||||||
u64 get_reset_count() const
|
|
||||||
{
|
|
||||||
return m_reset_count.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove all compiled function and free JIT memory
|
|
||||||
u64 reset(std::size_t last_reset_count);
|
|
||||||
|
|
||||||
// Handle cpu_flag::jit_return
|
|
||||||
void handle_return(spu_thread* _spu);
|
|
||||||
|
|
||||||
// All dispatchers (array allocated in jit memory)
|
// All dispatchers (array allocated in jit memory)
|
||||||
static std::array<atomic_t<spu_function_t>, (1 << 20)>* const g_dispatcher;
|
static std::array<atomic_t<spu_function_t>, (1 << 20)>* const g_dispatcher;
|
||||||
|
|
||||||
|
@ -146,26 +130,7 @@ public:
|
||||||
// Interpreter entry point
|
// Interpreter entry point
|
||||||
static spu_function_t g_interpreter;
|
static spu_function_t g_interpreter;
|
||||||
|
|
||||||
struct passive_lock
|
// Exclusive lock
|
||||||
{
|
|
||||||
spu_runtime& _this;
|
|
||||||
|
|
||||||
passive_lock(const passive_lock&) = delete;
|
|
||||||
|
|
||||||
passive_lock(spu_runtime& _this)
|
|
||||||
: _this(_this)
|
|
||||||
{
|
|
||||||
std::lock_guard lock(_this.m_mutex);
|
|
||||||
_this.m_passive_locks++;
|
|
||||||
}
|
|
||||||
|
|
||||||
~passive_lock()
|
|
||||||
{
|
|
||||||
_this.m_passive_locks--;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Exclusive lock within passive_lock scope
|
|
||||||
struct writer_lock
|
struct writer_lock
|
||||||
{
|
{
|
||||||
spu_runtime& _this;
|
spu_runtime& _this;
|
||||||
|
@ -176,14 +141,11 @@ public:
|
||||||
writer_lock(spu_runtime& _this)
|
writer_lock(spu_runtime& _this)
|
||||||
: _this(_this)
|
: _this(_this)
|
||||||
{
|
{
|
||||||
// Temporarily release the passive lock
|
|
||||||
_this.m_passive_locks--;
|
|
||||||
_this.m_mutex.lock();
|
_this.m_mutex.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
~writer_lock()
|
~writer_lock()
|
||||||
{
|
{
|
||||||
_this.m_passive_locks++;
|
|
||||||
_this.m_mutex.unlock();
|
_this.m_mutex.unlock();
|
||||||
|
|
||||||
if (notify)
|
if (notify)
|
||||||
|
@ -192,26 +154,6 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct reader_lock
|
|
||||||
{
|
|
||||||
const spu_runtime& _this;
|
|
||||||
|
|
||||||
reader_lock(const reader_lock&) = delete;
|
|
||||||
|
|
||||||
reader_lock(const spu_runtime& _this)
|
|
||||||
: _this(_this)
|
|
||||||
{
|
|
||||||
_this.m_passive_locks--;
|
|
||||||
_this.m_mutex.lock_shared();
|
|
||||||
}
|
|
||||||
|
|
||||||
~reader_lock()
|
|
||||||
{
|
|
||||||
_this.m_passive_locks++;
|
|
||||||
_this.m_mutex.unlock_shared();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// SPU Recompiler instance base class
|
// SPU Recompiler instance base class
|
||||||
|
@ -373,7 +315,7 @@ public:
|
||||||
virtual void init() = 0;
|
virtual void init() = 0;
|
||||||
|
|
||||||
// Compile function (may fail)
|
// Compile function (may fail)
|
||||||
virtual spu_function_t compile(u64 last_reset_count, const std::vector<u32>&, void*) = 0;
|
virtual spu_function_t compile(const std::vector<u32>&, void*) = 0;
|
||||||
|
|
||||||
// Compile function, handle failure
|
// Compile function, handle failure
|
||||||
void make_function(const std::vector<u32>&);
|
void make_function(const std::vector<u32>&);
|
||||||
|
|
|
@ -1145,25 +1145,13 @@ void spu_thread::cpu_task()
|
||||||
|
|
||||||
if (jit)
|
if (jit)
|
||||||
{
|
{
|
||||||
// Register SPU runtime user
|
|
||||||
spu_runtime::passive_lock _passive_lock(jit->get_runtime());
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (UNLIKELY(state))
|
if (UNLIKELY(state))
|
||||||
{
|
{
|
||||||
if (check_state())
|
if (check_state())
|
||||||
{
|
|
||||||
if (state & cpu_flag::jit_return)
|
|
||||||
{
|
|
||||||
// Handle jit_return as a special case
|
|
||||||
jit->get_runtime().handle_return(this);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
spu_runtime::g_gateway(*this, vm::_ptr<u8>(offset), nullptr);
|
spu_runtime::g_gateway(*this, vm::_ptr<u8>(offset), nullptr);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue