mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-04 22:11:26 +12:00
Merge pull request #370 from Nekotekina/master
Fixed some samples freeze
This commit is contained in:
commit
394b698e92
9 changed files with 137 additions and 64 deletions
|
@ -1,29 +1,45 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "Utilities/SSemaphore.h"
|
#include "Utilities/SSemaphore.h"
|
||||||
|
|
||||||
bool SSemaphore::wait(u64 timeout)
|
void SSemaphore::wait()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(m_cv_mutex);
|
u32 order;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
if (m_count && m_out_order == m_in_order)
|
||||||
|
{
|
||||||
|
m_count--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
order = m_in_order++;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_lock<std::mutex> cv_lock(m_cv_mutex);
|
||||||
|
|
||||||
u64 counter = 0;
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (Emu.IsStopped())
|
if (Emu.IsStopped())
|
||||||
{
|
{
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
if (timeout && counter >= timeout)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
m_cond.wait_for(lock, std::chrono::milliseconds(1));
|
|
||||||
counter++;
|
|
||||||
|
|
||||||
|
m_cond.wait_for(cv_lock, std::chrono::milliseconds(1));
|
||||||
|
|
||||||
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
if (m_count)
|
if (m_count)
|
||||||
|
{
|
||||||
|
if (m_out_order == order)
|
||||||
{
|
{
|
||||||
m_count--;
|
m_count--;
|
||||||
return true;
|
m_out_order++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_cond.notify_one();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +48,7 @@ bool SSemaphore::try_wait()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
if (m_count)
|
if (m_count && m_in_order == m_out_order)
|
||||||
{
|
{
|
||||||
m_count--;
|
m_count--;
|
||||||
return true;
|
return true;
|
||||||
|
@ -47,18 +63,21 @@ void SSemaphore::post()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
if (m_count >= m_max)
|
if (m_count < m_max)
|
||||||
|
{
|
||||||
|
m_count++;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_count++;
|
|
||||||
m_cond.notify_one();
|
m_cond.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SSemaphore::post_and_wait()
|
bool SSemaphore::post_and_wait()
|
||||||
{
|
{
|
||||||
// TODO: ???
|
// TODO: merge these functions? Probably has a race condition.
|
||||||
if (try_wait()) return false;
|
if (try_wait()) return false;
|
||||||
|
|
||||||
post();
|
post();
|
||||||
|
|
|
@ -4,19 +4,26 @@ class SSemaphore
|
||||||
{
|
{
|
||||||
const u32 m_max;
|
const u32 m_max;
|
||||||
u32 m_count;
|
u32 m_count;
|
||||||
std::mutex m_mutex, m_cv_mutex;
|
u32 m_in_order;
|
||||||
|
u32 m_out_order;
|
||||||
|
std::mutex m_cv_mutex;
|
||||||
|
std::mutex m_mutex;
|
||||||
std::condition_variable m_cond;
|
std::condition_variable m_cond;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SSemaphore(u32 value, u32 max = 1)
|
SSemaphore(u32 value, u32 max = 1)
|
||||||
: m_max(max > 0 ? max : 0xffffffff)
|
: m_max(max > 0 ? max : 0xffffffff)
|
||||||
, m_count(value > m_max ? m_max : value)
|
, m_count(value > m_max ? m_max : value)
|
||||||
|
, m_in_order(0)
|
||||||
|
, m_out_order(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SSemaphore()
|
SSemaphore()
|
||||||
: m_max(0xffffffff)
|
: m_max(0xffffffff)
|
||||||
, m_count(0)
|
, m_count(0)
|
||||||
|
, m_in_order(0)
|
||||||
|
, m_out_order(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +31,7 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wait(u64 timeout = 0);
|
void wait();
|
||||||
|
|
||||||
bool try_wait();
|
bool try_wait();
|
||||||
|
|
||||||
|
|
|
@ -2,36 +2,6 @@
|
||||||
#include "SPUThread.h"
|
#include "SPUThread.h"
|
||||||
#include "Emu/event.h"
|
#include "Emu/event.h"
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
MFC_LSA_offs = 0x3004,
|
|
||||||
MFC_EAH_offs = 0x3008,
|
|
||||||
MFC_EAL_offs = 0x300C,
|
|
||||||
MFC_Size_Tag_offs = 0x3010,
|
|
||||||
MFC_Class_CMD_offs = 0x3014,
|
|
||||||
MFC_CMDStatus_offs = 0x3014,
|
|
||||||
MFC_QStatus_offs = 0x3104,
|
|
||||||
Prxy_QueryType_offs = 0x3204,
|
|
||||||
Prxy_QueryMask_offs = 0x321C,
|
|
||||||
Prxy_TagStatus_offs = 0x322C,
|
|
||||||
SPU_Out_MBox_offs = 0x4004,
|
|
||||||
SPU_In_MBox_offs = 0x400C,
|
|
||||||
SPU_MBox_Status_offs = 0x4014,
|
|
||||||
SPU_RunCntl_offs = 0x401C,
|
|
||||||
SPU_Status_offs = 0x4024,
|
|
||||||
SPU_NPC_offs = 0x4034,
|
|
||||||
SPU_RdSigNotify1_offs = 0x1400C,
|
|
||||||
SPU_RdSigNotify2_offs = 0x1C00C,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum : u64
|
|
||||||
{
|
|
||||||
RAW_SPU_OFFSET = 0x0000000000100000,
|
|
||||||
RAW_SPU_BASE_ADDR = 0x00000000E0000000,
|
|
||||||
RAW_SPU_LS_OFFSET = 0x0000000000000000,
|
|
||||||
RAW_SPU_PROB_OFFSET = 0x0000000000040000,
|
|
||||||
};
|
|
||||||
|
|
||||||
__forceinline static u32 GetRawSPURegAddrByNum(int num, int offset)
|
__forceinline static u32 GetRawSPURegAddrByNum(int num, int offset)
|
||||||
{
|
{
|
||||||
return RAW_SPU_OFFSET * num + RAW_SPU_BASE_ADDR + RAW_SPU_PROB_OFFSET + offset;
|
return RAW_SPU_OFFSET * num + RAW_SPU_BASE_ADDR + RAW_SPU_PROB_OFFSET + offset;
|
||||||
|
|
|
@ -129,6 +129,36 @@ enum : u32
|
||||||
SYS_SPU_THREAD_SNR2 = 0x05C00c,
|
SYS_SPU_THREAD_SNR2 = 0x05C00c,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
MFC_LSA_offs = 0x3004,
|
||||||
|
MFC_EAH_offs = 0x3008,
|
||||||
|
MFC_EAL_offs = 0x300C,
|
||||||
|
MFC_Size_Tag_offs = 0x3010,
|
||||||
|
MFC_Class_CMD_offs = 0x3014,
|
||||||
|
MFC_CMDStatus_offs = 0x3014,
|
||||||
|
MFC_QStatus_offs = 0x3104,
|
||||||
|
Prxy_QueryType_offs = 0x3204,
|
||||||
|
Prxy_QueryMask_offs = 0x321C,
|
||||||
|
Prxy_TagStatus_offs = 0x322C,
|
||||||
|
SPU_Out_MBox_offs = 0x4004,
|
||||||
|
SPU_In_MBox_offs = 0x400C,
|
||||||
|
SPU_MBox_Status_offs = 0x4014,
|
||||||
|
SPU_RunCntl_offs = 0x401C,
|
||||||
|
SPU_Status_offs = 0x4024,
|
||||||
|
SPU_NPC_offs = 0x4034,
|
||||||
|
SPU_RdSigNotify1_offs = 0x1400C,
|
||||||
|
SPU_RdSigNotify2_offs = 0x1C00C,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum : u64
|
||||||
|
{
|
||||||
|
RAW_SPU_OFFSET = 0x0000000000100000,
|
||||||
|
RAW_SPU_BASE_ADDR = 0x00000000E0000000,
|
||||||
|
RAW_SPU_LS_OFFSET = 0x0000000000000000,
|
||||||
|
RAW_SPU_PROB_OFFSET = 0x0000000000040000,
|
||||||
|
};
|
||||||
|
|
||||||
//Floating point status and control register. Unsure if this is one of the GPRs or SPRs
|
//Floating point status and control register. Unsure if this is one of the GPRs or SPRs
|
||||||
//Is 128 bits, but bits 0-19, 24-28, 32-49, 56-60, 64-81, 88-92, 96-115, 120-124 are unused
|
//Is 128 bits, but bits 0-19, 24-28, 32-49, 56-60, 64-81, 88-92, 96-115, 120-124 are unused
|
||||||
class FPSCR
|
class FPSCR
|
||||||
|
@ -598,19 +628,20 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (ea >= RAW_SPU_BASE_ADDR && size == 4)
|
||||||
//Sleep(1); // hack
|
{
|
||||||
|
switch (cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK | MFC_RESULT_MASK))
|
||||||
switch(cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK | MFC_RESULT_MASK))
|
|
||||||
{
|
{
|
||||||
case MFC_PUT_CMD:
|
case MFC_PUT_CMD:
|
||||||
{
|
{
|
||||||
return Memory.Copy(ea, dmac.ls_offset + lsa, size);
|
Memory.Write32(ea, ReadLS32(lsa));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
case MFC_GET_CMD:
|
case MFC_GET_CMD:
|
||||||
{
|
{
|
||||||
return Memory.Copy(dmac.ls_offset + lsa, ea, size);
|
WriteLS32(lsa, Memory.Read32(ea));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -621,6 +652,44 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Sleep(1); // hack
|
||||||
|
|
||||||
|
switch (cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK | MFC_RESULT_MASK))
|
||||||
|
{
|
||||||
|
case MFC_PUT_CMD:
|
||||||
|
{
|
||||||
|
if (Memory.Copy(ea, dmac.ls_offset + lsa, size))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ConLog.Error("DMAC::ProcessCmd(): PUT* cmd failed (ea=0x%llx, lsa=0x%x, size=%d)", ea, lsa, size);
|
||||||
|
return false; // TODO: page fault (?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case MFC_GET_CMD:
|
||||||
|
{
|
||||||
|
if (Memory.Copy(dmac.ls_offset + lsa, ea, size))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ConLog.Error("DMAC::ProcessCmd(): GET* cmd failed (ea=0x%llx, lsa=0x%x, size=%d)", ea, lsa, size);
|
||||||
|
return false; // TODO: page fault (?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
ConLog.Error("DMAC::ProcessCmd(): Unknown DMA cmd.");
|
||||||
|
return false; // ???
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
u32 dmacCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
|
u32 dmacCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
|
||||||
{
|
{
|
||||||
/*if(proxy_pos >= MFC_PPU_MAX_QUEUE_SPACE)
|
/*if(proxy_pos >= MFC_PPU_MAX_QUEUE_SPACE)
|
||||||
|
|
|
@ -1882,8 +1882,13 @@ void RSXThread::Task()
|
||||||
inc=1;
|
inc=1;
|
||||||
|
|
||||||
u32 put, get;
|
u32 put, get;
|
||||||
|
// this code produces only mov + bswap:
|
||||||
se_t<u32>::func(put, std::atomic_load((volatile std::atomic<u32>*)((u8*)m_ctrl + offsetof(CellGcmControl, put))));
|
se_t<u32>::func(put, std::atomic_load((volatile std::atomic<u32>*)((u8*)m_ctrl + offsetof(CellGcmControl, put))));
|
||||||
se_t<u32>::func(get, std::atomic_load((volatile std::atomic<u32>*)((u8*)m_ctrl + offsetof(CellGcmControl, get))));
|
se_t<u32>::func(get, std::atomic_load((volatile std::atomic<u32>*)((u8*)m_ctrl + offsetof(CellGcmControl, get))));
|
||||||
|
/*
|
||||||
|
se_t<u32>::func(put, InterlockedCompareExchange((volatile unsigned long*)((u8*)m_ctrl + offsetof(CellGcmControl, put)), 0, 0));
|
||||||
|
se_t<u32>::func(get, InterlockedCompareExchange((volatile unsigned long*)((u8*)m_ctrl + offsetof(CellGcmControl, get)), 0, 0));
|
||||||
|
*/
|
||||||
|
|
||||||
if(put == get || !Emu.IsRunning())
|
if(put == get || !Emu.IsRunning())
|
||||||
{
|
{
|
||||||
|
|
|
@ -471,7 +471,7 @@ int cellGcmSetPrepareFlip(mem_ptr_t<CellGcmContextData> ctxt, u32 id)
|
||||||
return CELL_GCM_ERROR_FAILURE;
|
return CELL_GCM_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH); // could freeze on exit
|
GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH);
|
||||||
|
|
||||||
u32 current = ctxt->current;
|
u32 current = ctxt->current;
|
||||||
u32 end = ctxt->end;
|
u32 end = ctxt->end;
|
||||||
|
@ -488,6 +488,8 @@ int cellGcmSetPrepareFlip(mem_ptr_t<CellGcmContextData> ctxt, u32 id)
|
||||||
|
|
||||||
if(res > 0) Memory.Copy(ctxt->begin, ctxt->current - res, res);
|
if(res > 0) Memory.Copy(ctxt->begin, ctxt->current - res, res);
|
||||||
ctxt->current = ctxt->begin + res;
|
ctxt->current = ctxt->begin + res;
|
||||||
|
|
||||||
|
//InterlockedExchange64((volatile long long*)((u8*)&ctrl + offsetof(CellGcmControl, put)), (u64)(u32)re(res));
|
||||||
ctrl.put = res;
|
ctrl.put = res;
|
||||||
ctrl.get = 0;
|
ctrl.get = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -802,7 +802,7 @@ int cellRescSetConvertAndFlip(mem_ptr_t<CellGcmContextData> cntxt, s32 idx)
|
||||||
int cellRescSetWaitFlip()
|
int cellRescSetWaitFlip()
|
||||||
{
|
{
|
||||||
cellResc->Log("cellRescSetWaitFlip()");
|
cellResc->Log("cellRescSetWaitFlip()");
|
||||||
GSLockCurrent lock(GS_LOCK_WAIT_FLIP); // could stall on exit
|
GSLockCurrent lock(GS_LOCK_WAIT_FLIP);
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ extern gcmInfo gcm_info;
|
||||||
|
|
||||||
int cellGcmCallback(u32 context_addr, u32 count)
|
int cellGcmCallback(u32 context_addr, u32 count)
|
||||||
{
|
{
|
||||||
GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH); // could freeze on exit
|
GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH);
|
||||||
|
|
||||||
CellGcmContextData& ctx = (CellGcmContextData&)Memory[context_addr];
|
CellGcmContextData& ctx = (CellGcmContextData&)Memory[context_addr];
|
||||||
CellGcmControl& ctrl = (CellGcmControl&)Memory[gcm_info.control_addr];
|
CellGcmControl& ctrl = (CellGcmControl&)Memory[gcm_info.control_addr];
|
||||||
|
@ -24,6 +24,7 @@ int cellGcmCallback(u32 context_addr, u32 count)
|
||||||
|
|
||||||
ctx.current = ctx.begin + res;
|
ctx.current = ctx.begin + res;
|
||||||
|
|
||||||
|
//InterlockedExchange64((volatile long long*)((u8*)&ctrl + offsetof(CellGcmControl, put)), (u64)(u32)re(res));
|
||||||
ctrl.put = res;
|
ctrl.put = res;
|
||||||
ctrl.get = 0;
|
ctrl.get = 0;
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ static SysCallBase sc_int("sys_interrupt");
|
||||||
|
|
||||||
int sys_interrupt_tag_destroy(u32 intrtag)
|
int sys_interrupt_tag_destroy(u32 intrtag)
|
||||||
{
|
{
|
||||||
sc_int.Error("sys_interrupt_tag_destroy(intrtag=%d)", intrtag);
|
sc_int.Warning("sys_interrupt_tag_destroy(intrtag=%d)", intrtag);
|
||||||
|
|
||||||
u32 id = intrtag & 0xff;
|
u32 id = intrtag & 0xff;
|
||||||
u32 class_id = intrtag >> 8;
|
u32 class_id = intrtag >> 8;
|
||||||
|
@ -40,7 +40,7 @@ int sys_interrupt_tag_destroy(u32 intrtag)
|
||||||
|
|
||||||
int sys_interrupt_thread_establish(mem32_t ih, u32 intrtag, u64 intrthread, u64 arg)
|
int sys_interrupt_thread_establish(mem32_t ih, u32 intrtag, u64 intrthread, u64 arg)
|
||||||
{
|
{
|
||||||
sc_int.Error("sys_interrupt_thread_establish(ih_addr=0x%x, intrtag=%d, intrthread=%lld, arg=0x%llx)", ih.GetAddr(), intrtag, intrthread, arg);
|
sc_int.Warning("sys_interrupt_thread_establish(ih_addr=0x%x, intrtag=%d, intrthread=%lld, arg=0x%llx)", ih.GetAddr(), intrtag, intrthread, arg);
|
||||||
|
|
||||||
if (!ih.IsGood())
|
if (!ih.IsGood())
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue