Fix issues with relaxed memory model architectures
Former-commit-id: e37bc4ad40e852b67ee14e5aa87fd2f398f00eed
This commit is contained in:
parent
db5af7990d
commit
d65ce6fbbc
@ -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()
|
||||||
|
2
src/ae.h
2
src/ae.h
@ -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();
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
@ -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();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user