sys_spu_thread_group_exit

This commit is contained in:
Nekotekina 2014-08-28 01:04:55 +04:00
parent 1065eb17de
commit d5aa7aae43
3 changed files with 70 additions and 11 deletions

View file

@ -494,6 +494,7 @@ bool SPUThread::CheckEvents()
{ {
// checks events: // checks events:
// SPU_EVENT_LR: // SPU_EVENT_LR:
if (R_ADDR)
{ {
for (u32 i = 0; i < 16; i++) for (u32 i = 0; i < 16; i++)
{ {
@ -949,11 +950,14 @@ void SPUThread::ReadChannel(SPU_GPR_hdr& r, u32 ch)
void SPUThread::StopAndSignal(u32 code) void SPUThread::StopAndSignal(u32 code)
{ {
SetExitStatus(code); // exit code (not status) SetExitStatus(code); // exit code (not status)
// TODO: process interrupts for RawSPU
switch (code) switch (code)
{ {
case 0x110: /* ===== sys_spu_thread_receive_event ===== */ case 0x110:
{ {
/* ===== sys_spu_thread_receive_event ===== */
u32 spuq = 0; u32 spuq = 0;
if (!SPU.Out_MBox.Pop(spuq)) if (!SPU.Out_MBox.Pop(spuq))
{ {
@ -1027,22 +1031,60 @@ void SPUThread::StopAndSignal(u32 code)
return; return;
} }
} }
}
break; break;
}
case 0x101:
{
/* ===== sys_spu_thread_group_exit ===== */
if (!group)
{
LOG_ERROR(Log::SPU, "sys_spu_thread_group_exit(): group not set");
break;
}
else if (!SPU.Out_MBox.GetCount())
{
LOG_ERROR(Log::SPU, "sys_spu_thread_group_exit(): Out_MBox is empty");
}
else if (Ini.HLELogging.GetValue())
{
LOG_NOTICE(Log::SPU, "sys_spu_thread_group_exit(status=0x%x)", SPU.Out_MBox.GetValue());
}
group->m_group_exit = true;
group->m_exit_status = SPU.Out_MBox.GetValue();
for (auto& v : group->list)
{
if (CPUThread* t = Emu.GetCPU().GetThread(v))
{
t->Stop();
}
}
break;
}
case 0x102: case 0x102:
{
/* ===== sys_spu_thread_exit ===== */
if (!SPU.Out_MBox.GetCount()) if (!SPU.Out_MBox.GetCount())
{ {
LOG_ERROR(Log::SPU, "sys_spu_thread_exit (no status, code 0x102)"); LOG_ERROR(Log::SPU, "sys_spu_thread_exit(): Out_MBox is empty");
} }
else if (Ini.HLELogging.GetValue()) else if (Ini.HLELogging.GetValue())
{ {
// the real exit status // the real exit status
LOG_NOTICE(Log::SPU, "sys_spu_thread_exit (status=0x%x)", SPU.Out_MBox.GetValue()); LOG_NOTICE(Log::SPU, "sys_spu_thread_exit(status=0x%x)", SPU.Out_MBox.GetValue());
} }
SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_STOP); SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_STOP);
Stop(); Stop();
break; break;
}
default: default:
{
if (!SPU.Out_MBox.GetCount()) if (!SPU.Out_MBox.GetCount())
{ {
LOG_ERROR(Log::SPU, "Unknown STOP code: 0x%x (no message)", code); LOG_ERROR(Log::SPU, "Unknown STOP code: 0x%x (no message)", code);
@ -1051,8 +1093,8 @@ void SPUThread::StopAndSignal(u32 code)
{ {
LOG_ERROR(Log::SPU, "Unknown STOP code: 0x%x (message=0x%x)", code, SPU.Out_MBox.GetValue()); LOG_ERROR(Log::SPU, "Unknown STOP code: 0x%x (message=0x%x)", code, SPU.Out_MBox.GetValue());
} }
SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_STOP);
Stop(); Stop();
break; break;
} }
}
} }

View file

@ -387,6 +387,7 @@ s32 sys_spu_thread_group_terminate(u32 id, int value)
{ {
if (CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i])) if (CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]))
{ {
((SPUThread*)t)->SPU.Status.SetValue(SPU_STATUS_STOPPED);
t->Stop(); t->Stop();
} }
} }
@ -435,15 +436,17 @@ s32 sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status)
return CELL_EBUSY; return CELL_EBUSY;
} }
if (cause.GetAddr()) cause = SYS_SPU_THREAD_GROUP_JOIN_ALL_THREADS_EXIT; bool all_threads_exit = true;
if (status.GetAddr()) status = 0; //unspecified because of ALL_THREADS_EXIT
for (u32 i = 0; i < group_info->list.size(); i++) for (u32 i = 0; i < group_info->list.size(); i++)
{ {
while (CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i])) while (CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]))
{ {
if (!t->IsRunning()) if (!t->IsRunning())
{ {
if (((SPUThread*)t)->SPU.Status.GetValue() != SPU_STATUS_STOPPED_BY_STOP)
{
all_threads_exit = false;
}
break; break;
} }
if (Emu.IsStopped()) if (Emu.IsStopped())
@ -455,6 +458,17 @@ s32 sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status)
} }
} }
if (cause.GetAddr())
{
cause = group_info->m_group_exit
? SYS_SPU_THREAD_GROUP_JOIN_GROUP_EXIT
: (all_threads_exit
? SYS_SPU_THREAD_GROUP_JOIN_ALL_THREADS_EXIT
: SYS_SPU_THREAD_GROUP_JOIN_TERMINATED);
}
if (status.GetAddr()) status = group_info->m_exit_status;
group_info->m_state = SPU_THREAD_GROUP_STATUS_INITIALIZED; group_info->m_state = SPU_THREAD_GROUP_STATUS_INITIALIZED;
group_info->lock = 0; // release lock TODO: this LOCK may be replaced. group_info->lock = 0; // release lock TODO: this LOCK may be replaced.
return CELL_OK; return CELL_OK;

View file

@ -89,21 +89,24 @@ struct SpuGroupInfo
int m_ct; int m_ct;
u32 m_count; u32 m_count;
int m_state; //SPU Thread Group State. int m_state; //SPU Thread Group State.
int m_exit_status; u32 m_exit_status;
bool m_group_exit;
SpuGroupInfo(const std::string& name, u32 num, int prio, int type, u32 ct) SpuGroupInfo(const std::string& name, u32 num, int prio, int type, u32 ct)
: m_name(name) : m_name(name)
, m_prio(prio) , m_prio(prio)
, m_type(type) , m_type(type)
, m_ct(ct) , m_ct(ct)
, lock(0) , lock(0)
, m_count(num) , m_count(num)
, m_state(0)
, m_exit_status(0)
, m_group_exit(false)
{ {
m_state = SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED; //Before all the nums done, it is not initialized. m_state = SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED; //Before all the nums done, it is not initialized.
list.resize(256); list.resize(256);
for (auto& v : list) v = 0; for (auto& v : list) v = 0;
m_state = SPU_THREAD_GROUP_STATUS_INITIALIZED; //Then Ready to Start. Cause Reference use New i can only place this here. m_state = SPU_THREAD_GROUP_STATUS_INITIALIZED; //Then Ready to Start. Cause Reference use New i can only place this here.
m_exit_status = 0;
} }
}; };