Lock.h 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #pragma once
  2. #ifdef __serenity__
  3. #include <AK/Assertions.h>
  4. #include <AK/Types.h>
  5. #include <AK/Atomic.h>
  6. #include <unistd.h>
  7. namespace LibThread {
  8. class Lock {
  9. public:
  10. Lock() {}
  11. ~Lock() {}
  12. void lock();
  13. void unlock();
  14. private:
  15. AK::Atomic<bool> m_lock { false };
  16. u32 m_level { 0 };
  17. int m_holder { -1 };
  18. };
  19. class Locker {
  20. public:
  21. [[gnu::always_inline]] inline explicit Locker(Lock& l)
  22. : m_lock(l)
  23. {
  24. lock();
  25. }
  26. [[gnu::always_inline]] inline ~Locker() { unlock(); }
  27. [[gnu::always_inline]] inline void unlock() { m_lock.unlock(); }
  28. [[gnu::always_inline]] inline void lock() { m_lock.lock(); }
  29. private:
  30. Lock& m_lock;
  31. };
  32. [[gnu::always_inline]] inline void Lock::lock()
  33. {
  34. int tid = gettid();
  35. for (;;) {
  36. bool expected = false;
  37. if (m_lock.compare_exchange_strong(expected, true, AK::memory_order_acq_rel)) {
  38. if (m_holder == -1 || m_holder == tid) {
  39. m_holder = tid;
  40. ++m_level;
  41. m_lock.store(false, AK::memory_order_release);
  42. return;
  43. }
  44. m_lock.store(false, AK::memory_order_release);
  45. }
  46. donate(m_holder);
  47. }
  48. }
  49. inline void Lock::unlock()
  50. {
  51. for (;;) {
  52. bool expected = false;
  53. if (m_lock.compare_exchange_strong(expected, true, AK::memory_order_acq_rel)) {
  54. ASSERT(m_holder == gettid());
  55. ASSERT(m_level);
  56. --m_level;
  57. if (m_level) {
  58. m_lock.store(false, AK::memory_order_release);
  59. return;
  60. }
  61. m_holder = -1;
  62. m_lock.store(false, AK::memory_order_release);
  63. return;
  64. }
  65. donate(m_holder);
  66. }
  67. }
  68. #define LOCKER(lock) LibThread::Locker locker(lock)
  69. template<typename T>
  70. class Lockable {
  71. public:
  72. Lockable() {}
  73. Lockable(T&& resource)
  74. : m_resource(move(resource))
  75. {
  76. }
  77. Lock& lock() { return m_lock; }
  78. T& resource() { return m_resource; }
  79. T lock_and_copy()
  80. {
  81. LOCKER(m_lock);
  82. return m_resource;
  83. }
  84. private:
  85. T m_resource;
  86. Lock m_lock;
  87. };
  88. }
  89. #else
  90. namespace LibThread {
  91. class Lock {
  92. public:
  93. Lock() { }
  94. ~Lock() { }
  95. };
  96. }
  97. #define LOCKER(x)
  98. #endif