Merge pull request #752 from Syphurith/patch-syscall-177

SysCalls 177 sys_spu_thread_group_terminate
This commit is contained in:
Hykem 2014-08-14 16:36:53 +01:00
commit 004df937ed
3 changed files with 188 additions and 6 deletions

View File

@ -193,8 +193,8 @@ static func_caller* sc_table[kSyscallTableLength] =
bind_func(sys_spu_thread_group_start), //173 (0x0AD) bind_func(sys_spu_thread_group_start), //173 (0x0AD)
bind_func(sys_spu_thread_group_suspend), //174 (0x0AE) bind_func(sys_spu_thread_group_suspend), //174 (0x0AE)
bind_func(sys_spu_thread_group_resume), //175 (0x0AF) bind_func(sys_spu_thread_group_resume), //175 (0x0AF)
null_func,//bind_func(sys_spu_thread_group_yield) //176 (0x0B0) bind_func(sys_spu_thread_group_yield), //176 (0x0B0)
null_func,//bind_func(sys_spu_thread_group_terminate) //177 (0x0B1) bind_func(sys_spu_thread_group_terminate), //177 (0x0B1)
bind_func(sys_spu_thread_group_join), //178 (0x0B2) bind_func(sys_spu_thread_group_join), //178 (0x0B2)
null_func,//bind_func(sys_spu_thread_group_set_priority)//179 (0x0B3) null_func,//bind_func(sys_spu_thread_group_set_priority)//179 (0x0B3)
null_func,//bind_func(sys_spu_thread_group_get_priority)//180 (0x0B4) null_func,//bind_func(sys_spu_thread_group_get_priority)//180 (0x0B4)

View File

@ -160,10 +160,19 @@ s32 sys_spu_thread_group_destroy(u32 id)
return CELL_ESRCH; return CELL_ESRCH;
} }
if (group_info->lock) // ??? //TODO: New method to check busy. and even maybe in other sys_spu_thread_group_ calls.
//TODO: SPU_THREAD_GROUP lock may not be gracefully implemented now.
// But it could still be set using simple way?
//Check the state it should be in NOT_INITIALIZED / INITIALIZED.
if ((group_info->m_state != SPU_THREAD_GROUP_STATUS_INITIALIZED)
&& (group_info->m_state != SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED))
{ {
return CELL_EBUSY; sc_spu.Error("sys_spu_thread_group_destroy(id=%d) is not in NOT_INITIALIZED / INITIALIZED, state=%d", id, group_info->m_state);
return CELL_ESTAT; //Indeed this should not be encountered. If program itself all right.
} }
//SET BUSY
for (u32 i = 0; i < group_info->list.size(); i++) for (u32 i = 0; i < group_info->list.size(); i++)
{ {
@ -172,6 +181,9 @@ s32 sys_spu_thread_group_destroy(u32 id)
Emu.GetCPU().RemoveThread(group_info->list[i]); Emu.GetCPU().RemoveThread(group_info->list[i]);
} }
group_info->m_state = SPU_THREAD_GROUP_STATUS_UNKNOWN;
//REMOVE BUSY
Emu.GetIdManager().RemoveID(id); Emu.GetIdManager().RemoveID(id);
return CELL_OK; return CELL_OK;
} }
@ -189,6 +201,14 @@ s32 sys_spu_thread_group_start(u32 id)
// TODO: check group state // TODO: check group state
//Check for BUSY?
//SET BUSY
//Different from what i expected. Or else there would not be any with RUNNING.
group_info->m_state = SPU_THREAD_GROUP_STATUS_READY; //Added Group State
//Notice: I can not know the action preformed below be following the definition, but left unchanged.
for (u32 i = 0; i < group_info->list.size(); i++) for (u32 i = 0; i < group_info->list.size(); i++)
{ {
CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]); CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]);
@ -198,6 +218,9 @@ s32 sys_spu_thread_group_start(u32 id)
} }
} }
group_info->m_state = SPU_THREAD_GROUP_STATUS_RUNNING; //SPU Thread Group now all in running.
//REMOVE BUSY
return CELL_OK; return CELL_OK;
} }
@ -213,6 +236,17 @@ s32 sys_spu_thread_group_suspend(u32 id)
} }
// TODO: check group state // TODO: check group state
//Experimental implementation for the state checking
if ((group_info->m_state != SPU_THREAD_GROUP_STATUS_READY)
&& (group_info->m_state != SPU_THREAD_GROUP_STATUS_RUNNING)
&& (group_info->m_state != SPU_THREAD_GROUP_STATUS_WAITING))
{
return CELL_ESTAT;
}
//Check for BUSY?
//SET BUSY
for (u32 i = 0; i < group_info->list.size(); i++) for (u32 i = 0; i < group_info->list.size(); i++)
{ {
@ -222,6 +256,18 @@ s32 sys_spu_thread_group_suspend(u32 id)
} }
} }
//Now the state changes.
if ((group_info->m_state == SPU_THREAD_GROUP_STATUS_READY)
|| (group_info->m_state == SPU_THREAD_GROUP_STATUS_RUNNING))
{
group_info->m_state = SPU_THREAD_GROUP_STATUS_SUSPENDED;
}
else if (group_info->m_state == SPU_THREAD_GROUP_STATUS_WAITING)
{
group_info->m_state = SPU_THREAD_GROUP_STATUS_WAITING_AND_SUSPENDED;
}
//REMOVE BUSY
return CELL_OK; return CELL_OK;
} }
@ -237,6 +283,24 @@ s32 sys_spu_thread_group_resume(u32 id)
} }
// TODO: check group state // TODO: check group state
if ((group_info->m_state != SPU_THREAD_GROUP_STATUS_SUSPENDED)
&& (group_info->m_state != SPU_THREAD_GROUP_STATUS_WAITING_AND_SUSPENDED))
{
return CELL_ESTAT;
}
//Maybe check for BUSY
//SET BUSY
if (group_info->m_state == SPU_THREAD_GROUP_STATUS_SUSPENDED)
{
group_info->m_state = SPU_THREAD_GROUP_STATUS_READY;
}
else if (group_info->m_state == SPU_THREAD_GROUP_STATUS_WAITING_AND_SUSPENDED)
{
group_info->m_state = SPU_THREAD_GROUP_STATUS_WAITING;
}
for (u32 i = 0; i < group_info->list.size(); i++) for (u32 i = 0; i < group_info->list.size(); i++)
{ {
@ -246,6 +310,94 @@ s32 sys_spu_thread_group_resume(u32 id)
} }
} }
if (group_info->m_state == SPU_THREAD_GROUP_STATUS_READY)
{
group_info->m_state = SPU_THREAD_GROUP_STATUS_RUNNING;
}
//REMOVE BUSY
return CELL_OK;
}
//176: Left doing nothing, indeed
s32 sys_spu_thread_group_yield(u32 id)
{
sc_spu.Error("sys_spu_thread_group_yield(id=%d)", id);
SpuGroupInfo* group_info;
if (!Emu.GetIdManager().GetIDData(id, group_info))
{
return CELL_ESRCH;
}
////TODO::implement sys_spu_thread_group_yield.
//Sorry i don't know where to get the caller group. So Only checking.
//Removed some stupid comments.
//Check the priority of the target spu group info.
//And check the state of target spu.
//if ((group_info->m_prio < current_thread.GetPrio())
// ||(group_info->m_state != SPU_THREAD_GROUP_STATUS_READY))
//{
// return CELL_OK;
//}
////Maybe Check for BUSY
////SET BUSY
//for (u32 i = 0; i < current_group_info->list.size(); i++)
//{
//if (CPUThread* t = Emu.GetCPU().GetThread(current_group_info->list[i]))
//{
//Not finding anything that suite the yield test. Do nothing.
//t->WaitFor(group_info);
//}
//}
//Do nothing now, so not entering the WAITING state.
//current_group_info->m_state = SPU_THREAD_GROUP_STATUS_WAITING;
////CLEAR BUSY
return CELL_OK;
}
//177: Left omit the EPERM check.
s32 sys_spu_thread_group_terminate(u32 id, int value)
{
sc_spu.Error("sys_spu_thread_group_terminate(id=%d, value=%d)", id, value);
SpuGroupInfo* group_info;
if (!Emu.GetIdManager().GetIDData(id, group_info))
{
return CELL_ESRCH;
}
if ((group_info->m_state != SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED)
&& (group_info->m_state != SPU_THREAD_GROUP_STATUS_INITIALIZED)
&& (group_info->m_state != SPU_THREAD_GROUP_STATUS_WAITING))
{
return CELL_ESTAT;
}
//TODO::I don't know who should i be referred to check the EPERM.
//Also i don't know how to check that is a primary or not. so disabled the EPERM check.
//Removed some stupid comments made.
//Attention. This action may not check for BUSY
//SET BUSY
for (u32 i = 0; i < group_info->list.size(); i++)
{
if (CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]))
{
t->Stop();
}
}
group_info->m_state = SPU_THREAD_GROUP_STATUS_INITIALIZED; // In initialized state but not running, maybe.
//Remove BUSY
group_info->m_exit_status = value;
////TODO::implement sys_spu_thread_group_terminate
return CELL_OK; return CELL_OK;
} }
@ -280,7 +432,7 @@ s32 sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status)
return CELL_ESRCH; return CELL_ESRCH;
} }
if (group_info->lock.exchange(1)) // acquire lock if (group_info->lock.exchange(1)) // acquire lock TODO:: The lock might be replaced.
{ {
return CELL_EBUSY; return CELL_EBUSY;
} }
@ -305,7 +457,7 @@ s32 sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status)
} }
} }
group_info->lock = 0; // release lock group_info->lock = 0; // release lock TODO: this LOCK may be replaced.
return CELL_OK; return CELL_OK;
} }

View File

@ -2,6 +2,17 @@
u32 LoadSpuImage(vfsStream& stream, u32& spu_ep); u32 LoadSpuImage(vfsStream& stream, u32& spu_ep);
enum
{
SYS_SPU_THREAD_GROUP_TYPE_NORMAL = 0x00,
SYS_SPU_THREAD_GROUP_TYPE_SEQUENTIAL = 0x01,
SYS_SPU_THREAD_GROUP_TYPE_SYSTEM = 0x02,
SYS_SPU_THREAD_GROUP_TYPE_MEMORY_FROM_CONTAINER = 0x04,
SYS_SPU_THREAD_GROUP_TYPE_NON_CONTEXT = 0x08,
SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT = 0x18,
SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM = 0x20
};
enum enum
{ {
SYS_SPU_THREAD_GROUP_JOIN_GROUP_EXIT = 0x0001, SYS_SPU_THREAD_GROUP_JOIN_GROUP_EXIT = 0x0001,
@ -9,6 +20,18 @@ enum
SYS_SPU_THREAD_GROUP_JOIN_TERMINATED = 0x0004 SYS_SPU_THREAD_GROUP_JOIN_TERMINATED = 0x0004
}; };
enum {
SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED,
SPU_THREAD_GROUP_STATUS_INITIALIZED,
SPU_THREAD_GROUP_STATUS_READY,
SPU_THREAD_GROUP_STATUS_WAITING,
SPU_THREAD_GROUP_STATUS_SUSPENDED,
SPU_THREAD_GROUP_STATUS_WAITING_AND_SUSPENDED,
SPU_THREAD_GROUP_STATUS_RUNNING,
SPU_THREAD_GROUP_STATUS_STOPPED,
SPU_THREAD_GROUP_STATUS_UNKNOWN
};
enum enum
{ {
SYS_SPU_SEGMENT_TYPE_COPY = 0x0001, SYS_SPU_SEGMENT_TYPE_COPY = 0x0001,
@ -65,6 +88,8 @@ struct SpuGroupInfo
int m_type; int m_type;
int m_ct; int m_ct;
u32 m_count; u32 m_count;
int m_state; //SPU Thread Group State.
int m_exit_status;
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)
@ -74,8 +99,11 @@ struct SpuGroupInfo
, lock(0) , lock(0)
, m_count(num) , m_count(num)
{ {
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_exit_status = 0;
} }
}; };
@ -88,6 +116,8 @@ s32 sys_spu_thread_group_destroy(u32 id);
s32 sys_spu_thread_group_start(u32 id); s32 sys_spu_thread_group_start(u32 id);
s32 sys_spu_thread_group_suspend(u32 id); s32 sys_spu_thread_group_suspend(u32 id);
s32 sys_spu_thread_group_resume(u32 id); s32 sys_spu_thread_group_resume(u32 id);
s32 sys_spu_thread_group_yield(u32 id);
s32 sys_spu_thread_group_terminate(u32 id, int value);
s32 sys_spu_thread_group_create(mem32_t id, u32 num, int prio, mem_ptr_t<sys_spu_thread_group_attribute> attr); s32 sys_spu_thread_group_create(mem32_t id, u32 num, int prio, mem_ptr_t<sys_spu_thread_group_attribute> attr);
s32 sys_spu_thread_create(mem32_t thread_id, mem32_t entry, u64 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr); s32 sys_spu_thread_create(mem32_t thread_id, mem32_t entry, u64 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr);
s32 sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status); s32 sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status);