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();
|
CPU::disable_interrupts();
|
||||||
dump_heap_usage();
|
dump_heap_usage();
|
||||||
kdbgln("Kernel uses %lu vm pages", KernelVM::used() / ARCH_PAGE_SIZE);
|
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()
|
Result<void> init()
|
||||||
@ -67,6 +96,7 @@ Result<void> init()
|
|||||||
|
|
||||||
TRY(Scheduler::new_kernel_thread(async_thread));
|
TRY(Scheduler::new_kernel_thread(async_thread));
|
||||||
TRY(Scheduler::new_kernel_thread(heap_thread));
|
TRY(Scheduler::new_kernel_thread(heap_thread));
|
||||||
|
TRY(Scheduler::new_kernel_thread(reap_thread));
|
||||||
|
|
||||||
CPU::platform_finish_init();
|
CPU::platform_finish_init();
|
||||||
|
|
||||||
|
@ -167,6 +167,32 @@ namespace Scheduler
|
|||||||
|
|
||||||
if (!g_current->ticks_left) switch_task(regs);
|
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)
|
void kernel_sleep(u64 ms)
|
||||||
@ -174,4 +200,11 @@ void kernel_sleep(u64 ms)
|
|||||||
g_current->sleep_ticks_left = ms;
|
g_current->sleep_ticks_left = ms;
|
||||||
g_current->state = ThreadState::Sleeping;
|
g_current->state = ThreadState::Sleeping;
|
||||||
kernel_yield();
|
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 switch_task(Registers* regs);
|
||||||
|
|
||||||
void invoke(Registers* regs);
|
void invoke(Registers* regs);
|
||||||
|
|
||||||
|
DoublyLinkedList<Thread> check_for_dying_threads();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void kernel_yield();
|
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,
|
Idle,
|
||||||
Runnable,
|
Runnable,
|
||||||
Sleeping
|
Sleeping,
|
||||||
|
Dying
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Thread : public DoublyLinkedListNode<Thread>
|
struct Thread : public DoublyLinkedListNode<Thread>
|
||||||
|
Loading…
Reference in New Issue
Block a user