mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
sys_lwcond, sys_mutex, sys_cond rewritten
Some bugs fixed
This commit is contained in:
parent
209155d71d
commit
e94ea409fe
@ -449,7 +449,6 @@ int cellAudioSetNotifyEventQueue(u64 key)
|
||||
return CELL_AUDIO_ERROR_PARAM;
|
||||
}
|
||||
|
||||
eq->events.push(0, 0, 0, 0);
|
||||
eq->events.push(0, 0, 0, 0);
|
||||
|
||||
return CELL_OK;
|
||||
|
@ -725,7 +725,7 @@ int cellRescSetBufferAddress(mem32_t colorBuffers, mem32_t vertexArray, mem32_t
|
||||
|
||||
if(!s_rescInternalInstance->m_bInitialized)
|
||||
return CELL_RESC_ERROR_NOT_INITIALIZED;
|
||||
if(!colorBuffers.GetAddr() || !vertexArray.GetAddr() || !fragmentShader.GetAddr())
|
||||
if(!colorBuffers.IsGood() || !vertexArray.IsGood() || !fragmentShader.IsGood())
|
||||
return CELL_RESC_ERROR_BAD_ARGUMENT;
|
||||
if(colorBuffers.GetAddr() % COLOR_BUFFER_ALIGNMENT ||
|
||||
vertexArray.GetAddr() % VERTEX_BUFFER_ALIGNMENT ||
|
||||
|
@ -74,7 +74,7 @@ static func_caller* sc_table[1024] =
|
||||
bind_func(sys_cond_wait), //107 (0x06B)
|
||||
bind_func(sys_cond_signal), //108 (0x06C)
|
||||
bind_func(sys_cond_signal_all), //109 (0x06D)
|
||||
null_func, null_func, null_func, null_func, //113 (0x071)
|
||||
bind_func(sys_cond_signal_to), null_func, null_func, null_func, //113 (0x071)
|
||||
bind_func(sys_semaphore_get_value), //114 (0x072)
|
||||
null_func, null_func, null_func, bind_func(sys_event_flag_clear), null_func, //119 (0x077)
|
||||
bind_func(sys_rwlock_create), //120 (0x078)
|
||||
|
@ -179,7 +179,7 @@ extern int sys_cond_signal_all(u32 cond_id);
|
||||
extern int sys_cond_signal_to(u32 cond_id, u32 thread_id);
|
||||
|
||||
//sys_mutex
|
||||
extern int sys_mutex_create(u32 mutex_id_addr, u32 attr_addr);
|
||||
extern int sys_mutex_create(mem32_t mutex_id, mem_ptr_t<sys_mutex_attribute> attr);
|
||||
extern int sys_mutex_destroy(u32 mutex_id);
|
||||
extern int sys_mutex_lock(u32 mutex_id, u64 timeout);
|
||||
extern int sys_mutex_trylock(u32 mutex_id);
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "SC_Mutex.h"
|
||||
#include "Emu/SysCalls/lv2/SC_Condition.h"
|
||||
|
||||
SysCallBase sys_cond("sys_cond");
|
||||
@ -21,13 +20,16 @@ int sys_cond_create(mem32_t cond_id, u32 mutex_id, mem_ptr_t<sys_cond_attribute>
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
mutex* mtx_data;
|
||||
if (!Emu.GetIdManager().GetIDData(mutex_id, mtx_data))
|
||||
Mutex* mutex;
|
||||
if (!Emu.GetIdManager().GetIDData(mutex_id, mutex))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
cond_id = sys_cond.GetNewId(new condition(mtx_data->mtx, attr->name_u64));
|
||||
Cond* cond = new Cond(mutex, attr->name_u64);
|
||||
u32 id = sys_cond.GetNewId(cond);
|
||||
cond_id = id;
|
||||
mutex->cond_count++;
|
||||
sys_cond.Warning("*** condition created [%s]: id = %d", wxString(attr->name, 8).wx_str(), cond_id.GetValue());
|
||||
|
||||
return CELL_OK;
|
||||
@ -35,88 +37,165 @@ int sys_cond_create(mem32_t cond_id, u32 mutex_id, mem_ptr_t<sys_cond_attribute>
|
||||
|
||||
int sys_cond_destroy(u32 cond_id)
|
||||
{
|
||||
sys_cond.Error("sys_cond_destroy(cond_id=%d)", cond_id);
|
||||
sys_cond.Warning("sys_cond_destroy(cond_id=%d)", cond_id);
|
||||
|
||||
condition* cond;
|
||||
Cond* cond;
|
||||
if (!Emu.GetIdManager().GetIDData(cond_id, cond))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (true) // TODO
|
||||
if (!cond->m_queue.finalize())
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
cond->mutex->cond_count--;
|
||||
Emu.GetIdManager().RemoveID(cond_id);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_cond_wait(u32 cond_id, u64 timeout)
|
||||
{
|
||||
sys_cond.Warning("sys_cond_wait(cond_id=%d, timeout=%lld)", cond_id, timeout);
|
||||
sys_cond.Log("sys_cond_wait(cond_id=%d, timeout=%lld)", cond_id, timeout);
|
||||
|
||||
condition* cond_data = nullptr;
|
||||
if(!sys_cond.CheckId(cond_id, cond_data)) return CELL_ESRCH;
|
||||
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);
|
||||
|
||||
mutex->m_mutex.unlock(tid);
|
||||
|
||||
u32 counter = 0;
|
||||
const u32 max_counter = timeout ? (timeout / 1000) : 20000;
|
||||
do
|
||||
const u32 max_counter = timeout ? (timeout / 1000) : ~0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
/* switch (mutex->m_mutex.trylock(tid))
|
||||
{
|
||||
ConLog.Warning("sys_cond_wait(cond_id=%d, ...) aborted", cond_id);
|
||||
return CELL_ETIMEDOUT;
|
||||
case SMR_OK: mutex->m_mutex.unlock(tid); break;
|
||||
case SMR_SIGNAL: return CELL_OK;
|
||||
} */
|
||||
if (mutex->m_mutex.GetOwner() == tid)
|
||||
{
|
||||
_mm_mfence();
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
switch (cond_data->cond.WaitTimeout(1))
|
||||
{
|
||||
case wxCOND_NO_ERROR: return CELL_OK;
|
||||
case wxCOND_TIMEOUT: break;
|
||||
default: return CELL_EPERM;
|
||||
}
|
||||
Sleep(1);
|
||||
|
||||
if (counter++ > max_counter)
|
||||
{
|
||||
if (!timeout)
|
||||
{
|
||||
counter = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
} while (true);
|
||||
cond->m_queue.invalidate(tid);
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_cond_wait(id=%d) aborted", cond_id);
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int sys_cond_signal(u32 cond_id)
|
||||
{
|
||||
sys_cond.Warning("sys_cond_signal(cond_id=%d)", cond_id);
|
||||
sys_cond.Log("sys_cond_signal(cond_id=%d)", cond_id);
|
||||
|
||||
condition* cond_data = nullptr;
|
||||
if(!sys_cond.CheckId(cond_id, cond_data)) return CELL_ESRCH;
|
||||
Cond* cond;
|
||||
if (!Emu.GetIdManager().GetIDData(cond_id, cond))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
cond_data->cond.Signal();
|
||||
Mutex* mutex = cond->mutex;
|
||||
u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
if (u32 target = mutex->protocol == SYS_SYNC_PRIORITY ? mutex->m_queue.pop_prio() : mutex->m_queue.pop())
|
||||
{
|
||||
if (mutex->m_mutex.trylock(target) != SMR_OK)
|
||||
{
|
||||
mutex->m_mutex.lock(tid);
|
||||
mutex->m_mutex.unlock(tid, target);
|
||||
}
|
||||
}
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_cond_signal(id=%d) aborted", cond_id);
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_cond_signal_all(u32 cond_id)
|
||||
{
|
||||
sys_cond.Warning("sys_cond_signal_all(cond_id=%d)", cond_id);
|
||||
sys_cond.Log("sys_cond_signal_all(cond_id=%d)", cond_id);
|
||||
|
||||
condition* cond_data = nullptr;
|
||||
if(!sys_cond.CheckId(cond_id, cond_data)) return CELL_ESRCH;
|
||||
Cond* cond;
|
||||
if (!Emu.GetIdManager().GetIDData(cond_id, cond))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
cond_data->cond.Broadcast();
|
||||
Mutex* mutex = cond->mutex;
|
||||
u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
while (u32 target = mutex->protocol == SYS_SYNC_PRIORITY ? mutex->m_queue.pop_prio() : mutex->m_queue.pop())
|
||||
{
|
||||
if (mutex->m_mutex.trylock(target) != SMR_OK)
|
||||
{
|
||||
mutex->m_mutex.lock(tid);
|
||||
mutex->m_mutex.unlock(tid, target);
|
||||
}
|
||||
}
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_cond_signal_all(id=%d) aborted", cond_id);
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_cond_signal_to(u32 cond_id, u32 thread_id)
|
||||
{
|
||||
sys_cond.Error("sys_cond_signal_to(cond_id=%d, thread_id=%d)", cond_id, thread_id);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "SC_Mutex.h"
|
||||
|
||||
struct sys_cond_attribute
|
||||
{
|
||||
@ -12,14 +13,14 @@ struct sys_cond_attribute
|
||||
};
|
||||
};
|
||||
|
||||
struct condition
|
||||
struct Cond
|
||||
{
|
||||
wxCondition cond;
|
||||
u64 name_u64;
|
||||
Mutex* mutex; // associated with mutex
|
||||
SleepQueue m_queue;
|
||||
|
||||
condition(wxMutex& mtx, u64 name)
|
||||
: cond(mtx)
|
||||
, name_u64(name)
|
||||
Cond(Mutex* mutex, u64 name)
|
||||
: mutex(mutex)
|
||||
, m_queue(name)
|
||||
{
|
||||
}
|
||||
};
|
@ -59,7 +59,7 @@ int sys_event_queue_create(mem32_t equeue_id, mem_ptr_t<sys_event_queue_attr> at
|
||||
|
||||
int sys_event_queue_destroy(u32 equeue_id, int mode)
|
||||
{
|
||||
sys_event.Warning("sys_event_queue_destroy(equeue_id=%d, mode=0x%x)", equeue_id, mode);
|
||||
sys_event.Error("sys_event_queue_destroy(equeue_id=%d, mode=0x%x)", equeue_id, mode);
|
||||
|
||||
EventQueue* eq;
|
||||
if (!Emu.GetIdManager().GetIDData(equeue_id, eq))
|
||||
|
@ -10,13 +10,22 @@ int sys_lwcond_create(mem_ptr_t<sys_lwcond_t> lwcond, mem_ptr_t<sys_lwmutex_t> l
|
||||
sys_lwcond.Warning("sys_lwcond_create(lwcond_addr=0x%x, lwmutex_addr=0x%x, attr_addr=0x%x)",
|
||||
lwcond.GetAddr(), lwmutex.GetAddr(), attr.GetAddr());
|
||||
|
||||
if (!lwcond.IsGood() || !lwmutex.IsGood() || !attr.IsGood()) return CELL_EFAULT;
|
||||
if (!lwcond.IsGood() || !lwmutex.IsGood() || !attr.IsGood())
|
||||
{
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
lwcond->lwmutex = lwmutex.GetAddr();
|
||||
lwcond->lwcond_queue = sys_lwcond.GetNewId(new LWCond(attr->name_u64));
|
||||
lwcond->lwcond_queue = sys_lwcond.GetNewId(new SleepQueue(attr->name_u64));
|
||||
|
||||
if (lwmutex->attribute.ToBE() == se32(SYS_SYNC_RETRY))
|
||||
{
|
||||
sys_lwcond.Warning("Unsupported SYS_SYNC_RETRY lwmutex protocol");
|
||||
}
|
||||
|
||||
sys_lwcond.Warning("*** lwcond created [%s] (lwmutex.attr=0x%x): id = %d",
|
||||
wxString(attr->name, 8).wx_str(), (u32)lwmutex->attribute, (u32)lwcond->lwcond_queue);
|
||||
|
||||
sys_lwcond.Warning("*** lwcond created [%s] (attr=0x%x, lwmutex.sq=0x%x): id = %d",
|
||||
wxString(attr->name, 8).wx_str(), (u32)lwmutex->attribute, (u32)lwmutex->sleep_queue, (u32)lwcond->lwcond_queue);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -24,12 +33,25 @@ int sys_lwcond_destroy(mem_ptr_t<sys_lwcond_t> lwcond)
|
||||
{
|
||||
sys_lwcond.Warning("sys_lwcond_destroy(lwcond_addr=0x%x)", lwcond.GetAddr());
|
||||
|
||||
if (!lwcond.IsGood()) return CELL_EFAULT;
|
||||
LWCond* lwc;
|
||||
u32 id = (u32)lwcond->lwcond_queue;
|
||||
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
|
||||
if (!lwcond.IsGood())
|
||||
{
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
Emu.GetIdManager().RemoveID(id);
|
||||
u32 lwc = lwcond->lwcond_queue;
|
||||
|
||||
SleepQueue* sq;
|
||||
if (!Emu.GetIdManager().GetIDData(lwc, sq))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (!sq->finalize())
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
Emu.GetIdManager().RemoveID(lwc);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -37,12 +59,33 @@ int sys_lwcond_signal(mem_ptr_t<sys_lwcond_t> lwcond)
|
||||
{
|
||||
sys_lwcond.Log("sys_lwcond_signal(lwcond_addr=0x%x)", lwcond.GetAddr());
|
||||
|
||||
if (!lwcond.IsGood()) return CELL_EFAULT;
|
||||
LWCond* lwc;
|
||||
u32 id = (u32)lwcond->lwcond_queue;
|
||||
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
|
||||
if (!lwcond.IsGood())
|
||||
{
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
lwc->signal(mem_ptr_t<sys_lwmutex_t>(lwcond->lwmutex)->attribute);
|
||||
SleepQueue* sq;
|
||||
if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, sq))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
mem_ptr_t<sys_lwmutex_t> mutex(lwcond->lwmutex);
|
||||
be_t<u32> tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
if (be_t<u32> target = mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? sq->pop_prio() : sq->pop())
|
||||
{
|
||||
if (mutex->owner.trylock(target) != SMR_OK)
|
||||
{
|
||||
mutex->owner.lock(tid);
|
||||
mutex->owner.unlock(tid, target);
|
||||
}
|
||||
}
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_lwcond_signal(sq=%d) aborted", (u32)lwcond->lwcond_queue);
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -51,12 +94,33 @@ int sys_lwcond_signal_all(mem_ptr_t<sys_lwcond_t> lwcond)
|
||||
{
|
||||
sys_lwcond.Log("sys_lwcond_signal_all(lwcond_addr=0x%x)", lwcond.GetAddr());
|
||||
|
||||
if (!lwcond.IsGood()) return CELL_EFAULT;
|
||||
LWCond* lwc;
|
||||
u32 id = (u32)lwcond->lwcond_queue;
|
||||
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
|
||||
if (!lwcond.IsGood())
|
||||
{
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
lwc->signal_all();
|
||||
SleepQueue* sq;
|
||||
if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, sq))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
mem_ptr_t<sys_lwmutex_t> mutex(lwcond->lwmutex);
|
||||
be_t<u32> tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
while (be_t<u32> target = mutex->attribute.ToBE() == se32(SYS_SYNC_PRIORITY) ? sq->pop_prio() : sq->pop())
|
||||
{
|
||||
if (mutex->owner.trylock(target) != SMR_OK)
|
||||
{
|
||||
mutex->owner.lock(tid);
|
||||
mutex->owner.unlock(tid, target);
|
||||
}
|
||||
}
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_lwcond_signal_all(sq=%d) aborted", (u32)lwcond->lwcond_queue);
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -65,12 +129,37 @@ int sys_lwcond_signal_to(mem_ptr_t<sys_lwcond_t> lwcond, u32 ppu_thread_id)
|
||||
{
|
||||
sys_lwcond.Log("sys_lwcond_signal_to(lwcond_addr=0x%x, ppu_thread_id=%d)", lwcond.GetAddr(), ppu_thread_id);
|
||||
|
||||
if (!lwcond.IsGood()) return CELL_EFAULT;
|
||||
LWCond* lwc;
|
||||
u32 id = (u32)lwcond->lwcond_queue;
|
||||
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
|
||||
if (!lwcond.IsGood())
|
||||
{
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
if (!lwc->signal_to(ppu_thread_id)) return CELL_EPERM;
|
||||
SleepQueue* sq;
|
||||
if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, sq))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (!sq->invalidate(ppu_thread_id))
|
||||
{
|
||||
return CELL_EPERM;
|
||||
}
|
||||
|
||||
mem_ptr_t<sys_lwmutex_t> mutex(lwcond->lwmutex);
|
||||
be_t<u32> tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
be_t<u32> target = ppu_thread_id;
|
||||
|
||||
if (mutex->owner.trylock(target) != SMR_OK)
|
||||
{
|
||||
mutex->owner.lock(tid);
|
||||
mutex->owner.unlock(tid, target);
|
||||
}
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_lwcond_signal_to(sq=%d, to=%d) aborted", (u32)lwcond->lwcond_queue, ppu_thread_id);
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -79,49 +168,56 @@ int sys_lwcond_wait(mem_ptr_t<sys_lwcond_t> lwcond, u64 timeout)
|
||||
{
|
||||
sys_lwcond.Log("sys_lwcond_wait(lwcond_addr=0x%x, timeout=%lld)", lwcond.GetAddr(), timeout);
|
||||
|
||||
if (!lwcond.IsGood()) return CELL_EFAULT;
|
||||
LWCond* lwc;
|
||||
u32 id = (u32)lwcond->lwcond_queue;
|
||||
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
|
||||
const u32 tid = GetCurrentPPUThread().GetId();
|
||||
if (!lwcond.IsGood())
|
||||
{
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
mem_ptr_t<sys_lwmutex_t> lwmutex(lwcond->lwmutex);
|
||||
SleepQueue* sq;
|
||||
if (!Emu.GetIdManager().GetIDData((u32)lwcond->lwcond_queue, sq))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if ((u32)lwmutex->owner.GetOwner() != tid) return CELL_EPERM; // caller must own this lwmutex
|
||||
lwc->begin_waiting(tid);
|
||||
mem_ptr_t<sys_lwmutex_t> mutex(lwcond->lwmutex);
|
||||
u32 tid_le = GetCurrentPPUThread().GetId();
|
||||
be_t<u32> tid = tid_le;
|
||||
|
||||
if (mutex->owner.GetOwner() != tid)
|
||||
{
|
||||
return CELL_EPERM; // caller must own this lwmutex
|
||||
}
|
||||
|
||||
sq->push(tid_le);
|
||||
|
||||
mutex->owner.unlock(tid);
|
||||
|
||||
u32 counter = 0;
|
||||
const u32 max_counter = timeout ? (timeout / 1000) : 20000;
|
||||
bool was_locked = true;
|
||||
do
|
||||
const u32 max_counter = timeout ? (timeout / 1000) : ~0;
|
||||
while (true)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
/* switch (mutex->trylock(tid))
|
||||
{
|
||||
ConLog.Warning("sys_lwcond_wait(sq id=%d, ...) aborted", id);
|
||||
return CELL_ETIMEDOUT;
|
||||
case SMR_OK: mutex->unlock(tid); break;
|
||||
case SMR_SIGNAL: return CELL_OK;
|
||||
} */
|
||||
if (mutex->owner.GetOwner() == tid)
|
||||
{
|
||||
_mm_mfence();
|
||||
return CELL_OK;
|
||||
}
|
||||
if (was_locked) lwmutex->unlock(tid);
|
||||
|
||||
Sleep(1);
|
||||
if (was_locked = (lwmutex->trylock(tid) == CELL_OK))
|
||||
{
|
||||
if (lwc->check(tid))
|
||||
{
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (counter++ > max_counter)
|
||||
{
|
||||
if (!timeout)
|
||||
{
|
||||
sys_lwcond.Warning("sys_lwcond_wait(lwcond_addr=0x%x): TIMEOUT", lwcond.GetAddr());
|
||||
counter = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
lwc->stop_waiting(tid);
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
} while (true);
|
||||
sq->invalidate(tid_le);
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_lwcond_wait(sq=%d) aborted", (u32)lwcond->lwcond_queue);
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,108 +13,4 @@ struct sys_lwcond_t
|
||||
{
|
||||
be_t<u32> lwmutex;
|
||||
be_t<u32> lwcond_queue;
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
struct LWCond
|
||||
{
|
||||
std::mutex m_lock;
|
||||
Array<u32> waiters; // list of waiting threads
|
||||
Array<u32> signaled; // list of signaled threads
|
||||
u64 m_name; // not used
|
||||
|
||||
LWCond(u64 name)
|
||||
: m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
void signal(u32 _protocol)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
|
||||
if (waiters.GetCount())
|
||||
{
|
||||
if ((_protocol & SYS_SYNC_ATTR_PROTOCOL_MASK) == SYS_SYNC_PRIORITY)
|
||||
{
|
||||
u64 max_prio = 0;
|
||||
u32 sel = 0;
|
||||
for (u32 i = 0; i < waiters.GetCount(); i++)
|
||||
{
|
||||
CPUThread* t = Emu.GetCPU().GetThread(waiters[i]);
|
||||
if (!t) continue;
|
||||
|
||||
u64 prio = t->GetPrio();
|
||||
if (prio > max_prio)
|
||||
{
|
||||
max_prio = prio;
|
||||
sel = i;
|
||||
}
|
||||
}
|
||||
signaled.AddCpy(waiters[sel]);
|
||||
waiters.RemoveAt(sel);
|
||||
}
|
||||
else // SYS_SYNC_FIFO
|
||||
{
|
||||
signaled.AddCpy(waiters[0]);
|
||||
waiters.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void signal_all()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
|
||||
signaled.AppendFrom(waiters); // "nobody cares" protocol (!)
|
||||
waiters.Clear();
|
||||
}
|
||||
|
||||
bool signal_to(u32 id) // returns false if not found
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
for (u32 i = waiters.GetCount() - 1; ~i; i--)
|
||||
{
|
||||
if (waiters[i] == id)
|
||||
{
|
||||
waiters.RemoveAt(i);
|
||||
signaled.AddCpy(id);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void begin_waiting(u32 id)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
waiters.AddCpy(id);
|
||||
}
|
||||
|
||||
void stop_waiting(u32 id)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
for (u32 i = waiters.GetCount() - 1; ~i; i--)
|
||||
{
|
||||
if (waiters[i] == id)
|
||||
{
|
||||
waiters.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool check(u32 id) // returns true if signaled
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
for (u32 i = signaled.GetCount() - 1; ~i; i--)
|
||||
{
|
||||
if (signaled[i] == id)
|
||||
{
|
||||
signaled.RemoveAt(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
@ -6,7 +6,7 @@ SysCallBase sc_lwmutex("sys_lwmutex");
|
||||
|
||||
int sys_lwmutex_create(mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_attribute_t> attr)
|
||||
{
|
||||
sc_lwmutex.Log("sys_lwmutex_create(lwmutex_addr=0x%x, lwmutex_attr_addr=0x%x)",
|
||||
sc_lwmutex.Warning("sys_lwmutex_create(lwmutex_addr=0x%x, lwmutex_attr_addr=0x%x)",
|
||||
lwmutex.GetAddr(), attr.GetAddr());
|
||||
|
||||
if (!lwmutex.IsGood() || !attr.IsGood()) return CELL_EFAULT;
|
||||
@ -15,7 +15,7 @@ int sys_lwmutex_create(mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_a
|
||||
{
|
||||
case se32(SYS_SYNC_RECURSIVE): break;
|
||||
case se32(SYS_SYNC_NOT_RECURSIVE): break;
|
||||
default: sc_lwmutex.Error("Unknown 0x%x recursive attr", (u32)attr->attr_recursive); return CELL_EINVAL;
|
||||
default: sc_lwmutex.Error("Unknown recursive attribute(0x%x)", (u32)attr->attr_recursive); return CELL_EINVAL;
|
||||
}
|
||||
|
||||
switch (attr->attr_protocol.ToBE())
|
||||
@ -24,7 +24,7 @@ int sys_lwmutex_create(mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_a
|
||||
case se32(SYS_SYNC_RETRY): break;
|
||||
case se32(SYS_SYNC_PRIORITY_INHERIT): sc_lwmutex.Error("Invalid SYS_SYNC_PRIORITY_INHERIT protocol attr"); return CELL_EINVAL;
|
||||
case se32(SYS_SYNC_FIFO): break;
|
||||
default: sc_lwmutex.Error("Unknown 0x%x protocol attr", (u32)attr->attr_protocol); return CELL_EINVAL;
|
||||
default: sc_lwmutex.Error("Unknown protocol attribute(0x%x)", (u32)attr->attr_protocol); return CELL_EINVAL;
|
||||
}
|
||||
|
||||
lwmutex->attribute = attr->attr_protocol | attr->attr_recursive;
|
||||
@ -35,7 +35,7 @@ int sys_lwmutex_create(mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_a
|
||||
u32 sq_id = sc_lwmutex.GetNewId(new SleepQueue(attr->name_u64));
|
||||
lwmutex->sleep_queue = sq_id;
|
||||
|
||||
sc_lwmutex.Log("*** lwmutex created [%s] (attribute=0x%x): sq_id = %d",
|
||||
sc_lwmutex.Warning("*** lwmutex created [%s] (attribute=0x%x): sq_id = %d",
|
||||
wxString(attr->name, 8).wx_str(), (u32)lwmutex->attribute, sq_id);
|
||||
|
||||
return CELL_OK;
|
||||
@ -43,7 +43,7 @@ int sys_lwmutex_create(mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_a
|
||||
|
||||
int sys_lwmutex_destroy(mem_ptr_t<sys_lwmutex_t> lwmutex)
|
||||
{
|
||||
sc_lwmutex.Log("sys_lwmutex_destroy(lwmutex_addr=0x%x)", lwmutex.GetAddr());
|
||||
sc_lwmutex.Warning("sys_lwmutex_destroy(lwmutex_addr=0x%x)", lwmutex.GetAddr());
|
||||
|
||||
if (!lwmutex.IsGood()) return CELL_EFAULT;
|
||||
|
||||
@ -160,18 +160,38 @@ u32 SleepQueue::pop_prio_inherit() // (TODO)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SleepQueue::invalidate(u32 tid)
|
||||
bool SleepQueue::invalidate(u32 tid)
|
||||
{
|
||||
SMutexLocker lock(m_mutex);
|
||||
|
||||
for (u32 i = 0; i < list.GetCount(); i++)
|
||||
if (tid) for (u32 i = 0; i < list.GetCount(); i++)
|
||||
{
|
||||
if (list[i] = tid)
|
||||
{
|
||||
list[i] = 0;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SleepQueue::finalize()
|
||||
{
|
||||
u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
m_mutex.lock(tid);
|
||||
|
||||
for (u32 i = 0; i < list.GetCount(); i++)
|
||||
{
|
||||
if (list[i])
|
||||
{
|
||||
m_mutex.unlock(tid);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int sys_lwmutex_t::trylock(be_t<u32> tid)
|
||||
|
@ -8,7 +8,7 @@ enum
|
||||
SYS_SYNC_FIFO = 1,
|
||||
// Priority Order
|
||||
SYS_SYNC_PRIORITY = 2,
|
||||
// Basic Priority Inheritance Protocol
|
||||
// Basic Priority Inheritance Protocol (probably not implemented)
|
||||
SYS_SYNC_PRIORITY_INHERIT = 3,
|
||||
// Not selected while unlocking
|
||||
SYS_SYNC_RETRY = 4,
|
||||
@ -59,7 +59,8 @@ struct SleepQueue
|
||||
u32 pop(); // SYS_SYNC_FIFO
|
||||
u32 pop_prio(); // SYS_SYNC_PRIORITY
|
||||
u32 pop_prio_inherit(); // (TODO)
|
||||
void invalidate(u32 tid);
|
||||
bool invalidate(u32 tid);
|
||||
bool finalize();
|
||||
};
|
||||
|
||||
struct sys_lwmutex_t
|
||||
@ -84,26 +85,4 @@ struct sys_lwmutex_t
|
||||
int trylock(be_t<u32> tid);
|
||||
int unlock(be_t<u32> tid);
|
||||
int lock(be_t<u32> tid, u64 timeout);
|
||||
};
|
||||
/*
|
||||
class lwmutex_locker
|
||||
{
|
||||
mem_ptr_t<sys_lwmutex_t> m_mutex;
|
||||
be_t<u32> m_id;
|
||||
|
||||
lwmutex_locker(mem_ptr_t<sys_lwmutex_t> lwmutex, be_t<u32> tid, u64 timeout = 0)
|
||||
: m_id(tid)
|
||||
, m_mutex(lwmutex)
|
||||
{
|
||||
if (int res = m_mutex->lock(m_id, timeout))
|
||||
{
|
||||
ConLog.Error("lwmutex_locker: m_mutex->lock failed(res=0x%x)", res);
|
||||
Emu.Pause();
|
||||
}
|
||||
}
|
||||
|
||||
~lwmutex_locker()
|
||||
{
|
||||
m_mutex->unlock(m_id);
|
||||
}
|
||||
};*/
|
||||
};
|
@ -5,39 +5,74 @@
|
||||
|
||||
SysCallBase sys_mtx("sys_mutex");
|
||||
|
||||
int sys_mutex_create(u32 mutex_id_addr, u32 attr_addr)
|
||||
int sys_mutex_create(mem32_t mutex_id, mem_ptr_t<sys_mutex_attribute> attr)
|
||||
{
|
||||
sys_mtx.Warning("sys_mutex_create(mutex_id_addr=0x%x, attr_addr=0x%x)",
|
||||
mutex_id_addr, attr_addr);
|
||||
sys_mtx.Warning("sys_mutex_create(mutex_id_addr=0x%x, attr_addr=0x%x)", mutex_id.GetAddr(), attr.GetAddr());
|
||||
|
||||
if(!Memory.IsGoodAddr(mutex_id_addr) || !Memory.IsGoodAddr(attr_addr)) return CELL_EFAULT;
|
||||
if (!mutex_id.IsGood() || !attr.IsGood())
|
||||
{
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
mutex_attr attr = (mutex_attr&)Memory[attr_addr];
|
||||
attr.protocol = re(attr.protocol);
|
||||
attr.recursive = re(attr.recursive);
|
||||
attr.pshared = re(attr.pshared);
|
||||
attr.adaptive = re(attr.adaptive);
|
||||
attr.ipc_key = re(attr.ipc_key);
|
||||
attr.flags = re(attr.flags);
|
||||
|
||||
sys_mtx.Log("*** protocol = %d", attr.protocol);
|
||||
sys_mtx.Log("*** recursive = %d", attr.recursive);
|
||||
sys_mtx.Log("*** pshared = %d", attr.pshared);
|
||||
sys_mtx.Log("*** ipc_key = 0x%llx", attr.ipc_key);
|
||||
sys_mtx.Log("*** flags = 0x%x", attr.flags);
|
||||
sys_mtx.Log("*** name = %s", attr.name);
|
||||
switch (attr->protocol.ToBE())
|
||||
{
|
||||
case se32(SYS_SYNC_FIFO): break;
|
||||
case se32(SYS_SYNC_PRIORITY): break;
|
||||
case se32(SYS_SYNC_PRIORITY_INHERIT): sys_mtx.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT protocol"); break;
|
||||
case se32(SYS_SYNC_RETRY): sys_mtx.Error("Invalid SYS_SYNC_RETRY protocol"); return CELL_EINVAL;
|
||||
default: sys_mtx.Error("Unknown protocol attribute(0x%x)", (u32)attr->protocol); return CELL_EINVAL;
|
||||
}
|
||||
|
||||
Memory.Write32(mutex_id_addr, sys_mtx.GetNewId(new mutex(attr)));
|
||||
bool is_recursive;
|
||||
switch (attr->recursive.ToBE())
|
||||
{
|
||||
case se32(SYS_SYNC_RECURSIVE): is_recursive = true; break;
|
||||
case se32(SYS_SYNC_NOT_RECURSIVE): is_recursive = false; break;
|
||||
default: sys_mtx.Error("Unknown recursive attribute(0x%x)", (u32)attr->recursive); return CELL_EINVAL;
|
||||
}
|
||||
|
||||
if (attr->pshared.ToBE() != se32(0x200))
|
||||
{
|
||||
sys_mtx.Error("Unknown pshared attribute(0x%x)", (u32)attr->pshared);
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
mutex_id = sys_mtx.GetNewId(new Mutex((u32)attr->protocol, is_recursive, attr->name_u64));
|
||||
sys_mtx.Warning("*** mutex created [%s] (protocol=0x%x, recursive=%d): id = %d",
|
||||
wxString(attr->name, 8).wx_str(), (u32)attr->protocol, is_recursive, mutex_id.GetValue());
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_mutex_destroy(u32 mutex_id)
|
||||
{
|
||||
sys_mtx.Log("sys_mutex_destroy(mutex_id=0x%x)", mutex_id);
|
||||
sys_mtx.Warning("sys_mutex_destroy(mutex_id=0x%x)", mutex_id);
|
||||
|
||||
if(!sys_mtx.CheckId(mutex_id)) return CELL_ESRCH;
|
||||
Mutex* mutex;
|
||||
if (!Emu.GetIdManager().GetIDData(mutex_id, mutex))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if ((u32&)mutex->cond_count) // check if associated condition variable exists
|
||||
{
|
||||
return CELL_EPERM;
|
||||
}
|
||||
|
||||
u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
if (mutex->m_mutex.trylock(tid)) // check if locked
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
if (!mutex->m_queue.finalize())
|
||||
{
|
||||
mutex->m_mutex.unlock(tid);
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
mutex->m_mutex.unlock(tid, ~0);
|
||||
Emu.GetIdManager().RemoveID(mutex_id);
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -46,56 +81,113 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout)
|
||||
{
|
||||
sys_mtx.Log("sys_mutex_lock(mutex_id=0x%x, timeout=0x%llx)", mutex_id, timeout);
|
||||
|
||||
mutex* mtx_data = nullptr;
|
||||
if(!sys_mtx.CheckId(mutex_id, mtx_data)) return CELL_ESRCH;
|
||||
|
||||
u32 counter = 0;
|
||||
const u32 max_counter = timeout ? (timeout / 1000) : 20000;
|
||||
do
|
||||
Mutex* mutex;
|
||||
if (!Emu.GetIdManager().GetIDData(mutex_id, mutex))
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
if (mutex->m_mutex.GetOwner() == tid)
|
||||
{
|
||||
if (mutex->is_recursive)
|
||||
{
|
||||
ConLog.Warning("sys_mutex_lock(mutex_id=%d, ...) aborted", mutex_id);
|
||||
return CELL_ETIMEDOUT;
|
||||
if (mutex->recursive++ == 0)
|
||||
{
|
||||
return CELL_EKRESOURCE;
|
||||
}
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
if (mtx_data->mtx.TryLock() == wxMUTEX_NO_ERROR) return CELL_OK;
|
||||
Sleep(1);
|
||||
|
||||
if (counter++ > max_counter)
|
||||
else
|
||||
{
|
||||
if (!timeout)
|
||||
{
|
||||
counter = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
} while (true);
|
||||
return CELL_EDEADLK;
|
||||
}
|
||||
}
|
||||
|
||||
switch (mutex->m_mutex.trylock(tid))
|
||||
{
|
||||
case SMR_OK: return CELL_OK;
|
||||
case SMR_FAILED: break;
|
||||
default: goto abort;
|
||||
}
|
||||
|
||||
mutex->m_queue.push(tid);
|
||||
|
||||
switch (mutex->m_mutex.lock(tid, timeout ? ((timeout < 1000) ? 1 : (timeout / 1000)) : 0))
|
||||
{
|
||||
case SMR_OK: mutex->m_queue.invalidate(tid);
|
||||
case SMR_SIGNAL: mutex->recursive = 1; return CELL_OK;
|
||||
case SMR_TIMEOUT: return CELL_ETIMEDOUT;
|
||||
default: goto abort;
|
||||
}
|
||||
|
||||
abort:
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_mutex_lock(id=%d) aborted", mutex_id);
|
||||
return CELL_OK;
|
||||
}
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
int sys_mutex_trylock(u32 mutex_id)
|
||||
{
|
||||
sys_mtx.Log("sys_mutex_trylock(mutex_id=0x%x)", mutex_id);
|
||||
|
||||
mutex* mtx_data = nullptr;
|
||||
if(!sys_mtx.CheckId(mutex_id, mtx_data)) return CELL_ESRCH;
|
||||
Mutex* mutex;
|
||||
if (!Emu.GetIdManager().GetIDData(mutex_id, mutex))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (mtx_data->mtx.TryLock() != wxMUTEX_NO_ERROR) return CELL_EBUSY;
|
||||
u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
return CELL_OK;
|
||||
if (mutex->m_mutex.GetOwner() == tid)
|
||||
{
|
||||
if (mutex->is_recursive)
|
||||
{
|
||||
if (++mutex->recursive == 0)
|
||||
{
|
||||
return CELL_EKRESOURCE;
|
||||
}
|
||||
return CELL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CELL_EDEADLK;
|
||||
}
|
||||
}
|
||||
|
||||
switch (mutex->m_mutex.trylock(tid))
|
||||
{
|
||||
case SMR_OK: return CELL_OK;
|
||||
}
|
||||
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
int sys_mutex_unlock(u32 mutex_id)
|
||||
{
|
||||
sys_mtx.Log("sys_mutex_unlock(mutex_id=0x%x)", mutex_id);
|
||||
|
||||
mutex* mtx_data = nullptr;
|
||||
if(!sys_mtx.CheckId(mutex_id, mtx_data)) return CELL_ESRCH;
|
||||
Mutex* mutex;
|
||||
if (!Emu.GetIdManager().GetIDData(mutex_id, mutex))
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
mtx_data->mtx.Unlock();
|
||||
u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
return CELL_OK;
|
||||
if (mutex->m_mutex.GetOwner() == tid)
|
||||
{
|
||||
mutex->recursive--;
|
||||
if (!mutex->recursive)
|
||||
{
|
||||
mutex->m_mutex.unlock(tid, mutex->protocol == SYS_SYNC_PRIORITY ? mutex->m_queue.pop_prio() : mutex->m_queue.pop());
|
||||
}
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
return CELL_EPERM;
|
||||
}
|
||||
|
@ -1,25 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
struct mutex_attr
|
||||
struct sys_mutex_attribute
|
||||
{
|
||||
u32 protocol;
|
||||
u32 recursive;
|
||||
u32 pshared;
|
||||
u32 adaptive;
|
||||
u64 ipc_key;
|
||||
int flags;
|
||||
u32 pad;
|
||||
char name[8];
|
||||
be_t<u32> protocol; // SYS_SYNC_FIFO, SYS_SYNC_PRIORITY or SYS_SYNC_PRIORITY_INHERIT
|
||||
be_t<u32> recursive; // SYS_SYNC_RECURSIVE or SYS_SYNC_NOT_RECURSIVE
|
||||
be_t<u32> pshared; // always 0x200 (not shared)
|
||||
be_t<u32> adaptive;
|
||||
be_t<u64> ipc_key;
|
||||
be_t<int> flags;
|
||||
be_t<u32> pad;
|
||||
union
|
||||
{
|
||||
char name[8];
|
||||
u64 name_u64;
|
||||
};
|
||||
};
|
||||
|
||||
struct mutex
|
||||
struct Mutex
|
||||
{
|
||||
wxMutex mtx;
|
||||
mutex_attr attr;
|
||||
SMutex m_mutex;
|
||||
SleepQueue m_queue;
|
||||
u32 recursive; // recursive locks count
|
||||
std::atomic<u32> cond_count; // count of condition variables associated
|
||||
|
||||
mutex(const mutex_attr& attr)
|
||||
: mtx()
|
||||
, attr(attr)
|
||||
const u32 protocol;
|
||||
const bool is_recursive;
|
||||
|
||||
Mutex(u32 protocol, bool is_recursive, u64 name)
|
||||
: protocol(protocol)
|
||||
, is_recursive(is_recursive)
|
||||
, m_queue(name)
|
||||
, cond_count(0)
|
||||
{
|
||||
}
|
||||
};
|
@ -32,7 +32,8 @@ void sys_ppu_thread_exit(int errorcode)
|
||||
|
||||
int sys_ppu_thread_yield()
|
||||
{
|
||||
sysPrxForUser.Log("sys_ppu_thread_yield()");
|
||||
sysPrxForUser.Log("sys_ppu_thread_yield()");
|
||||
Sleep(1);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user