Fix race in futex_sleep
Former-commit-id: 73300c57005a49bafbfc44db9c40ba7d1d4eedce
This commit is contained in:
parent
4a110615f3
commit
891977d9b7
@ -293,12 +293,21 @@ uint64_t fastlock_getlongwaitcount()
|
|||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void fastlock_sleep(fastlock *lock, pid_t pid, unsigned wake, unsigned mask)
|
extern "C" void fastlock_sleep(fastlock *lock, pid_t pid, unsigned wake, unsigned myticket)
|
||||||
{
|
{
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
g_dlock.registerwait(lock, pid);
|
g_dlock.registerwait(lock, pid);
|
||||||
|
unsigned mask = (1U << (myticket % 32));
|
||||||
__atomic_fetch_or(&lock->futex, mask, __ATOMIC_ACQUIRE);
|
__atomic_fetch_or(&lock->futex, mask, __ATOMIC_ACQUIRE);
|
||||||
futex(&lock->m_ticket.u, FUTEX_WAIT_BITSET_PRIVATE, wake, nullptr, mask);
|
|
||||||
|
// double check the lock wasn't release between the last check and us setting the futex mask
|
||||||
|
uint32_t u;
|
||||||
|
__atomic_load(&lock->m_ticket.u, &u, __ATOMIC_ACQUIRE);
|
||||||
|
if ((u & 0xffff) != myticket)
|
||||||
|
{
|
||||||
|
futex(&lock->m_ticket.u, FUTEX_WAIT_BITSET_PRIVATE, wake, nullptr, mask);
|
||||||
|
}
|
||||||
|
|
||||||
__atomic_fetch_and(&lock->futex, ~mask, __ATOMIC_RELEASE);
|
__atomic_fetch_and(&lock->futex, ~mask, __ATOMIC_RELEASE);
|
||||||
g_dlock.clearwait(lock, pid);
|
g_dlock.clearwait(lock, pid);
|
||||||
#endif
|
#endif
|
||||||
@ -332,7 +341,6 @@ extern "C" void fastlock_lock(struct fastlock *lock)
|
|||||||
|
|
||||||
int tid = gettid();
|
int tid = gettid();
|
||||||
unsigned myticket = __atomic_fetch_add(&lock->m_ticket.m_avail, 1, __ATOMIC_RELEASE);
|
unsigned myticket = __atomic_fetch_add(&lock->m_ticket.m_avail, 1, __ATOMIC_RELEASE);
|
||||||
unsigned mask = (1U << (myticket % 32));
|
|
||||||
unsigned cloops = 0;
|
unsigned cloops = 0;
|
||||||
ticket ticketT;
|
ticket ticketT;
|
||||||
unsigned loopLimit = g_fHighCpuPressure ? 0x10000 : 0x100000;
|
unsigned loopLimit = g_fHighCpuPressure ? 0x10000 : 0x100000;
|
||||||
@ -350,7 +358,7 @@ extern "C" void fastlock_lock(struct fastlock *lock)
|
|||||||
#endif
|
#endif
|
||||||
if ((++cloops % loopLimit) == 0)
|
if ((++cloops % loopLimit) == 0)
|
||||||
{
|
{
|
||||||
fastlock_sleep(lock, tid, ticketT.u, mask);
|
fastlock_sleep(lock, tid, ticketT.u, myticket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ fastlock_lock:
|
|||||||
# rdi ARG1 futex (already in rdi)
|
# rdi ARG1 futex (already in rdi)
|
||||||
# rsi ARG2 tid (already in esi)
|
# rsi ARG2 tid (already in esi)
|
||||||
# rdx ARG3 ticketT.u (already in edx)
|
# rdx ARG3 ticketT.u (already in edx)
|
||||||
bts ecx, eax # rcx ARG4 mask
|
mov ecx, eax # rcx ARG4 myticket
|
||||||
call fastlock_sleep
|
call fastlock_sleep
|
||||||
# cleanup and continue
|
# cleanup and continue
|
||||||
pop rax
|
pop rax
|
||||||
|
Loading…
x
Reference in New Issue
Block a user