Use atomic functions in more places

This commit is contained in:
lehoangquyen 2018-12-17 14:14:21 +08:00 committed by Vicki Pfau
parent bb7f41e8cc
commit 7a5840fb5a
3 changed files with 33 additions and 10 deletions

View File

@ -81,6 +81,7 @@ typedef intptr_t ssize_t;
#define ATOMIC_STORE(DST, SRC) __atomic_store_n(&DST, SRC, __ATOMIC_RELEASE)
#define ATOMIC_LOAD(DST, SRC) DST = __atomic_load_n(&SRC, __ATOMIC_ACQUIRE)
#define ATOMIC_ADD(DST, OP) __atomic_add_fetch(&DST, OP, __ATOMIC_RELEASE)
#define ATOMIC_SUB(DST, OP) __atomic_sub_fetch(&DST, OP, __ATOMIC_RELEASE)
#define ATOMIC_OR(DST, OP) __atomic_or_fetch(&DST, OP, __ATOMIC_RELEASE)
#define ATOMIC_AND(DST, OP) __atomic_and_fetch(&DST, OP, __ATOMIC_RELEASE)
#define ATOMIC_CMPXCHG(DST, EXPECTED, SRC) __atomic_compare_exchange_n(&DST, &EXPECTED, SRC, true,__ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)
@ -89,6 +90,7 @@ typedef intptr_t ssize_t;
#define ATOMIC_STORE(DST, SRC) DST = SRC
#define ATOMIC_LOAD(DST, SRC) DST = SRC
#define ATOMIC_ADD(DST, OP) DST += OP
#define ATOMIC_SUB(DST, OP) DST -= OP
#define ATOMIC_OR(DST, OP) DST |= OP
#define ATOMIC_AND(DST, OP) DST &= OP
#define ATOMIC_CMPXCHG(DST, EXPECTED, OP) ((DST == EXPECTED) ? ((DST = OP), true) : false)

View File

@ -236,6 +236,8 @@ static uint8_t GBSIOLockstepNodeWriteSC(struct GBSIODriver* driver, uint8_t valu
mTimingDeschedule(&driver->p->p->timing, &driver->p->event);
mTimingDeschedule(&driver->p->p->timing, &node->event);
mTimingSchedule(&driver->p->p->timing, &node->event, 0);
} else {
mLOG(GB_SIO, FATAL, "GBSIOLockstepNodeWriteSC() failed to write to masterClaimed\n");
}
}
return value;

View File

@ -93,7 +93,7 @@ bool GBASIOLockstepNodeLoad(struct GBASIODriver* driver) {
case SIO_MULTI:
node->d.writeRegister = GBASIOLockstepNodeMultiWriteRegister;
node->d.p->rcnt |= 3;
++node->p->attachedMulti;
ATOMIC_ADD(node->p->attachedMulti, 1);
node->d.p->multiplayerControl.ready = node->p->attachedMulti == node->p->d.attached;
if (node->id) {
node->d.p->rcnt |= 4;
@ -118,7 +118,7 @@ bool GBASIOLockstepNodeUnload(struct GBASIODriver* driver) {
node->mode = driver->p->mode;
switch (node->mode) {
case SIO_MULTI:
--node->p->attachedMulti;
ATOMIC_SUB(node->p->attachedMulti, 1);
break;
default:
break;
@ -132,11 +132,15 @@ static uint16_t GBASIOLockstepNodeMultiWriteRegister(struct GBASIODriver* driver
struct GBASIOLockstepNode* node = (struct GBASIOLockstepNode*) driver;
if (address == REG_SIOCNT) {
mLOG(GBA_SIO, DEBUG, "Lockstep %i: SIOCNT <- %04x", node->id, value);
if (value & 0x0080 && node->p->d.transferActive == TRANSFER_IDLE) {
enum mLockstepPhase transferActive;
ATOMIC_LOAD(transferActive, node->p->d.transferActive);
if (value & 0x0080 && transferActive == TRANSFER_IDLE) {
if (!node->id && node->d.p->multiplayerControl.ready) {
mLOG(GBA_SIO, DEBUG, "Lockstep %i: Transfer initiated", node->id);
node->p->d.transferActive = TRANSFER_STARTING;
node->p->d.transferCycles = GBASIOCyclesPerTransfer[node->d.p->multiplayerControl.baud][node->p->d.attached - 1];
ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING);
ATOMIC_STORE(node->p->d.transferCycles, GBASIOCyclesPerTransfer[node->d.p->multiplayerControl.baud][node->p->d.attached - 1]);
mTimingDeschedule(&driver->p->p->timing, &node->event);
mTimingSchedule(&driver->p->p->timing, &node->event, 0);
} else {
@ -209,11 +213,19 @@ static void _finishTransfer(struct GBASIOLockstepNode* node) {
static int32_t _masterUpdate(struct GBASIOLockstepNode* node) {
bool needsToWait = false;
int i;
switch (node->p->d.transferActive) {
enum mLockstepPhase transferActive;
int attachedMulti, attached;
ATOMIC_LOAD(transferActive, node->p->d.transferActive);
ATOMIC_LOAD(attachedMulti, node->p->attachedMulti);
ATOMIC_LOAD(attached, node->p->d.attached);
switch (transferActive) {
case TRANSFER_IDLE:
// If the master hasn't initiated a transfer, it can keep going.
node->nextEvent += LOCKSTEP_INCREMENT;
node->d.p->multiplayerControl.ready = node->p->attachedMulti == node->p->d.attached;
node->d.p->multiplayerControl.ready = attachedMulti == attached;
break;
case TRANSFER_STARTING:
// Start the transfer, but wait for the other GBAs to catch up
@ -276,9 +288,16 @@ static int32_t _masterUpdate(struct GBASIOLockstepNode* node) {
}
static uint32_t _slaveUpdate(struct GBASIOLockstepNode* node) {
node->d.p->multiplayerControl.ready = node->p->attachedMulti == node->p->d.attached;
enum mLockstepPhase transferActive;
int attachedMulti, attached;
ATOMIC_LOAD(transferActive, node->p->d.transferActive);
ATOMIC_LOAD(attachedMulti, node->p->attachedMulti);
ATOMIC_LOAD(attached, node->p->d.attached);
node->d.p->multiplayerControl.ready = attachedMulti == attached;
bool signal = false;
switch (node->p->d.transferActive) {
switch (transferActive) {
case TRANSFER_IDLE:
if (!node->d.p->multiplayerControl.ready) {
node->p->d.addCycles(&node->p->d, node->id, LOCKSTEP_INCREMENT);
@ -368,7 +387,7 @@ static uint16_t GBASIOLockstepNodeNormalWriteRegister(struct GBASIODriver* drive
if (value & 0x0080 && !node->id) {
// Internal shift clock
if (value & 1) {
node->p->d.transferActive = TRANSFER_STARTING;
ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTING);
}
// Frequency
if (value & 2) {