2022-12-07 15:03:34 +01:00
|
|
|
#include "thread/Scheduler.h"
|
|
|
|
#include "Log.h"
|
|
|
|
#include "arch/CPU.h"
|
|
|
|
#include "arch/MMU.h"
|
2023-07-30 18:25:44 +02:00
|
|
|
#include "binfmt/ELF.h"
|
2022-12-07 15:03:34 +01:00
|
|
|
#include "memory/MemoryManager.h"
|
2023-03-16 22:44:58 +01:00
|
|
|
#include "thread/ThreadImage.h"
|
2023-01-11 23:01:47 +01:00
|
|
|
#include <luna/Alignment.h>
|
2022-12-08 14:56:11 +01:00
|
|
|
#include <luna/ScopeGuard.h>
|
2022-12-07 15:03:34 +01:00
|
|
|
#include <luna/Stack.h>
|
|
|
|
|
|
|
|
static Thread g_idle;
|
|
|
|
static Thread* g_current = nullptr;
|
2023-05-04 22:58:04 +02:00
|
|
|
static Thread* g_init = nullptr;
|
2023-05-04 23:06:00 +02:00
|
|
|
static Thread* g_reap = nullptr;
|
2023-08-17 20:14:33 +02:00
|
|
|
static Thread* g_oom = nullptr;
|
2022-12-07 15:03:34 +01:00
|
|
|
|
|
|
|
static const usize TICKS_PER_TIMESLICE = 20;
|
|
|
|
|
|
|
|
namespace Scheduler
|
|
|
|
{
|
|
|
|
void init()
|
|
|
|
{
|
|
|
|
g_idle.id = 0;
|
|
|
|
g_idle.init_regs_kernel();
|
|
|
|
g_idle.set_ip((u64)CPU::idle_loop);
|
2022-12-07 15:14:58 +01:00
|
|
|
g_idle.state = ThreadState::Idle;
|
2023-01-05 21:52:26 +01:00
|
|
|
g_idle.is_kernel = true;
|
2023-05-04 22:58:04 +02:00
|
|
|
g_idle.parent = nullptr;
|
2023-09-04 11:43:11 +02:00
|
|
|
g_idle.cmdline = "[idle]";
|
2023-07-10 13:04:18 +02:00
|
|
|
g_idle.active_directory = nullptr;
|
2022-12-07 15:03:34 +01:00
|
|
|
|
|
|
|
g_idle.ticks_left = 1;
|
|
|
|
|
|
|
|
// Map some stack for the idle task
|
2023-06-17 19:43:25 +02:00
|
|
|
u64 idle_stack_vm = mark_critical(MemoryManager::alloc_for_kernel(1, MMU::NoExecute | MMU::ReadWrite),
|
|
|
|
"Failed to allocate stack memory for the CPU idle thread");
|
2022-12-07 15:03:34 +01:00
|
|
|
|
2022-12-21 20:22:44 +01:00
|
|
|
Stack idle_stack { idle_stack_vm, ARCH_PAGE_SIZE };
|
2022-12-07 15:03:34 +01:00
|
|
|
g_idle.set_sp(idle_stack.top());
|
|
|
|
|
2022-12-18 18:43:17 +01:00
|
|
|
g_idle.stack = idle_stack;
|
|
|
|
|
2023-07-26 21:32:00 +02:00
|
|
|
kinfoln("Created idle thread: id %d with ip %#lx and sp %#lx", g_idle.id, g_idle.ip(), g_idle.sp());
|
2022-12-07 15:03:34 +01:00
|
|
|
|
|
|
|
g_current = &g_idle;
|
|
|
|
}
|
|
|
|
|
|
|
|
Thread* current()
|
|
|
|
{
|
|
|
|
return g_current;
|
|
|
|
}
|
|
|
|
|
2022-12-07 15:55:58 +01:00
|
|
|
Thread* idle()
|
|
|
|
{
|
|
|
|
return &g_idle;
|
|
|
|
}
|
|
|
|
|
2023-05-04 22:58:04 +02:00
|
|
|
Thread* init_thread()
|
|
|
|
{
|
|
|
|
return g_init;
|
|
|
|
}
|
|
|
|
|
2023-05-04 23:06:00 +02:00
|
|
|
void set_reap_thread(Thread* thread)
|
|
|
|
{
|
|
|
|
g_reap = thread;
|
|
|
|
}
|
|
|
|
|
|
|
|
void signal_reap_thread()
|
|
|
|
{
|
2023-05-04 23:35:54 +02:00
|
|
|
if (g_reap) g_reap->wake_up();
|
2023-05-04 23:06:00 +02:00
|
|
|
}
|
|
|
|
|
2023-08-17 20:14:33 +02:00
|
|
|
void set_oom_thread(Thread* thread)
|
|
|
|
{
|
|
|
|
g_oom = thread;
|
|
|
|
g_oom->unrestricted_task = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void signal_oom_thread()
|
|
|
|
{
|
|
|
|
if (g_oom) g_oom->wake_up();
|
|
|
|
}
|
|
|
|
|
2023-05-04 23:06:00 +02:00
|
|
|
Result<Thread*> new_kernel_thread_impl(Thread* thread, const char* name)
|
2022-12-07 15:03:34 +01:00
|
|
|
{
|
2022-12-08 14:56:11 +01:00
|
|
|
// If anything fails, make sure to clean up.
|
2022-12-16 19:36:38 +01:00
|
|
|
auto guard = make_scope_guard([&] { delete thread; });
|
2022-12-08 14:56:11 +01:00
|
|
|
|
2023-01-10 19:31:41 +01:00
|
|
|
const u64 thread_stack_vm = TRY(MemoryManager::alloc_for_kernel(4, MMU::NoExecute | MMU::ReadWrite));
|
2022-12-08 14:56:11 +01:00
|
|
|
|
2022-12-16 19:36:38 +01:00
|
|
|
guard.deactivate();
|
2022-12-08 14:56:11 +01:00
|
|
|
|
2023-01-10 19:31:41 +01:00
|
|
|
const Stack thread_stack { thread_stack_vm, ARCH_PAGE_SIZE * 4 };
|
2022-12-07 15:03:34 +01:00
|
|
|
thread->set_sp(thread_stack.top());
|
|
|
|
|
2022-12-18 18:43:17 +01:00
|
|
|
thread->stack = thread_stack;
|
|
|
|
|
2023-09-04 11:43:11 +02:00
|
|
|
thread->cmdline = name;
|
2023-03-24 21:05:38 +01:00
|
|
|
|
2023-01-05 21:52:26 +01:00
|
|
|
thread->is_kernel = true;
|
2023-07-10 13:04:00 +02:00
|
|
|
thread->active_directory = MMU::kernel_page_directory();
|
2023-01-05 21:52:26 +01:00
|
|
|
|
2023-04-08 13:12:49 +02:00
|
|
|
thread->auth = Credentials { .uid = 0, .euid = 0, .suid = 0, .gid = 0, .egid = 0, .sgid = 0 };
|
|
|
|
|
2022-12-07 15:03:34 +01:00
|
|
|
g_threads.append(thread);
|
|
|
|
|
2023-04-28 13:23:07 +02:00
|
|
|
thread->state = ThreadState::Runnable;
|
|
|
|
|
2023-07-26 21:32:00 +02:00
|
|
|
kinfoln("Created kernel thread: id %d with ip %#lx and sp %#lx", thread->id, thread->ip(), thread->sp());
|
2022-12-07 15:03:34 +01:00
|
|
|
|
2023-05-04 23:06:00 +02:00
|
|
|
return thread;
|
2022-12-07 15:03:34 +01:00
|
|
|
}
|
|
|
|
|
2023-05-04 23:06:00 +02:00
|
|
|
Result<Thread*> new_kernel_thread(u64 address, const char* name)
|
2022-12-07 15:03:34 +01:00
|
|
|
{
|
2023-01-10 19:31:41 +01:00
|
|
|
Thread* const thread = TRY(new_thread());
|
2022-12-07 15:03:34 +01:00
|
|
|
thread->init_regs_kernel();
|
|
|
|
thread->set_ip(address);
|
|
|
|
|
2023-03-24 21:05:38 +01:00
|
|
|
return new_kernel_thread_impl(thread, name);
|
2022-12-07 15:03:34 +01:00
|
|
|
}
|
|
|
|
|
2023-05-04 23:06:00 +02:00
|
|
|
Result<Thread*> new_kernel_thread(void (*func)(void), const char* name)
|
2022-12-07 15:03:34 +01:00
|
|
|
{
|
2023-01-10 19:31:41 +01:00
|
|
|
Thread* const thread = TRY(new_thread());
|
2022-12-07 15:03:34 +01:00
|
|
|
thread->init_regs_kernel();
|
|
|
|
thread->set_ip((u64)func);
|
|
|
|
|
2023-03-24 21:05:38 +01:00
|
|
|
return new_kernel_thread_impl(thread, name);
|
2022-12-07 15:03:34 +01:00
|
|
|
}
|
|
|
|
|
2023-05-04 23:06:00 +02:00
|
|
|
Result<Thread*> new_kernel_thread(void (*func)(void*), void* arg, const char* name)
|
2022-12-07 15:03:34 +01:00
|
|
|
{
|
2023-01-10 19:31:41 +01:00
|
|
|
Thread* const thread = TRY(new_thread());
|
2022-12-07 15:03:34 +01:00
|
|
|
thread->init_regs_kernel();
|
|
|
|
thread->set_ip((u64)func);
|
|
|
|
thread->set_arguments((u64)arg, 0, 0, 0);
|
|
|
|
|
2023-03-24 21:05:38 +01:00
|
|
|
return new_kernel_thread_impl(thread, name);
|
2022-12-07 15:03:34 +01:00
|
|
|
}
|
2023-03-18 23:45:48 +01:00
|
|
|
|
2023-04-28 13:23:07 +02:00
|
|
|
Result<Thread*> new_userspace_thread(SharedPtr<VFS::Inode> inode, const char* name)
|
2023-01-05 21:52:26 +01:00
|
|
|
{
|
2023-04-28 13:23:07 +02:00
|
|
|
Thread* const thread = TRY(make<Thread>());
|
2023-01-05 21:52:26 +01:00
|
|
|
|
2023-04-28 13:23:07 +02:00
|
|
|
thread->state = ThreadState::None;
|
2023-01-05 21:52:26 +01:00
|
|
|
thread->is_kernel = false;
|
2023-04-28 13:23:07 +02:00
|
|
|
thread->id = 1;
|
2023-07-12 13:48:43 +02:00
|
|
|
thread->pgid = 1;
|
2023-09-04 11:43:11 +02:00
|
|
|
thread->cmdline = name;
|
2023-04-08 13:12:49 +02:00
|
|
|
thread->auth = Credentials { .uid = 0, .euid = 0, .suid = 0, .gid = 0, .egid = 0, .sgid = 0 };
|
2023-01-05 21:52:26 +01:00
|
|
|
|
2023-04-07 15:03:38 +02:00
|
|
|
Vector<String> args;
|
|
|
|
auto name_string = TRY(String::from_cstring(name));
|
|
|
|
TRY(args.try_append(move(name_string)));
|
|
|
|
|
|
|
|
Vector<String> env;
|
|
|
|
|
2023-01-05 21:52:26 +01:00
|
|
|
auto guard = make_scope_guard([&] { delete thread; });
|
|
|
|
|
2023-07-30 18:25:44 +02:00
|
|
|
// Contrary to other programs, which use BinaryFormat::create_loader(), init must be a native executable.
|
2023-07-31 20:41:18 +02:00
|
|
|
auto loader = TRY(ELFLoader::create(inode, nullptr, 0));
|
2023-07-30 18:25:44 +02:00
|
|
|
|
|
|
|
auto image = TRY(ThreadImage::try_load_from_binary(loader));
|
2023-04-07 15:03:38 +02:00
|
|
|
u64 argv = TRY(image->push_string_vector_on_stack(args));
|
|
|
|
u64 envp = TRY(image->push_string_vector_on_stack(env));
|
2023-01-05 21:52:26 +01:00
|
|
|
|
2023-08-17 20:14:33 +02:00
|
|
|
const u64 kernel_stack_base = TRY(MemoryManager::alloc_for_kernel(4, MMU::ReadWrite | MMU::NoExecute));
|
|
|
|
Stack kernel_stack { kernel_stack_base, 4 * ARCH_PAGE_SIZE };
|
|
|
|
|
2023-01-05 21:52:26 +01:00
|
|
|
guard.deactivate();
|
2023-03-16 22:44:58 +01:00
|
|
|
|
2023-08-17 20:14:33 +02:00
|
|
|
thread->kernel_stack = kernel_stack;
|
|
|
|
|
2023-03-16 22:44:58 +01:00
|
|
|
image->apply(thread);
|
2023-04-07 15:03:38 +02:00
|
|
|
thread->set_arguments(args.size(), argv, env.size(), envp);
|
2023-01-05 21:52:26 +01:00
|
|
|
|
2023-07-10 19:46:57 +02:00
|
|
|
for (int i = 0; i < NSIG; i++)
|
|
|
|
{
|
|
|
|
thread->signal_handlers[i] = { .sa_handler = SIG_DFL, .sa_mask = 0, .sa_flags = 0 };
|
|
|
|
}
|
|
|
|
|
2023-07-26 21:32:00 +02:00
|
|
|
kinfoln("Created userspace thread: id %d with ip %#.16lx and sp %#.16lx (ksp %#lx)", thread->id, thread->ip(),
|
2023-01-05 21:52:26 +01:00
|
|
|
thread->sp(), thread->kernel_stack.top());
|
|
|
|
|
|
|
|
g_threads.append(thread);
|
2023-05-04 22:58:04 +02:00
|
|
|
g_init = thread;
|
2023-01-05 21:52:26 +01:00
|
|
|
|
2023-04-28 13:23:07 +02:00
|
|
|
return thread;
|
2023-01-05 21:52:26 +01:00
|
|
|
}
|
|
|
|
|
2023-03-18 23:45:48 +01:00
|
|
|
void add_thread(Thread* thread)
|
|
|
|
{
|
|
|
|
g_threads.append(thread);
|
|
|
|
}
|
|
|
|
|
2022-12-19 12:24:15 +01:00
|
|
|
void reap_thread(Thread* thread)
|
|
|
|
{
|
2023-03-18 23:45:48 +01:00
|
|
|
CPU::disable_interrupts();
|
|
|
|
|
2023-06-18 20:18:00 +02:00
|
|
|
#ifdef REAP_DEBUG
|
2023-08-16 09:03:25 +02:00
|
|
|
kdbgln("reap: reaping thread with id %d", thread->id);
|
2023-06-18 20:18:00 +02:00
|
|
|
#endif
|
2023-01-05 21:52:26 +01:00
|
|
|
|
|
|
|
if (thread->is_kernel)
|
|
|
|
{
|
|
|
|
auto stack = thread->stack;
|
|
|
|
MemoryManager::unmap_owned_and_free_vm(stack.bottom(), stack.bytes() / ARCH_PAGE_SIZE).release_value();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
auto stack = thread->kernel_stack;
|
|
|
|
MemoryManager::unmap_owned_and_free_vm(stack.bottom(), stack.bytes() / ARCH_PAGE_SIZE).release_value();
|
|
|
|
}
|
|
|
|
|
2022-12-19 12:24:15 +01:00
|
|
|
delete thread;
|
2023-03-18 23:45:48 +01:00
|
|
|
|
|
|
|
CPU::enable_interrupts();
|
2022-12-19 12:24:15 +01:00
|
|
|
}
|
|
|
|
|
2022-12-07 15:03:34 +01:00
|
|
|
Thread* pick_task()
|
|
|
|
{
|
|
|
|
Thread* old = g_current;
|
2022-12-07 15:14:58 +01:00
|
|
|
if (old->is_idle())
|
2022-12-07 15:03:34 +01:00
|
|
|
{
|
2022-12-07 15:17:20 +01:00
|
|
|
auto maybe_last = g_threads.last();
|
2022-12-08 16:09:04 +01:00
|
|
|
if (!maybe_last.has_value()) // No threads!!
|
2022-12-07 15:03:34 +01:00
|
|
|
return &g_idle;
|
2022-12-07 15:17:20 +01:00
|
|
|
g_current = old = maybe_last.value();
|
2022-12-07 15:03:34 +01:00
|
|
|
}
|
|
|
|
|
2022-12-07 15:17:20 +01:00
|
|
|
bool has_found_thread = false;
|
|
|
|
|
2022-12-07 15:03:34 +01:00
|
|
|
do {
|
|
|
|
auto maybe_next = g_threads.next(g_current);
|
2022-12-08 16:09:04 +01:00
|
|
|
if (!maybe_next.has_value()) g_current = g_threads.expect_first();
|
2022-12-07 15:03:34 +01:00
|
|
|
else
|
|
|
|
g_current = maybe_next.value();
|
|
|
|
|
2022-12-07 15:17:20 +01:00
|
|
|
if (g_current->state == ThreadState::Runnable)
|
|
|
|
{
|
|
|
|
has_found_thread = true;
|
2022-12-07 15:03:34 +01:00
|
|
|
break;
|
2022-12-07 15:17:20 +01:00
|
|
|
}
|
2022-12-07 15:03:34 +01:00
|
|
|
} while (g_current != old);
|
|
|
|
|
2022-12-07 15:17:20 +01:00
|
|
|
if (!has_found_thread) g_current = &g_idle;
|
|
|
|
|
2022-12-07 15:03:34 +01:00
|
|
|
return g_current;
|
|
|
|
}
|
|
|
|
|
|
|
|
void generic_switch_context(Thread* old_thread, Thread* new_thread, Registers* regs)
|
|
|
|
{
|
2023-01-05 21:52:26 +01:00
|
|
|
if (old_thread != new_thread)
|
|
|
|
{
|
|
|
|
switch_context(old_thread, new_thread, regs);
|
2023-03-07 20:59:11 +01:00
|
|
|
if (!old_thread->is_kernel) old_thread->fp_data.save();
|
2023-07-10 13:04:18 +02:00
|
|
|
if (old_thread->state != ThreadState::Idle && MMU::get_page_directory() != MMU::kernel_page_directory())
|
2023-06-25 20:09:40 +02:00
|
|
|
old_thread->active_directory = MMU::get_page_directory();
|
|
|
|
if (new_thread->active_directory) MMU::switch_page_directory(new_thread->active_directory);
|
2023-01-05 21:52:26 +01:00
|
|
|
if (!new_thread->is_kernel)
|
|
|
|
{
|
|
|
|
CPU::switch_kernel_stack(new_thread->kernel_stack.top());
|
2023-03-07 20:59:11 +01:00
|
|
|
new_thread->fp_data.restore();
|
2023-01-05 21:52:26 +01:00
|
|
|
}
|
|
|
|
}
|
2022-12-07 15:03:34 +01:00
|
|
|
|
2022-12-07 15:14:58 +01:00
|
|
|
if (new_thread->is_idle())
|
2022-12-07 15:03:34 +01:00
|
|
|
{
|
|
|
|
new_thread->ticks_left = 1; // The idle task only runs for 1 tick so we can check for new runnable tasks
|
|
|
|
// as fast as possible.
|
|
|
|
}
|
2023-08-17 20:14:33 +02:00
|
|
|
else if (new_thread->unrestricted_task)
|
|
|
|
{
|
|
|
|
check(new_thread->is_kernel);
|
|
|
|
new_thread->ticks_left = -1;
|
|
|
|
}
|
|
|
|
else { new_thread->ticks_left = TICKS_PER_TIMESLICE; }
|
2022-12-07 15:03:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void switch_task(Registers* regs)
|
|
|
|
{
|
|
|
|
Thread* old_thread = g_current;
|
|
|
|
Thread* new_thread = pick_task();
|
|
|
|
generic_switch_context(old_thread, new_thread, regs);
|
2023-07-10 19:46:57 +02:00
|
|
|
if (!is_in_kernel(regs)) new_thread->process_pending_signals(regs);
|
2022-12-07 15:03:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void invoke(Registers* regs)
|
|
|
|
{
|
|
|
|
CPU::disable_interrupts();
|
|
|
|
|
2023-05-20 12:48:07 +02:00
|
|
|
if (is_in_kernel(regs)) g_current->kernel_ticks_self++;
|
2022-12-07 15:03:34 +01:00
|
|
|
else
|
2023-05-20 12:48:07 +02:00
|
|
|
g_current->user_ticks_self++;
|
2022-12-07 15:03:34 +01:00
|
|
|
|
|
|
|
g_current->ticks_left--;
|
|
|
|
|
2023-04-28 15:13:53 +02:00
|
|
|
for (auto* const thread : g_threads)
|
|
|
|
{
|
2022-12-07 15:55:58 +01:00
|
|
|
if (thread->state == ThreadState::Sleeping)
|
|
|
|
{
|
2023-06-08 19:57:38 +02:00
|
|
|
if (thread->sleep_ticks_left == 0 || --thread->sleep_ticks_left == 0) thread->wake_up();
|
2022-12-07 15:55:58 +01:00
|
|
|
}
|
2023-08-11 18:09:12 +02:00
|
|
|
|
|
|
|
if (thread->alarm_ticks_left && --thread->alarm_ticks_left == 0) thread->send_signal(SIGALRM);
|
2023-04-28 15:13:53 +02:00
|
|
|
}
|
2022-12-07 15:55:58 +01:00
|
|
|
|
2022-12-07 15:03:34 +01:00
|
|
|
if (!g_current->ticks_left) switch_task(regs);
|
|
|
|
}
|
2022-12-18 18:43:34 +01:00
|
|
|
|
2022-12-19 12:43:23 +01:00
|
|
|
LinkedList<Thread> check_for_dying_threads()
|
2022-12-18 18:43:34 +01:00
|
|
|
{
|
2022-12-19 12:43:23 +01:00
|
|
|
LinkedList<Thread> result;
|
2022-12-18 18:43:34 +01:00
|
|
|
|
2022-12-19 12:41:25 +01:00
|
|
|
g_threads.delayed_for_each([&](Thread* thread) {
|
|
|
|
if (thread->state == ThreadState::Dying)
|
2022-12-18 18:43:34 +01:00
|
|
|
{
|
2022-12-19 12:41:25 +01:00
|
|
|
g_threads.remove(thread);
|
|
|
|
result.append(thread);
|
2022-12-18 18:43:34 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2023-03-23 22:42:24 +01:00
|
|
|
|
|
|
|
Option<Thread*> find_by_pid(pid_t pid)
|
|
|
|
{
|
2023-04-28 15:13:53 +02:00
|
|
|
for (auto* const thread : g_threads)
|
|
|
|
{
|
2023-07-26 21:32:00 +02:00
|
|
|
if (thread->id == pid && thread->state != ThreadState::Dying) return thread;
|
2023-04-28 15:13:53 +02:00
|
|
|
}
|
2023-03-23 22:42:24 +01:00
|
|
|
|
2023-04-28 15:13:53 +02:00
|
|
|
return {};
|
2023-03-23 22:42:24 +01:00
|
|
|
}
|
2023-03-24 17:37:04 +01:00
|
|
|
|
2023-04-28 15:19:01 +02:00
|
|
|
bool has_children(Thread* thread)
|
2023-03-24 17:37:04 +01:00
|
|
|
{
|
|
|
|
bool result { false };
|
|
|
|
|
2023-04-28 15:19:01 +02:00
|
|
|
for_each_child(thread, [&](Thread*) {
|
2023-04-28 15:13:53 +02:00
|
|
|
result = true;
|
|
|
|
return false;
|
|
|
|
});
|
2023-03-24 17:37:04 +01:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2023-04-28 15:19:01 +02:00
|
|
|
Option<Thread*> find_exited_child(Thread* thread)
|
2023-03-24 17:37:04 +01:00
|
|
|
{
|
|
|
|
Option<Thread*> result;
|
|
|
|
|
2023-04-28 15:19:01 +02:00
|
|
|
for_each_child(thread, [&](Thread* child) {
|
2023-04-28 15:13:53 +02:00
|
|
|
if (!result.has_value() && child->state == ThreadState::Exited)
|
|
|
|
{
|
|
|
|
result = child;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
2023-03-24 17:37:04 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2023-05-04 23:32:48 +02:00
|
|
|
|
|
|
|
void dump_state()
|
|
|
|
{
|
|
|
|
CPU::disable_interrupts();
|
|
|
|
|
|
|
|
kdbgln("--- BEGIN SCHEDULER DUMP ---");
|
2023-07-26 21:32:00 +02:00
|
|
|
kdbgln("current at %p, id = %d", g_current, g_current->id);
|
2023-05-04 23:32:48 +02:00
|
|
|
|
|
|
|
for (const auto* thread : g_threads)
|
|
|
|
{
|
2023-07-26 21:32:00 +02:00
|
|
|
kdbgln("%p %c [%-20s] %4d, parent = (%-18p,%d), state = %d, ticks: (k:%04zu,u:%04zu), status = "
|
2023-05-04 23:32:48 +02:00
|
|
|
"%d, cwd = %s",
|
2023-09-04 11:43:11 +02:00
|
|
|
thread, thread->is_kernel ? 'k' : 'u', thread->cmdline.chars(), thread->id, thread->parent,
|
2023-05-20 12:48:07 +02:00
|
|
|
thread->parent ? thread->parent->id : 0, (int)thread->state, thread->kernel_ticks_self,
|
|
|
|
thread->user_ticks_self, thread->status,
|
2023-05-04 23:32:48 +02:00
|
|
|
thread->current_directory_path.is_empty() ? "/" : thread->current_directory_path.chars());
|
|
|
|
}
|
|
|
|
|
|
|
|
kdbgln("--- END SCHEDULER DUMP ---");
|
|
|
|
|
|
|
|
CPU::enable_interrupts();
|
|
|
|
}
|
2022-12-07 15:55:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void kernel_sleep(u64 ms)
|
|
|
|
{
|
|
|
|
g_current->sleep_ticks_left = ms;
|
|
|
|
g_current->state = ThreadState::Sleeping;
|
|
|
|
kernel_yield();
|
2022-12-18 18:43:34 +01:00
|
|
|
}
|
|
|
|
|
2023-05-04 23:03:31 +02:00
|
|
|
void kernel_wait(pid_t pid)
|
|
|
|
{
|
|
|
|
g_current->child_being_waited_for = pid;
|
|
|
|
g_current->state = ThreadState::Waiting;
|
|
|
|
kernel_yield();
|
|
|
|
}
|
|
|
|
|
2023-05-04 23:43:00 +02:00
|
|
|
void kernel_wait_for_event()
|
|
|
|
{
|
|
|
|
g_current->state = ThreadState::Waiting;
|
|
|
|
kernel_yield();
|
|
|
|
}
|
|
|
|
|
2022-12-18 18:43:34 +01:00
|
|
|
[[noreturn]] void kernel_exit()
|
|
|
|
{
|
|
|
|
g_current->state = ThreadState::Dying;
|
2023-05-04 23:06:00 +02:00
|
|
|
Scheduler::signal_reap_thread();
|
2022-12-18 18:43:34 +01:00
|
|
|
kernel_yield();
|
|
|
|
unreachable();
|
2023-01-02 13:07:29 +01:00
|
|
|
}
|