mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 23:18:21 +00:00
scheduler: handle userland thread exit
This commit is contained in:
@@ -1,6 +1,9 @@
|
|||||||
section .text
|
section .text
|
||||||
global arch_context_switch
|
global arch_context_switch
|
||||||
arch_context_switch:
|
arch_context_switch:
|
||||||
|
extern sched_userspacecheck
|
||||||
|
call sched_userspacecheck ; compiled with no_caller_saved_registers
|
||||||
|
|
||||||
; rdi is the pointer to the context struct
|
; rdi is the pointer to the context struct
|
||||||
mov rsp, rdi
|
mov rsp, rdi
|
||||||
|
|
||||||
|
|||||||
@@ -195,6 +195,11 @@ arch_syscall_entry:
|
|||||||
extern arch_syscall_log_return
|
extern arch_syscall_log_return
|
||||||
call arch_syscall_log_return ; compiled with __attribute__((no_caller_saved_registers))
|
call arch_syscall_log_return ; compiled with __attribute__((no_caller_saved_registers))
|
||||||
|
|
||||||
|
mov rdi, rsp
|
||||||
|
add rdi, 8 ; context pointer is after r9 argument
|
||||||
|
extern sched_userspacecheck
|
||||||
|
call sched_userspacecheck ; compiled with __attribute__((no_caller_saved_registers))
|
||||||
|
|
||||||
; restore context
|
; restore context
|
||||||
add rsp, 32 ; r9 argument, cr2, gs, and fs are not popped.
|
add rsp, 32 ; r9 argument, cr2, gs, and fs are not popped.
|
||||||
pop rbx
|
pop rbx
|
||||||
|
|||||||
@@ -98,5 +98,6 @@ void arch_context_saveandcall(void (*fn)(context_t *context), void *stack);
|
|||||||
asm("ldmxcsr (%%rax)" : : "a"(&(t)->extracontext.mxcsr));
|
asm("ldmxcsr (%%rax)" : : "a"(&(t)->extracontext.mxcsr));
|
||||||
|
|
||||||
#define ARCH_CONTEXT_INTSTATUS(x) ((x)->rflags & 0x200 ? true : false)
|
#define ARCH_CONTEXT_INTSTATUS(x) ((x)->rflags & 0x200 ? true : false)
|
||||||
|
#define ARCH_CONTEXT_ISUSER(x) ((x)->cs == 0x23)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -229,6 +229,47 @@ __attribute__((noreturn)) void sched_stopcurrentthread() {
|
|||||||
switchthread(next);
|
switchthread(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sched_procexit() {
|
||||||
|
proc_t *proc = _cpu()->thread->proc;
|
||||||
|
|
||||||
|
// close fds
|
||||||
|
for (int fd = 0; fd < proc->fdcount; ++fd)
|
||||||
|
fd_close(fd);
|
||||||
|
|
||||||
|
// zombify the proc
|
||||||
|
spinlock_acquire(&proc->lock);
|
||||||
|
|
||||||
|
VOP_RELEASE(proc->root);
|
||||||
|
VOP_RELEASE(proc->cwd);
|
||||||
|
|
||||||
|
proc->state = SCHED_PROC_STATE_ZOMBIE;
|
||||||
|
proc_t *lastchild = proc->child;
|
||||||
|
|
||||||
|
spinlock_acquire(&sched_initproc->lock);
|
||||||
|
|
||||||
|
bool haszombie = false;
|
||||||
|
|
||||||
|
while (lastchild && lastchild->sibling) {
|
||||||
|
if (lastchild->state == SCHED_PROC_STATE_ZOMBIE)
|
||||||
|
haszombie = true;
|
||||||
|
|
||||||
|
lastchild->parent = sched_initproc;
|
||||||
|
lastchild = lastchild->sibling;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastchild) {
|
||||||
|
lastchild->sibling = sched_initproc->child;
|
||||||
|
sched_initproc->child = proc->child;
|
||||||
|
}
|
||||||
|
|
||||||
|
spinlock_release(&sched_initproc->lock);
|
||||||
|
spinlock_release(&proc->lock);
|
||||||
|
|
||||||
|
semaphore_signal(&proc->parent->waitsem);
|
||||||
|
if (haszombie)
|
||||||
|
semaphore_signal(&sched_initproc->waitsem);
|
||||||
|
}
|
||||||
|
|
||||||
__attribute__((noreturn)) void sched_threadexit() {
|
__attribute__((noreturn)) void sched_threadexit() {
|
||||||
thread_t *thread = _cpu()->thread;
|
thread_t *thread = _cpu()->thread;
|
||||||
proc_t *proc = thread->proc;
|
proc_t *proc = thread->proc;
|
||||||
@@ -239,8 +280,13 @@ __attribute__((noreturn)) void sched_threadexit() {
|
|||||||
if (proc) {
|
if (proc) {
|
||||||
__atomic_fetch_sub(&proc->runningthreadcount, 1, __ATOMIC_SEQ_CST);
|
__atomic_fetch_sub(&proc->runningthreadcount, 1, __ATOMIC_SEQ_CST);
|
||||||
__assert(oldctx != &vmm_kernelctx);
|
__assert(oldctx != &vmm_kernelctx);
|
||||||
if (proc->runningthreadcount == 0)
|
if (proc->runningthreadcount == 0) {
|
||||||
|
if (thread->shouldexit)
|
||||||
|
proc->status = -1;
|
||||||
|
|
||||||
|
sched_procexit();
|
||||||
vmm_destroycontext(oldctx);
|
vmm_destroycontext(oldctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interrupt_set(false);
|
interrupt_set(false);
|
||||||
@@ -253,6 +299,18 @@ __attribute__((noreturn)) void sched_threadexit() {
|
|||||||
sched_stopcurrentthread();
|
sched_stopcurrentthread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// called right before going back to userspace in places like the syscall handler or arch_context_switch
|
||||||
|
__attribute__((no_caller_saved_registers)) void sched_userspacecheck(context_t *context) {
|
||||||
|
thread_t *thread = _cpu()->thread;
|
||||||
|
if (thread == NULL || ARCH_CONTEXT_ISUSER(context) == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (thread->shouldexit) {
|
||||||
|
interrupt_set(true);
|
||||||
|
sched_threadexit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void sched_stopotherthreads() {
|
void sched_stopotherthreads() {
|
||||||
thread_t *thread = _cpu()->thread;
|
thread_t *thread = _cpu()->thread;
|
||||||
proc_t *proc = thread->proc;
|
proc_t *proc = thread->proc;
|
||||||
|
|||||||
@@ -13,43 +13,7 @@ __attribute__((noreturn)) void syscall_exit(context_t *context, int status) {
|
|||||||
|
|
||||||
sched_stopotherthreads();
|
sched_stopotherthreads();
|
||||||
|
|
||||||
// close fds
|
|
||||||
for (int fd = 0; fd < proc->fdcount; ++fd)
|
|
||||||
fd_close(fd);
|
|
||||||
|
|
||||||
// zombify the proc
|
|
||||||
spinlock_acquire(&proc->lock);
|
|
||||||
|
|
||||||
VOP_RELEASE(proc->root);
|
|
||||||
VOP_RELEASE(proc->cwd);
|
|
||||||
|
|
||||||
proc->status = status;
|
proc->status = status;
|
||||||
proc->state = SCHED_PROC_STATE_ZOMBIE;
|
|
||||||
proc_t *lastchild = proc->child;
|
|
||||||
|
|
||||||
spinlock_acquire(&sched_initproc->lock);
|
|
||||||
|
|
||||||
bool haszombie = false;
|
|
||||||
|
|
||||||
while (lastchild && lastchild->sibling) {
|
|
||||||
if (lastchild->state == SCHED_PROC_STATE_ZOMBIE)
|
|
||||||
haszombie = true;
|
|
||||||
|
|
||||||
lastchild->parent = sched_initproc;
|
|
||||||
lastchild = lastchild->sibling;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lastchild) {
|
|
||||||
lastchild->sibling = sched_initproc->child;
|
|
||||||
sched_initproc->child = proc->child;
|
|
||||||
}
|
|
||||||
|
|
||||||
spinlock_release(&sched_initproc->lock);
|
|
||||||
spinlock_release(&proc->lock);
|
|
||||||
|
|
||||||
semaphore_signal(&proc->parent->waitsem);
|
|
||||||
if (haszombie)
|
|
||||||
semaphore_signal(&sched_initproc->waitsem);
|
|
||||||
|
|
||||||
sched_threadexit();
|
sched_threadexit();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user