Ensures threads are stopped in join

This commit is contained in:
RipleyTom 2018-11-05 12:38:35 +01:00 committed by kd-11
parent 2e1aec4de8
commit 0e0a82e536
3 changed files with 70 additions and 36 deletions

View file

@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "Utilities/JIT.h"
#include "Utilities/sysinfo.h"
#include "Emu/Memory/vm.h"
@ -480,6 +480,21 @@ extern thread_local std::string(*g_tls_log_prefix)();
void spu_thread::cpu_task()
{
auto end_cpu_task = [&]()
{
// save next PC and current SPU Interrupt status
if (!group && offset >= RAW_SPU_BASE_ADDR)
{
npc = pc | (interrupts_enabled);
}
if (state & cpu_flag::stop)
{
status |= SPU_STATUS_STOPPED_BY_STOP;
if (group) group->cv.notify_all();
}
};
// Get next PC and SPU Interrupt status
pc = npc.exchange(0);
@ -508,14 +523,10 @@ void spu_thread::cpu_task()
jit_dispatcher[pc / 4](*this, vm::_ptr<u8>(offset), nullptr);
}
// save next PC and current SPU Interrupt status
if (!group && offset >= RAW_SPU_BASE_ADDR)
{
npc = pc | (interrupts_enabled);
}
// Print some stats
LOG_NOTICE(SPU, "Stats: Block Weight: %u (Retreats: %u);", block_counter, block_failure);
end_cpu_task();
return;
}
@ -597,11 +608,7 @@ void spu_thread::cpu_task()
}
}
// save next PC and current SPU Interrupt status
if (!group && offset >= RAW_SPU_BASE_ADDR)
{
npc = pc | (interrupts_enabled);
}
end_cpu_task();
}
void spu_thread::cpu_mem()
@ -2060,7 +2067,6 @@ bool spu_thread::stop_and_signal(u32 code)
status.atomic_op([code](u32& status)
{
status = (status & 0xffff) | (code << 16);
status |= SPU_STATUS_STOPPED_BY_STOP;
status &= ~SPU_STATUS_RUNNING;
});
@ -2352,10 +2358,29 @@ bool spu_thread::stop_and_signal(u32 code)
}
}
while (!Emu.IsStopped())
{
bool stopped = true;
for (auto& thread : group->threads)
{
if (thread && thread.get() != this)
{
if ((thread->status & SPU_STATUS_STOPPED_BY_STOP) == 0)
{
stopped = false;
break;
}
}
}
if (stopped) break;
group->cv.wait(group->mutex, 1000);
}
group->run_state = SPU_THREAD_GROUP_STATUS_INITIALIZED;
group->exit_status = value;
group->join_state |= SPU_TGJSF_GROUP_EXIT;
group->cv.notify_one();
state += cpu_flag::stop;
return true;
@ -2374,9 +2399,6 @@ bool spu_thread::stop_and_signal(u32 code)
std::lock_guard lock(group->mutex);
status |= SPU_STATUS_STOPPED_BY_STOP;
group->cv.notify_one();
state += cpu_flag::stop;
return true;
}