Fix issues with relaxed memory model architectures

Former-commit-id: e37bc4ad40e852b67ee14e5aa87fd2f398f00eed
This commit is contained in:
John Sully 2019-06-17 21:53:04 -04:00
parent db5af7990d
commit d65ce6fbbc
6 changed files with 29 additions and 23 deletions

View File

@ -803,9 +803,9 @@ void aeAcquireLock()
g_lock.lock();
}
int aeTryAcquireLock()
int aeTryAcquireLock(bool fWeak)
{
return g_lock.try_lock();
return g_lock.try_lock(fWeak);
}
void aeReleaseLock()

View File

@ -159,7 +159,7 @@ int aeGetSetSize(aeEventLoop *eventLoop);
int aeResizeSetSize(aeEventLoop *eventLoop, int setsize);
void aeAcquireLock();
int aeTryAcquireLock();
int aeTryAcquireLock(bool fWeak);
void aeReleaseLock();
int aeThreadOwnsLock();

View File

@ -16,13 +16,18 @@ public:
serverAssert(!m_fArmed);
serverAssert(c->lock.fOwnLock());
bool fClientLocked = true;
while (!aeTryAcquireLock())
if (!aeTryAcquireLock(true /*fWeak*/)) // avoid locking the client if we can
{
if (fClientLocked) c->lock.unlock();
fClientLocked = false;
bool fOwnClientLock = true;
for (;;)
{
if (fOwnClientLock)
{
c->lock.unlock();
fOwnClientLock = false;
}
aeAcquireLock();
if (!c->lock.try_lock())
if (!c->lock.try_lock(false)) // ensure a strong try because aeAcquireLock is expensive
{
aeReleaseLock();
}
@ -31,6 +36,7 @@ public:
break;
}
}
}
m_fArmed = true;
}

View File

@ -133,7 +133,7 @@ extern "C" void fastlock_lock(struct fastlock *lock)
std::atomic_thread_fence(std::memory_order_acquire);
}
extern "C" int fastlock_trylock(struct fastlock *lock)
extern "C" int fastlock_trylock(struct fastlock *lock, int fWeak)
{
if ((int)__atomic_load_4(&lock->m_pidOwner, __ATOMIC_ACQUIRE) == gettid())
{
@ -150,7 +150,7 @@ extern "C" int fastlock_trylock(struct fastlock *lock)
struct ticket ticket_expect { active, active };
struct ticket ticket_setiflocked { active, next };
if (__atomic_compare_exchange(&lock->m_ticket, &ticket_expect, &ticket_setiflocked, false /*weak*/, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE))
if (__atomic_compare_exchange(&lock->m_ticket, &ticket_expect, &ticket_setiflocked, fWeak /*weak*/, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
{
lock->m_depth = 1;
__atomic_store_4(&lock->m_pidOwner, gettid(), __ATOMIC_RELEASE);
@ -181,8 +181,8 @@ extern "C" void fastlock_unlock(struct fastlock *lock)
{
assert((int)__atomic_load_4(&lock->m_pidOwner, __ATOMIC_RELAXED) >= 0); // unlock after free
lock->m_pidOwner = -1;
std::atomic_thread_fence(std::memory_order_acquire);
uint16_t activeNew = __atomic_add_fetch(&lock->m_ticket.m_active, 1, __ATOMIC_ACQ_REL); // on x86 the atomic is not required here, but ASM handles that case
std::atomic_thread_fence(std::memory_order_release);
uint16_t activeNew = __atomic_add_fetch(&lock->m_ticket.m_active, 1, __ATOMIC_RELEASE); // on x86 the atomic is not required here, but ASM handles that case
unlock_futex(lock, activeNew);
}
}

View File

@ -9,7 +9,7 @@ extern "C" {
struct fastlock;
void fastlock_init(struct fastlock *lock);
void fastlock_lock(struct fastlock *lock);
int fastlock_trylock(struct fastlock *lock);
int fastlock_trylock(struct fastlock *lock, int fWeak);
void fastlock_unlock(struct fastlock *lock);
void fastlock_free(struct fastlock *lock);
@ -55,9 +55,9 @@ struct fastlock
fastlock_lock(this);
}
bool try_lock()
bool try_lock(bool fWeak = false)
{
return !!fastlock_trylock(this);
return !!fastlock_trylock(this, fWeak);
}
void unlock()

View File

@ -1475,7 +1475,7 @@ int writeToClient(int fd, client *c, int handler_installed) {
serverLog(LL_VERBOSE,
"Error writing to client: %s", strerror(errno));
lock.unlock();
if (aeTryAcquireLock())
if (aeTryAcquireLock(true /*fWeak*/))
{
freeClient(c);
aeReleaseLock();
@ -1502,7 +1502,7 @@ int writeToClient(int fd, client *c, int handler_installed) {
/* Close connection after entire reply has been sent. */
if (c->flags & CLIENT_CLOSE_AFTER_REPLY) {
lock.unlock();
if (aeTryAcquireLock())
if (aeTryAcquireLock(true /*fWeak*/))
{
freeClient(c);
aeReleaseLock();