summaryrefslogtreecommitdiffstats
path: root/compiler-rt/lib/scudo/standalone/linux.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler-rt/lib/scudo/standalone/linux.cc')
-rw-r--r--compiler-rt/lib/scudo/standalone/linux.cc20
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() {
OpenPOWER on IntegriCloud