diff options
-rw-r--r-- | sys/include/sys/proc.h | 5 | ||||
-rw-r--r-- | sys/kern/kern_exit.c | 78 | ||||
-rw-r--r-- | sys/kern/kern_sched.c | 26 |
3 files changed, 104 insertions, 5 deletions
diff --git a/sys/include/sys/proc.h b/sys/include/sys/proc.h index 684742a..5303072 100644 --- a/sys/include/sys/proc.h +++ b/sys/include/sys/proc.h @@ -33,6 +33,7 @@ #include <sys/types.h> #include <sys/spinlock.h> #include <sys/queue.h> +#include <sys/param.h> #if defined(_KERNEL) #include <machine/frame.h> #include <machine/pcb.h> @@ -47,13 +48,17 @@ struct proc { struct trapframe tf; struct pcb pcb; size_t priority; + uint32_t flags; uintptr_t stack_base; TAILQ_ENTRY(proc) link; }; +#define PROC_EXITING BIT(0) /* Exiting */ + struct proc *this_td(void); int md_fork(struct proc *p, struct proc *parent, uintptr_t ip); int fork1(struct proc *cur, int flags, void(*ip)(void), struct proc **newprocp); +int exit1(struct proc *td); #endif /* _KERNEL */ #endif /* !_SYS_PROC_H_ */ diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c new file mode 100644 index 0000000..9995f51 --- /dev/null +++ b/sys/kern/kern_exit.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/proc.h> +#include <sys/sched.h> +#include <vm/physmem.h> +#include <vm/dynalloc.h> +#include <vm/vm.h> + +/* + * Kill a thread and deallocate its resources. + * + * @td: Thread to exit + */ +int +exit1(struct proc *td) +{ + struct pcb *pcbp; + struct proc *curtd; + uintptr_t stack; + pid_t target_pid, curpid; + + target_pid = td->pid; + curtd = this_td(); + pcbp = &td->pcb; + + curpid = curtd->pid; + stack = td->stack_base; + td->flags |= PROC_EXITING; + + /* + * If this is on the higher half, it is kernel + * mapped and we need to convert it to a physical + * address. + */ + if (stack >= VM_HIGHER_HALF) { + stack -= VM_HIGHER_HALF; + } + + vm_free_frame(stack, PROC_STACK_PAGES); + pmap_destroy_vas(pcbp->addrsp); + dynfree(td); + + /* + * If we are the thread exiting, reenter the scheduler + * and do not return. + */ + if (target_pid == curpid) + sched_enter(); + + return 0; +} diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c index f1bd067..9df541e 100644 --- a/sys/kern/kern_sched.c +++ b/sys/kern/kern_sched.c @@ -31,6 +31,7 @@ #include <sys/sched.h> #include <sys/schedvar.h> #include <sys/cdefs.h> +#include <sys/param.h> #include <sys/syslog.h> #include <machine/frame.h> #include <machine/cpu.h> @@ -130,15 +131,30 @@ sched_switch(struct trapframe *tf) struct cpu_info *ci; struct pcb *pcbp; struct proc *next_td, *td; + bool use_current = true; + bool inexec; ci = this_cpu(); td = ci->curtd; - /* Do we have threads to switch to? */ - if ((next_td = sched_dequeue_td()) == NULL) { - sched_oneshot(false); - return; - } + /* + * Get the next thread and use it only if it isn't + * in the middle of an exit, exec, or whatever. + */ + do { + if ((next_td = sched_dequeue_td()) == NULL) { + sched_oneshot(false); + return; + } + + /* + * Don't use this thread if we are currently + * exiting. + */ + if (ISSET(next_td->flags, PROC_EXITING)) { + use_current = false; + } + } while (!use_current); /* Re-enqueue the old thread */ if (td != NULL) { |