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.)
This commit is contained in:
Andreas Kling 2019-04-01 20:02:05 +02:00
parent 54ea35703a
commit d5a9f4596b
5 changed files with 37 additions and 0 deletions

View file

@ -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<typename T>

View file

@ -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());

View file

@ -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 {

View file

@ -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();
}

View file

@ -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)