Lock.cpp 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. #include <Kernel/Lock.h>
  2. #include <Kernel/Thread.h>
  3. void Lock::lock()
  4. {
  5. ASSERT(!Scheduler::is_active());
  6. if (!are_interrupts_enabled()) {
  7. kprintf("Interrupts disabled when trying to take Lock{%s}\n", m_name);
  8. dump_backtrace();
  9. hang();
  10. }
  11. for (;;) {
  12. bool expected = false;
  13. if (m_lock.compare_exchange_strong(expected, true, AK::memory_order_acq_rel)) {
  14. if (!m_holder || m_holder == current) {
  15. m_holder = current;
  16. ++m_level;
  17. m_lock.store(false, AK::memory_order_release);
  18. return;
  19. }
  20. m_lock.store(false, AK::memory_order_release);
  21. current->wait_on(m_queue, m_holder, m_name);
  22. }
  23. }
  24. }
  25. void Lock::unlock()
  26. {
  27. for (;;) {
  28. bool expected = false;
  29. if (m_lock.compare_exchange_strong(expected, true, AK::memory_order_acq_rel)) {
  30. ASSERT(m_holder == current);
  31. ASSERT(m_level);
  32. --m_level;
  33. if (m_level) {
  34. m_lock.store(false, AK::memory_order_release);
  35. return;
  36. }
  37. m_holder = nullptr;
  38. m_queue.wake_one();
  39. m_lock.store(false, AK::memory_order_release);
  40. return;
  41. }
  42. // I don't know *who* is using "m_lock", so just yield.
  43. Scheduler::yield();
  44. }
  45. }
  46. bool Lock::unlock_if_locked()
  47. {
  48. for (;;) {
  49. bool expected = false;
  50. if (m_lock.compare_exchange_strong(expected, true, AK::memory_order_acq_rel)) {
  51. if (m_level == 0) {
  52. m_lock.store(false, AK::memory_order_release);
  53. return false;
  54. }
  55. if (m_holder != current) {
  56. m_lock.store(false, AK::memory_order_release);
  57. return false;
  58. }
  59. ASSERT(m_level);
  60. --m_level;
  61. if (m_level) {
  62. m_lock.store(false, AK::memory_order_release);
  63. return false;
  64. }
  65. m_holder = nullptr;
  66. m_lock.store(false, AK::memory_order_release);
  67. m_queue.wake_one();
  68. return true;
  69. }
  70. // I don't know *who* is using "m_lock", so just yield.
  71. Scheduler::yield();
  72. }
  73. }