mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-23 18:02:05 -05: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 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>
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue