diff options
Diffstat (limited to 'kernel/proc/proc.c')
-rw-r--r-- | kernel/proc/proc.c | 225 |
1 files changed, 216 insertions, 9 deletions
diff --git a/kernel/proc/proc.c b/kernel/proc/proc.c index f8453bd..91be451 100644 --- a/kernel/proc/proc.c +++ b/kernel/proc/proc.c @@ -174,8 +174,68 @@ proc_t *proc_lookup(pid_t pid) */ proc_t *proc_create(const char *name) { - NOT_YET_IMPLEMENTED("PROCS: proc_create"); - return NULL; + // NOT_YET_IMPLEMENTED("PROCS: proc_create"); + int proc_pid = _proc_getid(); + if (proc_pid == -1) + { + return NULL; + } + + proc_t *proc = (proc_t *)slab_obj_alloc(proc_allocator); + if (proc == NULL) + { + return NULL; + } + + pml4_t *pml4 = pt_create(); + if (pml4 == NULL) + { + slab_obj_free(proc_allocator, proc); + return NULL; + } + + // if successful building memory, fill the struct + proc->p_pid = proc_pid; + strncpy(proc->p_name, name, PROC_NAME_LEN); + proc->p_pml4 = pml4; + proc->p_state = PROC_RUNNING; // TODO: check if this is correct + proc->p_status = 0; + list_init(&proc->p_threads); + list_init(&proc->p_children); + list_link_init(&proc->p_child_link); + list_link_init(&proc->p_list_link); + sched_queue_init(&proc->p_wait); + + + if (proc_pid == PID_INIT) + { + // if it's init proc, set to global variable + proc_initproc = proc; + } + + proc->p_pproc = proc_initproc; + list_insert_tail(&curproc->p_children, &proc->p_child_link); + list_insert_tail(&proc_list, &proc->p_list_link); + dbg(DBG_PROC, "SUCESSFULLY created PROCESS name=%s & pid =%d\n", name, proc_pid); + +#ifdef __VFS__ + // clone and ref the files from curproc + for (int fd = 0; fd < NFILES; fd++) + { + proc->p_files[fd] = NULL; + } + if (proc->p_pid != PID_INIT) + { + proc->p_cwd = proc->p_pproc->p_cwd; + vref(proc->p_cwd); + } + else + { + proc->p_cwd = NULL; + } +#endif + + return proc; } /* @@ -197,7 +257,52 @@ proc_t *proc_create(const char *name) */ void proc_cleanup(long status) { - NOT_YET_IMPLEMENTED("PROCS: proc_cleanup"); + // NOT_YET_IMPLEMENTED("PROCS: proc_cleanup"); + dbg(DBG_PROC, "proc_cleanup called on proc with pid=%d with exit status=%d\n", curproc->p_pid, status); + +#ifdef __VFS__ + for (int fd = 0; fd < NFILES; fd++) + { + if (curproc->p_files[fd]) + { + fput(curproc->p_files + fd); + } + } + if (curproc->p_cwd) + { + vput(&curproc->p_cwd); + } +#endif + + + if (curproc->p_pid == PID_INIT) + { + // if it's init proc, shutdown weenix + initproc_finish(status); + } + + // if it's not init proc, reparent child processes to parent proc + if (curproc->p_pproc == NULL) + { + panic("parent process not found in proc_pleanup"); + } + + list_link_t *link; + list_iterate(&curproc->p_children, child, proc_t, p_child_link) + { + // remove & insert to init process + list_insert_tail(&curproc->p_pproc->p_children, &child->p_child_link); + list_remove(&child->p_child_link); + child->p_pproc = proc_initproc; + } + + // update state and status + curproc->p_state = PROC_DEAD; + // if (curthr->kt_cancelled) { + // curproc->p_status = curthr->kt_retval; + // } else { + curproc->p_status = status; + // } } /* @@ -216,7 +321,13 @@ void proc_cleanup(long status) */ void proc_thread_exiting(void *retval) { - NOT_YET_IMPLEMENTED("PROCS: proc_thread_exiting"); + // NOT_YET_IMPLEMENTED("PROCS: proc_thread_exiting"); + + proc_cleanup((long)retval); + curthr->kt_state = KT_EXITED; + + sched_broadcast_on(&curproc->p_pproc->p_wait); + sched_switch(0); } /* @@ -227,7 +338,16 @@ void proc_thread_exiting(void *retval) */ void proc_kill(proc_t *proc, long status) { - NOT_YET_IMPLEMENTED("PROCS: proc_kill"); + // NOT_YET_IMPLEMENTED("PROCS: proc_kill"); + dbg(DBG_PROC, "proc_kill called on proc with pid=%d\n", proc->p_pid); + + KASSERT(proc != curproc && "proc_kill called on curproc"); + + list_iterate(&proc->p_threads, thr, kthread_t, kt_plink) + { + dbg(DBG_PROC, "cancelling thread on proc with pid=%d with status=%ld\n", proc->p_pid, status); + kthread_cancel(thr, (void *)status); + } } /* @@ -241,7 +361,18 @@ void proc_kill(proc_t *proc, long status) */ void proc_kill_all() { - NOT_YET_IMPLEMENTED("PROCS: proc_kill_all"); + // NOT_YET_IMPLEMENTED("PROCS: proc_kill_all"); + + list_iterate(&proc_list, p, proc_t, p_list_link) + { + if (p->p_pid != curproc->p_pid && p->p_pid != PID_IDLE) + { + proc_kill(p, -1); + } + } + + // kill this proc + do_exit(0); } /* @@ -265,7 +396,9 @@ void proc_destroy(proc_t *proc) for (int fd = 0; fd < NFILES; fd++) { if (proc->p_files[fd]) + { fput(proc->p_files + fd); + } } if (proc->p_cwd) { @@ -278,7 +411,7 @@ void proc_destroy(proc_t *proc) vmmap_destroy(&proc->p_vmmap); #endif - dbg(DBG_THR, "destroying P%d\n", proc->p_pid); + dbg(DBG_PROC, "destroying P%d\n", proc->p_pid); KASSERT(proc->p_pml4); pt_destroy(proc->p_pml4); @@ -316,7 +449,77 @@ void proc_destroy(proc_t *proc) */ pid_t do_waitpid(pid_t pid, int *status, int options) { - NOT_YET_IMPLEMENTED("PROCS: do_waitpid"); + // NOT_YET_IMPLEMENTED("PROCS: do_waitpid"); + + if (pid == 0 || options != 0 || pid < -1) + { + return -ENOTSUP; + } + + dbg(DBG_PROC, "waiting for pid=%d\n", pid); + + if (pid > 0) + { + proc_t *child = proc_lookup(pid); + if (child == NULL || child->p_pproc != curproc) + { + return -ECHILD; + } + + // sleep until this specific child process exits + while (child->p_state != PROC_DEAD) + { + dbg(DBG_PROC, "waiting for specific child, calling sched_sleep_on\n"); + sched_sleep_on(&curproc->p_wait); + } + + if (status != NULL) + { + dbg(DBG_PROC, "setting status to %d\n", child->p_status); + *status = child->p_status; + } + list_remove(&child->p_child_link); + proc_destroy(child); + + dbg(DBG_PROC, "exited child pid=%d\n", child->p_pid); + return pid; + } + else if (pid == -1) + { + if (list_empty(&curproc->p_children)) + { + return -ECHILD; + } + + + while(1) { + proc_t *child; + list_iterate(&curproc->p_children, child, proc_t, p_child_link) + { + if (child->p_state == PROC_DEAD) + { + dbg(DBG_PROC, "found a dead thread with pid=%d\n", child->p_pid); + if (status != NULL) + { + dbg(DBG_PROC, "setting status to %d\n", child->p_status); + *status = child->p_status; + } + int child_pid = child->p_pid; + + + list_remove(&child->p_child_link); + proc_destroy(child); + + dbg(DBG_PROC, "exited child pid=%d\n", child->p_pid); + return child_pid; + } + } + + dbg(DBG_PROC, "waiting for any child, calling sched_sleep_on\n"); + sched_sleep_on(&curproc->p_wait); + } + } + return 0; } @@ -325,7 +528,11 @@ pid_t do_waitpid(pid_t pid, int *status, int options) */ void do_exit(long status) { - NOT_YET_IMPLEMENTED("PROCS: do_exit"); + // NOT_YET_IMPLEMENTED("PROCS: do_exit"); + + dbg(DBG_PROC, "proc exiting with pid=%d and status=%ld\n", curproc->p_pid, status); + + kthread_exit((void *)status); } /*========== |