summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/include/sys/proc.h5
-rw-r--r--sys/kern/kern_exit.c78
-rw-r--r--sys/kern/kern_sched.c26
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) {