2013-06-30 10:46:29 +02:00
|
|
|
#include "stdafx.h"
|
|
|
|
|
#include "Emu/SysCalls/SysCalls.h"
|
2014-02-13 17:59:13 +01:00
|
|
|
#include "Emu/SysCalls/lv2/SC_Condition.h"
|
2013-06-30 10:46:29 +02:00
|
|
|
|
|
|
|
|
SysCallBase sys_cond("sys_cond");
|
|
|
|
|
|
2014-02-13 17:59:13 +01:00
|
|
|
int sys_cond_create(mem32_t cond_id, u32 mutex_id, mem_ptr_t<sys_cond_attribute> attr)
|
2013-06-30 10:46:29 +02:00
|
|
|
{
|
2014-02-15 22:16:35 +01:00
|
|
|
sys_cond.Log("sys_cond_create(cond_id_addr=0x%x, mutex_id=%d, attr_addr=%d)",
|
2014-02-13 17:59:13 +01:00
|
|
|
cond_id.GetAddr(), mutex_id, attr.GetAddr());
|
2013-06-30 10:46:29 +02:00
|
|
|
|
2014-02-13 17:59:13 +01:00
|
|
|
if (!cond_id.IsGood() || !attr.IsGood())
|
2013-06-30 10:46:29 +02:00
|
|
|
{
|
2014-02-13 17:59:13 +01:00
|
|
|
return CELL_EFAULT;
|
2013-06-30 10:46:29 +02:00
|
|
|
}
|
|
|
|
|
|
2014-02-13 17:59:13 +01:00
|
|
|
if (attr->pshared.ToBE() != se32(0x200))
|
|
|
|
|
{
|
|
|
|
|
sys_cond.Error("Invalid pshared attribute(0x%x)", (u32)attr->pshared);
|
|
|
|
|
return CELL_EINVAL;
|
|
|
|
|
}
|
2013-06-30 10:46:29 +02:00
|
|
|
|
2014-02-14 12:40:41 +01:00
|
|
|
Mutex* mutex;
|
|
|
|
|
if (!Emu.GetIdManager().GetIDData(mutex_id, mutex))
|
2014-02-13 17:59:13 +01:00
|
|
|
{
|
|
|
|
|
return CELL_ESRCH;
|
|
|
|
|
}
|
2013-06-30 10:46:29 +02:00
|
|
|
|
2014-02-18 19:45:51 +01:00
|
|
|
if (mutex->is_recursive)
|
|
|
|
|
{
|
|
|
|
|
sys_cond.Warning("Recursive mutex(%d)", mutex_id);
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-14 12:40:41 +01:00
|
|
|
Cond* cond = new Cond(mutex, attr->name_u64);
|
|
|
|
|
u32 id = sys_cond.GetNewId(cond);
|
|
|
|
|
cond_id = id;
|
|
|
|
|
mutex->cond_count++;
|
2014-02-15 22:16:35 +01:00
|
|
|
sys_cond.Warning("*** condition created [%s] (mutex_id=%d): id = %d", wxString(attr->name, 8).wx_str(), mutex_id, cond_id.GetValue());
|
2013-06-30 10:46:29 +02:00
|
|
|
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sys_cond_destroy(u32 cond_id)
|
|
|
|
|
{
|
2014-02-14 12:40:41 +01:00
|
|
|
sys_cond.Warning("sys_cond_destroy(cond_id=%d)", cond_id);
|
2013-06-30 10:46:29 +02:00
|
|
|
|
2014-02-14 12:40:41 +01:00
|
|
|
Cond* cond;
|
2014-02-13 17:59:13 +01:00
|
|
|
if (!Emu.GetIdManager().GetIDData(cond_id, cond))
|
|
|
|
|
{
|
|
|
|
|
return CELL_ESRCH;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-14 12:40:41 +01:00
|
|
|
if (!cond->m_queue.finalize())
|
2014-02-13 17:59:13 +01:00
|
|
|
{
|
|
|
|
|
return CELL_EBUSY;
|
|
|
|
|
}
|
2013-06-30 10:46:29 +02:00
|
|
|
|
2014-02-14 12:40:41 +01:00
|
|
|
cond->mutex->cond_count--;
|
2013-06-30 10:46:29 +02:00
|
|
|
Emu.GetIdManager().RemoveID(cond_id);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sys_cond_wait(u32 cond_id, u64 timeout)
|
|
|
|
|
{
|
2014-02-14 12:40:41 +01:00
|
|
|
sys_cond.Log("sys_cond_wait(cond_id=%d, timeout=%lld)", cond_id, timeout);
|
2013-06-30 10:46:29 +02:00
|
|
|
|
2014-02-14 12:40:41 +01:00
|
|
|
Cond* cond;
|
|
|
|
|
if (!Emu.GetIdManager().GetIDData(cond_id, cond))
|
|
|
|
|
{
|
|
|
|
|
return CELL_ESRCH;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Mutex* mutex = cond->mutex;
|
|
|
|
|
u32 tid = GetCurrentPPUThread().GetId();
|
|
|
|
|
|
|
|
|
|
if (mutex->m_mutex.GetOwner() != tid)
|
|
|
|
|
{
|
|
|
|
|
return CELL_EPERM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cond->m_queue.push(tid);
|
|
|
|
|
|
2014-02-15 22:16:35 +01:00
|
|
|
mutex->recursive = 0;
|
2014-02-14 12:40:41 +01:00
|
|
|
mutex->m_mutex.unlock(tid);
|
2013-06-30 10:46:29 +02:00
|
|
|
|
2014-02-03 14:12:25 +01:00
|
|
|
u32 counter = 0;
|
2014-02-14 12:40:41 +01:00
|
|
|
const u32 max_counter = timeout ? (timeout / 1000) : ~0;
|
|
|
|
|
|
|
|
|
|
while (true)
|
2014-02-03 14:12:25 +01:00
|
|
|
{
|
2014-02-14 12:40:41 +01:00
|
|
|
/* switch (mutex->m_mutex.trylock(tid))
|
2014-02-12 20:03:14 +01:00
|
|
|
{
|
2014-02-14 12:40:41 +01:00
|
|
|
case SMR_OK: mutex->m_mutex.unlock(tid); break;
|
2014-02-15 22:16:35 +01:00
|
|
|
case SMR_SIGNAL: mutex->recursive = 1; return CELL_OK;
|
2014-02-14 12:40:41 +01:00
|
|
|
} */
|
|
|
|
|
if (mutex->m_mutex.GetOwner() == tid)
|
2014-02-03 14:12:25 +01:00
|
|
|
{
|
2014-02-14 12:40:41 +01:00
|
|
|
_mm_mfence();
|
2014-02-15 22:16:35 +01:00
|
|
|
mutex->recursive = 1;
|
2014-02-14 12:40:41 +01:00
|
|
|
return CELL_OK;
|
2014-02-03 14:12:25 +01:00
|
|
|
}
|
|
|
|
|
|
2014-02-14 12:40:41 +01:00
|
|
|
Sleep(1);
|
|
|
|
|
|
2014-02-03 14:12:25 +01:00
|
|
|
if (counter++ > max_counter)
|
|
|
|
|
{
|
2014-02-14 12:40:41 +01:00
|
|
|
cond->m_queue.invalidate(tid);
|
|
|
|
|
return CELL_ETIMEDOUT;
|
|
|
|
|
}
|
|
|
|
|
if (Emu.IsStopped())
|
|
|
|
|
{
|
|
|
|
|
ConLog.Warning("sys_cond_wait(id=%d) aborted", cond_id);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-06-30 10:46:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sys_cond_signal(u32 cond_id)
|
|
|
|
|
{
|
2014-02-14 12:40:41 +01:00
|
|
|
sys_cond.Log("sys_cond_signal(cond_id=%d)", cond_id);
|
2013-06-30 10:46:29 +02:00
|
|
|
|
2014-02-14 12:40:41 +01:00
|
|
|
Cond* cond;
|
|
|
|
|
if (!Emu.GetIdManager().GetIDData(cond_id, cond))
|
|
|
|
|
{
|
|
|
|
|
return CELL_ESRCH;
|
|
|
|
|
}
|
2013-06-30 10:46:29 +02:00
|
|
|
|
2014-02-14 12:40:41 +01:00
|
|
|
Mutex* mutex = cond->mutex;
|
|
|
|
|
u32 tid = GetCurrentPPUThread().GetId();
|
|
|
|
|
|
2014-02-20 03:16:17 +01:00
|
|
|
if (u32 target = (mutex->protocol == SYS_SYNC_PRIORITY ? mutex->m_queue.pop_prio() : mutex->m_queue.pop()))
|
2014-02-14 12:40:41 +01:00
|
|
|
{
|
|
|
|
|
if (mutex->m_mutex.trylock(target) != SMR_OK)
|
|
|
|
|
{
|
|
|
|
|
mutex->m_mutex.lock(tid);
|
2014-02-15 22:16:35 +01:00
|
|
|
mutex->recursive = 1;
|
2014-02-14 12:40:41 +01:00
|
|
|
mutex->m_mutex.unlock(tid, target);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Emu.IsStopped())
|
|
|
|
|
{
|
|
|
|
|
ConLog.Warning("sys_cond_signal(id=%d) aborted", cond_id);
|
|
|
|
|
}
|
2013-06-30 10:46:29 +02:00
|
|
|
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sys_cond_signal_all(u32 cond_id)
|
|
|
|
|
{
|
2014-02-14 12:40:41 +01:00
|
|
|
sys_cond.Log("sys_cond_signal_all(cond_id=%d)", cond_id);
|
|
|
|
|
|
|
|
|
|
Cond* cond;
|
|
|
|
|
if (!Emu.GetIdManager().GetIDData(cond_id, cond))
|
|
|
|
|
{
|
|
|
|
|
return CELL_ESRCH;
|
|
|
|
|
}
|
2013-06-30 10:46:29 +02:00
|
|
|
|
2014-02-14 12:40:41 +01:00
|
|
|
Mutex* mutex = cond->mutex;
|
|
|
|
|
u32 tid = GetCurrentPPUThread().GetId();
|
2013-06-30 10:46:29 +02:00
|
|
|
|
2014-02-20 03:16:17 +01:00
|
|
|
while (u32 target = (mutex->protocol == SYS_SYNC_PRIORITY ? mutex->m_queue.pop_prio() : mutex->m_queue.pop()))
|
2014-02-14 12:40:41 +01:00
|
|
|
{
|
|
|
|
|
if (mutex->m_mutex.trylock(target) != SMR_OK)
|
|
|
|
|
{
|
|
|
|
|
mutex->m_mutex.lock(tid);
|
2014-02-15 22:16:35 +01:00
|
|
|
mutex->recursive = 1;
|
2014-02-14 12:40:41 +01:00
|
|
|
mutex->m_mutex.unlock(tid, target);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Emu.IsStopped())
|
|
|
|
|
{
|
|
|
|
|
ConLog.Warning("sys_cond_signal_all(id=%d) aborted", cond_id);
|
|
|
|
|
}
|
2013-06-30 10:46:29 +02:00
|
|
|
|
2014-02-13 17:59:13 +01:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sys_cond_signal_to(u32 cond_id, u32 thread_id)
|
|
|
|
|
{
|
2014-02-14 12:40:41 +01:00
|
|
|
sys_cond.Log("sys_cond_signal_to(cond_id=%d, thread_id=%d)", cond_id, thread_id);
|
|
|
|
|
|
|
|
|
|
Cond* cond;
|
|
|
|
|
if (!Emu.GetIdManager().GetIDData(cond_id, cond))
|
|
|
|
|
{
|
|
|
|
|
return CELL_ESRCH;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!cond->m_queue.invalidate(thread_id))
|
|
|
|
|
{
|
|
|
|
|
return CELL_EPERM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Mutex* mutex = cond->mutex;
|
|
|
|
|
u32 tid = GetCurrentPPUThread().GetId();
|
|
|
|
|
|
|
|
|
|
if (mutex->m_mutex.trylock(thread_id) != SMR_OK)
|
|
|
|
|
{
|
|
|
|
|
mutex->m_mutex.lock(tid);
|
2014-02-15 22:16:35 +01:00
|
|
|
mutex->recursive = 1;
|
2014-02-14 12:40:41 +01:00
|
|
|
mutex->m_mutex.unlock(tid, thread_id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Emu.IsStopped())
|
|
|
|
|
{
|
|
|
|
|
ConLog.Warning("sys_cond_signal_to(id=%d, to=%d) aborted", cond_id, thread_id);
|
|
|
|
|
}
|
2014-02-13 17:59:13 +01:00
|
|
|
|
2013-06-30 10:46:29 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|