mutex.h 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  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. //===----------------------------------------------------------------------===//
  8. #ifndef SCUDO_MUTEX_H_
  9. #define SCUDO_MUTEX_H_
  10. #include "atomic_helpers.h"
  11. #include "common.h"
  12. #include <string.h>
  13. #if SCUDO_FUCHSIA
  14. #error #include <lib/sync/mutex.h> // for sync_mutex_t
  15. #endif
  16. namespace scudo {
  17. class HybridMutex {
  18. public:
  19. bool tryLock();
  20. NOINLINE void lock() {
  21. if (LIKELY(tryLock()))
  22. return;
  23. // The compiler may try to fully unroll the loop, ending up in a
  24. // NumberOfTries*NumberOfYields block of pauses mixed with tryLocks. This
  25. // is large, ugly and unneeded, a compact loop is better for our purpose
  26. // here. Use a pragma to tell the compiler not to unroll the loop.
  27. #ifdef __clang__
  28. #pragma nounroll
  29. #endif
  30. for (u8 I = 0U; I < NumberOfTries; I++) {
  31. yieldProcessor(NumberOfYields);
  32. if (tryLock())
  33. return;
  34. }
  35. lockSlow();
  36. }
  37. void unlock();
  38. private:
  39. static constexpr u8 NumberOfTries = 8U;
  40. static constexpr u8 NumberOfYields = 8U;
  41. #if SCUDO_LINUX
  42. atomic_u32 M = {};
  43. #elif SCUDO_FUCHSIA
  44. sync_mutex_t M = {};
  45. #endif
  46. void lockSlow();
  47. };
  48. class ScopedLock {
  49. public:
  50. explicit ScopedLock(HybridMutex &M) : Mutex(M) { Mutex.lock(); }
  51. ~ScopedLock() { Mutex.unlock(); }
  52. private:
  53. HybridMutex &Mutex;
  54. ScopedLock(const ScopedLock &) = delete;
  55. void operator=(const ScopedLock &) = delete;
  56. };
  57. } // namespace scudo
  58. #endif // SCUDO_MUTEX_H_