mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 03:08:11 +00:00
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:
parent
54ea35703a
commit
d5a9f4596b
5 changed files with 37 additions and 0 deletions
|
@ -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>
|
||||||
|
|
|
@ -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());
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue