mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 20:47:45 +00:00
Kernel: Initialize threading and process management earlier
This re-arranges the order of how things are initialized so that we try to initialize process and thread management earlier. This is neccessary because a lot of the code uses the Lock class, which really needs to have a running scheduler in place so that we can properly preempt. This also enables us to potentially initialize some things in parallel.
This commit is contained in:
parent
c2792212f4
commit
6938be00f1
4 changed files with 45 additions and 33 deletions
|
@ -133,8 +133,10 @@ void Process::register_new(Process& process)
|
||||||
{
|
{
|
||||||
// Note: this is essentially the same like process->ref()
|
// Note: this is essentially the same like process->ref()
|
||||||
RefPtr<Process> new_process = process;
|
RefPtr<Process> new_process = process;
|
||||||
ScopedSpinLock lock(g_processes_lock);
|
{
|
||||||
g_processes->prepend(process);
|
ScopedSpinLock lock(g_processes_lock);
|
||||||
|
g_processes->prepend(process);
|
||||||
|
}
|
||||||
ProcFSComponentRegistry::the().register_new_process(process);
|
ProcFSComponentRegistry::the().register_new_process(process);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +182,7 @@ RefPtr<Process> Process::create_user_process(RefPtr<Thread>& first_thread, const
|
||||||
return process;
|
return process;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<Process> Process::create_kernel_process(RefPtr<Thread>& first_thread, String&& name, void (*entry)(void*), void* entry_data, u32 affinity)
|
RefPtr<Process> Process::create_kernel_process(RefPtr<Thread>& first_thread, String&& name, void (*entry)(void*), void* entry_data, u32 affinity, RegisterProcess do_register)
|
||||||
{
|
{
|
||||||
auto process = Process::create(first_thread, move(name), (uid_t)0, (gid_t)0, ProcessID(0), true);
|
auto process = Process::create(first_thread, move(name), (uid_t)0, (gid_t)0, ProcessID(0), true);
|
||||||
if (!first_thread || !process)
|
if (!first_thread || !process)
|
||||||
|
@ -193,9 +195,8 @@ RefPtr<Process> Process::create_kernel_process(RefPtr<Thread>& first_thread, Str
|
||||||
first_thread->regs().rdi = FlatPtr(entry_data); // entry function argument is expected to be in regs.rdi
|
first_thread->regs().rdi = FlatPtr(entry_data); // entry function argument is expected to be in regs.rdi
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (process->pid() != 0) {
|
if (do_register == RegisterProcess::Yes)
|
||||||
register_new(*process);
|
register_new(*process);
|
||||||
}
|
|
||||||
|
|
||||||
ScopedSpinLock lock(g_scheduler_lock);
|
ScopedSpinLock lock(g_scheduler_lock);
|
||||||
first_thread->set_affinity(affinity);
|
first_thread->set_affinity(affinity);
|
||||||
|
|
|
@ -163,14 +163,19 @@ public:
|
||||||
delete func;
|
delete func;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class RegisterProcess {
|
||||||
|
No,
|
||||||
|
Yes
|
||||||
|
};
|
||||||
|
|
||||||
template<typename EntryFunction>
|
template<typename EntryFunction>
|
||||||
static RefPtr<Process> create_kernel_process(RefPtr<Thread>& first_thread, String&& name, EntryFunction entry, u32 affinity = THREAD_AFFINITY_DEFAULT)
|
static RefPtr<Process> create_kernel_process(RefPtr<Thread>& first_thread, String&& name, EntryFunction entry, u32 affinity = THREAD_AFFINITY_DEFAULT, RegisterProcess do_register = RegisterProcess::Yes)
|
||||||
{
|
{
|
||||||
auto* entry_func = new EntryFunction(move(entry));
|
auto* entry_func = new EntryFunction(move(entry));
|
||||||
return create_kernel_process(first_thread, move(name), &Process::kernel_process_trampoline<EntryFunction>, entry_func, affinity);
|
return create_kernel_process(first_thread, move(name), &Process::kernel_process_trampoline<EntryFunction>, entry_func, affinity, do_register);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RefPtr<Process> create_kernel_process(RefPtr<Thread>& first_thread, String&& name, void (*entry)(void*), void* entry_data = nullptr, u32 affinity = THREAD_AFFINITY_DEFAULT);
|
static RefPtr<Process> create_kernel_process(RefPtr<Thread>& first_thread, String&& name, void (*entry)(void*), void* entry_data = nullptr, u32 affinity = THREAD_AFFINITY_DEFAULT, RegisterProcess do_register = RegisterProcess::Yes);
|
||||||
static RefPtr<Process> create_user_process(RefPtr<Thread>& first_thread, const String& path, uid_t, gid_t, ProcessID ppid, int& error, Vector<String>&& arguments = Vector<String>(), Vector<String>&& environment = Vector<String>(), TTY* = nullptr);
|
static RefPtr<Process> create_user_process(RefPtr<Thread>& first_thread, const String& path, uid_t, gid_t, ProcessID ppid, int& error, Vector<String>&& arguments = Vector<String>(), Vector<String>&& environment = Vector<String>(), TTY* = nullptr);
|
||||||
static void register_new(Process&);
|
static void register_new(Process&);
|
||||||
~Process();
|
~Process();
|
||||||
|
|
|
@ -404,7 +404,7 @@ UNMAP_AFTER_INIT void Scheduler::initialize()
|
||||||
g_ready_queues = new ThreadReadyQueue[g_ready_queue_buckets];
|
g_ready_queues = new ThreadReadyQueue[g_ready_queue_buckets];
|
||||||
|
|
||||||
g_finalizer_has_work.store(false, AK::MemoryOrder::memory_order_release);
|
g_finalizer_has_work.store(false, AK::MemoryOrder::memory_order_release);
|
||||||
s_colonel_process = Process::create_kernel_process(idle_thread, "colonel", idle_loop, nullptr, 1).leak_ref();
|
s_colonel_process = Process::create_kernel_process(idle_thread, "colonel", idle_loop, nullptr, 1, Process::RegisterProcess::No).leak_ref();
|
||||||
VERIFY(s_colonel_process);
|
VERIFY(s_colonel_process);
|
||||||
VERIFY(idle_thread);
|
VERIFY(idle_thread);
|
||||||
idle_thread->set_priority(THREAD_PRIORITY_MIN);
|
idle_thread->set_priority(THREAD_PRIORITY_MIN);
|
||||||
|
|
|
@ -142,39 +142,21 @@ extern "C" [[noreturn]] UNMAP_AFTER_INIT void init()
|
||||||
InterruptManagement::initialize();
|
InterruptManagement::initialize();
|
||||||
ACPI::initialize();
|
ACPI::initialize();
|
||||||
|
|
||||||
// Initialize the PCI Bus as early as possible, for early boot (PCI based) serial logging
|
__stack_chk_guard = get_fast_random<u32>();
|
||||||
SysFSComponentRegistry::initialize();
|
|
||||||
ProcFSComponentRegistry::initialize();
|
ProcFSComponentRegistry::initialize();
|
||||||
PCI::initialize();
|
Thread::initialize();
|
||||||
PCISerialDevice::detect();
|
Process::initialize();
|
||||||
|
|
||||||
VirtualFileSystem::initialize();
|
|
||||||
|
|
||||||
dmesgln("Starting SerenityOS...");
|
|
||||||
|
|
||||||
TimeManagement::initialize(0);
|
TimeManagement::initialize(0);
|
||||||
|
|
||||||
__stack_chk_guard = get_fast_random<u32>();
|
|
||||||
|
|
||||||
NullDevice::initialize();
|
|
||||||
if (!get_serial_debug())
|
|
||||||
(void)SerialDevice::must_create(0).leak_ref();
|
|
||||||
(void)SerialDevice::must_create(1).leak_ref();
|
|
||||||
(void)SerialDevice::must_create(2).leak_ref();
|
|
||||||
(void)SerialDevice::must_create(3).leak_ref();
|
|
||||||
|
|
||||||
VMWareBackdoor::the(); // don't wait until first mouse packet
|
|
||||||
HIDManagement::initialize();
|
|
||||||
|
|
||||||
Thread::initialize();
|
|
||||||
Process::initialize();
|
|
||||||
Scheduler::initialize();
|
Scheduler::initialize();
|
||||||
|
|
||||||
WorkQueue::initialize();
|
dmesgln("Starting SerenityOS...");
|
||||||
|
|
||||||
{
|
{
|
||||||
RefPtr<Thread> init_stage2_thread;
|
RefPtr<Thread> init_stage2_thread;
|
||||||
Process::create_kernel_process(init_stage2_thread, "init_stage2", init_stage2, nullptr);
|
Process::create_kernel_process(init_stage2_thread, "init_stage2", init_stage2, nullptr, THREAD_AFFINITY_DEFAULT, Process::RegisterProcess::No);
|
||||||
// We need to make sure we drop the reference for init_stage2_thread
|
// We need to make sure we drop the reference for init_stage2_thread
|
||||||
// before calling into Scheduler::start, otherwise we will have a
|
// before calling into Scheduler::start, otherwise we will have a
|
||||||
// dangling Thread that never gets cleaned up
|
// dangling Thread that never gets cleaned up
|
||||||
|
@ -218,6 +200,13 @@ extern "C" UNMAP_AFTER_INIT void init_finished(u32 cpu)
|
||||||
|
|
||||||
void init_stage2(void*)
|
void init_stage2(void*)
|
||||||
{
|
{
|
||||||
|
// This is a little bit of a hack. We can't register our process at the time we're
|
||||||
|
// creating it, but we need to be registered otherwise finalization won't be happy.
|
||||||
|
// The colonel process gets away without having to do this because it never exits.
|
||||||
|
Process::register_new(*Process::current());
|
||||||
|
|
||||||
|
WorkQueue::initialize();
|
||||||
|
|
||||||
if (APIC::initialized() && APIC::the().enabled_processor_count() > 1) {
|
if (APIC::initialized() && APIC::the().enabled_processor_count() > 1) {
|
||||||
// We can't start the APs until we have a scheduler up and running.
|
// We can't start the APs until we have a scheduler up and running.
|
||||||
// We need to be able to process ICI messages, otherwise another
|
// We need to be able to process ICI messages, otherwise another
|
||||||
|
@ -226,6 +215,23 @@ void init_stage2(void*)
|
||||||
APIC::the().boot_aps();
|
APIC::the().boot_aps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize the PCI Bus as early as possible, for early boot (PCI based) serial logging
|
||||||
|
SysFSComponentRegistry::initialize();
|
||||||
|
PCI::initialize();
|
||||||
|
PCISerialDevice::detect();
|
||||||
|
|
||||||
|
VirtualFileSystem::initialize();
|
||||||
|
|
||||||
|
NullDevice::initialize();
|
||||||
|
if (!get_serial_debug())
|
||||||
|
(void)SerialDevice::must_create(0).leak_ref();
|
||||||
|
(void)SerialDevice::must_create(1).leak_ref();
|
||||||
|
(void)SerialDevice::must_create(2).leak_ref();
|
||||||
|
(void)SerialDevice::must_create(3).leak_ref();
|
||||||
|
|
||||||
|
VMWareBackdoor::the(); // don't wait until first mouse packet
|
||||||
|
HIDManagement::initialize();
|
||||||
|
|
||||||
GraphicsManagement::the().initialize();
|
GraphicsManagement::the().initialize();
|
||||||
ConsoleManagement::the().initialize();
|
ConsoleManagement::the().initialize();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue