mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-09 16:31:28 +12:00
sys_ppu_thread_join, sys_ppu_thread_exit fixed
Some diagnostic messages in mutexes
This commit is contained in:
parent
fac86aae58
commit
3127543b6e
13 changed files with 220 additions and 56 deletions
|
@ -361,7 +361,7 @@ void CPUThread::Task()
|
||||||
if (Ini.HLELogging.GetValue()) ConLog.Write("%s leave", CPUThread::GetFName().wx_str());
|
if (Ini.HLELogging.GetValue()) ConLog.Write("%s leave", CPUThread::GetFName().wx_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
int CPUThread::ExecAsCallback(u64 pc, bool wait, u64 a1, u64 a2, u64 a3, u64 a4) // not multithread-safe
|
s64 CPUThread::ExecAsCallback(u64 pc, bool wait, u64 a1, u64 a2, u64 a3, u64 a4) // not multithread-safe
|
||||||
{
|
{
|
||||||
while (m_alive)
|
while (m_alive)
|
||||||
{
|
{
|
||||||
|
|
|
@ -57,7 +57,7 @@ protected:
|
||||||
u64 m_stack_size;
|
u64 m_stack_size;
|
||||||
u64 m_stack_point;
|
u64 m_stack_point;
|
||||||
|
|
||||||
u32 m_exit_status;
|
u64 m_exit_status;
|
||||||
|
|
||||||
CPUDecoder* m_dec;
|
CPUDecoder* m_dec;
|
||||||
|
|
||||||
|
@ -80,10 +80,10 @@ public:
|
||||||
void SetName(const std::string& name);
|
void SetName(const std::string& name);
|
||||||
void SetPrio(const u64 prio) { m_prio = prio; }
|
void SetPrio(const u64 prio) { m_prio = prio; }
|
||||||
void SetOffset(const u64 offset) { m_offset = offset; }
|
void SetOffset(const u64 offset) { m_offset = offset; }
|
||||||
void SetExitStatus(const u32 status) { m_exit_status = status; }
|
void SetExitStatus(const u64 status) { m_exit_status = status; }
|
||||||
|
|
||||||
u64 GetOffset() const { return m_offset; }
|
u64 GetOffset() const { return m_offset; }
|
||||||
u32 GetExitStatus() const { return m_exit_status; }
|
u64 GetExitStatus() const { return m_exit_status; }
|
||||||
u64 GetPrio() const { return m_prio; }
|
u64 GetPrio() const { return m_prio; }
|
||||||
|
|
||||||
std::string GetName() const { return NamedThreadBase::GetThreadName(); }
|
std::string GetName() const { return NamedThreadBase::GetThreadName(); }
|
||||||
|
@ -234,7 +234,7 @@ public:
|
||||||
return pc + 4;
|
return pc + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ExecAsCallback(u64 pc, bool wait, u64 a1 = 0, u64 a2 = 0, u64 a3 = 0, u64 a4 = 0);
|
s64 ExecAsCallback(u64 pc, bool wait, u64 a1 = 0, u64 a2 = 0, u64 a3 = 0, u64 a4 = 0);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void DoReset()=0;
|
virtual void DoReset()=0;
|
||||||
|
|
|
@ -2096,8 +2096,11 @@ private:
|
||||||
case 0x2: SysCall(); break;
|
case 0x2: SysCall(); break;
|
||||||
case 0x3:
|
case 0x3:
|
||||||
StaticExecute(CPU.GPR[11]);
|
StaticExecute(CPU.GPR[11]);
|
||||||
ConLog.Write("'%s' done with code[0x%llx]! #pc: 0x%llx",
|
if (Ini.HLELogging.GetValue())
|
||||||
wxString(g_static_funcs_list[CPU.GPR[11]].name).wx_str(), CPU.GPR[3], CPU.PC);
|
{
|
||||||
|
ConLog.Write("'%s' done with code[0x%llx]! #pc: 0x%llx",
|
||||||
|
wxString(g_static_funcs_list[CPU.GPR[11]].name).wx_str(), CPU.GPR[3], CPU.PC);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0x22: UNK("HyperCall LV1"); break;
|
case 0x22: UNK("HyperCall LV1"); break;
|
||||||
default: UNK(wxString::Format("Unknown sc: %x", sc_code));
|
default: UNK(wxString::Format("Unknown sc: %x", sc_code));
|
||||||
|
|
|
@ -17,6 +17,7 @@ PPUThread& GetCurrentPPUThread()
|
||||||
|
|
||||||
PPUThread::PPUThread() : PPCThread(CPU_THREAD_PPU)
|
PPUThread::PPUThread() : PPCThread(CPU_THREAD_PPU)
|
||||||
{
|
{
|
||||||
|
owned_mutexes = 0;
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -525,6 +525,9 @@ static const s32 MAX_INT_VALUE = 0x7fffffff;
|
||||||
|
|
||||||
class PPUThread : public PPCThread
|
class PPUThread : public PPCThread
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
std::atomic<u32> owned_mutexes;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PPCdouble FPR[32]; //Floating Point Register
|
PPCdouble FPR[32]; //Floating Point Register
|
||||||
FPSCRhdr FPSCR; //Floating Point Status and Control Register
|
FPSCRhdr FPSCR; //Floating Point Status and Control Register
|
||||||
|
|
|
@ -80,8 +80,8 @@ u32 dmuxOpen(Demuxer* data)
|
||||||
cb.SetAddr(dmux.cbFunc);
|
cb.SetAddr(dmux.cbFunc);
|
||||||
cb.Handle(dmux.id, dmuxMsg.GetAddr(), dmux.cbArg);
|
cb.Handle(dmux.id, dmuxMsg.GetAddr(), dmux.cbArg);
|
||||||
cb.Branch(task.type == dmuxResetStreamAndWaitDone);*/
|
cb.Branch(task.type == dmuxResetStreamAndWaitDone);*/
|
||||||
dmux.dmuxCb->ExecAsCallback(dmux.cbFunc, true, dmux.id, dmuxMsg.GetAddr(), dmux.cbArg);
|
//dmux.dmuxCb->ExecAsCallback(dmux.cbFunc, true, dmux.id, dmuxMsg.GetAddr(), dmux.cbArg);
|
||||||
updates_signaled++;
|
//updates_signaled++;
|
||||||
}
|
}
|
||||||
else switch (code.ToLE())
|
else switch (code.ToLE())
|
||||||
{
|
{
|
||||||
|
@ -584,6 +584,17 @@ int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize
|
||||||
return CELL_DMUX_ERROR_FATAL;
|
return CELL_DMUX_ERROR_FATAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dmux->is_running) // maximum hack
|
||||||
|
{
|
||||||
|
mem_ptr_t<CellDmuxMsg> dmuxMsg(a128(dmux->memAddr) + 128);
|
||||||
|
dmuxMsg->msgType = CELL_DMUX_MSG_TYPE_DEMUX_DONE;
|
||||||
|
dmuxMsg->supplementalInfo = 0; // !!!
|
||||||
|
Callback cb;
|
||||||
|
cb.SetAddr(dmux->cbFunc);
|
||||||
|
cb.Handle(dmux->id, dmuxMsg.GetAddr(), dmux->cbArg);
|
||||||
|
cb.Branch(true);
|
||||||
|
}
|
||||||
|
|
||||||
while (dmux->is_running) // hack
|
while (dmux->is_running) // hack
|
||||||
{
|
{
|
||||||
if (Emu.IsStopped())
|
if (Emu.IsStopped())
|
||||||
|
|
|
@ -13,20 +13,21 @@ int cellAANAddData(u32 handle, u32 port, u32 offset, u32 addr, u32 samples)
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// libmixer Functions, NOT active in this moment
|
int cellAANConnect(u32 receive, u32 receivePortNo, u32 source, u32 sourcePortNo)
|
||||||
/*int cellAANConnect(CellAANHandle receive, u32 receivePortNo, CellAANHandle source, u32 sourcePortNo)
|
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(libmixer);
|
libmixer.Error("cellAANConnect(receive=0x%x, receivePortNo=0x%x, source=0x%x, sourcrPortNo=0x%x)",
|
||||||
|
receive, receivePortNo, source, sourcePortNo);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellAANDisconnect(CellAANHandle receive, u32 receivePortNo, CellAANHandle source, u32 sourcePortNo)
|
int cellAANDisconnect(u32 receive, u32 receivePortNo, u32 source, u32 sourcePortNo)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(libmixer);
|
libmixer.Error("cellAANDisconnect(receive=0x%x, receivePortNo=0x%x, source=0x%x, sourcrPortNo=0x%x)",
|
||||||
|
receive, receivePortNo, source, sourcePortNo);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellSSPlayerCreate(CellAANHandle *handle, CellSSPlayerConfig *config)
|
/*int cellSSPlayerCreate(CellAANHandle *handle, CellSSPlayerConfig *config)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED_FUNC(libmixer);
|
UNIMPLEMENTED_FUNC(libmixer);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -182,7 +183,6 @@ void libmixer_init()
|
||||||
0xffffffff81690000,
|
0xffffffff81690000,
|
||||||
0xffffffff7c050378,
|
0xffffffff7c050378,
|
||||||
0xffffffff7cc43378,
|
0xffffffff7cc43378,
|
||||||
// 78 63 00 20 clrldi r3,r3,32 # 20 // may be included
|
|
||||||
0xffffffff7d465378,
|
0xffffffff7d465378,
|
||||||
0xffffffff812b0030,
|
0xffffffff812b0030,
|
||||||
0xffffffff80090000,
|
0xffffffff80090000,
|
||||||
|
@ -200,6 +200,80 @@ void libmixer_init()
|
||||||
};
|
};
|
||||||
libmixer.AddFuncSub(cellAANAddData_table, "cellAANAddData", cellAANAddData);
|
libmixer.AddFuncSub(cellAANAddData_table, "cellAANAddData", cellAANAddData);
|
||||||
|
|
||||||
|
u64 cellAANConnect_table[39] = {
|
||||||
|
0xfffffffff821ff71,
|
||||||
|
0xffffffff7c0802a6,
|
||||||
|
0xffffffff2f830000,
|
||||||
|
0xfffffffff80100a0,
|
||||||
|
0xffffffff3c008031,
|
||||||
|
0xffffffff7c691b78,
|
||||||
|
0xffffffff7c8a2378,
|
||||||
|
0xffffffff60000003,
|
||||||
|
0xffffff00409e0018, // bne
|
||||||
|
0xffffffff7c0307b4,
|
||||||
|
0xffffffffe80100a0,
|
||||||
|
0xffffffff38210090,
|
||||||
|
0xffffffff7c0803a6,
|
||||||
|
0xffffffff4e800020,
|
||||||
|
0xffffffff2f850000,
|
||||||
|
0xffffffff78630020,
|
||||||
|
0xffffffff38810070,
|
||||||
|
0xffffff00419effe0, // beq
|
||||||
|
0xffffffff81690000,
|
||||||
|
0xffffffff38000001,
|
||||||
|
0xffffffff91210074,
|
||||||
|
0xffffffff90a10070,
|
||||||
|
0xffffffff90c10078,
|
||||||
|
0xffffffff9141007c,
|
||||||
|
0xffffffff812b0018, // [24]
|
||||||
|
0xffffffff90010080,
|
||||||
|
0xffffffff80090000,
|
||||||
|
0xfffffffff8410028,
|
||||||
|
0xffffffff7c0903a6,
|
||||||
|
0xffffffff80490004,
|
||||||
|
0xffffffff4e800421,
|
||||||
|
0xffffffffe8410028,
|
||||||
|
0xffffffff7c601b78,
|
||||||
|
0xffffffff7c0307b4,
|
||||||
|
0xffffffffe80100a0,
|
||||||
|
0xffffffff38210090,
|
||||||
|
0xffffffff7c0803a6,
|
||||||
|
0xffffffff4e800020,
|
||||||
|
0, // [38]
|
||||||
|
};
|
||||||
|
libmixer.AddFuncSub(cellAANConnect_table, "cellAANConnect", cellAANConnect);
|
||||||
|
cellAANConnect_table[24] = 0xffffffff812b001c;
|
||||||
|
libmixer.AddFuncSub(cellAANConnect_table, "cellAANDisconnect", cellAANDisconnect);
|
||||||
|
|
||||||
|
static const u64 cellAANAddData_table1[] = {
|
||||||
|
// TODO
|
||||||
|
0xffffffff7c691b78,
|
||||||
|
0xffffffff7c0802a6,
|
||||||
|
0xfffffffff821ff91,
|
||||||
|
0xfffffffff8010080,
|
||||||
|
0xffffffff7c802378,
|
||||||
|
0xffffffff7caa2b78,
|
||||||
|
0xffffffff81690000,
|
||||||
|
0xffffffff7c050378,
|
||||||
|
0xffffffff7cc43378,
|
||||||
|
0xffffffff78630020, // clrldi r3,r3,32
|
||||||
|
0xffffffff7d465378,
|
||||||
|
0xffffffff812b0030,
|
||||||
|
0xffffffff80090000,
|
||||||
|
0xfffffffff8410028,
|
||||||
|
0xffffffff7c0903a6,
|
||||||
|
0xffffffff80490004,
|
||||||
|
0xffffffff4e800421,
|
||||||
|
0xffffffffe8410028,
|
||||||
|
0xffffffffe8010080,
|
||||||
|
0xffffffff7c6307b4,
|
||||||
|
0xffffffff7c0803a6,
|
||||||
|
0xffffffff38210070,
|
||||||
|
0xffffffff4e800020,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
libmixer.AddFuncSub(cellAANAddData_table1, "cellAANAddData(1)", cellAANAddData);
|
||||||
|
|
||||||
static const u64 cellSurMixerCreate_table[] = {
|
static const u64 cellSurMixerCreate_table[] = {
|
||||||
0xffffffff2f830000,
|
0xffffffff2f830000,
|
||||||
0xffffffff7c0802a6,
|
0xffffffff7c0802a6,
|
||||||
|
|
|
@ -9,6 +9,8 @@ void StaticAnalyse(void* ptr, u32 size)
|
||||||
{
|
{
|
||||||
u32* data = (u32*)ptr; size /= 4;
|
u32* data = (u32*)ptr; size /= 4;
|
||||||
|
|
||||||
|
return; // disabled
|
||||||
|
|
||||||
// TODO: optimize search
|
// TODO: optimize search
|
||||||
for (u32 i = 0; i < size; i++)
|
for (u32 i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
|
@ -38,7 +40,7 @@ void StaticAnalyse(void* ptr, u32 size)
|
||||||
data[i] = re(0x39600000 | j); // li r11, j
|
data[i] = re(0x39600000 | j); // li r11, j
|
||||||
data[i+1] = se32(0x44000003); // sc 3
|
data[i+1] = se32(0x44000003); // sc 3
|
||||||
data[i+2] = se32(0x4e800020); // blr
|
data[i+2] = se32(0x4e800020); // blr
|
||||||
i += g_static_funcs_list[j].ops.GetCount(); // ???
|
i += 2; // ???
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,9 +201,9 @@ extern int sys_rwlock_trywlock(u32 rw_lock_id);
|
||||||
extern int sys_rwlock_wunlock(u32 rw_lock_id);
|
extern int sys_rwlock_wunlock(u32 rw_lock_id);
|
||||||
|
|
||||||
//ppu_thread
|
//ppu_thread
|
||||||
extern void sys_ppu_thread_exit(int errorcode);
|
extern void sys_ppu_thread_exit(u64 errorcode);
|
||||||
extern int sys_ppu_thread_yield();
|
extern int sys_ppu_thread_yield();
|
||||||
extern int sys_ppu_thread_join(u32 thread_id, u32 vptr_addr);
|
extern int sys_ppu_thread_join(u32 thread_id, mem64_t vptr);
|
||||||
extern int sys_ppu_thread_detach(u32 thread_id);
|
extern int sys_ppu_thread_detach(u32 thread_id);
|
||||||
extern void sys_ppu_thread_get_join_state(u32 isjoinable_addr);
|
extern void sys_ppu_thread_get_join_state(u32 isjoinable_addr);
|
||||||
extern int sys_ppu_thread_set_priority(u32 thread_id, int prio);
|
extern int sys_ppu_thread_set_priority(u32 thread_id, int prio);
|
||||||
|
|
|
@ -207,17 +207,40 @@ int sys_lwmutex_t::trylock(be_t<u32> tid)
|
||||||
{
|
{
|
||||||
if (attribute.ToBE() == se32(0xDEADBEEF)) return CELL_EINVAL;
|
if (attribute.ToBE() == se32(0xDEADBEEF)) return CELL_EINVAL;
|
||||||
|
|
||||||
|
be_t<u32> owner_tid = mutex.GetOwner();
|
||||||
|
|
||||||
|
if (owner_tid != mutex.GetFreeValue())
|
||||||
|
{
|
||||||
|
if (CPUThread* tt = Emu.GetCPU().GetThread(owner_tid))
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while ((attribute.ToBE() & se32(SYS_SYNC_ATTR_RECURSIVE_MASK)) == 0)
|
while ((attribute.ToBE() & se32(SYS_SYNC_ATTR_RECURSIVE_MASK)) == 0)
|
||||||
{
|
{
|
||||||
if (Emu.IsStopped())
|
if (Emu.IsStopped())
|
||||||
{
|
{
|
||||||
ConLog.Warning("(hack) sys_lwmutex_t::trylock aborted (waiting for recursive attribute, attr=0x%x)", (u32)attribute);
|
ConLog.Warning("(hack) sys_lwmutex_t::(try)lock aborted (waiting for recursive attribute, attr=0x%x)", (u32)attribute);
|
||||||
return CELL_ESRCH;
|
return CELL_ESRCH;
|
||||||
}
|
}
|
||||||
Sleep(1);
|
Sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tid == mutex.GetOwner())
|
if (tid == owner_tid)
|
||||||
{
|
{
|
||||||
if (attribute.ToBE() & se32(SYS_SYNC_RECURSIVE))
|
if (attribute.ToBE() & se32(SYS_SYNC_RECURSIVE))
|
||||||
{
|
{
|
||||||
|
@ -247,6 +270,11 @@ int sys_lwmutex_t::unlock(be_t<u32> tid)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (!recursive_count || (recursive_count.ToBE() != se32(1) && (attribute.ToBE() & se32(SYS_SYNC_NOT_RECURSIVE))))
|
||||||
|
{
|
||||||
|
sc_lwmutex.Error("sys_lwmutex_t::unlock(%d): wrong recursive value (%d)", (u32)sleep_queue, (u32)recursive_count);
|
||||||
|
recursive_count = 1;
|
||||||
|
}
|
||||||
recursive_count -= 1;
|
recursive_count -= 1;
|
||||||
if (!recursive_count.ToBE())
|
if (!recursive_count.ToBE())
|
||||||
{
|
{
|
||||||
|
|
|
@ -65,7 +65,7 @@ struct SleepQueue
|
||||||
|
|
||||||
struct sys_lwmutex_t
|
struct sys_lwmutex_t
|
||||||
{
|
{
|
||||||
/* volatile */ SMutexBase<be_t<u32>, ~0, 0> mutex;
|
/* volatile */ SMutexBase<be_t<u32>> mutex;
|
||||||
/* volatile */ be_t<u32> waiter; // not used
|
/* volatile */ be_t<u32> waiter; // not used
|
||||||
u64 &all_info(){return *(reinterpret_cast<u64*>(this));}
|
u64 &all_info(){return *(reinterpret_cast<u64*>(this));}
|
||||||
be_t<u32> attribute;
|
be_t<u32> attribute;
|
||||||
|
|
|
@ -95,7 +95,8 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout)
|
||||||
return CELL_ESRCH;
|
return CELL_ESRCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 tid = GetCurrentPPUThread().GetId();
|
PPUThread& t = GetCurrentPPUThread();
|
||||||
|
u32 tid = t.GetId();
|
||||||
u32 owner = mutex->m_mutex.GetOwner();
|
u32 owner = mutex->m_mutex.GetOwner();
|
||||||
|
|
||||||
if (owner == tid)
|
if (owner == tid)
|
||||||
|
@ -113,17 +114,32 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout)
|
||||||
return CELL_EDEADLK;
|
return CELL_EDEADLK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (owner && !Emu.GetIdManager().CheckID(owner))
|
else if (owner)
|
||||||
{
|
{
|
||||||
sys_mtx.Error("sys_mutex_lock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
|
if (CPUThread* tt = Emu.GetCPU().GetThread(owner))
|
||||||
mutex->m_mutex.unlock(owner, tid);
|
{
|
||||||
mutex->recursive = 1;
|
if (!tt->IsAlive())
|
||||||
return CELL_OK;
|
{
|
||||||
|
sys_mtx.Error("sys_mutex_lock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
|
||||||
|
mutex->m_mutex.unlock(owner, tid);
|
||||||
|
mutex->recursive = 1;
|
||||||
|
t.owned_mutexes++;
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sys_mtx.Error("sys_mutex_lock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
|
||||||
|
mutex->m_mutex.unlock(owner, tid);
|
||||||
|
mutex->recursive = 1;
|
||||||
|
t.owned_mutexes++;
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (mutex->m_mutex.trylock(tid))
|
switch (mutex->m_mutex.trylock(tid))
|
||||||
{
|
{
|
||||||
case SMR_OK: mutex->recursive = 1; return CELL_OK;
|
case SMR_OK: mutex->recursive = 1; t.owned_mutexes++; return CELL_OK;
|
||||||
case SMR_FAILED: break;
|
case SMR_FAILED: break;
|
||||||
default: goto abort;
|
default: goto abort;
|
||||||
}
|
}
|
||||||
|
@ -135,7 +151,7 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout)
|
||||||
case SMR_OK:
|
case SMR_OK:
|
||||||
mutex->m_queue.invalidate(tid);
|
mutex->m_queue.invalidate(tid);
|
||||||
case SMR_SIGNAL:
|
case SMR_SIGNAL:
|
||||||
mutex->recursive = 1; return CELL_OK;
|
mutex->recursive = 1; t.owned_mutexes++; return CELL_OK;
|
||||||
case SMR_TIMEOUT:
|
case SMR_TIMEOUT:
|
||||||
mutex->m_queue.invalidate(tid); return CELL_ETIMEDOUT;
|
mutex->m_queue.invalidate(tid); return CELL_ETIMEDOUT;
|
||||||
default:
|
default:
|
||||||
|
@ -161,7 +177,8 @@ int sys_mutex_trylock(u32 mutex_id)
|
||||||
return CELL_ESRCH;
|
return CELL_ESRCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 tid = GetCurrentPPUThread().GetId();
|
PPUThread& t = GetCurrentPPUThread();
|
||||||
|
u32 tid = t.GetId();
|
||||||
u32 owner = mutex->m_mutex.GetOwner();
|
u32 owner = mutex->m_mutex.GetOwner();
|
||||||
|
|
||||||
if (owner == tid)
|
if (owner == tid)
|
||||||
|
@ -179,17 +196,32 @@ int sys_mutex_trylock(u32 mutex_id)
|
||||||
return CELL_EDEADLK;
|
return CELL_EDEADLK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (owner && !Emu.GetIdManager().CheckID(owner))
|
else if (owner)
|
||||||
{
|
{
|
||||||
sys_mtx.Error("sys_mutex_trylock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
|
if (CPUThread* tt = Emu.GetCPU().GetThread(owner))
|
||||||
mutex->m_mutex.unlock(owner, tid);
|
{
|
||||||
mutex->recursive = 1;
|
if (!tt->IsAlive())
|
||||||
return CELL_OK;
|
{
|
||||||
|
sys_mtx.Error("sys_mutex_trylock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
|
||||||
|
mutex->m_mutex.unlock(owner, tid);
|
||||||
|
mutex->recursive = 1;
|
||||||
|
t.owned_mutexes++;
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sys_mtx.Error("sys_mutex_trylock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
|
||||||
|
mutex->m_mutex.unlock(owner, tid);
|
||||||
|
mutex->recursive = 1;
|
||||||
|
t.owned_mutexes++;
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (mutex->m_mutex.trylock(tid))
|
switch (mutex->m_mutex.trylock(tid))
|
||||||
{
|
{
|
||||||
case SMR_OK: mutex->recursive = 1; return CELL_OK;
|
case SMR_OK: mutex->recursive = 1; t.owned_mutexes++; return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CELL_EBUSY;
|
return CELL_EBUSY;
|
||||||
|
@ -205,18 +237,21 @@ int sys_mutex_unlock(u32 mutex_id)
|
||||||
return CELL_ESRCH;
|
return CELL_ESRCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 tid = GetCurrentPPUThread().GetId();
|
PPUThread& t = GetCurrentPPUThread();
|
||||||
|
u32 tid = t.GetId();
|
||||||
|
|
||||||
if (mutex->m_mutex.GetOwner() == tid)
|
if (mutex->m_mutex.GetOwner() == tid)
|
||||||
{
|
{
|
||||||
if (!mutex->recursive || (mutex->recursive > 1 && !mutex->is_recursive))
|
if (!mutex->recursive || (mutex->recursive != 1 && !mutex->is_recursive))
|
||||||
{
|
{
|
||||||
sys_mtx.Warning("sys_mutex_unlock(%d): wrong recursive value (%d)", mutex_id, mutex->recursive);
|
sys_mtx.Error("sys_mutex_unlock(%d): wrong recursive value (%d)", mutex_id, mutex->recursive);
|
||||||
|
mutex->recursive = 1;
|
||||||
}
|
}
|
||||||
mutex->recursive--;
|
mutex->recursive--;
|
||||||
if (!mutex->recursive)
|
if (!mutex->recursive)
|
||||||
{
|
{
|
||||||
mutex->m_mutex.unlock(tid, mutex->protocol == SYS_SYNC_PRIORITY ? mutex->m_queue.pop_prio() : mutex->m_queue.pop());
|
mutex->m_mutex.unlock(tid, mutex->protocol == SYS_SYNC_PRIORITY ? mutex->m_queue.pop_prio() : mutex->m_queue.pop());
|
||||||
|
t.owned_mutexes--;
|
||||||
}
|
}
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,24 +10,21 @@ enum
|
||||||
SYS_PPU_THREAD_DONE_INIT,
|
SYS_PPU_THREAD_DONE_INIT,
|
||||||
};
|
};
|
||||||
|
|
||||||
void sys_ppu_thread_exit(int errorcode)
|
void sys_ppu_thread_exit(u64 errorcode)
|
||||||
{
|
{
|
||||||
if(errorcode == 0)
|
sysPrxForUser.Log("sys_ppu_thread_exit(0x%llx)", errorcode);
|
||||||
{
|
|
||||||
sysPrxForUser.Log("sys_ppu_thread_exit(errorcode=%d)", errorcode);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sysPrxForUser.Warning("sys_ppu_thread_exit(errorcode=%d)", errorcode);
|
|
||||||
}
|
|
||||||
|
|
||||||
PPUThread& thr = GetCurrentPPUThread();
|
PPUThread& thr = GetCurrentPPUThread();
|
||||||
|
u32 tid = thr.GetId();
|
||||||
|
|
||||||
|
if (thr.owned_mutexes)
|
||||||
|
{
|
||||||
|
ConLog.Error("Owned mutexes found (%d)", thr.owned_mutexes);
|
||||||
|
thr.owned_mutexes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
thr.SetExitStatus(errorcode);
|
thr.SetExitStatus(errorcode);
|
||||||
thr.Stop();
|
thr.Stop();
|
||||||
|
|
||||||
//Emu.GetCPU().RemoveThread(thr.GetId());
|
|
||||||
|
|
||||||
//throw errorcode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_ppu_thread_yield()
|
int sys_ppu_thread_yield()
|
||||||
|
@ -37,14 +34,24 @@ int sys_ppu_thread_yield()
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_ppu_thread_join(u32 thread_id, u32 vptr_addr)
|
int sys_ppu_thread_join(u32 thread_id, mem64_t vptr)
|
||||||
{
|
{
|
||||||
sysPrxForUser.Warning("sys_ppu_thread_join(thread_id=%d, vptr_addr=0x%x)", thread_id, vptr_addr);
|
sysPrxForUser.Warning("sys_ppu_thread_join(thread_id=%d, vptr_addr=0x%x)", thread_id, vptr.GetAddr());
|
||||||
|
|
||||||
CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
|
CPUThread* thr = Emu.GetCPU().GetThread(thread_id);
|
||||||
if(!thr) return CELL_ESRCH;
|
if(!thr) return CELL_ESRCH;
|
||||||
|
|
||||||
GetCurrentPPUThread().Wait(*thr);
|
while (thr->IsAlive())
|
||||||
|
{
|
||||||
|
if (Emu.IsStopped())
|
||||||
|
{
|
||||||
|
ConLog.Warning("sys_ppu_thread_join(%d) aborted", thread_id);
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
Sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
vptr = thr->GetExitStatus();
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue