Browse Source

Kernel: Oops, forgot to add Lock.cpp.

Andreas Kling 6 years ago
parent
commit
2feddc58bb
1 changed files with 70 additions and 0 deletions
  1. 70 0
      Kernel/Lock.cpp

+ 70 - 0
Kernel/Lock.cpp

@@ -0,0 +1,70 @@
+#include <Kernel/Lock.h>
+
+void Lock::lock()
+{
+    if (!are_interrupts_enabled()) {
+        kprintf("Interrupts disabled when trying to take Lock{%s}\n", m_name);
+        dump_backtrace();
+        hang();
+    }
+    ASSERT(!Scheduler::is_active());
+    for (;;) {
+        if (CAS(&m_lock, 1, 0) == 0) {
+            if (!m_holder || m_holder == current) {
+                m_holder = current;
+                ++m_level;
+                memory_barrier();
+                m_lock = 0;
+                return;
+            }
+            m_lock = 0;
+        }
+        Scheduler::donate_to(m_holder, m_name);
+    }
+}
+
+void Lock::unlock()
+{
+    for (;;) {
+        if (CAS(&m_lock, 1, 0) == 0) {
+            ASSERT(m_holder == current);
+            ASSERT(m_level);
+            --m_level;
+            if (m_level) {
+                memory_barrier();
+                m_lock = 0;
+                return;
+            }
+            m_holder = nullptr;
+            memory_barrier();
+            m_lock = 0;
+            return;
+        }
+        Scheduler::donate_to(m_holder, m_name);
+    }
+}
+
+bool Lock::unlock_if_locked()
+{
+    for (;;) {
+        if (CAS(&m_lock, 1, 0) == 0) {
+            if (m_level == 0) {
+                memory_barrier();
+                m_lock = 0;
+                return false;
+            }
+            ASSERT(m_holder == current);
+            ASSERT(m_level);
+            --m_level;
+            if (m_level) {
+                memory_barrier();
+                m_lock = 0;
+                return false;
+            }
+            m_holder = nullptr;
+            memory_barrier();
+            m_lock = 0;
+            return true;
+        }
+    }
+}