mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-10 17:01:24 +12:00
Ensures threads are stopped in join
This commit is contained in:
parent
2e1aec4de8
commit
0e0a82e536
3 changed files with 70 additions and 36 deletions
|
@ -1,4 +1,4 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "Utilities/JIT.h"
|
#include "Utilities/JIT.h"
|
||||||
#include "Utilities/sysinfo.h"
|
#include "Utilities/sysinfo.h"
|
||||||
#include "Emu/Memory/vm.h"
|
#include "Emu/Memory/vm.h"
|
||||||
|
@ -480,6 +480,21 @@ extern thread_local std::string(*g_tls_log_prefix)();
|
||||||
|
|
||||||
void spu_thread::cpu_task()
|
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
|
// Get next PC and SPU Interrupt status
|
||||||
pc = npc.exchange(0);
|
pc = npc.exchange(0);
|
||||||
|
|
||||||
|
@ -508,14 +523,10 @@ void spu_thread::cpu_task()
|
||||||
jit_dispatcher[pc / 4](*this, vm::_ptr<u8>(offset), nullptr);
|
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
|
// Print some stats
|
||||||
LOG_NOTICE(SPU, "Stats: Block Weight: %u (Retreats: %u);", block_counter, block_failure);
|
LOG_NOTICE(SPU, "Stats: Block Weight: %u (Retreats: %u);", block_counter, block_failure);
|
||||||
|
|
||||||
|
end_cpu_task();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,11 +608,7 @@ void spu_thread::cpu_task()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// save next PC and current SPU Interrupt status
|
end_cpu_task();
|
||||||
if (!group && offset >= RAW_SPU_BASE_ADDR)
|
|
||||||
{
|
|
||||||
npc = pc | (interrupts_enabled);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void spu_thread::cpu_mem()
|
void spu_thread::cpu_mem()
|
||||||
|
@ -2060,7 +2067,6 @@ bool spu_thread::stop_and_signal(u32 code)
|
||||||
status.atomic_op([code](u32& status)
|
status.atomic_op([code](u32& status)
|
||||||
{
|
{
|
||||||
status = (status & 0xffff) | (code << 16);
|
status = (status & 0xffff) | (code << 16);
|
||||||
status |= SPU_STATUS_STOPPED_BY_STOP;
|
|
||||||
status &= ~SPU_STATUS_RUNNING;
|
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->run_state = SPU_THREAD_GROUP_STATUS_INITIALIZED;
|
||||||
group->exit_status = value;
|
group->exit_status = value;
|
||||||
group->join_state |= SPU_TGJSF_GROUP_EXIT;
|
group->join_state |= SPU_TGJSF_GROUP_EXIT;
|
||||||
group->cv.notify_one();
|
|
||||||
|
|
||||||
state += cpu_flag::stop;
|
state += cpu_flag::stop;
|
||||||
return true;
|
return true;
|
||||||
|
@ -2374,9 +2399,6 @@ bool spu_thread::stop_and_signal(u32 code)
|
||||||
|
|
||||||
std::lock_guard lock(group->mutex);
|
std::lock_guard lock(group->mutex);
|
||||||
|
|
||||||
status |= SPU_STATUS_STOPPED_BY_STOP;
|
|
||||||
group->cv.notify_one();
|
|
||||||
|
|
||||||
state += cpu_flag::stop;
|
state += cpu_flag::stop;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "Emu/Memory/vm.h"
|
#include "Emu/Memory/vm.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Emu/IdManager.h"
|
#include "Emu/IdManager.h"
|
||||||
|
@ -547,7 +547,7 @@ error_code sys_spu_thread_group_yield(u32 id)
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code sys_spu_thread_group_terminate(u32 id, s32 value)
|
error_code sys_spu_thread_group_terminate(ppu_thread& ppu, u32 id, s32 value)
|
||||||
{
|
{
|
||||||
sys_spu.warning("sys_spu_thread_group_terminate(id=0x%x, value=0x%x)", id, value);
|
sys_spu.warning("sys_spu_thread_group_terminate(id=0x%x, value=0x%x)", id, value);
|
||||||
|
|
||||||
|
@ -598,10 +598,33 @@ error_code sys_spu_thread_group_terminate(u32 id, s32 value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (!ppu.is_stopped())
|
||||||
|
{
|
||||||
|
bool stopped = true;
|
||||||
|
|
||||||
|
for (auto& t : group->threads)
|
||||||
|
{
|
||||||
|
if (t)
|
||||||
|
{
|
||||||
|
if ((t->status & SPU_STATUS_STOPPED_BY_STOP) == 0)
|
||||||
|
{
|
||||||
|
stopped = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stopped) break;
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
group->cv.wait(group->mutex, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ppu.is_stopped()) return 0;
|
||||||
|
|
||||||
group->run_state = SPU_THREAD_GROUP_STATUS_INITIALIZED;
|
group->run_state = SPU_THREAD_GROUP_STATUS_INITIALIZED;
|
||||||
group->exit_status = value;
|
group->exit_status = value;
|
||||||
group->join_state |= SPU_TGJSF_TERMINATED;
|
group->join_state |= SPU_TGJSF_TERMINATED;
|
||||||
group->cv.notify_one();
|
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
@ -638,13 +661,8 @@ error_code sys_spu_thread_group_join(ppu_thread& ppu, u32 id, vm::ptr<u32> cause
|
||||||
|
|
||||||
lv2_obj::sleep(ppu);
|
lv2_obj::sleep(ppu);
|
||||||
|
|
||||||
while ((group->join_state & ~SPU_TGJSF_IS_JOINING) == 0)
|
while (!ppu.is_stopped())
|
||||||
{
|
{
|
||||||
if (ppu.is_stopped())
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool stopped = true;
|
bool stopped = true;
|
||||||
|
|
||||||
for (auto& t : group->threads)
|
for (auto& t : group->threads)
|
||||||
|
@ -659,10 +677,7 @@ error_code sys_spu_thread_group_join(ppu_thread& ppu, u32 id, vm::ptr<u32> cause
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stopped)
|
if (stopped) break;
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
group->cv.wait(group->mutex, 1000);
|
group->cv.wait(group->mutex, 1000);
|
||||||
|
@ -674,10 +689,7 @@ error_code sys_spu_thread_group_join(ppu_thread& ppu, u32 id, vm::ptr<u32> cause
|
||||||
group->run_state = SPU_THREAD_GROUP_STATUS_INITIALIZED; // hack
|
group->run_state = SPU_THREAD_GROUP_STATUS_INITIALIZED; // hack
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ppu.test_stopped())
|
if (ppu.test_stopped()) return 0;
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (join_state & ~SPU_TGJSF_IS_JOINING)
|
switch (join_state & ~SPU_TGJSF_IS_JOINING)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "sys_event.h"
|
#include "sys_event.h"
|
||||||
#include "Emu/Cell/SPUThread.h"
|
#include "Emu/Cell/SPUThread.h"
|
||||||
|
@ -300,7 +300,7 @@ error_code sys_spu_thread_group_start(ppu_thread&, u32 id);
|
||||||
error_code sys_spu_thread_group_suspend(u32 id);
|
error_code sys_spu_thread_group_suspend(u32 id);
|
||||||
error_code sys_spu_thread_group_resume(u32 id);
|
error_code sys_spu_thread_group_resume(u32 id);
|
||||||
error_code sys_spu_thread_group_yield(u32 id);
|
error_code sys_spu_thread_group_yield(u32 id);
|
||||||
error_code sys_spu_thread_group_terminate(u32 id, s32 value);
|
error_code sys_spu_thread_group_terminate(ppu_thread&, u32 id, s32 value);
|
||||||
error_code sys_spu_thread_group_join(ppu_thread&, u32 id, vm::ptr<u32> cause, vm::ptr<u32> status);
|
error_code sys_spu_thread_group_join(ppu_thread&, u32 id, vm::ptr<u32> cause, vm::ptr<u32> status);
|
||||||
error_code sys_spu_thread_group_set_priority(u32 id, s32 priority);
|
error_code sys_spu_thread_group_set_priority(u32 id, s32 priority);
|
||||||
error_code sys_spu_thread_group_get_priority(u32 id, vm::ptr<s32> priority);
|
error_code sys_spu_thread_group_get_priority(u32 id, vm::ptr<s32> priority);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue