mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-09 16:31:28 +12:00
Event flag partial implementation
This commit is contained in:
parent
4aa6ddf3dd
commit
1a1bed2258
5 changed files with 162 additions and 16 deletions
|
@ -113,14 +113,26 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x102: default:
|
case 0x102:
|
||||||
if (!CPU.SPU.Out_MBox.GetCount()) // the real exit status
|
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();
|
CPU.Stop();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -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)
|
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);
|
eflag_id.GetAddr(), attr.GetAddr(), init);
|
||||||
|
|
||||||
if(!eflag_id.IsGood() || !attr.IsGood())
|
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())
|
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_SINGLE): break;
|
||||||
case se32(SYS_SYNC_WAITER_MULTIPLE): sys_event_flag.Warning("TODO: SYS_SYNC_WAITER_MULTIPLE type"); break;
|
case se32(SYS_SYNC_WAITER_MULTIPLE): sys_event_flag.Error("TODO: SYS_SYNC_WAITER_MULTIPLE type"); break;
|
||||||
default: return CELL_EINVAL;
|
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)
|
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);
|
eflag_id, bitptn, mode, result.GetAddr(), timeout);
|
||||||
|
|
||||||
|
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_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)
|
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());
|
eflag_id, bitptn, mode, result.GetAddr());
|
||||||
|
|
||||||
|
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_OK;
|
||||||
|
}
|
||||||
|
return CELL_EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CELL_EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_event_flag_set(u32 eflag_id, u64 bitptn)
|
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;
|
event_flag* ef;
|
||||||
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
|
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
|
||||||
|
|
||||||
|
SMutexLocker lock(ef->m_mutex);
|
||||||
ef->flags |= bitptn;
|
ef->flags |= bitptn;
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
|
@ -88,6 +209,7 @@ int sys_event_flag_clear(u32 eflag_id, u64 bitptn)
|
||||||
event_flag* ef;
|
event_flag* ef;
|
||||||
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
|
if(!sys_event_flag.CheckId(eflag_id, ef)) return CELL_ESRCH;
|
||||||
|
|
||||||
|
SMutexLocker lock(ef->m_mutex);
|
||||||
ef->flags &= bitptn;
|
ef->flags &= bitptn;
|
||||||
|
|
||||||
return CELL_OK;
|
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)
|
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());
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,12 @@ enum
|
||||||
{
|
{
|
||||||
SYS_SYNC_WAITER_SINGLE = 0x10000,
|
SYS_SYNC_WAITER_SINGLE = 0x10000,
|
||||||
SYS_SYNC_WAITER_MULTIPLE = 0x20000,
|
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
|
struct sys_event_flag_attr
|
||||||
|
@ -18,7 +24,9 @@ struct sys_event_flag_attr
|
||||||
|
|
||||||
struct event_flag
|
struct event_flag
|
||||||
{
|
{
|
||||||
std::atomic<u64> flags;
|
SMutex m_mutex;
|
||||||
|
u64 flags;
|
||||||
|
SleepQueue waiters;
|
||||||
const u32 m_protocol;
|
const u32 m_protocol;
|
||||||
const int m_type;
|
const int m_type;
|
||||||
|
|
||||||
|
|
|
@ -177,7 +177,7 @@ bool SleepQueue::invalidate(u32 tid)
|
||||||
{
|
{
|
||||||
if (list[i] = tid)
|
if (list[i] = tid)
|
||||||
{
|
{
|
||||||
list[i] = 0;
|
list.RemoveAt(i);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue