1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-24 11:43:05 +01:00

Event flag partial implementation

This commit is contained in:
Nekotekina 2014-03-17 00:14:46 +04:00
parent 4aa6ddf3dd
commit 1a1bed2258
5 changed files with 162 additions and 16 deletions

View File

@ -4,10 +4,10 @@
enum
{
MFC_PUT_CMD = 0x20, MFC_PUTB_CMD = 0x21, MFC_PUTF_CMD = 0x22,
MFC_PUTR_CMD = 0x30, MFC_PUTRB_CMD = 0x31, MFC_PUTRF_CMD = 0x32,
MFC_PUTR_CMD = 0x30, MFC_PUTRB_CMD = 0x31, MFC_PUTRF_CMD = 0x32,
MFC_GET_CMD = 0x40, MFC_GETB_CMD = 0x41, MFC_GETF_CMD = 0x42,
MFC_PUTL_CMD = 0x24, MFC_PUTLB_CMD = 0x25, MFC_PUTLF_CMD = 0x26,
MFC_PUTRL_CMD = 0x34, MFC_PUTRLB_CMD = 0x35, MFC_PUTRLF_CMD = 0x36,
MFC_PUTRL_CMD = 0x34, MFC_PUTRLB_CMD = 0x35, MFC_PUTRLF_CMD = 0x36,
MFC_GETL_CMD = 0x44, MFC_GETLB_CMD = 0x45, MFC_GETLF_CMD = 0x46,
MFC_GETLLAR_CMD = 0xD0,
MFC_PUTLLC_CMD = 0xB4,

View File

@ -113,14 +113,26 @@ private:
}
}
break;
case 0x102: default:
if (!CPU.SPU.Out_MBox.GetCount()) // the real exit status
case 0x102:
if (!CPU.SPU.Out_MBox.GetCount())
{
ConLog.Warning("STOP: 0x%x (no message)", code);
ConLog.Error("sys_spu_thread_exit (no status, code 0x102)");
}
else if (Ini.HLELogging.GetValue() || code != 0x102)
else if (Ini.HLELogging.GetValue())
{
ConLog.Warning("STOP: 0x%x (message=0x%x)", code, CPU.SPU.Out_MBox.GetValue());
// the real exit status
ConLog.Write("sys_spu_thread_exit (status=0x%x)", CPU.SPU.Out_MBox.GetValue());
}
CPU.Stop();
break;
default:
if (!CPU.SPU.Out_MBox.GetCount())
{
ConLog.Error("Unknown STOP code: 0x%x (no message)", code);
}
else
{
ConLog.Error("Unknown STOP code: 0x%x (message=0x%x)", code, CPU.SPU.Out_MBox.GetValue());
}
CPU.Stop();
break;

View File

@ -6,7 +6,7 @@ SysCallBase sys_event_flag("sys_event_flag");
int sys_event_flag_create(mem32_t eflag_id, mem_ptr_t<sys_event_flag_attr> attr, u64 init)
{
sys_event_flag.Warning("sys_event_flag_create(eflag_id_addr=0x%x, attr_addr=0x%x, init=0x%llx)",
sys_event_flag.Log("sys_event_flag_create(eflag_id_addr=0x%x, attr_addr=0x%x, init=0x%llx)",
eflag_id.GetAddr(), attr.GetAddr(), init);
if(!eflag_id.IsGood() || !attr.IsGood())
@ -30,8 +30,8 @@ int sys_event_flag_create(mem32_t eflag_id, mem_ptr_t<sys_event_flag_attr> attr,
switch (attr->type.ToBE())
{
case se32(SYS_SYNC_WAITER_SINGLE): sys_event_flag.Warning("TODO: SYS_SYNC_WAITER_SINGLE type"); break;
case se32(SYS_SYNC_WAITER_MULTIPLE): sys_event_flag.Warning("TODO: SYS_SYNC_WAITER_MULTIPLE type"); break;
case se32(SYS_SYNC_WAITER_SINGLE): break;
case se32(SYS_SYNC_WAITER_MULTIPLE): sys_event_flag.Error("TODO: SYS_SYNC_WAITER_MULTIPLE type"); break;
default: return CELL_EINVAL;
}
@ -57,16 +57,136 @@ int sys_event_flag_destroy(u32 eflag_id)
int sys_event_flag_wait(u32 eflag_id, u64 bitptn, u32 mode, mem64_t result, u64 timeout)
{
sys_event_flag.Error("sys_event_flag_wait(eflag_id=%d, bitptn=0x%llx, mode=0x%x, result_addr=0x%x, timeout=%lld)",
sys_event_flag.Warning("sys_event_flag_wait(eflag_id=%d, bitptn=0x%llx, mode=0x%x, result_addr=0x%x, timeout=%lld)",
eflag_id, bitptn, mode, result.GetAddr(), timeout);
return CELL_OK;
if (result.IsGood()) result = 0;
switch (mode & 0xf)
{
case SYS_EVENT_FLAG_WAIT_AND: break;
case SYS_EVENT_FLAG_WAIT_OR: break;
default: return CELL_EINVAL;
}
switch (mode & ~0xf)
{
case 0: break; // ???
case SYS_EVENT_FLAG_WAIT_CLEAR: break;
case SYS_EVENT_FLAG_WAIT_CLEAR_ALL: break;
default: return CELL_EINVAL;
}
event_flag* ef;
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
u32 tid = GetCurrentPPUThread().GetId();
ef->waiters.push(tid);
if (ef->m_type == SYS_SYNC_WAITER_SINGLE && ef->waiters.list.GetCount() > 1)
{
ef->waiters.invalidate(tid);
return CELL_EPERM;
}
u32 counter = 0;
const u32 max_counter = timeout ? (timeout / 1000) : ~0;
while (true)
{
{
SMutexLocker lock(ef->m_mutex);
u64 flags = ef->flags;
if (((mode & SYS_EVENT_FLAG_WAIT_AND) && (flags & bitptn) == bitptn) ||
((mode & SYS_EVENT_FLAG_WAIT_OR) && (flags & bitptn)))
{
ef->waiters.invalidate(tid);
if (mode & SYS_EVENT_FLAG_WAIT_CLEAR)
{
ef->flags &= ~bitptn;
}
else if (mode & SYS_EVENT_FLAG_WAIT_CLEAR_ALL)
{
ef->flags = 0;
}
if (result.IsGood())
{
result = flags;
return CELL_OK;
}
return CELL_EFAULT;
}
}
Sleep(1);
if (counter++ > max_counter)
{
ef->waiters.invalidate(tid);
return CELL_ETIMEDOUT;
}
if (Emu.IsStopped())
{
ConLog.Warning("sys_event_flag_wait(id=%d) aborted", eflag_id);
return CELL_OK;
}
}
}
int sys_event_flag_trywait(u32 eflag_id, u64 bitptn, u32 mode, mem64_t result)
{
sys_event_flag.Error("sys_event_flag_trywait(eflag_id=%d, bitptn=0x%llx, mode=0x%x, result_addr=0x%x)",
sys_event_flag.Warning("sys_event_flag_trywait(eflag_id=%d, bitptn=0x%llx, mode=0x%x, result_addr=0x%x)",
eflag_id, bitptn, mode, result.GetAddr());
return CELL_OK;
if (result.IsGood()) result = 0;
switch (mode & 0xf)
{
case SYS_EVENT_FLAG_WAIT_AND: break;
case SYS_EVENT_FLAG_WAIT_OR: break;
default: return CELL_EINVAL;
}
switch (mode & ~0xf)
{
case 0: break; // ???
case SYS_EVENT_FLAG_WAIT_CLEAR: break;
case SYS_EVENT_FLAG_WAIT_CLEAR_ALL: break;
default: return CELL_EINVAL;
}
event_flag* ef;
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
SMutexLocker lock(ef->m_mutex);
u64 flags = ef->flags;
if (((mode & SYS_EVENT_FLAG_WAIT_AND) && (flags & bitptn) == bitptn) ||
((mode & SYS_EVENT_FLAG_WAIT_OR) && (flags & bitptn)))
{
if (mode & SYS_EVENT_FLAG_WAIT_CLEAR)
{
ef->flags &= ~bitptn;
}
else if (mode & SYS_EVENT_FLAG_WAIT_CLEAR_ALL)
{
ef->flags = 0;
}
if (result.IsGood())
{
result = flags;
return CELL_OK;
}
return CELL_EFAULT;
}
return CELL_EBUSY;
}
int sys_event_flag_set(u32 eflag_id, u64 bitptn)
@ -76,6 +196,7 @@ int sys_event_flag_set(u32 eflag_id, u64 bitptn)
event_flag* ef;
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
SMutexLocker lock(ef->m_mutex);
ef->flags |= bitptn;
return CELL_OK;
@ -88,6 +209,7 @@ int sys_event_flag_clear(u32 eflag_id, u64 bitptn)
event_flag* ef;
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
SMutexLocker lock(ef->m_mutex);
ef->flags &= bitptn;
return CELL_OK;
@ -96,6 +218,10 @@ int sys_event_flag_clear(u32 eflag_id, u64 bitptn)
int sys_event_flag_cancel(u32 eflag_id, mem32_t num)
{
sys_event_flag.Error("sys_event_flag_cancel(eflag_id=%d, num_addr=0x%x)", eflag_id, num.GetAddr());
event_flag* ef;
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
return CELL_OK;
}

View File

@ -4,6 +4,12 @@ enum
{
SYS_SYNC_WAITER_SINGLE = 0x10000,
SYS_SYNC_WAITER_MULTIPLE = 0x20000,
SYS_EVENT_FLAG_WAIT_AND = 0x01,
SYS_EVENT_FLAG_WAIT_OR = 0x02,
SYS_EVENT_FLAG_WAIT_CLEAR = 0x10,
SYS_EVENT_FLAG_WAIT_CLEAR_ALL = 0x20,
};
struct sys_event_flag_attr
@ -18,7 +24,9 @@ struct sys_event_flag_attr
struct event_flag
{
std::atomic<u64> flags;
SMutex m_mutex;
u64 flags;
SleepQueue waiters;
const u32 m_protocol;
const int m_type;

View File

@ -177,7 +177,7 @@ bool SleepQueue::invalidate(u32 tid)
{
if (list[i] = tid)
{
list[i] = 0;
list.RemoveAt(i);
return true;
}
}