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(); g_lock.lock();
} }
int aeTryAcquireLock() int aeTryAcquireLock(bool fWeak)
{ {
return g_lock.try_lock(); return g_lock.try_lock(fWeak);
} }
void aeReleaseLock() void aeReleaseLock()

View File

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

View File

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

View File

@ -133,7 +133,7 @@ extern "C" void fastlock_lock(struct fastlock *lock)
std::atomic_thread_fence(std::memory_order_acquire); 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()) 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_expect { active, active };
struct ticket ticket_setiflocked { active, next }; 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; lock->m_depth = 1;
__atomic_store_4(&lock->m_pidOwner, gettid(), __ATOMIC_RELEASE); __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 assert((int)__atomic_load_4(&lock->m_pidOwner, __ATOMIC_RELAXED) >= 0); // unlock after free
lock->m_pidOwner = -1; lock->m_pidOwner = -1;
std::atomic_thread_fence(std::memory_order_acquire); std::atomic_thread_fence(std::memory_order_release);
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 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); unlock_futex(lock, activeNew);
} }
} }

View File

@ -9,7 +9,7 @@ extern "C" {
struct fastlock; struct fastlock;
void fastlock_init(struct fastlock *lock); void fastlock_init(struct fastlock *lock);
void fastlock_lock(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_unlock(struct fastlock *lock);
void fastlock_free(struct fastlock *lock); void fastlock_free(struct fastlock *lock);
@ -55,9 +55,9 @@ struct fastlock
fastlock_lock(this); fastlock_lock(this);
} }
bool try_lock() bool try_lock(bool fWeak = false)
{ {
return !!fastlock_trylock(this); return !!fastlock_trylock(this, fWeak);
} }
void unlock() void unlock()

View File

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