[DAG] TransformFPLoadStorePair - early out if we're not loading a simple type
[llvm-project.git] / compiler-rt / lib / scudo / standalone / mutex.h
blob4caa945219b5233ac00948af00ee7d69ef1a440a
1 //===-- mutex.h -------------------------------------------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
9 #ifndef SCUDO_MUTEX_H_
10 #define SCUDO_MUTEX_H_
12 #include "atomic_helpers.h"
13 #include "common.h"
14 #include "thread_annotations.h"
16 #include <string.h>
18 #if SCUDO_FUCHSIA
19 #include <lib/sync/mutex.h> // for sync_mutex_t
20 #endif
22 namespace scudo {
24 class CAPABILITY("mutex") HybridMutex {
25 public:
26 bool tryLock() TRY_ACQUIRE(true);
27 NOINLINE void lock() ACQUIRE() {
28 if (LIKELY(tryLock()))
29 return;
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.
34 #ifdef __clang__
35 #pragma nounroll
36 #endif
37 for (u8 I = 0U; I < NumberOfTries; I++) {
38 delayLoop();
39 if (tryLock())
40 return;
42 lockSlow();
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) {
51 if (SCUDO_DEBUG)
52 assertHeldImpl();
55 private:
56 void delayLoop() {
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
59 // fast operations.
60 constexpr u32 SpinTimes = 16;
61 volatile u32 V = 0;
62 for (u32 I = 0; I < SpinTimes; ++I) {
63 u32 Tmp = V + 1;
64 V = Tmp;
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;
74 #if SCUDO_LINUX
75 atomic_u32 M = {};
76 #elif SCUDO_FUCHSIA
77 sync_mutex_t M = {};
78 #endif
80 void lockSlow() ACQUIRE();
83 class SCOPED_CAPABILITY ScopedLock {
84 public:
85 explicit ScopedLock(HybridMutex &M) ACQUIRE(M) : Mutex(M) { Mutex.lock(); }
86 ~ScopedLock() RELEASE() { Mutex.unlock(); }
88 private:
89 HybridMutex &Mutex;
91 ScopedLock(const ScopedLock &) = delete;
92 void operator=(const ScopedLock &) = delete;
95 } // namespace scudo
97 #endif // SCUDO_MUTEX_H_