mirror of https://github.com/RPCS3/rpcs3.git
parent
ed40732e7b
commit
3308fefa7f
|
@ -126,7 +126,11 @@ public:
|
||||||
: sm(_sm)
|
: sm(_sm)
|
||||||
, tid(get_tid())
|
, tid(get_tid())
|
||||||
{
|
{
|
||||||
if (!tid) throw "SMutexLockerBase: invalid thread id";
|
if (!tid)
|
||||||
|
{
|
||||||
|
ConLog.Error("SMutexLockerBase: thread id == 0");
|
||||||
|
Emu.Pause();
|
||||||
|
}
|
||||||
sm.lock(tid);
|
sm.lock(tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,13 @@ struct reservation_struct
|
||||||
volatile u32 owner; // id of thread that got reservation
|
volatile u32 owner; // id of thread that got reservation
|
||||||
volatile u32 addr;
|
volatile u32 addr;
|
||||||
volatile u32 size;
|
volatile u32 size;
|
||||||
|
volatile u32 data32;
|
||||||
|
volatile u64 data64;
|
||||||
|
// atm, PPU can't break SPU MFC reservation correctly
|
||||||
|
|
||||||
__forceinline void clear()
|
__forceinline void clear()
|
||||||
{
|
{
|
||||||
owner = 0;
|
owner = 0;
|
||||||
addr = 0;
|
|
||||||
size = 0;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2361,14 +2361,13 @@ private:
|
||||||
}
|
}
|
||||||
void LWARX(u32 rd, u32 ra, u32 rb)
|
void LWARX(u32 rd, u32 ra, u32 rb)
|
||||||
{
|
{
|
||||||
ConLog.Warning("LWARX");
|
|
||||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||||
|
|
||||||
SMutexLocker lock(reservation.mutex);
|
SMutexLocker lock(reservation.mutex);
|
||||||
reservation.owner = lock.tid;
|
reservation.owner = lock.tid;
|
||||||
reservation.addr = addr;
|
reservation.addr = addr;
|
||||||
reservation.size = 4;
|
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)
|
void LDX(u32 rd, u32 ra, u32 rb)
|
||||||
{
|
{
|
||||||
|
@ -2538,14 +2537,13 @@ private:
|
||||||
}
|
}
|
||||||
void LDARX(u32 rd, u32 ra, u32 rb)
|
void LDARX(u32 rd, u32 ra, u32 rb)
|
||||||
{
|
{
|
||||||
ConLog.Warning("LDARX");
|
|
||||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||||
|
|
||||||
SMutexLocker lock(reservation.mutex);
|
SMutexLocker lock(reservation.mutex);
|
||||||
reservation.owner = lock.tid;
|
reservation.owner = lock.tid;
|
||||||
reservation.addr = addr;
|
reservation.addr = addr;
|
||||||
reservation.size = 8;
|
reservation.size = 8;
|
||||||
CPU.GPR[rd] = Memory.Read64(addr);
|
reservation.data64 = CPU.GPR[rd] = Memory.Read64(addr);
|
||||||
}
|
}
|
||||||
void DCBF(u32 ra, u32 rb)
|
void DCBF(u32 ra, u32 rb)
|
||||||
{
|
{
|
||||||
|
@ -2658,14 +2656,13 @@ private:
|
||||||
}
|
}
|
||||||
void STWCX_(u32 rs, u32 ra, u32 rb)
|
void STWCX_(u32 rs, u32 ra, u32 rb)
|
||||||
{
|
{
|
||||||
ConLog.Warning("STWCX_");
|
|
||||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||||
|
|
||||||
SMutexLocker lock(reservation.mutex);
|
SMutexLocker lock(reservation.mutex);
|
||||||
if (lock.tid == reservation.owner && reservation.addr == addr && reservation.size == 4)
|
if (lock.tid == reservation.owner && reservation.addr == addr && reservation.size == 4)
|
||||||
{
|
{
|
||||||
Memory.Write32(addr, CPU.GPR[rs]);
|
// Memory.Write32(addr, CPU.GPR[rs]);
|
||||||
CPU.SetCR_EQ(0, true);
|
CPU.SetCR_EQ(0, InterlockedCompareExchange((volatile long*)(Memory + addr), (u32)CPU.GPR[rs], reservation.data32) == reservation.data32);
|
||||||
reservation.clear();
|
reservation.clear();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2712,14 +2709,13 @@ private:
|
||||||
}
|
}
|
||||||
void STDCX_(u32 rs, u32 ra, u32 rb)
|
void STDCX_(u32 rs, u32 ra, u32 rb)
|
||||||
{
|
{
|
||||||
ConLog.Warning("STDCX_");
|
|
||||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||||
|
|
||||||
SMutexLocker lock(reservation.mutex);
|
SMutexLocker lock(reservation.mutex);
|
||||||
if (lock.tid == reservation.owner && reservation.addr == addr && reservation.size == 8)
|
if (lock.tid == reservation.owner && reservation.addr == addr && reservation.size == 8)
|
||||||
{
|
{
|
||||||
Memory.Write64(addr, CPU.GPR[rs]);
|
// Memory.Write64(addr, CPU.GPR[rs]);
|
||||||
CPU.SetCR_EQ(0, true);
|
CPU.SetCR_EQ(0, InterlockedCompareExchange64((volatile long long*)(Memory + addr), CPU.GPR[rs], reservation.data64) == reservation.data64);
|
||||||
reservation.clear();
|
reservation.clear();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -83,7 +83,7 @@ struct CellAudioPortConfig
|
||||||
struct CellAudioConfig //custom structure
|
struct CellAudioConfig //custom structure
|
||||||
{
|
{
|
||||||
bool m_is_audio_initialized;
|
bool m_is_audio_initialized;
|
||||||
bool m_is_audio_port_open;
|
bool m_is_audio_port_opened;
|
||||||
bool m_is_audio_port_started;
|
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());
|
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;
|
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->nChannel = audioParam->nChannel;
|
||||||
m_param->nBlock = audioParam->nBlock;
|
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(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;
|
portConfig->status = CELL_AUDIO_STATUS_CLOSE;
|
||||||
return CELL_OK;
|
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;
|
portConfig->status = CELL_AUDIO_STATUS_RUN;
|
||||||
}
|
}
|
||||||
|
@ -268,7 +268,7 @@ int cellAudioPortStart(u32 portNum)
|
||||||
{
|
{
|
||||||
cellAudio.Warning("cellAudioPortStart(portNum=0x%x)",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;
|
return CELL_AUDIO_ERROR_PORT_OPEN;
|
||||||
|
|
||||||
m_config->m_is_audio_port_started = true;
|
m_config->m_is_audio_port_started = true;
|
||||||
|
@ -279,10 +279,10 @@ int cellAudioPortClose(u32 portNum)
|
||||||
{
|
{
|
||||||
cellAudio.Warning("cellAudioPortClose(portNum=0x%x)",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;
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1016,6 +1016,6 @@ void cellAudio_init()
|
||||||
void cellAudio_unload()
|
void cellAudio_unload()
|
||||||
{
|
{
|
||||||
m_config->m_is_audio_initialized = false;
|
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;
|
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 );
|
u32 data, u32 data_size, int prio, u64 flags );
|
||||||
|
|
||||||
//sys_event
|
//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_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_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);
|
extern int sys_event_port_connect_local(u32 event_port_id, u32 event_queue_id);
|
||||||
|
|
|
@ -6,30 +6,24 @@
|
||||||
SysCallBase sys_event("sys_event");
|
SysCallBase sys_event("sys_event");
|
||||||
|
|
||||||
//128
|
//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)",
|
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)
|
if(size <= 0 || size > 127)
|
||||||
{
|
{
|
||||||
return CELL_EINVAL;
|
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;
|
return CELL_EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& attr = (sys_event_queue_attr&)Memory[attr_addr];
|
equeue_id = sys_event.GetNewId(new EventQueue((u32)attr->protocol, (int)attr->type, attr->name_u64, event_queue_key, size));
|
||||||
sys_event.Warning("name = %s", attr.name);
|
sys_event.Warning("*** event_queue created[%s] (protocol=0x%x, type=0x%x): id = %d",
|
||||||
sys_event.Warning("type = %d", re(attr.type));
|
attr->name, (u32)attr->protocol, (int)attr->type, equeue_id.GetValue());
|
||||||
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));
|
|
||||||
|
|
||||||
return CELL_OK;
|
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];
|
auto dst = (sys_event_data&)Memory[event_addr];
|
||||||
|
|
||||||
re(dst.source, equeue->ports[i]->name);
|
dst.source = equeue->ports[i]->name;
|
||||||
re(dst.data1, equeue->ports[i]->data1);
|
dst.data1 = equeue->ports[i]->data1;
|
||||||
re(dst.data2, equeue->ports[i]->data2);
|
dst.data2 = equeue->ports[i]->data2;
|
||||||
re(dst.data3, equeue->ports[i]->data3);
|
dst.data3 = equeue->ports[i]->data3;
|
||||||
|
|
||||||
equeue->ports[i]->has_data = false;
|
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)
|
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());
|
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;
|
||||||
|
|
||||||
switch (lwmutex->attribute.ToBE())
|
lwcond->lwmutex = lwmutex.GetAddr();
|
||||||
{
|
lwcond->lwcond_queue = sys_lwcond.GetNewId(new LWCond(attr->name_u64));
|
||||||
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_addr = lwmutex.GetAddr();
|
sys_lwcond.Warning("*** lwcond created [%s] (attr=0x%x, lwmutex.sq=0x%x): id=0x%x",
|
||||||
lwcond->lwcond_queue = sys_lwcond.GetNewId(new LWCond((u32)lwmutex->attribute, *(u64*)&attr->name));
|
attr->name, (u32)lwmutex->attribute, (u32)lwmutex->sleep_queue, (u32)lwcond->lwcond_queue);
|
||||||
|
|
||||||
sys_lwcond.Warning("*** lwcond created [%s] (protocol=0x%x): id=%d", attr->name, (u32)lwmutex->attribute, (u32)lwcond->lwcond_queue);
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +42,7 @@ int sys_lwcond_signal(mem_ptr_t<sys_lwcond_t> lwcond)
|
||||||
u32 id = (u32)lwcond->lwcond_queue;
|
u32 id = (u32)lwcond->lwcond_queue;
|
||||||
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
|
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;
|
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;
|
u32 id = (u32)lwcond->lwcond_queue;
|
||||||
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
|
if (!sys_lwcond.CheckId(id, lwc)) return CELL_ESRCH;
|
||||||
const u32 tid = GetCurrentPPUThread().GetId();
|
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
|
if ((u32)lwmutex->owner.GetOwner() != tid) return CELL_EPERM; // caller must own this lwmutex
|
||||||
lwc->begin_waiting(tid);
|
lwc->begin_waiting(tid);
|
||||||
|
|
|
@ -2,12 +2,16 @@
|
||||||
|
|
||||||
struct sys_lwcond_attribute_t
|
struct sys_lwcond_attribute_t
|
||||||
{
|
{
|
||||||
char name[8];
|
union
|
||||||
|
{
|
||||||
|
char name[8];
|
||||||
|
u64 name_u64;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sys_lwcond_t
|
struct sys_lwcond_t
|
||||||
{
|
{
|
||||||
be_t<u32> lwmutex_addr;
|
be_t<u32> lwmutex;
|
||||||
be_t<u32> lwcond_queue;
|
be_t<u32> lwcond_queue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,22 +22,20 @@ struct LWCond
|
||||||
std::mutex m_lock;
|
std::mutex m_lock;
|
||||||
Array<u32> waiters; // list of waiting threads
|
Array<u32> waiters; // list of waiting threads
|
||||||
Array<u32> signaled; // list of signaled threads
|
Array<u32> signaled; // list of signaled threads
|
||||||
u32 m_protocol; // protocol
|
|
||||||
u64 m_name; // not used
|
u64 m_name; // not used
|
||||||
|
|
||||||
LWCond(u32 prot, u64 name)
|
LWCond(u64 name)
|
||||||
: m_name(name)
|
: m_name(name)
|
||||||
, m_protocol(prot)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void signal()
|
void signal(u32 _protocol)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_lock);
|
std::lock_guard<std::mutex> lock(m_lock);
|
||||||
|
|
||||||
if (waiters.GetCount())
|
if (waiters.GetCount())
|
||||||
{
|
{
|
||||||
if (m_protocol == SYS_SYNC_PRIORITY)
|
if ((_protocol & SYS_SYNC_ATTR_PROTOCOL_MASK) == SYS_SYNC_PRIORITY)
|
||||||
{
|
{
|
||||||
u64 max_prio = 0;
|
u64 max_prio = 0;
|
||||||
u32 sel = 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)
|
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());
|
lwmutex.GetAddr(), attr.GetAddr());
|
||||||
|
|
||||||
if (!lwmutex.IsGood() || !attr.IsGood()) return CELL_EFAULT;
|
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_RECURSIVE): break;
|
||||||
case se32(SYS_SYNC_NOT_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())
|
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_RETRY): break;
|
||||||
case se32(SYS_SYNC_PRIORITY_INHERIT): sc_lwmutex.Error("Invalid SYS_SYNC_PRIORITY_INHERIT attr"); 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): sc_lwmutex.Warning("TODO: SYS_SYNC_FIFO attr"); break;
|
case se32(SYS_SYNC_FIFO): break;
|
||||||
default: return CELL_EINVAL;
|
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->all_info = 0;
|
||||||
lwmutex->pad = 0;
|
lwmutex->pad = 0;
|
||||||
lwmutex->recursive_count = 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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_lwmutex_destroy(mem_ptr_t<sys_lwmutex_t> lwmutex)
|
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;
|
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
|
// try to make it unable to lock
|
||||||
switch (int res = lwmutex->trylock(~0))
|
switch (int res = lwmutex->trylock(~0))
|
||||||
{
|
{
|
||||||
case CELL_OK: lwmutex->attribute = 0;
|
case CELL_OK:
|
||||||
default: return res;
|
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_protocol;
|
||||||
be_t<u32> attr_recursive;
|
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
|
struct sys_lwmutex_t
|
||||||
|
@ -53,16 +149,16 @@ struct sys_lwmutex_t
|
||||||
be_t<u32> sleep_queue;
|
be_t<u32> sleep_queue;
|
||||||
be_t<u32> pad;
|
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))
|
if (attribute.ToBE() & se32(SYS_SYNC_RECURSIVE))
|
||||||
{
|
{
|
||||||
recursive_count += 1;
|
recursive_count += 1;
|
||||||
if (!recursive_count) return CELL_EKRESOURCE;
|
if (!recursive_count.ToBE()) return CELL_EKRESOURCE;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -70,52 +166,64 @@ struct sys_lwmutex_t
|
||||||
return CELL_EDEADLK;
|
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))
|
switch (owner.trylock(tid))
|
||||||
{
|
{
|
||||||
case SMR_OK: recursive_count = 1; return CELL_OK;
|
case SMR_OK: recursive_count = 1; return CELL_OK;
|
||||||
default: return CELL_EBUSY;
|
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;
|
return CELL_EPERM;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
recursive_count -= 1;
|
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;
|
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;
|
case CELL_EBUSY: break;
|
||||||
default: return res;
|
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))
|
switch (owner.lock(tid, timeout))
|
||||||
{
|
{
|
||||||
case SMR_OK: recursive_count = 1; return CELL_OK;
|
case SMR_OK: case SMR_SIGNAL: recursive_count = 1; return CELL_OK;
|
||||||
case SMR_TIMEOUT: return CELL_ETIMEDOUT;
|
case SMR_TIMEOUT: return CELL_ETIMEDOUT;
|
||||||
default: return CELL_EINVAL;
|
default: return CELL_EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -123,13 +231,17 @@ struct sys_lwmutex_t
|
||||||
class lwmutex_locker
|
class lwmutex_locker
|
||||||
{
|
{
|
||||||
mem_ptr_t<sys_lwmutex_t> m_mutex;
|
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_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()
|
~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))
|
if (attr->attr_pshared.ToBE() != se32(0x200))
|
||||||
{
|
{
|
||||||
|
sys_rwlock.Error("Invalid attr_pshared(0x%x)", (u32)attr->attr_pshared);
|
||||||
return CELL_EINVAL;
|
return CELL_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rw_lock_id = sys_rwlock.GetNewId(new RWLock((u32)attr->attr_protocol, (u32)attr->attr_pshared,
|
rw_lock_id = sys_rwlock.GetNewId(new RWLock((u32)attr->attr_protocol, attr->name_u64));
|
||||||
(u64)attr->key, (s32)attr->flags, *(u64*)&attr->name));
|
|
||||||
|
|
||||||
sys_rwlock.Warning("*** rwlock created [%s] (protocol=0x%x): id=%d",
|
sys_rwlock.Warning("*** rwlock created [%s] (protocol=0x%x): id=%d",
|
||||||
attr->name, (u32)attr->attr_protocol, rw_lock_id.GetValue());
|
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<u32> attr_pshared; // == 0x200 (NOT SHARED)
|
||||||
be_t<u64> key; // process-shared key (not used)
|
be_t<u64> key; // process-shared key (not used)
|
||||||
be_t<s32> flags; // process-shared flags (not used)
|
be_t<s32> flags; // process-shared flags (not used)
|
||||||
be_t<u32> pad;
|
be_t<u32> pad; // not used
|
||||||
char name[8];
|
union
|
||||||
|
{
|
||||||
|
char name[8];
|
||||||
|
u64 name_u64;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
@ -20,21 +24,15 @@ struct RWLock
|
||||||
Array<u32> rlock_list; // read lock list
|
Array<u32> rlock_list; // read lock list
|
||||||
u32 m_protocol; // TODO
|
u32 m_protocol; // TODO
|
||||||
|
|
||||||
u32 m_pshared; // not used
|
|
||||||
u64 m_key; // not used
|
|
||||||
s32 m_flags; // not used
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
u64 m_name_data; // not used
|
u64 m_name_u64;
|
||||||
char m_name[8];
|
char m_name[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
RWLock(u32 protocol, u32 pshared, u64 key, s32 flags, u64 name)
|
RWLock(u32 protocol, u64 name)
|
||||||
: m_protocol(protocol)
|
: m_protocol(protocol)
|
||||||
, m_pshared(pshared)
|
, m_name_u64(name)
|
||||||
, m_key(key)
|
|
||||||
, m_flags(flags)
|
|
||||||
, m_name_data(name)
|
|
||||||
, wlock_thread(0)
|
, wlock_thread(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,13 +194,12 @@ int sys_spu_thread_get_exit_status(u32 id, mem32_t status)
|
||||||
return CELL_ESRCH;
|
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;
|
return CELL_ESTAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 res;
|
|
||||||
(*(SPUThread*)thr).SPU.Out_MBox.PopUncond(res);
|
|
||||||
status = res;
|
status = res;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,28 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
enum EventQueueType
|
||||||
|
{
|
||||||
|
SYS_PPU_QUEUE = 1,
|
||||||
|
SYS_SPU_QUEUE = 2,
|
||||||
|
};
|
||||||
|
|
||||||
struct sys_event_queue_attr
|
struct sys_event_queue_attr
|
||||||
{
|
{
|
||||||
u32 attr_protocol;
|
be_t<u32> protocol; // SYS_SYNC_PRIORITY or SYS_SYNC_FIFO
|
||||||
int type;
|
be_t<int> type;
|
||||||
char name[8];
|
union
|
||||||
|
{
|
||||||
|
char name[8];
|
||||||
|
u64 name_u64;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sys_event_data
|
struct sys_event_data
|
||||||
{
|
{
|
||||||
u64 source;
|
be_t<u64> source;
|
||||||
u64 data1;
|
be_t<u64> data1;
|
||||||
u64 data2;
|
be_t<u64> data2;
|
||||||
u64 data3;
|
be_t<u64> data3;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EventQueue;
|
struct EventQueue;
|
||||||
|
@ -34,6 +44,19 @@ struct EventQueue
|
||||||
EventPort* ports[127];
|
EventPort* ports[127];
|
||||||
int size;
|
int size;
|
||||||
int pos;
|
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