Merge pull request #169 from yuriks/gsp-racecond
GSP: Use atomics in interrupt reading loop
This commit is contained in:
commit
43e1137148
@ -82,6 +82,50 @@ void gspWaitForEvent(GSP_Event id, bool nextEvent)
|
|||||||
svcClearEvent(gspEvents[id]);
|
svcClearEvent(gspEvents[id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int popInterrupt()
|
||||||
|
{
|
||||||
|
int curEvt;
|
||||||
|
u32 strexFailed;
|
||||||
|
do {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
u8 cur;
|
||||||
|
u8 count;
|
||||||
|
u8 err;
|
||||||
|
u8 unused;
|
||||||
|
};
|
||||||
|
u32 as_u32;
|
||||||
|
} header;
|
||||||
|
|
||||||
|
u32* gsp_header_ptr = (u32*)(gspEventData + 0);
|
||||||
|
|
||||||
|
// Do a load on all header fields as an atomic unit
|
||||||
|
__asm__ volatile (
|
||||||
|
"ldrex %[result], %[addr]" :
|
||||||
|
[result]"=r"(header.as_u32) :
|
||||||
|
[addr]"Q"(*gsp_header_ptr));
|
||||||
|
|
||||||
|
if (__builtin_expect(header.count == 0, 0)) {
|
||||||
|
__asm__ volatile ("clrex");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
curEvt = gspEventData[0xC + header.cur];
|
||||||
|
|
||||||
|
header.cur += 1;
|
||||||
|
if (header.cur >= 0x34) header.cur -= 0x34;
|
||||||
|
header.count -= 1;
|
||||||
|
header.err = 0; // Should this really be set?
|
||||||
|
|
||||||
|
__asm__ volatile (
|
||||||
|
"strex %[result], %[val], %[addr]" :
|
||||||
|
[result]"=&r"(strexFailed), [addr]"=Q"(*gsp_header_ptr) :
|
||||||
|
[val]"r"(header.as_u32));
|
||||||
|
} while (__builtin_expect(strexFailed, 0));
|
||||||
|
|
||||||
|
return curEvt;
|
||||||
|
}
|
||||||
|
|
||||||
void gspEventThreadMain(void *arg)
|
void gspEventThreadMain(void *arg)
|
||||||
{
|
{
|
||||||
while (gspRunEvents)
|
while (gspRunEvents)
|
||||||
@ -89,24 +133,18 @@ void gspEventThreadMain(void *arg)
|
|||||||
svcWaitSynchronization(gspEvent, U64_MAX);
|
svcWaitSynchronization(gspEvent, U64_MAX);
|
||||||
svcClearEvent(gspEvent);
|
svcClearEvent(gspEvent);
|
||||||
|
|
||||||
int count = gspEventData[1];
|
while (true)
|
||||||
int cur = gspEventData[0];
|
|
||||||
int last = cur + count;
|
|
||||||
while (last >= 0x34) last -= 0x34;
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < count; i ++)
|
|
||||||
{
|
{
|
||||||
int curEvt = gspEventData[0xC + cur];
|
int curEvt = popInterrupt();
|
||||||
cur ++;
|
|
||||||
if (cur >= 0x34) cur -= 0x34;
|
|
||||||
if (curEvt >= GSPEVENT_MAX) continue;
|
|
||||||
svcSignalEvent(gspEvents[curEvt]);
|
|
||||||
gspEventCounts[curEvt]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
gspEventData[0] = last;
|
if (curEvt == -1)
|
||||||
gspEventData[1] -= count;
|
break;
|
||||||
gspEventData[2] = 0;
|
|
||||||
|
if (curEvt < GSPEVENT_MAX) {
|
||||||
|
svcSignalEvent(gspEvents[curEvt]);
|
||||||
|
gspEventCounts[curEvt]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
svcExitThread();
|
svcExitThread();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user