mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-29 05:38:21 +00:00
sched: finish preparing scheduler for rewrite
This commit is contained in:
+153
-1
@@ -5,6 +5,10 @@
|
||||
#include <kernel/alloc.h>
|
||||
#include <kernel/slab.h>
|
||||
#include <kernel/file.h>
|
||||
#include <kernel/scheduler.h>
|
||||
#include <kernel/elf.h>
|
||||
#include <kernel/devfs.h>
|
||||
#include <kernel/cmdline.h>
|
||||
|
||||
static hashtable_t pid_table;
|
||||
static scache_t *processcache;
|
||||
@@ -76,7 +80,7 @@ proc_t *proc_create() {
|
||||
memset(proc, 0, sizeof(proc_t));
|
||||
|
||||
// TODO move this to slab
|
||||
proc->state = SCHED_PROC_STATE_NORMAL;
|
||||
proc->state = PROC_STATE_NORMAL;
|
||||
proc->runningthreadcount = 1;
|
||||
MUTEX_INIT(&proc->mutex);
|
||||
SPINLOCK_INIT(proc->nodeslock);
|
||||
@@ -228,3 +232,151 @@ void proc_init(void) {
|
||||
__assert(hashtable_init(&pid_table, 100) == 0);
|
||||
MUTEX_INIT(&proc_pid_table_mutex);
|
||||
}
|
||||
|
||||
// called when all threads in a process have exited
|
||||
void proc_exit(void) {
|
||||
proc_t *proc = current_thread()->proc;
|
||||
__assert(proc != init_proc);
|
||||
|
||||
// the process is going to be referenced by the child list, hold it
|
||||
// it only holds it now because it has to have running threads to be in the list
|
||||
// which hold a reference. it won't now since its a zombie, which is why it will be held
|
||||
PROC_HOLD(proc);
|
||||
|
||||
jobctl_detach(proc);
|
||||
|
||||
// close fds
|
||||
for (int fd = 0; fd < proc->fdcount; ++fd)
|
||||
fd_close(fd);
|
||||
|
||||
// turn off interval timers
|
||||
itimer_pause(&proc->timer.realtime, NULL, NULL);
|
||||
itimer_pause(&proc->timer.virtualtime, NULL, NULL);
|
||||
itimer_pause(&proc->timer.profiling, NULL, NULL);
|
||||
|
||||
// zombify the proc
|
||||
MUTEX_ACQUIRE(&proc->mutex, false);
|
||||
|
||||
VOP_RELEASE(proc->root);
|
||||
VOP_RELEASE(proc->cwd);
|
||||
|
||||
proc->state = PROC_STATE_ZOMBIE;
|
||||
proc_t *lastchild = proc->child;
|
||||
|
||||
|
||||
MUTEX_ACQUIRE(&init_proc->mutex, false);
|
||||
|
||||
int belowzombiecount = 0;
|
||||
|
||||
while (lastchild && lastchild->sibling) {
|
||||
if (lastchild->state == PROC_STATE_ZOMBIE)
|
||||
++belowzombiecount;
|
||||
|
||||
lastchild->parent = init_proc;
|
||||
lastchild = lastchild->sibling;
|
||||
}
|
||||
|
||||
if (lastchild) {
|
||||
lastchild->sibling = init_proc->child;
|
||||
init_proc->child = proc->child;
|
||||
}
|
||||
|
||||
MUTEX_RELEASE(&init_proc->mutex);
|
||||
MUTEX_RELEASE(&proc->mutex);
|
||||
|
||||
signal_signalproc(proc->parent, SIGCHLD);
|
||||
semaphore_signal(&proc->parent->waitsem);
|
||||
// TODO sigaction flag for this
|
||||
for (int i = 0; i < belowzombiecount; ++i) {
|
||||
semaphore_signal(&init_proc->waitsem);
|
||||
}
|
||||
}
|
||||
|
||||
void proc_run_init() {
|
||||
printf("sched: loading /init\n");
|
||||
|
||||
vmmcontext_t *vmmctx = vmm_newcontext();
|
||||
__assert(vmmctx);
|
||||
|
||||
// leave kernel context to load elf
|
||||
vmm_switchcontext(vmmctx);
|
||||
|
||||
proc_t *proc = proc_create();
|
||||
__assert(proc);
|
||||
|
||||
init_proc = proc;
|
||||
|
||||
vnode_t *initnode;
|
||||
__assert(vfs_open(vfsroot, "/init", 0, &initnode) == 0);
|
||||
|
||||
auxv64list_t auxv64;
|
||||
char *interp = NULL;
|
||||
void *entry;
|
||||
|
||||
__assert(elf_load(initnode, NULL, &entry, &interp, &auxv64) == 0);
|
||||
if (interp) {
|
||||
vnode_t *interpnode;
|
||||
__assert(vfs_open(vfsroot, interp, 0, &interpnode) == 0);
|
||||
auxv64list_t interpauxv;
|
||||
char *interpinterp = NULL;
|
||||
__assert(elf_load(interpnode, INTERP_BASE, &entry, &interpinterp, &interpauxv) == 0);
|
||||
__assert(interpinterp == NULL);
|
||||
}
|
||||
|
||||
vnode_t *consolenode;
|
||||
__assert(devfs_getbyname("console", &consolenode) == 0);
|
||||
VOP_LOCK(consolenode);
|
||||
__assert(VOP_OPEN(&consolenode, V_FFLAGS_READ | V_FFLAGS_NOCTTY, &proc->cred) == 0);
|
||||
VOP_HOLD(consolenode);
|
||||
__assert(VOP_OPEN(&consolenode, V_FFLAGS_WRITE | V_FFLAGS_NOCTTY, &proc->cred) == 0);
|
||||
VOP_HOLD(consolenode);
|
||||
__assert(VOP_OPEN(&consolenode, V_FFLAGS_WRITE | V_FFLAGS_NOCTTY, &proc->cred) == 0);
|
||||
VOP_UNLOCK(consolenode);
|
||||
|
||||
file_t *stdin = fd_allocate();
|
||||
file_t *stdout = fd_allocate();
|
||||
file_t *stderr = fd_allocate();
|
||||
|
||||
stdin->vnode = consolenode;
|
||||
stdout->vnode = consolenode;
|
||||
stderr->vnode = consolenode;
|
||||
|
||||
stdin->flags = FILE_READ;
|
||||
stdout->flags = stderr->flags = FILE_WRITE;
|
||||
stdin->offset = stdout->offset = stderr->offset = 0;
|
||||
stdin->mode = stdout->mode = stderr-> mode = 0644;
|
||||
|
||||
proc->fd[0].file = stdin;
|
||||
proc->fd[0].flags = 0;
|
||||
proc->fd[1].file = stdout;
|
||||
proc->fd[1].flags = 0;
|
||||
proc->fd[2].file = stderr;
|
||||
proc->fd[2].flags = 0;
|
||||
|
||||
proc->cwd = vfsroot;
|
||||
VOP_HOLD(vfsroot);
|
||||
proc->root = vfsroot;
|
||||
VOP_HOLD(vfsroot);
|
||||
|
||||
char *argv[] = {"/init", cmdline_get("initarg"), NULL};
|
||||
char *envp[] = {NULL};
|
||||
|
||||
void *stack = elf_preparestack(STACK_TOP, &auxv64, argv, envp);
|
||||
__assert(stack);
|
||||
|
||||
// reenter kernel context
|
||||
vmm_switchcontext(&vmm_kernelctx);
|
||||
|
||||
thread_t *uthread = sched_newthread(entry, PAGE_SIZE * 16, 1, proc, stack);
|
||||
__assert(uthread);
|
||||
|
||||
proc->threadlist = uthread;
|
||||
uthread->procnext = NULL;
|
||||
|
||||
uthread->vmmctx = vmmctx;
|
||||
sched_queue(uthread);
|
||||
|
||||
VOP_RELEASE(initnode);
|
||||
// proc starts with 1 refcount, release it here as to only have the thread reference
|
||||
PROC_RELEASE(proc);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user