sys_ppu_thread_join, sys_ppu_thread_exit fixed

Some diagnostic messages in mutexes
This commit is contained in:
Nekotekina 2014-03-07 16:03:42 +04:00
parent fac86aae58
commit 3127543b6e
13 changed files with 220 additions and 56 deletions

View file

@ -361,7 +361,7 @@ void CPUThread::Task()
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)
{

View file

@ -57,7 +57,7 @@ protected:
u64 m_stack_size;
u64 m_stack_point;
u32 m_exit_status;
u64 m_exit_status;
CPUDecoder* m_dec;
@ -80,10 +80,10 @@ public:
void SetName(const std::string& name);
void SetPrio(const u64 prio) { m_prio = prio; }
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; }
u32 GetExitStatus() const { return m_exit_status; }
u64 GetExitStatus() const { return m_exit_status; }
u64 GetPrio() const { return m_prio; }
std::string GetName() const { return NamedThreadBase::GetThreadName(); }
@ -234,7 +234,7 @@ public:
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:
virtual void DoReset()=0;

View file

@ -2096,8 +2096,11 @@ private:
case 0x2: SysCall(); break;
case 0x3:
StaticExecute(CPU.GPR[11]);
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);
if (Ini.HLELogging.GetValue())
{
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;
case 0x22: UNK("HyperCall LV1"); break;
default: UNK(wxString::Format("Unknown sc: %x", sc_code));

View file

@ -17,6 +17,7 @@ PPUThread& GetCurrentPPUThread()
PPUThread::PPUThread() : PPCThread(CPU_THREAD_PPU)
{
owned_mutexes = 0;
Reset();
}

View file

@ -525,6 +525,9 @@ static const s32 MAX_INT_VALUE = 0x7fffffff;
class PPUThread : public PPCThread
{
public:
std::atomic<u32> owned_mutexes;
public:
PPCdouble FPR[32]; //Floating Point Register
FPSCRhdr FPSCR; //Floating Point Status and Control Register

View file

@ -80,8 +80,8 @@ u32 dmuxOpen(Demuxer* data)
cb.SetAddr(dmux.cbFunc);
cb.Handle(dmux.id, dmuxMsg.GetAddr(), dmux.cbArg);
cb.Branch(task.type == dmuxResetStreamAndWaitDone);*/
dmux.dmuxCb->ExecAsCallback(dmux.cbFunc, true, dmux.id, dmuxMsg.GetAddr(), dmux.cbArg);
updates_signaled++;
//dmux.dmuxCb->ExecAsCallback(dmux.cbFunc, true, dmux.id, dmuxMsg.GetAddr(), dmux.cbArg);
//updates_signaled++;
}
else switch (code.ToLE())
{
@ -584,6 +584,17 @@ int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize
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
{
if (Emu.IsStopped())

View file

@ -13,20 +13,21 @@ int cellAANAddData(u32 handle, u32 port, u32 offset, u32 addr, u32 samples)
return CELL_OK;
}
// libmixer Functions, NOT active in this moment
/*int cellAANConnect(CellAANHandle receive, u32 receivePortNo, CellAANHandle source, u32 sourcePortNo)
int cellAANConnect(u32 receive, u32 receivePortNo, u32 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;
}
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;
}
int cellSSPlayerCreate(CellAANHandle *handle, CellSSPlayerConfig *config)
/*int cellSSPlayerCreate(CellAANHandle *handle, CellSSPlayerConfig *config)
{
UNIMPLEMENTED_FUNC(libmixer);
return 0;
@ -182,7 +183,6 @@ void libmixer_init()
0xffffffff81690000,
0xffffffff7c050378,
0xffffffff7cc43378,
// 78 63 00 20 clrldi r3,r3,32 # 20 // may be included
0xffffffff7d465378,
0xffffffff812b0030,
0xffffffff80090000,
@ -200,6 +200,80 @@ void libmixer_init()
};
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[] = {
0xffffffff2f830000,
0xffffffff7c0802a6,

View file

@ -9,6 +9,8 @@ void StaticAnalyse(void* ptr, u32 size)
{
u32* data = (u32*)ptr; size /= 4;
return; // disabled
// TODO: optimize search
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+1] = se32(0x44000003); // sc 3
data[i+2] = se32(0x4e800020); // blr
i += g_static_funcs_list[j].ops.GetCount(); // ???
i += 2; // ???
}
}
}

View file

@ -201,9 +201,9 @@ extern int sys_rwlock_trywlock(u32 rw_lock_id);
extern int sys_rwlock_wunlock(u32 rw_lock_id);
//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_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 void sys_ppu_thread_get_join_state(u32 isjoinable_addr);
extern int sys_ppu_thread_set_priority(u32 thread_id, int prio);

View file

@ -207,17 +207,40 @@ int sys_lwmutex_t::trylock(be_t<u32> tid)
{
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)
{
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;
}
Sleep(1);
}
if (tid == mutex.GetOwner())
if (tid == owner_tid)
{
if (attribute.ToBE() & se32(SYS_SYNC_RECURSIVE))
{
@ -247,6 +270,11 @@ int sys_lwmutex_t::unlock(be_t<u32> tid)
}
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;
if (!recursive_count.ToBE())
{

View file

@ -65,7 +65,7 @@ struct SleepQueue
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
u64 &all_info(){return *(reinterpret_cast<u64*>(this));}
be_t<u32> attribute;

View file

@ -95,7 +95,8 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout)
return CELL_ESRCH;
}
u32 tid = GetCurrentPPUThread().GetId();
PPUThread& t = GetCurrentPPUThread();
u32 tid = t.GetId();
u32 owner = mutex->m_mutex.GetOwner();
if (owner == tid)
@ -113,17 +114,32 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout)
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);
mutex->m_mutex.unlock(owner, tid);
mutex->recursive = 1;
return CELL_OK;
if (CPUThread* tt = Emu.GetCPU().GetThread(owner))
{
if (!tt->IsAlive())
{
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))
{
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;
default: goto abort;
}
@ -135,7 +151,7 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout)
case SMR_OK:
mutex->m_queue.invalidate(tid);
case SMR_SIGNAL:
mutex->recursive = 1; return CELL_OK;
mutex->recursive = 1; t.owned_mutexes++; return CELL_OK;
case SMR_TIMEOUT:
mutex->m_queue.invalidate(tid); return CELL_ETIMEDOUT;
default:
@ -161,7 +177,8 @@ int sys_mutex_trylock(u32 mutex_id)
return CELL_ESRCH;
}
u32 tid = GetCurrentPPUThread().GetId();
PPUThread& t = GetCurrentPPUThread();
u32 tid = t.GetId();
u32 owner = mutex->m_mutex.GetOwner();
if (owner == tid)
@ -179,17 +196,32 @@ int sys_mutex_trylock(u32 mutex_id)
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);
mutex->m_mutex.unlock(owner, tid);
mutex->recursive = 1;
return CELL_OK;
if (CPUThread* tt = Emu.GetCPU().GetThread(owner))
{
if (!tt->IsAlive())
{
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))
{
case SMR_OK: mutex->recursive = 1; return CELL_OK;
case SMR_OK: mutex->recursive = 1; t.owned_mutexes++; return CELL_OK;
}
return CELL_EBUSY;
@ -205,18 +237,21 @@ int sys_mutex_unlock(u32 mutex_id)
return CELL_ESRCH;
}
u32 tid = GetCurrentPPUThread().GetId();
PPUThread& t = GetCurrentPPUThread();
u32 tid = t.GetId();
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--;
if (!mutex->recursive)
{
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;
}

View file

@ -10,24 +10,21 @@ enum
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(errorcode=%d)", errorcode);
}
else
{
sysPrxForUser.Warning("sys_ppu_thread_exit(errorcode=%d)", errorcode);
}
sysPrxForUser.Log("sys_ppu_thread_exit(0x%llx)", errorcode);
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.Stop();
//Emu.GetCPU().RemoveThread(thr.GetId());
//throw errorcode;
}
int sys_ppu_thread_yield()
@ -37,14 +34,24 @@ int sys_ppu_thread_yield()
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);
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;
}