diff --git a/Kernel/Lock.h b/Kernel/Lock.h index c91c13faeb..3b26cd14b2 100644 --- a/Kernel/Lock.h +++ b/Kernel/Lock.h @@ -26,6 +26,7 @@ public: void lock(); void unlock(); + bool unlock_if_locked(); 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) template diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 6df7a1e2db..e4445667bd 100644 --- a/Kernel/Process.cpp +++ b/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_tty(tty) , m_ppid(ppid) + , m_big_lock("Big Process Lock") { dbgprintf("Process: New process PID=%u with name=%s\n", m_pid, m_name.characters()); diff --git a/Kernel/Process.h b/Kernel/Process.h index cc15c1c251..826bcd194f 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -241,6 +241,8 @@ public: int thread_count() const; + Lock& big_lock() { return m_big_lock; } + private: friend class MemoryManager; friend class Scheduler; @@ -315,6 +317,8 @@ private: bool m_dead { false }; int m_next_tid { 0 }; + + Lock m_big_lock; }; class ProcessInspectionHandle { diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index abce43a6c2..3b91202739 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -252,10 +252,12 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2, void syscall_trap_entry(RegisterDump& regs) { + current->process().big_lock().lock(); dword function = regs.eax; dword arg1 = regs.edx; dword arg2 = regs.ecx; dword arg3 = regs.ebx; regs.eax = Syscall::handle(regs, function, arg1, arg2, arg3); + current->process().big_lock().unlock(); } diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp index 0e649106b3..038abfacef 100644 --- a/Kernel/Thread.cpp +++ b/Kernel/Thread.cpp @@ -112,6 +112,7 @@ void Thread::snooze_until(Alarm& alarm) void Thread::block(Thread::State new_state) { + bool did_unlock = process().big_lock().unlock_if_locked(); 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())); } @@ -120,6 +121,8 @@ void Thread::block(Thread::State new_state) m_was_interrupted_while_blocked = false; set_state(new_state); Scheduler::yield(); + if (did_unlock) + process().big_lock().lock(); } void Thread::sleep(dword ticks)