mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 03:25:16 +00:00
Reservation global struct removed
It wasn't solving anything, unfortunately.
This commit is contained in:
parent
184007e1e0
commit
a169c5bcac
3 changed files with 61 additions and 75 deletions
|
@ -9,8 +9,6 @@
|
|||
|
||||
#include "CPUThread.h"
|
||||
|
||||
reservation_struct reservation;
|
||||
|
||||
CPUThread* GetCurrentCPUThread()
|
||||
{
|
||||
return (CPUThread*)GetCurrentNamedThread();
|
||||
|
|
|
@ -3,26 +3,6 @@
|
|||
#include "Emu/CPU/CPUDecoder.h"
|
||||
#include "Utilities/SMutex.h"
|
||||
|
||||
typedef SMutexBase<u32, 0, 0xffffffff, /* busy wait: specify nullptr */ SM_Sleep> SMutexR;
|
||||
typedef SMutexLockerBase<SMutexR, u32, SM_GetCurrentCPUThreadId> SMutexLockerR;
|
||||
|
||||
struct reservation_struct
|
||||
{
|
||||
SMutexR mutex; // mutex for updating reservation_owner and data
|
||||
// std::mutex doesn't work because it probably wakes up waiting threads in the most unwanted order
|
||||
// and doesn't give a chance to finish some work before losing the reservation
|
||||
u32 owner; // id of thread that got reservation
|
||||
u64 addr;
|
||||
u64 data[16];
|
||||
|
||||
__forceinline void clear()
|
||||
{
|
||||
owner = 0;
|
||||
}
|
||||
};
|
||||
|
||||
extern reservation_struct reservation;
|
||||
|
||||
enum CPUThreadType :unsigned char
|
||||
{
|
||||
CPU_THREAD_PPU,
|
||||
|
|
|
@ -309,9 +309,12 @@ union SPU_SNRConfig_hdr
|
|||
class SPUThread : public PPCThread
|
||||
{
|
||||
public:
|
||||
SPU_GPR_hdr GPR[128]; //General-Purpose Registers
|
||||
SPU_GPR_hdr GPR[128]; // General-Purpose Registers
|
||||
//FPSCR FPSCR;
|
||||
SPU_SNRConfig_hdr cfg; //Signal Notification Registers Configuration (OR-mode enabled: 0x1 for SNR1, 0x2 for SNR2)
|
||||
SPU_SNRConfig_hdr cfg; // Signal Notification Registers Configuration (OR-mode enabled: 0x1 for SNR1, 0x2 for SNR2)
|
||||
|
||||
u64 R_ADDR; // reservation address
|
||||
u64 R_DATA[16]; // lock line data (BE)
|
||||
|
||||
EventPort SPUPs[64]; // SPU Thread Event Ports
|
||||
EventManager SPUQs; // SPU Queue Mapping
|
||||
|
@ -796,83 +799,90 @@ public:
|
|||
|
||||
if (op == MFC_GETLLAR_CMD) // get reservation
|
||||
{
|
||||
SMutexLockerR lock(reservation.mutex);
|
||||
reservation.owner = lock.tid;
|
||||
reservation.addr = ea;
|
||||
if (R_ADDR)
|
||||
{
|
||||
m_events |= SPU_EVENT_LR;
|
||||
}
|
||||
|
||||
R_ADDR = ea;
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
{
|
||||
reservation.data[i] = *(u64*)&Memory[(u32)ea + i * 8];
|
||||
*(u64*)&Memory[dmac.ls_offset + lsa + i * 8] = reservation.data[i];
|
||||
R_DATA[i] = *(u64*)&Memory[R_ADDR + i * 8];
|
||||
*(u64*)&Memory[dmac.ls_offset + lsa + i * 8] = R_DATA[i];
|
||||
}
|
||||
MFCArgs.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS);
|
||||
}
|
||||
else if (op == MFC_PUTLLC_CMD) // store conditional
|
||||
{
|
||||
SMutexLockerR lock(reservation.mutex);
|
||||
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS);
|
||||
|
||||
if (reservation.owner == lock.tid) // succeeded
|
||||
if (R_ADDR == ea)
|
||||
{
|
||||
if (reservation.addr == ea)
|
||||
u32 changed = 0, mask = 0;
|
||||
u64 buf[16];
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
{
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
buf[i] = *(u64*)&Memory[dmac.ls_offset + lsa + i * 8];
|
||||
if (buf[i] != R_DATA[i])
|
||||
{
|
||||
if (*(u64*)&Memory[reservation.addr + i * 8] != reservation.data[i])
|
||||
changed++;
|
||||
mask |= (0x3 << (i * 2));
|
||||
if (*(u64*)&Memory[R_ADDR + i * 8] != R_DATA[i])
|
||||
{
|
||||
m_events |= SPU_EVENT_LR;
|
||||
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE);
|
||||
reservation.clear();
|
||||
R_ADDR = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 changed = 0, mask = 0;
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
{
|
||||
if (buf[i] != R_DATA[i])
|
||||
{
|
||||
u64 buf = *(u64*)&Memory[dmac.ls_offset + lsa + i * 8];
|
||||
if (buf != reservation.data[i])
|
||||
if (InterlockedCompareExchange64((volatile long long*)(Memory + (ea + i * 8)), buf[i], R_DATA[i]) != R_DATA[i])
|
||||
{
|
||||
changed++;
|
||||
mask |= (0x3 << (i * 2));
|
||||
m_events |= SPU_EVENT_LR;
|
||||
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE);
|
||||
|
||||
if (InterlockedCompareExchange64((volatile long long*)(Memory + ((u32)ea + i * 8)), buf, reservation.data[i]) != reservation.data[i])
|
||||
if (changed > 1)
|
||||
{
|
||||
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE);
|
||||
|
||||
if (changed > 1)
|
||||
{
|
||||
LOG_ERROR(Log::SPU, "MFC_PUTLLC_CMD: Reservation Error: impossibru (~ 8x%d (mask=0x%x)) (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)",
|
||||
changed, mask, op, cmd, lsa, ea, tag, size);
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
break;
|
||||
LOG_ERROR(Log::SPU, "MFC_PUTLLC_CMD: Memory corrupted (~x%d (mask=0x%x)) (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)",
|
||||
changed, mask, op, cmd, lsa, ea, tag, size);
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (changed > 1)
|
||||
{
|
||||
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE);
|
||||
LOG_WARNING(Log::SPU, "MFC_PUTLLC_CMD: Reservation impossibru (~x%d (mask=0x%x)) (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)",
|
||||
changed, mask, op, cmd, lsa, ea, tag, size);
|
||||
}
|
||||
reservation.clear();
|
||||
}
|
||||
else // failed
|
||||
else
|
||||
{
|
||||
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE);
|
||||
}
|
||||
R_ADDR = 0;
|
||||
}
|
||||
else // store unconditional
|
||||
{
|
||||
SMutexLockerR lock(reservation.mutex);
|
||||
if (R_ADDR)
|
||||
{
|
||||
m_events |= SPU_EVENT_LR;
|
||||
}
|
||||
|
||||
ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128);
|
||||
if (op == MFC_PUTLLUC_CMD)
|
||||
{
|
||||
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLUC_SUCCESS);
|
||||
}
|
||||
if (reservation.addr == ea)
|
||||
{
|
||||
reservation.clear();
|
||||
}
|
||||
R_ADDR = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -888,24 +898,15 @@ public:
|
|||
{
|
||||
// SPU_EVENT_LR:
|
||||
{
|
||||
SMutexLockerR lock(reservation.mutex);
|
||||
|
||||
if (reservation.owner == lock.tid)
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
{
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
if (*(u64*)&Memory[R_ADDR + i * 8] != R_DATA[i])
|
||||
{
|
||||
if (*(u64*)&Memory[reservation.addr + i * 8] != reservation.data[i])
|
||||
{
|
||||
m_events |= SPU_EVENT_LR;
|
||||
reservation.clear(); // ???
|
||||
break;
|
||||
}
|
||||
m_events |= SPU_EVENT_LR;
|
||||
R_ADDR = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_events |= SPU_EVENT_LR; // ???
|
||||
}
|
||||
}
|
||||
|
||||
return (m_events & m_event_mask) != 0;
|
||||
|
@ -1338,6 +1339,13 @@ public:
|
|||
break;
|
||||
}
|
||||
|
||||
case SPU_RdMachStat:
|
||||
{
|
||||
v = 1; // hack (not isolated, interrupts enabled)
|
||||
// TODO: check value
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
LOG_ERROR(Log::SPU, "%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]);
|
||||
|
|
Loading…
Add table
Reference in a new issue