Scheduler: Make it possible for a thread to stop existing
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
apio 2022-12-18 18:43:34 +01:00
parent 1b92fe36b4
commit 751377de0a
Signed by: apio
GPG Key ID: B8A7D06E42258954
4 changed files with 70 additions and 3 deletions

View File

@ -35,7 +35,36 @@ void heap_thread()
CPU::disable_interrupts();
dump_heap_usage();
kdbgln("Kernel uses %lu vm pages", KernelVM::used() / ARCH_PAGE_SIZE);
while (true) kernel_sleep(UINT64_MAX);
kernel_exit();
}
void reap_thread()
{
while (true)
{
CPU::disable_interrupts();
auto dying_threads = Scheduler::check_for_dying_threads();
CPU::enable_interrupts();
if (dying_threads.count())
{
Thread* thread_to_reap = dying_threads.expect_first();
Thread* next_thread = thread_to_reap;
while (thread_to_reap)
{
next_thread = dying_threads.next(thread_to_reap).value_or(nullptr);
kinfoln("reap: reaping thread with id %zu", thread_to_reap->id);
auto stack = thread_to_reap->stack;
kinfoln("deleting thread stack @ %#lx, has %zu bytes of stack", stack.bottom(), stack.bytes());
MemoryManager::unmap_owned_and_free_vm(stack.bottom(), stack.bytes() / ARCH_PAGE_SIZE).release_value();
delete thread_to_reap;
thread_to_reap = next_thread;
}
}
kernel_sleep(250);
}
}
Result<void> init()
@ -67,6 +96,7 @@ Result<void> init()
TRY(Scheduler::new_kernel_thread(async_thread));
TRY(Scheduler::new_kernel_thread(heap_thread));
TRY(Scheduler::new_kernel_thread(reap_thread));
CPU::platform_finish_init();

View File

@ -167,6 +167,32 @@ namespace Scheduler
if (!g_current->ticks_left) switch_task(regs);
}
DoublyLinkedList<Thread> check_for_dying_threads()
{
DoublyLinkedList<Thread> result;
Thread* thread_to_remove = nullptr;
g_threads.for_each([&](Thread* thread) {
if (thread_to_remove)
{
g_threads.remove(thread_to_remove);
result.append(thread_to_remove);
}
if (thread->state == ThreadState::Dying) { thread_to_remove = thread; }
else { thread_to_remove = nullptr; }
});
if (thread_to_remove)
{
g_threads.remove(thread_to_remove);
result.append(thread_to_remove);
}
return result;
}
}
void kernel_sleep(u64 ms)
@ -175,3 +201,10 @@ void kernel_sleep(u64 ms)
g_current->state = ThreadState::Sleeping;
kernel_yield();
}
[[noreturn]] void kernel_exit()
{
g_current->state = ThreadState::Dying;
kernel_yield();
unreachable();
}

View File

@ -17,7 +17,10 @@ namespace Scheduler
void switch_task(Registers* regs);
void invoke(Registers* regs);
DoublyLinkedList<Thread> check_for_dying_threads();
}
extern "C" void kernel_yield();
void kernel_sleep(u64 ms);
[[noreturn]] void kernel_exit();

View File

@ -14,7 +14,8 @@ enum class ThreadState
{
Idle,
Runnable,
Sleeping
Sleeping,
Dying
};
struct Thread : public DoublyLinkedListNode<Thread>