2012-11-15 00:39:56 +01:00
|
|
|
#include "stdafx.h"
|
2014-06-02 19:27:24 +02:00
|
|
|
#include "Emu/Memory/Memory.h"
|
|
|
|
|
#include "Emu/System.h"
|
2012-11-15 00:39:56 +01:00
|
|
|
#include "Emu/SysCalls/SysCalls.h"
|
2014-08-23 16:51:51 +02:00
|
|
|
|
2014-08-26 01:55:37 +02:00
|
|
|
#include "Emu/CPU/CPUThreadManager.h"
|
2014-08-23 16:51:51 +02:00
|
|
|
#include "Emu/Cell/PPUThread.h"
|
2014-06-25 00:38:34 +02:00
|
|
|
#include "sys_lwmutex.h"
|
2012-11-15 00:39:56 +01:00
|
|
|
|
2014-08-23 16:51:51 +02:00
|
|
|
SysCallBase sys_lwmutex("sys_lwmutex");
|
|
|
|
|
|
|
|
|
|
// TODO: move SleepQueue somewhere
|
2012-11-15 00:39:56 +01:00
|
|
|
|
2014-09-02 03:05:13 +02:00
|
|
|
s32 sys_lwmutex_create(vm::ptr<sys_lwmutex_t> lwmutex, vm::ptr<sys_lwmutex_attribute_t> attr)
|
2012-11-15 00:39:56 +01:00
|
|
|
{
|
2014-08-23 16:51:51 +02:00
|
|
|
sys_lwmutex.Log("sys_lwmutex_create(lwmutex_addr=0x%x, lwmutex_attr_addr=0x%x)",
|
2014-09-02 03:05:13 +02:00
|
|
|
lwmutex.addr(), attr.addr());
|
2012-11-15 00:39:56 +01:00
|
|
|
|
2014-06-07 09:08:16 +02:00
|
|
|
switch (attr->attr_recursive.ToBE())
|
2013-07-06 01:49:38 +02:00
|
|
|
{
|
2014-06-07 09:08:16 +02:00
|
|
|
case se32(SYS_SYNC_RECURSIVE): break;
|
|
|
|
|
case se32(SYS_SYNC_NOT_RECURSIVE): break;
|
2014-08-23 16:51:51 +02:00
|
|
|
default: sys_lwmutex.Error("Unknown recursive attribute(0x%x)", (u32)attr->attr_recursive); return CELL_EINVAL;
|
2013-07-06 01:49:38 +02:00
|
|
|
}
|
|
|
|
|
|
2014-06-07 09:08:16 +02:00
|
|
|
switch (attr->attr_protocol.ToBE())
|
2014-01-19 22:19:37 +01:00
|
|
|
{
|
2014-06-07 09:08:16 +02:00
|
|
|
case se32(SYS_SYNC_PRIORITY): break;
|
|
|
|
|
case se32(SYS_SYNC_RETRY): break;
|
2014-08-23 16:51:51 +02:00
|
|
|
case se32(SYS_SYNC_PRIORITY_INHERIT): sys_lwmutex.Error("Invalid SYS_SYNC_PRIORITY_INHERIT protocol attr"); return CELL_EINVAL;
|
2014-06-07 09:08:16 +02:00
|
|
|
case se32(SYS_SYNC_FIFO): break;
|
2014-08-23 16:51:51 +02:00
|
|
|
default: sys_lwmutex.Error("Unknown protocol attribute(0x%x)", (u32)attr->attr_protocol); return CELL_EINVAL;
|
2014-01-19 22:19:37 +01:00
|
|
|
}
|
|
|
|
|
|
2014-02-09 12:11:48 +01:00
|
|
|
lwmutex->attribute = attr->attr_protocol | attr->attr_recursive;
|
2014-03-31 12:04:34 +02:00
|
|
|
lwmutex->waiter = 0;
|
2014-02-26 12:27:06 +01:00
|
|
|
lwmutex->mutex.initialize();
|
2014-02-22 01:26:50 +01:00
|
|
|
//lwmutex->waiter = lwmutex->owner.GetOwner();
|
2014-01-19 22:19:37 +01:00
|
|
|
lwmutex->pad = 0;
|
|
|
|
|
lwmutex->recursive_count = 0;
|
|
|
|
|
|
2014-08-23 16:51:51 +02:00
|
|
|
u32 sq_id = sys_lwmutex.GetNewId(new SleepQueue(attr->name_u64), TYPE_LWMUTEX);
|
2014-02-09 12:11:48 +01:00
|
|
|
lwmutex->sleep_queue = sq_id;
|
|
|
|
|
|
2014-08-23 16:51:51 +02:00
|
|
|
sys_lwmutex.Warning("*** lwmutex created [%s] (attribute=0x%x): sq_id = %d",
|
2014-04-01 02:33:55 +02:00
|
|
|
std::string(attr->name, 8).c_str(), (u32) lwmutex->attribute, sq_id);
|
2012-11-15 00:39:56 +01:00
|
|
|
|
2014-09-13 22:40:12 +02:00
|
|
|
Emu.GetSyncPrimManager().AddLwMutexData(sq_id, std::string(attr->name, 8), GetCurrentPPUThread().GetId());
|
|
|
|
|
|
2013-06-30 10:46:29 +02:00
|
|
|
return CELL_OK;
|
2012-11-15 00:39:56 +01:00
|
|
|
}
|
|
|
|
|
|
2014-09-02 03:05:13 +02:00
|
|
|
s32 sys_lwmutex_destroy(vm::ptr<sys_lwmutex_t> lwmutex)
|
2012-11-15 00:39:56 +01:00
|
|
|
{
|
2014-09-02 03:05:13 +02:00
|
|
|
sys_lwmutex.Warning("sys_lwmutex_destroy(lwmutex_addr=0x%x)", lwmutex.addr());
|
2014-01-29 21:31:09 +01:00
|
|
|
|
2014-02-09 12:11:48 +01:00
|
|
|
u32 sq_id = lwmutex->sleep_queue;
|
|
|
|
|
if (!Emu.GetIdManager().CheckID(sq_id)) return CELL_ESRCH;
|
|
|
|
|
|
2014-02-05 12:55:32 +01:00
|
|
|
// try to make it unable to lock
|
2014-02-26 12:27:06 +01:00
|
|
|
switch (int res = lwmutex->trylock(lwmutex->mutex.GetDeadValue()))
|
2014-02-06 23:55:48 +01:00
|
|
|
{
|
2014-02-09 12:11:48 +01:00
|
|
|
case CELL_OK:
|
2014-02-26 12:27:06 +01:00
|
|
|
lwmutex->all_info() = 0;
|
2014-03-06 12:40:50 +01:00
|
|
|
lwmutex->attribute = 0xDEADBEEF;
|
2014-02-09 12:11:48 +01:00
|
|
|
lwmutex->sleep_queue = 0;
|
|
|
|
|
Emu.GetIdManager().RemoveID(sq_id);
|
2014-09-13 22:40:12 +02:00
|
|
|
Emu.GetSyncPrimManager().EraseLwMutexData(sq_id);
|
2014-02-09 12:11:48 +01:00
|
|
|
default: return res;
|
2014-02-06 23:55:48 +01:00
|
|
|
}
|
2012-11-15 00:39:56 +01:00
|
|
|
}
|
|
|
|
|
|
2014-09-02 03:05:13 +02:00
|
|
|
s32 sys_lwmutex_lock(vm::ptr<sys_lwmutex_t> lwmutex, u64 timeout)
|
2012-11-15 00:39:56 +01:00
|
|
|
{
|
2014-09-02 03:05:13 +02:00
|
|
|
sys_lwmutex.Log("sys_lwmutex_lock(lwmutex_addr=0x%x, timeout=%lld)", lwmutex.addr(), timeout);
|
2014-01-19 22:19:37 +01:00
|
|
|
|
2014-02-18 19:45:51 +01:00
|
|
|
//ConLog.Write("*** lock mutex (addr=0x%x, attr=0x%x, Nrec=%d, owner=%d, waiter=%d)",
|
2014-09-02 03:05:13 +02:00
|
|
|
//lwmutex.addr(), (u32)lwmutex->attribute, (u32)lwmutex->recursive_count, lwmutex->vars.parts.owner.GetOwner(), (u32)lwmutex->waiter);
|
2014-02-18 19:45:51 +01:00
|
|
|
|
2014-07-18 18:55:26 +02:00
|
|
|
return lwmutex->lock(be_t<u32>::MakeFromLE(GetCurrentPPUThread().GetId()), timeout ? ((timeout < 1000) ? 1 : (timeout / 1000)) : 0);
|
2012-11-15 00:39:56 +01:00
|
|
|
}
|
|
|
|
|
|
2014-09-02 03:05:13 +02:00
|
|
|
s32 sys_lwmutex_trylock(vm::ptr<sys_lwmutex_t> lwmutex)
|
2012-11-15 00:39:56 +01:00
|
|
|
{
|
2014-09-02 03:05:13 +02:00
|
|
|
sys_lwmutex.Log("sys_lwmutex_trylock(lwmutex_addr=0x%x)", lwmutex.addr());
|
2013-06-30 10:46:29 +02:00
|
|
|
|
2014-07-18 18:55:26 +02:00
|
|
|
return lwmutex->trylock(be_t<u32>::MakeFromLE(GetCurrentPPUThread().GetId()));
|
2012-11-15 00:39:56 +01:00
|
|
|
}
|
|
|
|
|
|
2014-09-02 03:05:13 +02:00
|
|
|
s32 sys_lwmutex_unlock(vm::ptr<sys_lwmutex_t> lwmutex)
|
2012-11-15 00:39:56 +01:00
|
|
|
{
|
2014-09-02 03:05:13 +02:00
|
|
|
sys_lwmutex.Log("sys_lwmutex_unlock(lwmutex_addr=0x%x)", lwmutex.addr());
|
2014-01-19 22:19:37 +01:00
|
|
|
|
2014-02-18 19:45:51 +01:00
|
|
|
//ConLog.Write("*** unlocking mutex (addr=0x%x, attr=0x%x, Nrec=%d, owner=%d, waiter=%d)",
|
2014-09-02 03:05:13 +02:00
|
|
|
//lwmutex.addr(), (u32)lwmutex->attribute, (u32)lwmutex->recursive_count, (u32)lwmutex->vars.parts.owner.GetOwner(), (u32)lwmutex->waiter);
|
2014-02-18 19:45:51 +01:00
|
|
|
|
2014-07-18 18:55:26 +02:00
|
|
|
return lwmutex->unlock(be_t<u32>::MakeFromLE(GetCurrentPPUThread().GetId()));
|
2012-11-15 00:39:56 +01:00
|
|
|
}
|
2013-06-30 10:46:29 +02:00
|
|
|
|
2014-02-12 20:03:14 +01:00
|
|
|
void SleepQueue::push(u32 tid)
|
|
|
|
|
{
|
2014-03-07 22:31:08 +01:00
|
|
|
std::lock_guard<std::mutex> lock(m_mutex);
|
2014-04-10 00:54:32 +02:00
|
|
|
list.push_back(tid);
|
2014-02-12 20:03:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u32 SleepQueue::pop() // SYS_SYNC_FIFO
|
|
|
|
|
{
|
2014-03-07 22:31:08 +01:00
|
|
|
std::lock_guard<std::mutex> lock(m_mutex);
|
2014-02-12 20:03:14 +01:00
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
2014-04-10 00:54:32 +02:00
|
|
|
if (list.size())
|
2014-02-12 20:03:14 +01:00
|
|
|
{
|
|
|
|
|
u32 res = list[0];
|
2014-04-10 00:54:32 +02:00
|
|
|
list.erase(list.begin());
|
2014-02-12 20:03:14 +01:00
|
|
|
if (res && Emu.GetIdManager().CheckID(res))
|
|
|
|
|
// check thread
|
|
|
|
|
{
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u32 SleepQueue::pop_prio() // SYS_SYNC_PRIORITY
|
|
|
|
|
{
|
2014-03-07 22:31:08 +01:00
|
|
|
std::lock_guard<std::mutex> lock(m_mutex);
|
2014-02-12 20:03:14 +01:00
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
2014-04-10 00:54:32 +02:00
|
|
|
if (list.size())
|
2014-02-12 20:03:14 +01:00
|
|
|
{
|
2014-08-30 20:35:18 +02:00
|
|
|
u64 highest_prio = ~0ull;
|
2014-02-12 20:03:14 +01:00
|
|
|
u32 sel = 0;
|
2014-04-10 00:54:32 +02:00
|
|
|
for (u32 i = 0; i < list.size(); i++)
|
2014-02-12 20:03:14 +01:00
|
|
|
{
|
|
|
|
|
CPUThread* t = Emu.GetCPU().GetThread(list[i]);
|
|
|
|
|
if (!t)
|
|
|
|
|
{
|
|
|
|
|
list[i] = 0;
|
|
|
|
|
sel = i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
u64 prio = t->GetPrio();
|
2014-02-22 01:26:50 +01:00
|
|
|
if (prio < highest_prio)
|
2014-02-12 20:03:14 +01:00
|
|
|
{
|
2014-02-22 01:26:50 +01:00
|
|
|
highest_prio = prio;
|
2014-02-12 20:03:14 +01:00
|
|
|
sel = i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
u32 res = list[sel];
|
2014-04-10 00:54:32 +02:00
|
|
|
list.erase(list.begin() + sel);
|
2014-02-12 20:03:14 +01:00
|
|
|
/* if (Emu.GetIdManager().CheckID(res)) */
|
|
|
|
|
if (res)
|
|
|
|
|
// check thread
|
|
|
|
|
{
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u32 SleepQueue::pop_prio_inherit() // (TODO)
|
|
|
|
|
{
|
2014-08-23 16:51:51 +02:00
|
|
|
sys_lwmutex.Error("TODO: SleepQueue::pop_prio_inherit()");
|
2014-02-12 20:03:14 +01:00
|
|
|
Emu.Pause();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-14 12:40:41 +01:00
|
|
|
bool SleepQueue::invalidate(u32 tid)
|
2014-02-12 20:03:14 +01:00
|
|
|
{
|
2014-03-07 22:31:08 +01:00
|
|
|
std::lock_guard<std::mutex> lock(m_mutex);
|
2014-02-12 20:03:14 +01:00
|
|
|
|
2014-04-10 00:54:32 +02:00
|
|
|
if (tid) for (u32 i = 0; i < list.size(); i++)
|
2014-02-12 20:03:14 +01:00
|
|
|
{
|
2014-03-26 01:29:17 +01:00
|
|
|
if (list[i] == tid)
|
2014-02-12 20:03:14 +01:00
|
|
|
{
|
2014-04-10 00:54:32 +02:00
|
|
|
list.erase(list.begin() + i);
|
2014-02-14 12:40:41 +01:00
|
|
|
return true;
|
2014-02-12 20:03:14 +01:00
|
|
|
}
|
|
|
|
|
}
|
2014-02-14 12:40:41 +01:00
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-21 16:24:27 +02:00
|
|
|
u32 SleepQueue::count()
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(m_mutex);
|
|
|
|
|
|
2014-06-22 12:59:28 +02:00
|
|
|
u32 result = 0;
|
|
|
|
|
for (u32 i = 0; i < list.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
if (list[i]) result++;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
2014-06-21 16:24:27 +02:00
|
|
|
}
|
|
|
|
|
|
2014-02-14 12:40:41 +01:00
|
|
|
bool SleepQueue::finalize()
|
|
|
|
|
{
|
2014-03-07 22:31:08 +01:00
|
|
|
if (!m_mutex.try_lock()) return false;
|
2014-02-14 12:40:41 +01:00
|
|
|
|
2014-04-10 00:54:32 +02:00
|
|
|
for (u32 i = 0; i < list.size(); i++)
|
2014-02-14 12:40:41 +01:00
|
|
|
{
|
|
|
|
|
if (list[i])
|
|
|
|
|
{
|
2014-03-07 22:31:08 +01:00
|
|
|
m_mutex.unlock();
|
2014-02-14 12:40:41 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-13 10:17:45 +01:00
|
|
|
m_mutex.unlock();
|
2014-02-14 12:40:41 +01:00
|
|
|
return true;
|
2014-02-12 20:03:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sys_lwmutex_t::trylock(be_t<u32> tid)
|
|
|
|
|
{
|
2014-03-06 12:40:50 +01:00
|
|
|
if (attribute.ToBE() == se32(0xDEADBEEF)) return CELL_EINVAL;
|
|
|
|
|
|
2014-03-22 22:04:55 +01:00
|
|
|
be_t<u32> owner_tid = mutex.GetFreeValue();
|
2014-03-07 13:03:42 +01:00
|
|
|
|
2014-03-22 22:04:55 +01:00
|
|
|
if (mutex.unlock(owner_tid, owner_tid) != SMR_OK) // check free value
|
2014-03-07 13:03:42 +01:00
|
|
|
{
|
2014-03-22 22:04:55 +01:00
|
|
|
owner_tid = mutex.GetOwner();
|
2014-03-31 12:04:34 +02:00
|
|
|
/*if (CPUThread* tt = Emu.GetCPU().GetThread(owner_tid))
|
2014-03-07 13:03:42 +01:00
|
|
|
{
|
|
|
|
|
if (!tt->IsAlive())
|
|
|
|
|
{
|
|
|
|
|
sc_lwmutex.Error("sys_lwmutex_t::(try)lock(%d): deadlock on invalid thread(%d)", (u32)sleep_queue, (u32)owner_tid);
|
|
|
|
|
mutex.unlock(owner_tid, tid);
|
|
|
|
|
recursive_count = 1;
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
sc_lwmutex.Error("sys_lwmutex_t::(try)lock(%d): deadlock on invalid thread(%d)", (u32)sleep_queue, (u32)owner_tid);
|
|
|
|
|
mutex.unlock(owner_tid, tid);
|
|
|
|
|
recursive_count = 1;
|
|
|
|
|
return CELL_OK;
|
2014-03-31 12:04:34 +02:00
|
|
|
}*/
|
2014-03-07 13:03:42 +01:00
|
|
|
}
|
|
|
|
|
|
2014-03-07 22:31:08 +01:00
|
|
|
/*while ((attribute.ToBE() & se32(SYS_SYNC_ATTR_RECURSIVE_MASK)) == 0)
|
2014-03-06 12:40:50 +01:00
|
|
|
{
|
|
|
|
|
if (Emu.IsStopped())
|
|
|
|
|
{
|
2014-06-27 15:26:46 +02:00
|
|
|
LOG_WARNING(HLE, "(hack) sys_lwmutex_t::(try)lock aborted (waiting for recursive attribute, attr=0x%x)", (u32)attribute);
|
2014-03-06 12:40:50 +01:00
|
|
|
return CELL_ESRCH;
|
|
|
|
|
}
|
2014-07-12 09:02:39 +02:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
2014-03-07 22:31:08 +01:00
|
|
|
}*/
|
2014-02-12 20:03:14 +01:00
|
|
|
|
2014-03-07 13:03:42 +01:00
|
|
|
if (tid == owner_tid)
|
2014-02-12 20:03:14 +01:00
|
|
|
{
|
|
|
|
|
if (attribute.ToBE() & se32(SYS_SYNC_RECURSIVE))
|
|
|
|
|
{
|
|
|
|
|
recursive_count += 1;
|
|
|
|
|
if (!recursive_count.ToBE()) return CELL_EKRESOURCE;
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return CELL_EDEADLK;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-26 12:27:06 +01:00
|
|
|
switch (mutex.trylock(tid))
|
2014-02-12 20:03:14 +01:00
|
|
|
{
|
|
|
|
|
case SMR_OK: recursive_count = 1; return CELL_OK;
|
|
|
|
|
case SMR_FAILED: return CELL_EBUSY;
|
|
|
|
|
default: return CELL_EINVAL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sys_lwmutex_t::unlock(be_t<u32> tid)
|
|
|
|
|
{
|
2014-03-22 22:04:55 +01:00
|
|
|
if (mutex.unlock(tid, tid) != SMR_OK)
|
2014-02-12 20:03:14 +01:00
|
|
|
{
|
|
|
|
|
return CELL_EPERM;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2014-03-07 13:03:42 +01:00
|
|
|
if (!recursive_count || (recursive_count.ToBE() != se32(1) && (attribute.ToBE() & se32(SYS_SYNC_NOT_RECURSIVE))))
|
|
|
|
|
{
|
2014-08-23 16:51:51 +02:00
|
|
|
sys_lwmutex.Error("sys_lwmutex_t::unlock(%d): wrong recursive value fixed (%d)", (u32)sleep_queue, (u32)recursive_count);
|
2014-03-07 13:03:42 +01:00
|
|
|
recursive_count = 1;
|
|
|
|
|
}
|
2014-02-12 20:03:14 +01:00
|
|
|
recursive_count -= 1;
|
|
|
|
|
if (!recursive_count.ToBE())
|
|
|
|
|
{
|
2014-07-18 18:55:26 +02:00
|
|
|
be_t<u32> target = be_t<u32>::MakeFromBE(se32(0));
|
2014-06-07 09:08:16 +02:00
|
|
|
switch (attribute.ToBE() & se32(SYS_SYNC_ATTR_PROTOCOL_MASK))
|
2014-02-12 20:03:14 +01:00
|
|
|
{
|
2014-06-07 09:08:16 +02:00
|
|
|
case se32(SYS_SYNC_FIFO):
|
|
|
|
|
case se32(SYS_SYNC_PRIORITY):
|
2014-02-12 20:03:14 +01:00
|
|
|
SleepQueue* sq;
|
|
|
|
|
if (!Emu.GetIdManager().GetIDData(sleep_queue, sq)) return CELL_ESRCH;
|
2014-06-07 08:34:36 +02:00
|
|
|
target = attribute & SYS_SYNC_FIFO ? sq->pop() : sq->pop_prio();
|
2014-06-07 09:08:16 +02:00
|
|
|
case se32(SYS_SYNC_RETRY): break;
|
2014-02-12 20:03:14 +01:00
|
|
|
}
|
2014-02-26 12:27:06 +01:00
|
|
|
if (target) mutex.unlock(tid, target);
|
|
|
|
|
else mutex.unlock(tid);
|
2014-02-12 20:03:14 +01:00
|
|
|
}
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sys_lwmutex_t::lock(be_t<u32> tid, u64 timeout)
|
|
|
|
|
{
|
|
|
|
|
switch (int res = trylock(tid))
|
|
|
|
|
{
|
2014-04-10 00:54:32 +02:00
|
|
|
case static_cast<int>(CELL_EBUSY): break;
|
2014-02-12 20:03:14 +01:00
|
|
|
default: return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SleepQueue* sq;
|
|
|
|
|
if (!Emu.GetIdManager().GetIDData(sleep_queue, sq)) return CELL_ESRCH;
|
|
|
|
|
|
2014-06-07 09:08:16 +02:00
|
|
|
switch (attribute.ToBE() & se32(SYS_SYNC_ATTR_PROTOCOL_MASK))
|
2014-02-12 20:03:14 +01:00
|
|
|
{
|
2014-06-07 09:08:16 +02:00
|
|
|
case se32(SYS_SYNC_PRIORITY):
|
|
|
|
|
case se32(SYS_SYNC_FIFO):
|
2014-02-12 20:03:14 +01:00
|
|
|
sq->push(tid);
|
|
|
|
|
default: break;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-26 12:27:06 +01:00
|
|
|
switch (mutex.lock(tid, timeout))
|
2014-02-12 20:03:14 +01:00
|
|
|
{
|
|
|
|
|
case SMR_OK:
|
|
|
|
|
sq->invalidate(tid);
|
|
|
|
|
case SMR_SIGNAL:
|
|
|
|
|
recursive_count = 1; return CELL_OK;
|
|
|
|
|
case SMR_TIMEOUT:
|
|
|
|
|
sq->invalidate(tid); return CELL_ETIMEDOUT;
|
|
|
|
|
case SMR_ABORT:
|
2014-08-23 16:51:51 +02:00
|
|
|
if (Emu.IsStopped()) sys_lwmutex.Warning("sys_lwmutex_t::lock(sq=%d) aborted", (u32)sleep_queue);
|
2014-02-12 20:03:14 +01:00
|
|
|
default:
|
|
|
|
|
sq->invalidate(tid); return CELL_EINVAL;
|
|
|
|
|
}
|
2014-02-23 17:52:52 +01:00
|
|
|
}
|