diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 5fd261ab65..02f9b7e71d 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -52,11 +52,11 @@ CoolGlobals* g_cool_globals; static const DWORD defaultStackSize = 16384; Process* current; -Process* s_kernelProcess; +Process* s_colonel_process; static pid_t next_pid; static InlineLinkedList* s_processes; -static InlineLinkedList* s_deadProcesses; +static InlineLinkedList* s_dead_processes; static String* s_hostname; static String& hostnameStorage(InterruptDisabler&) @@ -73,14 +73,14 @@ static String getHostname() static bool contextSwitch(Process*); -static void redoKernelProcessTSS() +static void redo_colonel_process_tss() { - if (!s_kernelProcess->selector()) - s_kernelProcess->setSelector(gdt_alloc_entry()); + if (!s_colonel_process->selector()) + s_colonel_process->setSelector(gdt_alloc_entry()); - auto& tssDescriptor = getGDTEntry(s_kernelProcess->selector()); + auto& tssDescriptor = getGDTEntry(s_colonel_process->selector()); - tssDescriptor.setBase(&s_kernelProcess->tss()); + tssDescriptor.setBase(&s_colonel_process->tss()); tssDescriptor.setLimit(0xffff); tssDescriptor.dpl = 0; tssDescriptor.segment_present = 1; @@ -93,11 +93,11 @@ static void redoKernelProcessTSS() flushGDT(); } -void Process::prepForIRETToNewProcess() +void Process::prepare_for_iret_to_new_process() { - redoKernelProcessTSS(); - s_kernelProcess->tss().backlink = current->selector(); - loadTaskRegister(s_kernelProcess->selector()); + redo_colonel_process_tss(); + s_colonel_process->tss().backlink = current->selector(); + load_task_register(s_colonel_process->selector()); } static void hlt_loop() @@ -115,30 +115,11 @@ void Process::initialize() current = nullptr; next_pid = 0; s_processes = new InlineLinkedList; - s_deadProcesses = new InlineLinkedList; - s_kernelProcess = Process::createKernelProcess(hlt_loop, "colonel"); + s_dead_processes = new InlineLinkedList; + s_colonel_process = Process::create_kernel_process(hlt_loop, "colonel"); s_hostname = new String("birx"); - redoKernelProcessTSS(); - loadTaskRegister(s_kernelProcess->selector()); -} - -template -static void forEachProcess(Callback callback) -{ - ASSERT_INTERRUPTS_DISABLED(); - for (auto* process = s_processes->head(); process; process = process->next()) { - if (!callback(*process)) - break; - } -} - -void Process::for_each_in_pgrp(pid_t pgid, Function callback) -{ - ASSERT_INTERRUPTS_DISABLED(); - for (auto* process = s_processes->head(); process; process = process->next()) { - if (process->pgid() == pgid) - callback(*process); - } + redo_colonel_process_tss(); + load_task_register(s_colonel_process->selector()); } Vector Process::allProcesses() @@ -356,7 +337,7 @@ int Process::exec(const String& path, Vector&& arguments, Vector InterruptDisabler disabler; if (current == this) - loadTaskRegister(s_kernelProcess->selector()); + load_task_register(s_colonel_process->selector()); m_name = parts.takeLast(); @@ -484,7 +465,7 @@ Process* Process::create_user_process(const String& path, uid_t uid, gid_t gid, RetainPtr cwd; { InterruptDisabler disabler; - if (auto* parent = Process::fromPID(parent_pid)) + if (auto* parent = Process::from_pid(parent_pid)) cwd = parent->m_cwd.copyRef(); } if (!cwd) @@ -545,7 +526,7 @@ int Process::sys$get_arguments(int* argc, char*** argv) return 0; } -Process* Process::createKernelProcess(void (*e)(), String&& name) +Process* Process::create_kernel_process(void (*e)(), String&& name) { auto* process = new Process(move(name), (uid_t)0, (gid_t)0, (pid_t)0, Ring0); process->m_tss.eip = (dword)e; @@ -585,7 +566,7 @@ Process::Process(String&& name, uid_t uid, gid_t gid, pid_t ppid, RingLevel ring } else { // FIXME: Use a ProcessHandle? Presumably we're executing *IN* the parent right now though.. InterruptDisabler disabler; - if (auto* parent = Process::fromPID(m_ppid)) { + if (auto* parent = Process::from_pid(m_ppid)) { m_sid = parent->m_sid; m_pgid = parent->m_pgid; } @@ -789,8 +770,6 @@ void Process::dispatch_signal(byte signal) kprintf("resume tss pc: %w:%x\n", m_tss_to_resume_kernel.cs, m_tss_to_resume_kernel.eip); #endif - word ret_ss = m_tss.ss; - dword ret_esp = m_tss.esp; word ret_cs = m_tss.cs; dword ret_eip = m_tss.eip; dword ret_eflags = m_tss.eflags; @@ -891,7 +870,7 @@ void Process::sys$sigreturn() dbgprintf("sys$sigreturn in %s(%u)\n", name().characters(), pid()); dbgprintf(" -> resuming execution at %w:%x\n", m_tss.cs, m_tss.eip); #endif - loadTaskRegister(s_kernelProcess->selector()); + load_task_register(s_colonel_process->selector()); sched_yield(); kprintf("sys$sigreturn failed in %s(%u)\n", name().characters(), pid()); ASSERT_NOT_REACHED(); @@ -922,15 +901,15 @@ void Process::crash() void Process::doHouseKeeping() { - if (s_deadProcesses->isEmpty()) + if (s_dead_processes->isEmpty()) return; InterruptDisabler disabler; Process* next = nullptr; - for (auto* deadProcess = s_deadProcesses->head(); deadProcess; deadProcess = next) { + for (auto* deadProcess = s_dead_processes->head(); deadProcess; deadProcess = next) { next = deadProcess->next(); delete deadProcess; } - s_deadProcesses->clear(); + s_dead_processes->clear(); } int sched_yield() @@ -962,8 +941,27 @@ void switchNow() ); } -template -static void for_each_process_in_state(Process::State state, Callback callback) +void Process::for_each(Function callback) +{ + ASSERT_INTERRUPTS_DISABLED(); + for (auto* process = s_processes->head(); process; process = process->next()) { + if (!callback(*process)) + break; + } +} + +void Process::for_each_in_pgrp(pid_t pgid, Function callback) +{ + ASSERT_INTERRUPTS_DISABLED(); + for (auto* process = s_processes->head(); process; process = process->next()) { + if (process->pgid() == pgid) { + if (!callback(*process)) + break; + } + } +} + +void Process::for_each_in_state(State state, Function callback) { ASSERT_INTERRUPTS_DISABLED(); for (auto* process = s_processes->head(); process;) { @@ -974,8 +972,7 @@ static void for_each_process_in_state(Process::State state, Callback callback) } } -template -static void for_each_process_not_in_state(Process::State state, Callback callback) +void Process::for_each_not_in_state(State state, Function callback) { ASSERT_INTERRUPTS_DISABLED(); for (auto* process = s_processes->head(); process;) { @@ -986,18 +983,6 @@ static void for_each_process_not_in_state(Process::State state, Callback callbac } } -template -static void for_each_blocked_process(Callback callback) -{ - ASSERT_INTERRUPTS_DISABLED(); - for (auto* process = s_processes->head(); process;) { - auto* next_process = process->next(); - if (process->is_blocked()) - callback(*process); - process = next_process; - } -} - bool scheduleNewProcess() { ASSERT_INTERRUPTS_DISABLED(); @@ -1005,59 +990,62 @@ bool scheduleNewProcess() if (!current) { // XXX: The first ever context_switch() goes to the idle process. // This to setup a reliable place we can return to. - return contextSwitch(Process::kernelProcess()); + return contextSwitch(Process::colonel_process()); } // Check and unblock processes whose wait conditions have been met. - for (auto* process = s_processes->head(); process; process = process->next()) { - if (process->state() == Process::BlockedSleep) { - if (process->wakeupTime() <= system.uptime) - process->unblock(); - continue; + Process::for_each([] (auto& process) { + if (process.state() == Process::BlockedSleep) { + if (process.wakeupTime() <= system.uptime) + process.unblock(); + return true; } - if (process->state() == Process::BlockedWait) { - auto* waitee = Process::fromPID(process->waitee()); + if (process.state() == Process::BlockedWait) { + auto* waitee = Process::from_pid(process.waitee()); if (!waitee) { - kprintf("waitee %u of %s(%u) reaped before I could wait?\n", process->waitee(), process->name().characters(), process->pid()); + kprintf("waitee %u of %s(%u) reaped before I could wait?\n", process.waitee(), process.name().characters(), process.pid()); ASSERT_NOT_REACHED(); } if (waitee->state() == Process::Dead) { - process->m_waitee_status = (waitee->m_termination_status << 8) | waitee->m_termination_signal; - process->unblock(); + process.m_waitee_status = (waitee->m_termination_status << 8) | waitee->m_termination_signal; + process.unblock(); waitee->set_state(Process::Forgiven); } - continue; + return true; } - if (process->state() == Process::BlockedRead) { - ASSERT(process->m_fdBlockedOnRead != -1); + if (process.state() == Process::BlockedRead) { + ASSERT(process.m_fdBlockedOnRead != -1); // FIXME: Block until the amount of data wanted is available. - if (process->m_file_descriptors[process->m_fdBlockedOnRead]->hasDataAvailableForRead()) - process->unblock(); - continue; + if (process.m_file_descriptors[process.m_fdBlockedOnRead]->hasDataAvailableForRead()) + process.unblock(); + return true; } - } + return true; + }); // Forgive dead orphans. // FIXME: Does this really make sense? - for_each_process_in_state(Process::Dead, [] (auto& process) { - if (!Process::fromPID(process.ppid())) + Process::for_each_in_state(Process::Dead, [] (auto& process) { + if (!Process::from_pid(process.ppid())) process.set_state(Process::Forgiven); + return true; }); // Clean up forgiven processes. // FIXME: Do we really need this to be a separate pass over the process list? - for_each_process_in_state(Process::Forgiven, [] (auto& process) { + Process::for_each_in_state(Process::Forgiven, [] (auto& process) { s_processes->remove(&process); - s_deadProcesses->append(&process); + s_dead_processes->append(&process); + return true; }); // Dispatch any pending signals. // FIXME: Do we really need this to be a separate pass over the process list? - for_each_process_not_in_state(Process::Dead, [] (auto& process) { + Process::for_each_not_in_state(Process::Dead, [] (auto& process) { if (!process.has_unmasked_pending_signals()) - return; + return true; // We know how to interrupt blocked processes, but if they are just executing // at some random point in the kernel, let them continue. They'll be in userspace // sooner or later and we can deliver the signal then. @@ -1065,12 +1053,13 @@ bool scheduleNewProcess() // signal and dispatch it then and there? Would that be doable without the // syscall effectively being "interrupted" despite having completed? if (process.in_kernel() && !process.is_blocked()) - return; + return true; process.dispatch_one_pending_signal(); if (process.is_blocked()) { process.m_was_interrupted_while_blocked = true; process.unblock(); } + return true; }); #ifdef SCHEDULER_DEBUG @@ -1108,8 +1097,8 @@ bool scheduleNewProcess() process->timesScheduled(), process->name().characters()); } - kprintf("Switch to kernel process @ %w:%x\n", s_kernelProcess->tss().cs, s_kernelProcess->tss().eip); - return contextSwitch(Process::kernelProcess()); + kprintf("Switch to kernel process @ %w:%x\n", s_colonel_process->tss().cs, s_colonel_process->tss().eip); + return contextSwitch(Process::colonel_process()); } } } @@ -1171,7 +1160,7 @@ static bool contextSwitch(Process* t) return true; } -Process* Process::fromPID(pid_t pid) +Process* Process::from_pid(pid_t pid) { ASSERT_INTERRUPTS_DISABLED(); for (auto* process = s_processes->head(); process; process = process->next()) { @@ -1425,7 +1414,7 @@ int Process::sys$kill(pid_t pid, int signal) } ASSERT(pid != current->pid()); // FIXME: Support this scenario. InterruptDisabler disabler; - auto* peer = Process::fromPID(pid); + auto* peer = Process::from_pid(pid); if (!peer) return -ESRCH; peer->send_signal(signal, this); @@ -1498,7 +1487,7 @@ pid_t Process::sys$waitpid(pid_t waitee, int* wstatus, int options) VALIDATE_USER_WRITE(wstatus, sizeof(int)); InterruptDisabler disabler; - if (!Process::fromPID(waitee)) + if (!Process::from_pid(waitee)) return -1; m_waitee = waitee; m_waitee_status = 0; @@ -1540,10 +1529,10 @@ void sleep(DWORD ticks) sched_yield(); } -Process* Process::kernelProcess() +Process* Process::colonel_process() { - ASSERT(s_kernelProcess); - return s_kernelProcess; + ASSERT(s_colonel_process); + return s_colonel_process; } bool Process::isValidAddressForKernel(LinearAddress laddr) const @@ -1576,7 +1565,7 @@ pid_t Process::sys$getsid(pid_t pid) if (pid == 0) return m_sid; InterruptDisabler disabler; - auto* process = Process::fromPID(pid); + auto* process = Process::from_pid(pid); if (!process) return -ESRCH; if (m_sid != process->m_sid) @@ -1588,12 +1577,9 @@ pid_t Process::sys$setsid() { InterruptDisabler disabler; bool found_process_with_same_pgid_as_my_pid = false; - forEachProcess([&] (auto& process) { - if (process.pgid() == pid()) { - found_process_with_same_pgid_as_my_pid = true; - return false; - } - return true; + Process::for_each_in_pgrp(pid(), [&] (auto& process) { + found_process_with_same_pgid_as_my_pid = true; + return false; }); if (found_process_with_same_pgid_as_my_pid) return -EPERM; @@ -1607,7 +1593,7 @@ pid_t Process::sys$getpgid(pid_t pid) if (pid == 0) return m_pgid; InterruptDisabler disabler; // FIXME: Use a ProcessHandle - auto* process = Process::fromPID(pid); + auto* process = Process::from_pid(pid); if (!process) return -ESRCH; return process->m_pgid; @@ -1621,7 +1607,7 @@ pid_t Process::sys$getpgrp() static pid_t get_sid_from_pgid(pid_t pgid) { InterruptDisabler disabler; - auto* group_leader = Process::fromPID(pgid); + auto* group_leader = Process::from_pid(pgid); if (!group_leader) return -1; return group_leader->sid(); @@ -1633,7 +1619,7 @@ int Process::sys$setpgid(pid_t specified_pid, pid_t specified_pgid) pid_t pid = specified_pid ? specified_pid : m_pid; if (specified_pgid < 0) return -EINVAL; - auto* process = Process::fromPID(pid); + auto* process = Process::from_pid(pid); if (!process) return -ESRCH; pid_t new_pgid = specified_pgid ? specified_pgid : process->m_pid; diff --git a/Kernel/Process.h b/Kernel/Process.h index 32c7e803ae..8971007281 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -25,7 +25,7 @@ struct SignalActionData { class Process : public InlineLinkedListNode { friend class InlineLinkedListNode; public: - static Process* createKernelProcess(void (*entry)(), String&& name); + static Process* create_kernel_process(void (*entry)(), String&& name); static Process* create_user_process(const String& path, uid_t, gid_t, pid_t ppid, int& error, Vector&& arguments = Vector(), Vector&& environment = Vector(), TTY* = nullptr); ~Process(); @@ -58,8 +58,8 @@ public: bool in_kernel() const { return (m_tss.cs & 0x03) == 0; } - static Process* fromPID(pid_t); - static Process* kernelProcess(); + static Process* from_pid(pid_t); + static Process* colonel_process(); const String& name() const { return m_name; } pid_t pid() const { return m_pid; } @@ -88,9 +88,12 @@ public: void setWakeupTime(DWORD t) { m_wakeupTime = t; } DWORD wakeupTime() const { return m_wakeupTime; } - static void for_each_in_pgrp(pid_t pgid, Function); + static void for_each(Function); + static void for_each_in_pgrp(pid_t, Function); + static void for_each_in_state(State, Function); + static void for_each_not_in_state(State, Function); - static void prepForIRETToNewProcess(); + static void prepare_for_iret_to_new_process(); bool tick() { ++m_ticks; return --m_ticksLeft; } void setTicksLeft(DWORD t) { m_ticksLeft = t; } diff --git a/Kernel/TTY.cpp b/Kernel/TTY.cpp index 0161a54043..382ac2a6f8 100644 --- a/Kernel/TTY.cpp +++ b/Kernel/TTY.cpp @@ -50,6 +50,7 @@ void TTY::interrupt() Process::for_each_in_pgrp(pgid(), [this] (auto& process) { dbgprintf("%s: Send SIGINT to %d\n", ttyName().characters(), process.pid()); process.send_signal(SIGINT, nullptr); + return true; }); } } diff --git a/Kernel/i386.cpp b/Kernel/i386.cpp index 6cdd738661..f7b21b504f 100644 --- a/Kernel/i386.cpp +++ b/Kernel/i386.cpp @@ -414,7 +414,7 @@ void idt_init() flushIDT(); } -void loadTaskRegister(WORD selector) +void load_task_register(WORD selector) { asm("ltr %0"::"r"(selector)); } diff --git a/Kernel/i386.h b/Kernel/i386.h index 7842c1ce08..3b56be9e72 100644 --- a/Kernel/i386.h +++ b/Kernel/i386.h @@ -65,7 +65,7 @@ void registerIRQHandler(BYTE number, IRQHandler&); void unregisterIRQHandler(BYTE number, IRQHandler&); void flushIDT(); void flushGDT(); -void loadTaskRegister(WORD selector); +void load_task_register(WORD selector); word gdt_alloc_entry(); void gdt_free_entry(word); Descriptor& getGDTEntry(WORD selector); diff --git a/Kernel/i8253.cpp b/Kernel/i8253.cpp index 0ab08f6527..e1b1f60860 100644 --- a/Kernel/i8253.cpp +++ b/Kernel/i8253.cpp @@ -105,7 +105,7 @@ void clock_handle() if (!scheduleNewProcess()) return; - Process::prepForIRETToNewProcess(); + Process::prepare_for_iret_to_new_process(); // Set the NT (nested task) flag. asm( diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 9efff1acfd..8029b063b1 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -308,8 +308,8 @@ void init() Process::initialize(); - Process::createKernelProcess(undertaker_main, "undertaker"); - Process::createKernelProcess(init_stage2, "init"); + Process::create_kernel_process(undertaker_main, "undertaker"); + Process::create_kernel_process(init_stage2, "init"); scheduleNewProcess();