Scheduler: Make it possible for a thread to stop existing
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
1b92fe36b4
commit
751377de0a
@ -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();
|
||||
|
||||
|
@ -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)
|
||||
@ -174,4 +200,11 @@ void kernel_sleep(u64 ms)
|
||||
g_current->sleep_ticks_left = ms;
|
||||
g_current->state = ThreadState::Sleeping;
|
||||
kernel_yield();
|
||||
}
|
||||
|
||||
[[noreturn]] void kernel_exit()
|
||||
{
|
||||
g_current->state = ThreadState::Dying;
|
||||
kernel_yield();
|
||||
unreachable();
|
||||
}
|
@ -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);
|
||||
void kernel_sleep(u64 ms);
|
||||
[[noreturn]] void kernel_exit();
|
@ -14,7 +14,8 @@ enum class ThreadState
|
||||
{
|
||||
Idle,
|
||||
Runnable,
|
||||
Sleeping
|
||||
Sleeping,
|
||||
Dying
|
||||
};
|
||||
|
||||
struct Thread : public DoublyLinkedListNode<Thread>
|
||||
|
Loading…
Reference in New Issue
Block a user