瀏覽代碼

Kernel: Add a blunt big process lock.

We can't have multiple threads in the same process running in the kernel
at the same time, so let's have a per-process lock that threads have to
acquire on syscall entry/exit (and yield while blocked.)
Andreas Kling 6 年之前
父節點
當前提交
d5a9f4596b
共有 5 個文件被更改,包括 37 次插入0 次删除
  1. 27 0
      Kernel/Lock.h
  2. 1 0
      Kernel/Process.cpp
  3. 4 0
      Kernel/Process.h
  4. 2 0
      Kernel/Syscall.cpp
  5. 3 0
      Kernel/Thread.cpp

+ 27 - 0
Kernel/Lock.h

@@ -26,6 +26,7 @@ public:
 
 
     void lock();
     void lock();
     void unlock();
     void unlock();
+    bool unlock_if_locked();
 
 
     const char* name() const { return m_name; }
     const char* name() const { return m_name; }
 
 
@@ -90,6 +91,32 @@ inline void Lock::unlock()
     }
     }
 }
 }
 
 
+inline 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;
+        }
+        Scheduler::donate_to(m_holder, m_name);
+    }
+}
+
 #define LOCKER(lock) Locker locker(lock)
 #define LOCKER(lock) Locker locker(lock)
 
 
 template<typename T>
 template<typename T>

+ 1 - 0
Kernel/Process.cpp

@@ -550,6 +550,7 @@ Process::Process(String&& name, uid_t uid, gid_t gid, pid_t ppid, RingLevel ring
     , m_executable(move(executable))
     , m_executable(move(executable))
     , m_tty(tty)
     , m_tty(tty)
     , m_ppid(ppid)
     , m_ppid(ppid)
+    , m_big_lock("Big Process Lock")
 {
 {
     dbgprintf("Process: New process PID=%u with name=%s\n", m_pid, m_name.characters());
     dbgprintf("Process: New process PID=%u with name=%s\n", m_pid, m_name.characters());
 
 

+ 4 - 0
Kernel/Process.h

@@ -241,6 +241,8 @@ public:
 
 
     int thread_count() const;
     int thread_count() const;
 
 
+    Lock& big_lock() { return m_big_lock; }
+
 private:
 private:
     friend class MemoryManager;
     friend class MemoryManager;
     friend class Scheduler;
     friend class Scheduler;
@@ -315,6 +317,8 @@ private:
     bool m_dead { false };
     bool m_dead { false };
 
 
     int m_next_tid { 0 };
     int m_next_tid { 0 };
+
+    Lock m_big_lock;
 };
 };
 
 
 class ProcessInspectionHandle {
 class ProcessInspectionHandle {

+ 2 - 0
Kernel/Syscall.cpp

@@ -252,10 +252,12 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2,
 
 
 void syscall_trap_entry(RegisterDump& regs)
 void syscall_trap_entry(RegisterDump& regs)
 {
 {
+    current->process().big_lock().lock();
     dword function = regs.eax;
     dword function = regs.eax;
     dword arg1 = regs.edx;
     dword arg1 = regs.edx;
     dword arg2 = regs.ecx;
     dword arg2 = regs.ecx;
     dword arg3 = regs.ebx;
     dword arg3 = regs.ebx;
     regs.eax = Syscall::handle(regs, function, arg1, arg2, arg3);
     regs.eax = Syscall::handle(regs, function, arg1, arg2, arg3);
+    current->process().big_lock().unlock();
 }
 }
 
 

+ 3 - 0
Kernel/Thread.cpp

@@ -112,6 +112,7 @@ void Thread::snooze_until(Alarm& alarm)
 
 
 void Thread::block(Thread::State new_state)
 void Thread::block(Thread::State new_state)
 {
 {
+    bool did_unlock = process().big_lock().unlock_if_locked();
     if (state() != Thread::Running) {
     if (state() != Thread::Running) {
         kprintf("Thread::block: %s(%u) block(%u/%s) with state=%u/%s\n", process().name().characters(), process().pid(), new_state, to_string(new_state), state(), to_string(state()));
         kprintf("Thread::block: %s(%u) block(%u/%s) with state=%u/%s\n", process().name().characters(), process().pid(), new_state, to_string(new_state), state(), to_string(state()));
     }
     }
@@ -120,6 +121,8 @@ void Thread::block(Thread::State new_state)
     m_was_interrupted_while_blocked = false;
     m_was_interrupted_while_blocked = false;
     set_state(new_state);
     set_state(new_state);
     Scheduler::yield();
     Scheduler::yield();
+    if (did_unlock)
+        process().big_lock().lock();
 }
 }
 
 
 void Thread::sleep(dword ticks)
 void Thread::sleep(dword ticks)