1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-16 19:55:06 +00:00

Some refactor and style tweaks.

This commit is contained in:
Andreas Kling 2018-11-07 21:38:18 +01:00
parent 03a8357e84
commit 6304c771dd
7 changed files with 103 additions and 113 deletions

View file

@ -52,11 +52,11 @@ CoolGlobals* g_cool_globals;
static const DWORD defaultStackSize = 16384; static const DWORD defaultStackSize = 16384;
Process* current; Process* current;
Process* s_kernelProcess; Process* s_colonel_process;
static pid_t next_pid; static pid_t next_pid;
static InlineLinkedList<Process>* s_processes; static InlineLinkedList<Process>* s_processes;
static InlineLinkedList<Process>* s_deadProcesses; static InlineLinkedList<Process>* s_dead_processes;
static String* s_hostname; static String* s_hostname;
static String& hostnameStorage(InterruptDisabler&) static String& hostnameStorage(InterruptDisabler&)
@ -73,14 +73,14 @@ static String getHostname()
static bool contextSwitch(Process*); static bool contextSwitch(Process*);
static void redoKernelProcessTSS() static void redo_colonel_process_tss()
{ {
if (!s_kernelProcess->selector()) if (!s_colonel_process->selector())
s_kernelProcess->setSelector(gdt_alloc_entry()); 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.setLimit(0xffff);
tssDescriptor.dpl = 0; tssDescriptor.dpl = 0;
tssDescriptor.segment_present = 1; tssDescriptor.segment_present = 1;
@ -93,11 +93,11 @@ static void redoKernelProcessTSS()
flushGDT(); flushGDT();
} }
void Process::prepForIRETToNewProcess() void Process::prepare_for_iret_to_new_process()
{ {
redoKernelProcessTSS(); redo_colonel_process_tss();
s_kernelProcess->tss().backlink = current->selector(); s_colonel_process->tss().backlink = current->selector();
loadTaskRegister(s_kernelProcess->selector()); load_task_register(s_colonel_process->selector());
} }
static void hlt_loop() static void hlt_loop()
@ -115,30 +115,11 @@ void Process::initialize()
current = nullptr; current = nullptr;
next_pid = 0; next_pid = 0;
s_processes = new InlineLinkedList<Process>; s_processes = new InlineLinkedList<Process>;
s_deadProcesses = new InlineLinkedList<Process>; s_dead_processes = new InlineLinkedList<Process>;
s_kernelProcess = Process::createKernelProcess(hlt_loop, "colonel"); s_colonel_process = Process::create_kernel_process(hlt_loop, "colonel");
s_hostname = new String("birx"); s_hostname = new String("birx");
redoKernelProcessTSS(); redo_colonel_process_tss();
loadTaskRegister(s_kernelProcess->selector()); load_task_register(s_colonel_process->selector());
}
template<typename Callback>
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<void(Process&)> callback)
{
ASSERT_INTERRUPTS_DISABLED();
for (auto* process = s_processes->head(); process; process = process->next()) {
if (process->pgid() == pgid)
callback(*process);
}
} }
Vector<Process*> Process::allProcesses() Vector<Process*> Process::allProcesses()
@ -356,7 +337,7 @@ int Process::exec(const String& path, Vector<String>&& arguments, Vector<String>
InterruptDisabler disabler; InterruptDisabler disabler;
if (current == this) if (current == this)
loadTaskRegister(s_kernelProcess->selector()); load_task_register(s_colonel_process->selector());
m_name = parts.takeLast(); m_name = parts.takeLast();
@ -484,7 +465,7 @@ Process* Process::create_user_process(const String& path, uid_t uid, gid_t gid,
RetainPtr<VirtualFileSystem::Node> cwd; RetainPtr<VirtualFileSystem::Node> cwd;
{ {
InterruptDisabler disabler; InterruptDisabler disabler;
if (auto* parent = Process::fromPID(parent_pid)) if (auto* parent = Process::from_pid(parent_pid))
cwd = parent->m_cwd.copyRef(); cwd = parent->m_cwd.copyRef();
} }
if (!cwd) if (!cwd)
@ -545,7 +526,7 @@ int Process::sys$get_arguments(int* argc, char*** argv)
return 0; 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); auto* process = new Process(move(name), (uid_t)0, (gid_t)0, (pid_t)0, Ring0);
process->m_tss.eip = (dword)e; 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 { } else {
// FIXME: Use a ProcessHandle? Presumably we're executing *IN* the parent right now though.. // FIXME: Use a ProcessHandle? Presumably we're executing *IN* the parent right now though..
InterruptDisabler disabler; InterruptDisabler disabler;
if (auto* parent = Process::fromPID(m_ppid)) { if (auto* parent = Process::from_pid(m_ppid)) {
m_sid = parent->m_sid; m_sid = parent->m_sid;
m_pgid = parent->m_pgid; 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); kprintf("resume tss pc: %w:%x\n", m_tss_to_resume_kernel.cs, m_tss_to_resume_kernel.eip);
#endif #endif
word ret_ss = m_tss.ss;
dword ret_esp = m_tss.esp;
word ret_cs = m_tss.cs; word ret_cs = m_tss.cs;
dword ret_eip = m_tss.eip; dword ret_eip = m_tss.eip;
dword ret_eflags = m_tss.eflags; 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("sys$sigreturn in %s(%u)\n", name().characters(), pid());
dbgprintf(" -> resuming execution at %w:%x\n", m_tss.cs, m_tss.eip); dbgprintf(" -> resuming execution at %w:%x\n", m_tss.cs, m_tss.eip);
#endif #endif
loadTaskRegister(s_kernelProcess->selector()); load_task_register(s_colonel_process->selector());
sched_yield(); sched_yield();
kprintf("sys$sigreturn failed in %s(%u)\n", name().characters(), pid()); kprintf("sys$sigreturn failed in %s(%u)\n", name().characters(), pid());
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
@ -922,15 +901,15 @@ void Process::crash()
void Process::doHouseKeeping() void Process::doHouseKeeping()
{ {
if (s_deadProcesses->isEmpty()) if (s_dead_processes->isEmpty())
return; return;
InterruptDisabler disabler; InterruptDisabler disabler;
Process* next = nullptr; 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(); next = deadProcess->next();
delete deadProcess; delete deadProcess;
} }
s_deadProcesses->clear(); s_dead_processes->clear();
} }
int sched_yield() int sched_yield()
@ -962,8 +941,27 @@ void switchNow()
); );
} }
template<typename Callback> void Process::for_each(Function<bool(Process&)> callback)
static void for_each_process_in_state(Process::State state, 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<bool(Process&)> 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<bool(Process&)> callback)
{ {
ASSERT_INTERRUPTS_DISABLED(); ASSERT_INTERRUPTS_DISABLED();
for (auto* process = s_processes->head(); process;) { for (auto* process = s_processes->head(); process;) {
@ -974,8 +972,7 @@ static void for_each_process_in_state(Process::State state, Callback callback)
} }
} }
template<typename Callback> void Process::for_each_not_in_state(State state, Function<bool(Process&)> callback)
static void for_each_process_not_in_state(Process::State state, Callback callback)
{ {
ASSERT_INTERRUPTS_DISABLED(); ASSERT_INTERRUPTS_DISABLED();
for (auto* process = s_processes->head(); process;) { 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<typename Callback>
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() bool scheduleNewProcess()
{ {
ASSERT_INTERRUPTS_DISABLED(); ASSERT_INTERRUPTS_DISABLED();
@ -1005,59 +990,62 @@ bool scheduleNewProcess()
if (!current) { if (!current) {
// XXX: The first ever context_switch() goes to the idle process. // XXX: The first ever context_switch() goes to the idle process.
// This to setup a reliable place we can return to. // 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. // Check and unblock processes whose wait conditions have been met.
for (auto* process = s_processes->head(); process; process = process->next()) { Process::for_each([] (auto& process) {
if (process->state() == Process::BlockedSleep) { if (process.state() == Process::BlockedSleep) {
if (process->wakeupTime() <= system.uptime) if (process.wakeupTime() <= system.uptime)
process->unblock(); process.unblock();
continue; return true;
} }
if (process->state() == Process::BlockedWait) { if (process.state() == Process::BlockedWait) {
auto* waitee = Process::fromPID(process->waitee()); auto* waitee = Process::from_pid(process.waitee());
if (!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(); ASSERT_NOT_REACHED();
} }
if (waitee->state() == Process::Dead) { if (waitee->state() == Process::Dead) {
process->m_waitee_status = (waitee->m_termination_status << 8) | waitee->m_termination_signal; process.m_waitee_status = (waitee->m_termination_status << 8) | waitee->m_termination_signal;
process->unblock(); process.unblock();
waitee->set_state(Process::Forgiven); waitee->set_state(Process::Forgiven);
} }
continue; return true;
} }
if (process->state() == Process::BlockedRead) { if (process.state() == Process::BlockedRead) {
ASSERT(process->m_fdBlockedOnRead != -1); ASSERT(process.m_fdBlockedOnRead != -1);
// FIXME: Block until the amount of data wanted is available. // FIXME: Block until the amount of data wanted is available.
if (process->m_file_descriptors[process->m_fdBlockedOnRead]->hasDataAvailableForRead()) if (process.m_file_descriptors[process.m_fdBlockedOnRead]->hasDataAvailableForRead())
process->unblock(); process.unblock();
continue; return true;
} }
} return true;
});
// Forgive dead orphans. // Forgive dead orphans.
// FIXME: Does this really make sense? // FIXME: Does this really make sense?
for_each_process_in_state(Process::Dead, [] (auto& process) { Process::for_each_in_state(Process::Dead, [] (auto& process) {
if (!Process::fromPID(process.ppid())) if (!Process::from_pid(process.ppid()))
process.set_state(Process::Forgiven); process.set_state(Process::Forgiven);
return true;
}); });
// Clean up forgiven processes. // Clean up forgiven processes.
// FIXME: Do we really need this to be a separate pass over the process list? // 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_processes->remove(&process);
s_deadProcesses->append(&process); s_dead_processes->append(&process);
return true;
}); });
// Dispatch any pending signals. // Dispatch any pending signals.
// FIXME: Do we really need this to be a separate pass over the process list? // 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()) if (!process.has_unmasked_pending_signals())
return; return true;
// We know how to interrupt blocked processes, but if they are just executing // 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 // 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. // 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 // signal and dispatch it then and there? Would that be doable without the
// syscall effectively being "interrupted" despite having completed? // syscall effectively being "interrupted" despite having completed?
if (process.in_kernel() && !process.is_blocked()) if (process.in_kernel() && !process.is_blocked())
return; return true;
process.dispatch_one_pending_signal(); process.dispatch_one_pending_signal();
if (process.is_blocked()) { if (process.is_blocked()) {
process.m_was_interrupted_while_blocked = true; process.m_was_interrupted_while_blocked = true;
process.unblock(); process.unblock();
} }
return true;
}); });
#ifdef SCHEDULER_DEBUG #ifdef SCHEDULER_DEBUG
@ -1108,8 +1097,8 @@ bool scheduleNewProcess()
process->timesScheduled(), process->timesScheduled(),
process->name().characters()); process->name().characters());
} }
kprintf("Switch to kernel process @ %w:%x\n", s_kernelProcess->tss().cs, s_kernelProcess->tss().eip); kprintf("Switch to kernel process @ %w:%x\n", s_colonel_process->tss().cs, s_colonel_process->tss().eip);
return contextSwitch(Process::kernelProcess()); return contextSwitch(Process::colonel_process());
} }
} }
} }
@ -1171,7 +1160,7 @@ static bool contextSwitch(Process* t)
return true; return true;
} }
Process* Process::fromPID(pid_t pid) Process* Process::from_pid(pid_t pid)
{ {
ASSERT_INTERRUPTS_DISABLED(); ASSERT_INTERRUPTS_DISABLED();
for (auto* process = s_processes->head(); process; process = process->next()) { 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. ASSERT(pid != current->pid()); // FIXME: Support this scenario.
InterruptDisabler disabler; InterruptDisabler disabler;
auto* peer = Process::fromPID(pid); auto* peer = Process::from_pid(pid);
if (!peer) if (!peer)
return -ESRCH; return -ESRCH;
peer->send_signal(signal, this); 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)); VALIDATE_USER_WRITE(wstatus, sizeof(int));
InterruptDisabler disabler; InterruptDisabler disabler;
if (!Process::fromPID(waitee)) if (!Process::from_pid(waitee))
return -1; return -1;
m_waitee = waitee; m_waitee = waitee;
m_waitee_status = 0; m_waitee_status = 0;
@ -1540,10 +1529,10 @@ void sleep(DWORD ticks)
sched_yield(); sched_yield();
} }
Process* Process::kernelProcess() Process* Process::colonel_process()
{ {
ASSERT(s_kernelProcess); ASSERT(s_colonel_process);
return s_kernelProcess; return s_colonel_process;
} }
bool Process::isValidAddressForKernel(LinearAddress laddr) const bool Process::isValidAddressForKernel(LinearAddress laddr) const
@ -1576,7 +1565,7 @@ pid_t Process::sys$getsid(pid_t pid)
if (pid == 0) if (pid == 0)
return m_sid; return m_sid;
InterruptDisabler disabler; InterruptDisabler disabler;
auto* process = Process::fromPID(pid); auto* process = Process::from_pid(pid);
if (!process) if (!process)
return -ESRCH; return -ESRCH;
if (m_sid != process->m_sid) if (m_sid != process->m_sid)
@ -1588,12 +1577,9 @@ pid_t Process::sys$setsid()
{ {
InterruptDisabler disabler; InterruptDisabler disabler;
bool found_process_with_same_pgid_as_my_pid = false; bool found_process_with_same_pgid_as_my_pid = false;
forEachProcess([&] (auto& process) { Process::for_each_in_pgrp(pid(), [&] (auto& process) {
if (process.pgid() == pid()) { found_process_with_same_pgid_as_my_pid = true;
found_process_with_same_pgid_as_my_pid = true; return false;
return false;
}
return true;
}); });
if (found_process_with_same_pgid_as_my_pid) if (found_process_with_same_pgid_as_my_pid)
return -EPERM; return -EPERM;
@ -1607,7 +1593,7 @@ pid_t Process::sys$getpgid(pid_t pid)
if (pid == 0) if (pid == 0)
return m_pgid; return m_pgid;
InterruptDisabler disabler; // FIXME: Use a ProcessHandle InterruptDisabler disabler; // FIXME: Use a ProcessHandle
auto* process = Process::fromPID(pid); auto* process = Process::from_pid(pid);
if (!process) if (!process)
return -ESRCH; return -ESRCH;
return process->m_pgid; return process->m_pgid;
@ -1621,7 +1607,7 @@ pid_t Process::sys$getpgrp()
static pid_t get_sid_from_pgid(pid_t pgid) static pid_t get_sid_from_pgid(pid_t pgid)
{ {
InterruptDisabler disabler; InterruptDisabler disabler;
auto* group_leader = Process::fromPID(pgid); auto* group_leader = Process::from_pid(pgid);
if (!group_leader) if (!group_leader)
return -1; return -1;
return group_leader->sid(); 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; pid_t pid = specified_pid ? specified_pid : m_pid;
if (specified_pgid < 0) if (specified_pgid < 0)
return -EINVAL; return -EINVAL;
auto* process = Process::fromPID(pid); auto* process = Process::from_pid(pid);
if (!process) if (!process)
return -ESRCH; return -ESRCH;
pid_t new_pgid = specified_pgid ? specified_pgid : process->m_pid; pid_t new_pgid = specified_pgid ? specified_pgid : process->m_pid;

View file

@ -25,7 +25,7 @@ struct SignalActionData {
class Process : public InlineLinkedListNode<Process> { class Process : public InlineLinkedListNode<Process> {
friend class InlineLinkedListNode<Process>; friend class InlineLinkedListNode<Process>;
public: 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<String>&& arguments = Vector<String>(), Vector<String>&& environment = Vector<String>(), TTY* = nullptr); static Process* create_user_process(const String& path, uid_t, gid_t, pid_t ppid, int& error, Vector<String>&& arguments = Vector<String>(), Vector<String>&& environment = Vector<String>(), TTY* = nullptr);
~Process(); ~Process();
@ -58,8 +58,8 @@ public:
bool in_kernel() const { return (m_tss.cs & 0x03) == 0; } bool in_kernel() const { return (m_tss.cs & 0x03) == 0; }
static Process* fromPID(pid_t); static Process* from_pid(pid_t);
static Process* kernelProcess(); static Process* colonel_process();
const String& name() const { return m_name; } const String& name() const { return m_name; }
pid_t pid() const { return m_pid; } pid_t pid() const { return m_pid; }
@ -88,9 +88,12 @@ public:
void setWakeupTime(DWORD t) { m_wakeupTime = t; } void setWakeupTime(DWORD t) { m_wakeupTime = t; }
DWORD wakeupTime() const { return m_wakeupTime; } DWORD wakeupTime() const { return m_wakeupTime; }
static void for_each_in_pgrp(pid_t pgid, Function<void(Process&)>); static void for_each(Function<bool(Process&)>);
static void for_each_in_pgrp(pid_t, Function<bool(Process&)>);
static void for_each_in_state(State, Function<bool(Process&)>);
static void for_each_not_in_state(State, Function<bool(Process&)>);
static void prepForIRETToNewProcess(); static void prepare_for_iret_to_new_process();
bool tick() { ++m_ticks; return --m_ticksLeft; } bool tick() { ++m_ticks; return --m_ticksLeft; }
void setTicksLeft(DWORD t) { m_ticksLeft = t; } void setTicksLeft(DWORD t) { m_ticksLeft = t; }

View file

@ -50,6 +50,7 @@ void TTY::interrupt()
Process::for_each_in_pgrp(pgid(), [this] (auto& process) { Process::for_each_in_pgrp(pgid(), [this] (auto& process) {
dbgprintf("%s: Send SIGINT to %d\n", ttyName().characters(), process.pid()); dbgprintf("%s: Send SIGINT to %d\n", ttyName().characters(), process.pid());
process.send_signal(SIGINT, nullptr); process.send_signal(SIGINT, nullptr);
return true;
}); });
} }
} }

View file

@ -414,7 +414,7 @@ void idt_init()
flushIDT(); flushIDT();
} }
void loadTaskRegister(WORD selector) void load_task_register(WORD selector)
{ {
asm("ltr %0"::"r"(selector)); asm("ltr %0"::"r"(selector));
} }

View file

@ -65,7 +65,7 @@ void registerIRQHandler(BYTE number, IRQHandler&);
void unregisterIRQHandler(BYTE number, IRQHandler&); void unregisterIRQHandler(BYTE number, IRQHandler&);
void flushIDT(); void flushIDT();
void flushGDT(); void flushGDT();
void loadTaskRegister(WORD selector); void load_task_register(WORD selector);
word gdt_alloc_entry(); word gdt_alloc_entry();
void gdt_free_entry(word); void gdt_free_entry(word);
Descriptor& getGDTEntry(WORD selector); Descriptor& getGDTEntry(WORD selector);

View file

@ -105,7 +105,7 @@ void clock_handle()
if (!scheduleNewProcess()) if (!scheduleNewProcess())
return; return;
Process::prepForIRETToNewProcess(); Process::prepare_for_iret_to_new_process();
// Set the NT (nested task) flag. // Set the NT (nested task) flag.
asm( asm(

View file

@ -308,8 +308,8 @@ void init()
Process::initialize(); Process::initialize();
Process::createKernelProcess(undertaker_main, "undertaker"); Process::create_kernel_process(undertaker_main, "undertaker");
Process::createKernelProcess(init_stage2, "init"); Process::create_kernel_process(init_stage2, "init");
scheduleNewProcess(); scheduleNewProcess();