summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/include/sys/sched.h1
-rw-r--r--sys/kern/kern_sched.c44
2 files changed, 45 insertions, 0 deletions
diff --git a/sys/include/sys/sched.h b/sys/include/sys/sched.h
index d803df0..f06c104 100644
--- a/sys/include/sys/sched.h
+++ b/sys/include/sys/sched.h
@@ -38,6 +38,7 @@
#include <machine/frame.h>
void sched_init(void);
+void sched_exit(void);
void sched_context_switch(struct trapframe *tf);
__noreturn
diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c
index f985f62..c3d1e09 100644
--- a/sys/kern/kern_sched.c
+++ b/sys/kern/kern_sched.c
@@ -280,6 +280,50 @@ sched_create_td(uintptr_t rip, char *argvp[], char *envp[], struct auxval auxv,
return td;
}
+static void
+sched_destroy_td(struct proc *td)
+{
+ processor_free_pcb(td);
+
+ /*
+ * User stacks are allocated with vm_alloc_pageframe(),
+ * while kernel stacks are allocated with dynalloc().
+ * We want to check if we are a user program or kernel
+ * program to perform the proper deallocation method.
+ */
+ if (td->is_user) {
+ vm_free_pageframe(td->stack_base, STACK_PAGES);
+ } else {
+ dynfree((void *)td->stack_base);
+ }
+
+ pmap_free_vas(vm_get_ctx(), td->addrsp);
+ dynfree(td);
+}
+
+void
+sched_exit(void)
+{
+ struct sched_state *state;
+ struct cpu_info *ci;
+ struct proc *td;
+ struct vas kvas = vm_get_kvas();
+
+ intr_mask();
+
+ /* Get the thread running on the current processor */
+ ci = this_cpu();
+ state = &ci->sched_state;
+ td = state->td;
+
+ /* Switch back to the kernel address space and destroy ourself */
+ pmap_switch_vas(vm_get_ctx(), kvas);
+ sched_destroy_td(td);
+
+ intr_unmask();
+ sched_enter();
+}
+
/*
* Thread context switch routine
*/