mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-17 17:11:23 +00:00
Small changes
lwmutex completely implemented
This commit is contained in:
parent
ed40732e7b
commit
3308fefa7f
@ -126,7 +126,11 @@ public:
|
||||
: sm(_sm)
|
||||
, tid(get_tid())
|
||||
{
|
||||
if (!tid) throw "SMutexLockerBase: invalid thread id";
|
||||
if (!tid)
|
||||
{
|
||||
ConLog.Error("SMutexLockerBase: thread id == 0");
|
||||
Emu.Pause();
|
||||
}
|
||||
sm.lock(tid);
|
||||
}
|
||||
|
||||
|
@ -9,12 +9,13 @@ struct reservation_struct
|
||||
volatile u32 owner; // id of thread that got reservation
|
||||
volatile u32 addr;
|
||||
volatile u32 size;
|
||||
volatile u32 data32;
|
||||
volatile u64 data64;
|
||||
// atm, PPU can't break SPU MFC reservation correctly
|
||||
|
||||
__forceinline void clear()
|
||||
{
|
||||
owner = 0;
|
||||
addr = 0;
|
||||
size = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2361,14 +2361,13 @@ private:
|
||||
}
|
||||
void LWARX(u32 rd, u32 ra, u32 rb)
|
||||
{
|
||||
ConLog.Warning("LWARX");
|
||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
|
||||
SMutexLocker lock(reservation.mutex);
|
||||
reservation.owner = lock.tid;
|
||||
reservation.addr = addr;
|
||||
reservation.size = 4;
|
||||
CPU.GPR[rd] = Memory.Read32(addr);
|
||||
reservation.data32 = CPU.GPR[rd] = Memory.Read32(addr);
|
||||
}
|
||||
void LDX(u32 rd, u32 ra, u32 rb)
|
||||
{
|
||||
@ -2538,14 +2537,13 @@ private:
|
||||
}
|
||||
void LDARX(u32 rd, u32 ra, u32 rb)
|
||||
{
|
||||
ConLog.Warning("LDARX");
|
||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
|
||||
SMutexLocker lock(reservation.mutex);
|
||||
reservation.owner = lock.tid;
|
||||
reservation.addr = addr;
|
||||
reservation.size = 8;
|
||||
CPU.GPR[rd] = Memory.Read64(addr);
|
||||
reservation.data64 = CPU.GPR[rd] = Memory.Read64(addr);
|
||||
}
|
||||
void DCBF(u32 ra, u32 rb)
|
||||
{
|
||||
@ -2658,14 +2656,13 @@ private:
|
||||
}
|
||||
void STWCX_(u32 rs, u32 ra, u32 rb)
|
||||
{
|
||||
ConLog.Warning("STWCX_");
|
||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
|
||||
SMutexLocker lock(reservation.mutex);
|
||||
if (lock.tid == reservation.owner && reservation.addr == addr && reservation.size == 4)
|
||||
{
|
||||
Memory.Write32(addr, CPU.GPR[rs]);
|
||||
CPU.SetCR_EQ(0, true);
|
||||
// Memory.Write32(addr, CPU.GPR[rs]);
|
||||
CPU.SetCR_EQ(0, InterlockedCompareExchange((volatile long*)(Memory + addr), (u32)CPU.GPR[rs], reservation.data32) == reservation.data32);
|
||||
reservation.clear();
|
||||
}
|
||||
else
|
||||
@ -2712,14 +2709,13 @@ private:
|
||||
}
|
||||
void STDCX_(u32 rs, u32 ra, u32 rb)
|
||||
{
|
||||
ConLog.Warning("STDCX_");
|
||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
|
||||
SMutexLocker lock(reservation.mutex);
|
||||
if (lock.tid == reservation.owner && reservation.addr == addr && reservation.size == 8)
|
||||
{
|
||||
Memory.Write64(addr, CPU.GPR[rs]);
|
||||
CPU.SetCR_EQ(0, true);
|
||||
// Memory.Write64(addr, CPU.GPR[rs]);
|
||||
CPU.SetCR_EQ(0, InterlockedCompareExchange64((volatile long long*)(Memory + addr), CPU.GPR[rs], reservation.data64) == reservation.data64);
|
||||
reservation.clear();
|
||||
}
|
||||
else
|
||||
|
@ -83,7 +83,7 @@ struct CellAudioPortConfig
|
||||
struct CellAudioConfig //custom structure
|
||||
{
|
||||
bool m_is_audio_initialized;
|
||||
bool m_is_audio_port_open;
|
||||
bool m_is_audio_port_opened;
|
||||
bool m_is_audio_port_started;
|
||||
};
|
||||
|
||||
@ -216,7 +216,7 @@ int cellAudioPortOpen(mem_ptr_t<CellAudioPortParam> audioParam, mem32_t portNum)
|
||||
cellAudio.Warning("cellAudioPortOpen(audioParam_addr=0x%x,portNum_addr=0x%x)",audioParam.GetAddr(),portNum.GetAddr());
|
||||
|
||||
if(!audioParam.IsGood() || !portNum.IsGood()) return CELL_AUDIO_ERROR_PORT_OPEN;
|
||||
m_config->m_is_audio_port_open = true;
|
||||
m_config->m_is_audio_port_opened = true;
|
||||
|
||||
m_param->nChannel = audioParam->nChannel;
|
||||
m_param->nBlock = audioParam->nBlock;
|
||||
@ -238,13 +238,13 @@ int cellAudioGetPortConfig(u32 portNum, mem_ptr_t<CellAudioPortConfig> portConfi
|
||||
|
||||
//if(portNum > 7) return CELL_AUDIO_ERROR_PORT_FULL;
|
||||
|
||||
if(m_config->m_is_audio_port_open == false)
|
||||
if(!m_config->m_is_audio_port_opened)
|
||||
{
|
||||
portConfig->status = CELL_AUDIO_STATUS_CLOSE;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
if(m_config->m_is_audio_port_started == true)
|
||||
if(m_config->m_is_audio_port_started)
|
||||
{
|
||||
portConfig->status = CELL_AUDIO_STATUS_RUN;
|
||||
}
|
||||
@ -268,7 +268,7 @@ int cellAudioPortStart(u32 portNum)
|
||||
{
|
||||
cellAudio.Warning("cellAudioPortStart(portNum=0x%x)",portNum);
|
||||
|
||||
if (m_config->m_is_audio_port_open == true)
|
||||
if (!m_config->m_is_audio_port_opened)
|
||||
return CELL_AUDIO_ERROR_PORT_OPEN;
|
||||
|
||||
m_config->m_is_audio_port_started = true;
|
||||
@ -279,10 +279,10 @@ int cellAudioPortClose(u32 portNum)
|
||||
{
|
||||
cellAudio.Warning("cellAudioPortClose(portNum=0x%x)",portNum);
|
||||
|
||||
if (m_config->m_is_audio_port_open == false)
|
||||
if (!m_config->m_is_audio_port_opened)
|
||||
return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
|
||||
|
||||
m_config->m_is_audio_port_open = false;
|
||||
m_config->m_is_audio_port_opened = false;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -1016,6 +1016,6 @@ void cellAudio_init()
|
||||
void cellAudio_unload()
|
||||
{
|
||||
m_config->m_is_audio_initialized = false;
|
||||
m_config->m_is_audio_port_open = false;
|
||||
m_config->m_is_audio_port_opened = false;
|
||||
m_config->m_is_audio_port_started = false;
|
||||
}
|
@ -127,7 +127,7 @@ extern int sys_game_process_exitspawn(u32 path_addr, u32 argv_addr, u32 envp_add
|
||||
u32 data, u32 data_size, int prio, u64 flags );
|
||||
|
||||
//sys_event
|
||||
extern int sys_event_queue_create(u32 equeue_id_addr, u32 attr_addr, u64 event_queue_key, int size);
|
||||
extern int sys_event_queue_create(mem32_t equeue_id, mem_ptr_t<sys_event_queue_attr> attr, u64 event_queue_key, int size);
|
||||
extern int sys_event_queue_receive(u32 equeue_id, u32 event_addr, u32 timeout);
|
||||
extern int sys_event_port_create(u32 eport_id_addr, int port_type, u64 name);
|
||||
extern int sys_event_port_connect_local(u32 event_port_id, u32 event_queue_id);
|
||||
|
@ -6,30 +6,24 @@
|
||||
SysCallBase sys_event("sys_event");
|
||||
|
||||
//128
|
||||
int sys_event_queue_create(u32 equeue_id_addr, u32 attr_addr, u64 event_queue_key, int size)
|
||||
int sys_event_queue_create(mem32_t equeue_id, mem_ptr_t<sys_event_queue_attr> attr, u64 event_queue_key, int size)
|
||||
{
|
||||
sys_event.Warning("sys_event_queue_create(equeue_id_addr=0x%x, attr_addr=0x%x, event_queue_key=0x%llx, size=%d)",
|
||||
equeue_id_addr, attr_addr, event_queue_key, size);
|
||||
equeue_id.GetAddr(), attr.GetAddr(), event_queue_key, size);
|
||||
|
||||
if(size <= 0 || size > 127)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
if(!Memory.IsGoodAddr(equeue_id_addr, 4) || !Memory.IsGoodAddr(attr_addr, sizeof(sys_event_queue_attr)))
|
||||
if(!equeue_id.IsGood() || !attr.IsGood())
|
||||
{
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
auto& attr = (sys_event_queue_attr&)Memory[attr_addr];
|
||||
sys_event.Warning("name = %s", attr.name);
|
||||
sys_event.Warning("type = %d", re(attr.type));
|
||||
EventQueue* equeue = new EventQueue();
|
||||
equeue->size = size;
|
||||
equeue->pos = 0;
|
||||
equeue->type = re(attr.type);
|
||||
strncpy(equeue->name, attr.name, 8);
|
||||
Memory.Write32(equeue_id_addr, sys_event.GetNewId(equeue));
|
||||
equeue_id = sys_event.GetNewId(new EventQueue((u32)attr->protocol, (int)attr->type, attr->name_u64, event_queue_key, size));
|
||||
sys_event.Warning("*** event_queue created[%s] (protocol=0x%x, type=0x%x): id = %d",
|
||||
attr->name, (u32)attr->protocol, (int)attr->type, equeue_id.GetValue());
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -79,10 +73,10 @@ int sys_event_queue_receive(u32 equeue_id, u32 event_addr, u32 timeout)
|
||||
{
|
||||
auto dst = (sys_event_data&)Memory[event_addr];
|
||||
|
||||
re(dst.source, equeue->ports[i]->name);
|
||||
re(dst.data1, equeue->ports[i]->data1);
|
||||
re(dst.data2, equeue->ports[i]->data2);
|
||||
re(dst.data3, equeue->ports[i]->data3);
|
||||
dst.source = equeue->ports[i]->name;
|
||||
dst.data1 = equeue->ports[i]->data1;
|
||||
dst.data2 = equeue->ports[i]->data2;
|
||||
dst.data3 = equeue->ports[i]->data3;
|
||||
|
||||
equeue->ports[i]->has_data = false;
|
||||
|
||||
|
@ -7,24 +7,16 @@ SysCallBase sys_lwcond("sys_lwcond");
|
||||
|
||||
int sys_lwcond_create(mem_ptr_t<sys_lwcond_t> lwcond, mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwcond_attribute_t> attr)
|
||||
{
|
||||
sys_lwcond.Warning("sys_lwcond_create(lwcond_addr=0x%x, lwmutex_addr=0x%x, attr_addr=0x%x)",
|
||||
sys_lwcond.Log("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;
|
||||
|
||||
switch (lwmutex->attribute.ToBE())
|
||||
{
|
||||
case se32(SYS_SYNC_PRIORITY): break;
|
||||
case se32(SYS_SYNC_RETRY): sys_lwcond.Error("Invalid SYS_SYNC_RETRY attr"); break;
|
||||
case se32(SYS_SYNC_PRIORITY_INHERIT): sys_lwcond.Warning("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break;
|
||||
case se32(SYS_SYNC_FIFO): break;
|
||||
default: sys_lwcond.Error("Invalid lwmutex protocol(%d)", (u32)lwmutex->attribute); break;
|
||||
}
|
||||
lwcond->lwmutex = lwmutex.GetAddr();
|
||||
lwcond->lwcond_queue = sys_lwcond.GetNewId(new LWCond(attr->name_u64));
|
||||
|
||||
lwcond->lwmutex_addr = lwmutex.GetAddr();
|
||||
lwcond->lwcond_queue = sys_lwcond.GetNewId(new LWCond((u32)lwmutex->attribute, *(u64*)&attr->name));
|
||||
|
||||
sys_lwcond.Warning("*** lwcond created [%s] (protocol=0x%x): id=%d", attr->name, (u32)lwmutex->attribute, (u32)lwcond->lwcond_queue);
|
||||
sys_lwcond.Warning("*** lwcond created [%s] (attr=0x%x, lwmutex.sq=0x%x): id=0x%x",
|
||||
attr->name, (u32)lwmutex->attribute, (u32)lwmutex->sleep_queue, (u32)lwcond->lwcond_queue);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -50,7 +42,7 @@ int sys_lwcond_signal(mem_ptr_t<sys_lwcond_t> lwcond)
|
||||
u32 id = (u32)lwcond->lwcond_queue;
|
||||
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
|
||||
|
||||
lwc->signal();
|
||||
lwc->signal(mem_ptr_t<sys_lwmutex_t>(lwcond->lwmutex)->attribute);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -92,7 +84,8 @@ int sys_lwcond_wait(mem_ptr_t<sys_lwcond_t> lwcond, u64 timeout)
|
||||
u32 id = (u32)lwcond->lwcond_queue;
|
||||
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
|
||||
const u32 tid = GetCurrentPPUThread().GetId();
|
||||
mem_ptr_t<sys_lwmutex_t> lwmutex((u32)lwcond->lwmutex_addr);
|
||||
|
||||
mem_ptr_t<sys_lwmutex_t> lwmutex(lwcond->lwmutex);
|
||||
|
||||
if ((u32)lwmutex->owner.GetOwner() != tid) return CELL_EPERM; // caller must own this lwmutex
|
||||
lwc->begin_waiting(tid);
|
||||
|
@ -2,12 +2,16 @@
|
||||
|
||||
struct sys_lwcond_attribute_t
|
||||
{
|
||||
char name[8];
|
||||
union
|
||||
{
|
||||
char name[8];
|
||||
u64 name_u64;
|
||||
};
|
||||
};
|
||||
|
||||
struct sys_lwcond_t
|
||||
{
|
||||
be_t<u32> lwmutex_addr;
|
||||
be_t<u32> lwmutex;
|
||||
be_t<u32> lwcond_queue;
|
||||
};
|
||||
|
||||
@ -18,22 +22,20 @@ struct LWCond
|
||||
std::mutex m_lock;
|
||||
Array<u32> waiters; // list of waiting threads
|
||||
Array<u32> signaled; // list of signaled threads
|
||||
u32 m_protocol; // protocol
|
||||
u64 m_name; // not used
|
||||
|
||||
LWCond(u32 prot, u64 name)
|
||||
LWCond(u64 name)
|
||||
: m_name(name)
|
||||
, m_protocol(prot)
|
||||
{
|
||||
}
|
||||
|
||||
void signal()
|
||||
void signal(u32 _protocol)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
|
||||
if (waiters.GetCount())
|
||||
{
|
||||
if (m_protocol == SYS_SYNC_PRIORITY)
|
||||
if ((_protocol & SYS_SYNC_ATTR_PROTOCOL_MASK) == SYS_SYNC_PRIORITY)
|
||||
{
|
||||
u64 max_prio = 0;
|
||||
u32 sel = 0;
|
||||
|
@ -7,7 +7,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.Warning("sys_lwmutex_create(lwmutex_addr=0x%x, lwmutex_attr_addr=0x%x)",
|
||||
sc_lwmutex.Log("sys_lwmutex_create(lwmutex_addr=0x%x, lwmutex_attr_addr=0x%x)",
|
||||
lwmutex.GetAddr(), attr.GetAddr());
|
||||
|
||||
if (!lwmutex.IsGood() || !attr.IsGood()) return CELL_EFAULT;
|
||||
@ -16,40 +16,49 @@ 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: return CELL_EINVAL;
|
||||
default: sc_lwmutex.Error("Unknown 0x%x recursive attr", (u32)attr->attr_recursive); return CELL_EINVAL;
|
||||
}
|
||||
|
||||
switch (attr->attr_protocol.ToBE())
|
||||
{
|
||||
case se32(SYS_SYNC_PRIORITY): sc_lwmutex.Warning("TODO: SYS_SYNC_PRIORITY attr"); break;
|
||||
case se32(SYS_SYNC_PRIORITY): break;
|
||||
case se32(SYS_SYNC_RETRY): break;
|
||||
case se32(SYS_SYNC_PRIORITY_INHERIT): sc_lwmutex.Error("Invalid SYS_SYNC_PRIORITY_INHERIT attr"); break;
|
||||
case se32(SYS_SYNC_FIFO): sc_lwmutex.Warning("TODO: SYS_SYNC_FIFO attr"); break;
|
||||
default: return CELL_EINVAL;
|
||||
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;
|
||||
}
|
||||
|
||||
lwmutex->attribute = (u32)attr->attr_protocol | (u32)attr->attr_recursive;
|
||||
lwmutex->attribute = attr->attr_protocol | attr->attr_recursive;
|
||||
lwmutex->all_info = 0;
|
||||
lwmutex->pad = 0;
|
||||
lwmutex->recursive_count = 0;
|
||||
lwmutex->sleep_queue = 0;
|
||||
|
||||
sc_lwmutex.Warning("*** lwmutex created [%s] (attribute=0x%x): id=???", attr->name, (u32)lwmutex->attribute);
|
||||
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): sleep_queue=0x%x",
|
||||
attr->name, (u32)lwmutex->attribute, sq_id);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int sys_lwmutex_destroy(mem_ptr_t<sys_lwmutex_t> lwmutex)
|
||||
{
|
||||
sc_lwmutex.Warning("sys_lwmutex_destroy(lwmutex_addr=0x%x)", lwmutex.GetAddr());
|
||||
sc_lwmutex.Log("sys_lwmutex_destroy(lwmutex_addr=0x%x)", lwmutex.GetAddr());
|
||||
|
||||
if (!lwmutex.IsGood()) return CELL_EFAULT;
|
||||
|
||||
u32 sq_id = lwmutex->sleep_queue;
|
||||
if (!Emu.GetIdManager().CheckID(sq_id)) return CELL_ESRCH;
|
||||
|
||||
// try to make it unable to lock
|
||||
switch (int res = lwmutex->trylock(~0))
|
||||
{
|
||||
case CELL_OK: lwmutex->attribute = 0;
|
||||
default: return res;
|
||||
case CELL_OK:
|
||||
lwmutex->attribute = 0;
|
||||
lwmutex->sleep_queue = 0;
|
||||
Emu.GetIdManager().RemoveID(sq_id);
|
||||
default: return res;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,103 @@ struct sys_lwmutex_attribute_t
|
||||
{
|
||||
be_t<u32> attr_protocol;
|
||||
be_t<u32> attr_recursive;
|
||||
char name[8];
|
||||
union
|
||||
{
|
||||
char name[8];
|
||||
u64 name_u64;
|
||||
};
|
||||
};
|
||||
|
||||
class SleepQueue
|
||||
{
|
||||
/* struct q_rec
|
||||
{
|
||||
u32 tid;
|
||||
u64 prio;
|
||||
q_rec(u32 tid, u64 prio): tid(tid), prio(prio) {}
|
||||
}; */
|
||||
|
||||
SMutex m_mutex;
|
||||
Array<u32> list;
|
||||
u64 m_name;
|
||||
|
||||
public:
|
||||
SleepQueue(u64 name)
|
||||
: m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
void push(u32 tid)
|
||||
{
|
||||
SMutexLocker lock(m_mutex);
|
||||
list.AddCpy(tid);
|
||||
}
|
||||
|
||||
u32 pop() // SYS_SYNC_FIFO
|
||||
{
|
||||
SMutexLocker lock(m_mutex);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (list.GetCount())
|
||||
{
|
||||
u32 res = list[0];
|
||||
list.RemoveAt(0);
|
||||
if (Emu.GetIdManager().CheckID(res))
|
||||
// check thread
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
u32 pop_prio() // SYS_SYNC_PRIORITY
|
||||
{
|
||||
SMutexLocker lock(m_mutex);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (list.GetCount())
|
||||
{
|
||||
u64 max_prio = 0;
|
||||
u32 sel = 0;
|
||||
for (u32 i = 0; i < list.GetCount(); i++)
|
||||
{
|
||||
CPUThread* t = Emu.GetCPU().GetThread(list[i]);
|
||||
if (!t)
|
||||
{
|
||||
list[i] = 0;
|
||||
sel = i;
|
||||
break;
|
||||
}
|
||||
|
||||
u64 prio = t->GetPrio();
|
||||
if (prio > max_prio)
|
||||
{
|
||||
max_prio = prio;
|
||||
sel = i;
|
||||
}
|
||||
}
|
||||
u32 res = list[sel];
|
||||
list.RemoveAt(sel);
|
||||
/* if (Emu.GetIdManager().CheckID(res)) */
|
||||
if (res)
|
||||
// check thread
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
u32 pop_prio_inherit() // (TODO)
|
||||
{
|
||||
ConLog.Error("TODO: SleepQueue::pop_prio_inherit()");
|
||||
Emu.Pause();
|
||||
}
|
||||
};
|
||||
|
||||
struct sys_lwmutex_t
|
||||
@ -53,16 +149,16 @@ struct sys_lwmutex_t
|
||||
be_t<u32> sleep_queue;
|
||||
be_t<u32> pad;
|
||||
|
||||
int enter(u32 tid) // check and process (non-)recursive mutex
|
||||
int trylock(be_t<u32> tid)
|
||||
{
|
||||
if (!attribute) return CELL_EINVAL;
|
||||
if (!attribute.ToBE()) return CELL_EINVAL;
|
||||
|
||||
if (tid == (u32)owner.GetOwner())
|
||||
if (tid == owner.GetOwner())
|
||||
{
|
||||
if (attribute.ToBE() & se32(SYS_SYNC_RECURSIVE))
|
||||
{
|
||||
recursive_count += 1;
|
||||
if (!recursive_count) return CELL_EKRESOURCE;
|
||||
if (!recursive_count.ToBE()) return CELL_EKRESOURCE;
|
||||
return CELL_OK;
|
||||
}
|
||||
else
|
||||
@ -70,52 +166,64 @@ struct sys_lwmutex_t
|
||||
return CELL_EDEADLK;
|
||||
}
|
||||
}
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
int trylock(u32 tid)
|
||||
{
|
||||
switch (int res = enter(tid))
|
||||
{
|
||||
case CELL_EBUSY: break;
|
||||
default: return res;
|
||||
}
|
||||
switch (owner.trylock(tid))
|
||||
{
|
||||
case SMR_OK: recursive_count = 1; return CELL_OK;
|
||||
default: return CELL_EBUSY;
|
||||
case SMR_OK: recursive_count = 1; return CELL_OK;
|
||||
case SMR_FAILED: return CELL_EBUSY;
|
||||
default: return CELL_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int unlock(u32 tid)
|
||||
int unlock(be_t<u32> tid)
|
||||
{
|
||||
if (tid != (u32)owner.GetOwner())
|
||||
if (tid != owner.GetOwner())
|
||||
{
|
||||
return CELL_EPERM;
|
||||
}
|
||||
else
|
||||
{
|
||||
recursive_count -= 1;
|
||||
if (!recursive_count)
|
||||
if (!recursive_count.ToBE())
|
||||
{
|
||||
owner.unlock(tid);
|
||||
be_t<u32> target = 0;
|
||||
switch (attribute.ToBE() & se32(SYS_SYNC_ATTR_PROTOCOL_MASK))
|
||||
{
|
||||
case se32(SYS_SYNC_FIFO):
|
||||
case se32(SYS_SYNC_PRIORITY):
|
||||
SleepQueue* sq;
|
||||
if (!Emu.GetIdManager().GetIDData(sleep_queue, sq)) return CELL_ESRCH;
|
||||
target = attribute.ToBE() & se32(SYS_SYNC_FIFO) ? sq->pop() : sq->pop_prio();
|
||||
case se32(SYS_SYNC_RETRY): default: owner.unlock(tid, target); break;
|
||||
}
|
||||
}
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
int lock(u32 tid, u64 timeout)
|
||||
int lock(be_t<u32> tid, u64 timeout)
|
||||
{
|
||||
switch (int res = enter(tid))
|
||||
switch (int res = trylock(tid))
|
||||
{
|
||||
case CELL_EBUSY: break;
|
||||
default: return res;
|
||||
case CELL_EBUSY: break;
|
||||
default: return res;
|
||||
}
|
||||
|
||||
switch (attribute.ToBE() & se32(SYS_SYNC_ATTR_PROTOCOL_MASK))
|
||||
{
|
||||
case se32(SYS_SYNC_PRIORITY):
|
||||
case se32(SYS_SYNC_FIFO):
|
||||
SleepQueue* sq;
|
||||
if (!Emu.GetIdManager().GetIDData(sleep_queue, sq)) return CELL_ESRCH;
|
||||
sq->push(tid);
|
||||
default: break;
|
||||
}
|
||||
|
||||
switch (owner.lock(tid, timeout))
|
||||
{
|
||||
case SMR_OK: recursive_count = 1; return CELL_OK;
|
||||
case SMR_TIMEOUT: return CELL_ETIMEDOUT;
|
||||
default: return CELL_EINVAL;
|
||||
case SMR_OK: case SMR_SIGNAL: recursive_count = 1; return CELL_OK;
|
||||
case SMR_TIMEOUT: return CELL_ETIMEDOUT;
|
||||
default: return CELL_EINVAL;
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -123,13 +231,17 @@ struct sys_lwmutex_t
|
||||
class lwmutex_locker
|
||||
{
|
||||
mem_ptr_t<sys_lwmutex_t> m_mutex;
|
||||
u32 m_id;
|
||||
be_t<u32> m_id;
|
||||
|
||||
lwmutex_locker(u32 lwmutex_addr, u32 tid, u64 timeout = 0)
|
||||
lwmutex_locker(mem_ptr_t<sys_lwmutex_t> lwmutex, be_t<u32> tid, u64 timeout = 0)
|
||||
: m_id(tid)
|
||||
, m_mutex(lwmutex_addr)
|
||||
, m_mutex(lwmutex)
|
||||
{
|
||||
if (int res = m_mutex->lock(m_id, timeout)) throw "lwmutex_locker: m_mutex->lock failed";
|
||||
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()
|
||||
|
@ -21,11 +21,11 @@ int sys_rwlock_create(mem32_t rw_lock_id, mem_ptr_t<sys_rwlock_attribute_t> attr
|
||||
|
||||
if (attr->attr_pshared.ToBE() != se32(0x200))
|
||||
{
|
||||
sys_rwlock.Error("Invalid attr_pshared(0x%x)", (u32)attr->attr_pshared);
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
rw_lock_id = sys_rwlock.GetNewId(new RWLock((u32)attr->attr_protocol, (u32)attr->attr_pshared,
|
||||
(u64)attr->key, (s32)attr->flags, *(u64*)&attr->name));
|
||||
rw_lock_id = sys_rwlock.GetNewId(new RWLock((u32)attr->attr_protocol, attr->name_u64));
|
||||
|
||||
sys_rwlock.Warning("*** rwlock created [%s] (protocol=0x%x): id=%d",
|
||||
attr->name, (u32)attr->attr_protocol, rw_lock_id.GetValue());
|
||||
|
@ -6,8 +6,12 @@ struct sys_rwlock_attribute_t
|
||||
be_t<u32> attr_pshared; // == 0x200 (NOT SHARED)
|
||||
be_t<u64> key; // process-shared key (not used)
|
||||
be_t<s32> flags; // process-shared flags (not used)
|
||||
be_t<u32> pad;
|
||||
char name[8];
|
||||
be_t<u32> pad; // not used
|
||||
union
|
||||
{
|
||||
char name[8];
|
||||
u64 name_u64;
|
||||
};
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
@ -20,21 +24,15 @@ struct RWLock
|
||||
Array<u32> rlock_list; // read lock list
|
||||
u32 m_protocol; // TODO
|
||||
|
||||
u32 m_pshared; // not used
|
||||
u64 m_key; // not used
|
||||
s32 m_flags; // not used
|
||||
union
|
||||
{
|
||||
u64 m_name_data; // not used
|
||||
u64 m_name_u64;
|
||||
char m_name[8];
|
||||
};
|
||||
|
||||
RWLock(u32 protocol, u32 pshared, u64 key, s32 flags, u64 name)
|
||||
RWLock(u32 protocol, u64 name)
|
||||
: m_protocol(protocol)
|
||||
, m_pshared(pshared)
|
||||
, m_key(key)
|
||||
, m_flags(flags)
|
||||
, m_name_data(name)
|
||||
, m_name_u64(name)
|
||||
, wlock_thread(0)
|
||||
{
|
||||
}
|
||||
|
@ -194,13 +194,12 @@ int sys_spu_thread_get_exit_status(u32 id, mem32_t status)
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
if (!(*(SPUThread*)thr).SPU.Out_MBox.GetCount() || !thr->IsStopped())
|
||||
u32 res;
|
||||
if (!(*(SPUThread*)thr).SPU.Out_MBox.Pop(res) || !thr->IsStopped())
|
||||
{
|
||||
return CELL_ESTAT;
|
||||
}
|
||||
|
||||
u32 res;
|
||||
(*(SPUThread*)thr).SPU.Out_MBox.PopUncond(res);
|
||||
status = res;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -1,18 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
enum EventQueueType
|
||||
{
|
||||
SYS_PPU_QUEUE = 1,
|
||||
SYS_SPU_QUEUE = 2,
|
||||
};
|
||||
|
||||
struct sys_event_queue_attr
|
||||
{
|
||||
u32 attr_protocol;
|
||||
int type;
|
||||
char name[8];
|
||||
be_t<u32> protocol; // SYS_SYNC_PRIORITY or SYS_SYNC_FIFO
|
||||
be_t<int> type;
|
||||
union
|
||||
{
|
||||
char name[8];
|
||||
u64 name_u64;
|
||||
};
|
||||
};
|
||||
|
||||
struct sys_event_data
|
||||
{
|
||||
u64 source;
|
||||
u64 data1;
|
||||
u64 data2;
|
||||
u64 data3;
|
||||
be_t<u64> source;
|
||||
be_t<u64> data1;
|
||||
be_t<u64> data2;
|
||||
be_t<u64> data3;
|
||||
};
|
||||
|
||||
struct EventQueue;
|
||||
@ -34,6 +44,19 @@ struct EventQueue
|
||||
EventPort* ports[127];
|
||||
int size;
|
||||
int pos;
|
||||
int type;
|
||||
char name[8];
|
||||
|
||||
u32 m_protocol;
|
||||
int m_type;
|
||||
u64 m_name;
|
||||
u64 m_key;
|
||||
|
||||
EventQueue(u32 protocol, int type, u64 name, u64 key, int size)
|
||||
: m_type(type)
|
||||
, m_protocol(protocol)
|
||||
, m_name(name)
|
||||
, m_key(key)
|
||||
, size(size)
|
||||
, pos(0)
|
||||
{
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user