1 //===-- mutex.h -------------------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 #define SCUDO_MUTEX_H_
12 #include "atomic_helpers.h"
14 #include "thread_annotations.h"
19 #include <lib/sync/mutex.h> // for sync_mutex_t
24 class CAPABILITY("mutex") HybridMutex
{
26 bool tryLock() TRY_ACQUIRE(true);
27 NOINLINE
void lock() ACQUIRE() {
28 if (LIKELY(tryLock()))
30 // The compiler may try to fully unroll the loop, ending up in a
31 // NumberOfTries*NumberOfYields block of pauses mixed with tryLocks. This
32 // is large, ugly and unneeded, a compact loop is better for our purpose
33 // here. Use a pragma to tell the compiler not to unroll the loop.
37 for (u8 I
= 0U; I
< NumberOfTries
; I
++) {
44 void unlock() RELEASE();
46 // TODO(chiahungduan): In general, we may want to assert the owner of lock as
47 // well. Given the current uses of HybridMutex, it's acceptable without
48 // asserting the owner. Re-evaluate this when we have certain scenarios which
49 // requires a more fine-grained lock granularity.
50 ALWAYS_INLINE
void assertHeld() ASSERT_CAPABILITY(this) {
57 // The value comes from the average time spent in accessing caches (which
58 // are the fastest operations) so that we are unlikely to wait too long for
60 constexpr u32 SpinTimes
= 16;
62 for (u32 I
= 0; I
< SpinTimes
; ++I
) {
68 void assertHeldImpl();
70 // TODO(chiahungduan): Adapt this value based on scenarios. E.g., primary and
71 // secondary allocator have different allocation times.
72 static constexpr u8 NumberOfTries
= 32U;
80 void lockSlow() ACQUIRE();
83 class SCOPED_CAPABILITY ScopedLock
{
85 explicit ScopedLock(HybridMutex
&M
) ACQUIRE(M
) : Mutex(M
) { Mutex
.lock(); }
86 ~ScopedLock() RELEASE() { Mutex
.unlock(); }
91 ScopedLock(const ScopedLock
&) = delete;
92 void operator=(const ScopedLock
&) = delete;
97 #endif // SCUDO_MUTEX_H_