diff options
Diffstat (limited to 'compiler-rt/lib/scudo/standalone/linux.cc')
| -rw-r--r-- | compiler-rt/lib/scudo/standalone/linux.cc | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/compiler-rt/lib/scudo/standalone/linux.cc b/compiler-rt/lib/scudo/standalone/linux.cc index 5e695d72ff4..bfda03239f4 100644 --- a/compiler-rt/lib/scudo/standalone/linux.cc +++ b/compiler-rt/lib/scudo/standalone/linux.cc @@ -84,14 +84,22 @@ void releasePagesToOS(uptr BaseAddress, uptr Offset, uptr Size, // Calling getenv should be fine (c)(tm) at any time. const char *getEnv(const char *Name) { return getenv(Name); } -void BlockingMutex::wait() { - syscall(SYS_futex, reinterpret_cast<uptr>(OpaqueStorage), FUTEX_WAIT_PRIVATE, - MtxSleeping, nullptr, nullptr, 0); +void BlockingMutex::lock() { + atomic_u32 *M = reinterpret_cast<atomic_u32 *>(&OpaqueStorage); + if (atomic_exchange(M, MtxLocked, memory_order_acquire) == MtxUnlocked) + return; + while (atomic_exchange(M, MtxSleeping, memory_order_acquire) != MtxUnlocked) + syscall(SYS_futex, reinterpret_cast<uptr>(OpaqueStorage), + FUTEX_WAIT_PRIVATE, MtxSleeping, nullptr, nullptr, 0); } -void BlockingMutex::wake() { - syscall(SYS_futex, reinterpret_cast<uptr>(OpaqueStorage), FUTEX_WAKE_PRIVATE, - 1, nullptr, nullptr, 0); +void BlockingMutex::unlock() { + atomic_u32 *M = reinterpret_cast<atomic_u32 *>(&OpaqueStorage); + const u32 V = atomic_exchange(M, MtxUnlocked, memory_order_release); + DCHECK_NE(V, MtxUnlocked); + if (V == MtxSleeping) + syscall(SYS_futex, reinterpret_cast<uptr>(OpaqueStorage), + FUTEX_WAKE_PRIVATE, 1, nullptr, nullptr, 0); } u64 getMonotonicTime() { |

