From dd5acf2c0dcad07cecfe380f40f7c25a6b032290 Mon Sep 17 00:00:00 2001 From: John Sully Date: Thu, 28 Nov 2019 14:26:43 -0500 Subject: [PATCH 1/2] Fastlock should yield in ARM Former-commit-id: 6c65a11b8d841517f372ea9962b8dbc127390943 --- src/fastlock.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/fastlock.cpp b/src/fastlock.cpp index 4a64b20fc..4c942cbf9 100644 --- a/src/fastlock.cpp +++ b/src/fastlock.cpp @@ -289,7 +289,9 @@ extern "C" void fastlock_lock(struct fastlock *lock) break; #if defined(__i386__) || defined(__amd64__) - __asm__ ("pause"); + __asm__ __volatile__ ("pause"); +#elif defined(__arm__) + __asm__ __volatile__ ("yield"); #endif if ((++cloops % 1024*1024) == 0) { From 0860489563f67d6c835fb04cb5492b278d497fdc Mon Sep 17 00:00:00 2001 From: John Sully Date: Sat, 30 Nov 2019 00:51:58 -0500 Subject: [PATCH 2/2] Fix deadlock in spinlock (mfence) also spin for less time before sleeping Former-commit-id: 8a9045c028128ad1ceaaa7a482ae4d241592d164 --- src/fastlock.cpp | 4 ++-- src/fastlock_x64.asm | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/fastlock.cpp b/src/fastlock.cpp index 4c942cbf9..d566bb267 100644 --- a/src/fastlock.cpp +++ b/src/fastlock.cpp @@ -279,7 +279,7 @@ extern "C" void fastlock_lock(struct fastlock *lock) int tid = gettid(); unsigned myticket = __atomic_fetch_add(&lock->m_ticket.m_avail, 1, __ATOMIC_RELEASE); unsigned mask = (1U << (myticket % 32)); - int cloops = 0; + unsigned cloops = 0; ticket ticketT; for (;;) @@ -293,7 +293,7 @@ extern "C" void fastlock_lock(struct fastlock *lock) #elif defined(__arm__) __asm__ __volatile__ ("yield"); #endif - if ((++cloops % 1024*1024) == 0) + if ((++cloops % 0x10000) == 0) { fastlock_sleep(lock, tid, ticketT.u, mask); } diff --git a/src/fastlock_x64.asm b/src/fastlock_x64.asm index 80791a6de..f7ab6316e 100644 --- a/src/fastlock_x64.asm +++ b/src/fastlock_x64.asm @@ -45,7 +45,7 @@ fastlock_lock: cmp dx, ax # is our ticket up? je .LLocked # leave the loop pause - add ecx, 0x1000 # Have we been waiting a long time? (oflow if we have) + add ecx, 0x10000 # Have we been waiting a long time? (oflow if we have) # 1000h is set so we overflow on the 1024*1024'th iteration (like the C code) jnc .LLoop # If so, give up our timeslice to someone who's doing real work # Like the compiler, you're probably thinking: "Hey! I should take these pushs out of the loop" @@ -140,6 +140,7 @@ fastlock_unlock: mov ecx, [rdi+64] # get current active (this one) inc ecx # bump it to the next thread mov [rdi+64], cx # give up our ticket (note: lock is not required here because the spinlock itself guards this variable) + mfence # sync other threads # At this point the lock is removed, however we must wake up any pending futexs mov r9d, 1 # eax is the bitmask for 2 threads rol r9d, cl # place the mask in the right spot for the next 2 threads