diff options
Diffstat (limited to 'kernel/proc')
-rw-r--r-- | kernel/proc/kthread.c | 54 | ||||
-rw-r--r-- | kernel/proc/proc.c | 225 | ||||
-rw-r--r-- | kernel/proc/sched.c | 100 |
3 files changed, 359 insertions, 20 deletions
diff --git a/kernel/proc/kthread.c b/kernel/proc/kthread.c index 1104b31..d066dac 100644 --- a/kernel/proc/kthread.c +++ b/kernel/proc/kthread.c @@ -68,8 +68,43 @@ void kthread_init() kthread_t *kthread_create(proc_t *proc, kthread_func_t func, long arg1, void *arg2) { - NOT_YET_IMPLEMENTED("PROCS: kthread_create"); - return NULL; + // NOT_YET_IMPLEMENTED("PROCS: kthread_create"); + dbg(DBG_THR, "ATTEMPT to create a new thread with proc name=%s, id=%d\n", proc->p_name, proc->p_pid); + + kthread_t *new_thread = slab_obj_alloc(kthread_allocator); + if (new_thread == NULL) + { + return NULL; + } + new_thread->kt_state = KT_NO_STATE; + + new_thread->kt_kstack = alloc_stack(); + if (new_thread->kt_kstack == NULL) + { + slab_obj_free(kthread_allocator, new_thread); + return NULL; + } + + new_thread->kt_proc = proc; + context_setup(&new_thread->kt_ctx, func, arg1, arg2, new_thread->kt_kstack, + DEFAULT_STACK_SIZE, new_thread->kt_proc->p_pml4); + + // give default values to rest of struct + new_thread->kt_retval = NULL; + new_thread->kt_errno = 0; + new_thread->kt_cancelled = 0; + new_thread->kt_wchan = NULL; + list_link_init(&new_thread->kt_plink); + list_link_init(&new_thread->kt_qlink); + list_init(&new_thread->kt_mutexes); + new_thread->kt_recent_core = 0; + + // put this thread on the process's thread list + list_insert_tail(&proc->p_threads, &new_thread->kt_plink); + + dbg(DBG_THR, "SUCCESFULLY created a new THREAD with proc name=%s, id=%d\n", proc->p_name, proc->p_pid); + + return new_thread; } /* @@ -124,7 +159,15 @@ void kthread_destroy(kthread_t *thr) */ void kthread_cancel(kthread_t *thr, void *retval) { - NOT_YET_IMPLEMENTED("PROCS: kthread_cancel"); + // NOT_YET_IMPLEMENTED("PROCS: kthread_cancel"); + KASSERT(thr != curthr); + + // FIXME: ask about the use of check_curthr_cancelled() in syscall_handler() + int status = (int) retval; + dbg(DBG_THR, "Cancelling thread with proc name=%s, id=%d, status=%d\n", + thr->kt_proc->p_name, thr->kt_proc->p_pid, status); + thr->kt_retval = retval; + sched_cancel(thr); } /* @@ -132,5 +175,8 @@ void kthread_cancel(kthread_t *thr, void *retval) */ void kthread_exit(void *retval) { - NOT_YET_IMPLEMENTED("PROCS: kthread_exit"); + // NOT_YET_IMPLEMENTED("PROCS: kthread_exit"); + dbg(DBG_THR, "Exiting thread with proc name=%s, id=%d, status=%d\n", + curthr->kt_proc->p_name, curthr->kt_proc->p_pid, (int) retval); + proc_thread_exiting(retval); } 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); } /*========== diff --git a/kernel/proc/sched.c b/kernel/proc/sched.c index 3bc20c8..b422ef1 100644 --- a/kernel/proc/sched.c +++ b/kernel/proc/sched.c @@ -162,7 +162,23 @@ void sched_init(void) */ long sched_cancellable_sleep_on(ktqueue_t *queue) { - NOT_YET_IMPLEMENTED("PROCS: sched_cancellable_sleep_on"); + // NOT_YET_IMPLEMENTED("PROCS: sched_cancellable_sleep_on"); + + KASSERT(queue != NULL); + + if (curthr->kt_cancelled) + { + return -EINTR; + } + + curthr->kt_state = KT_SLEEP_CANCELLABLE; + sched_switch(queue); + + if (curthr->kt_cancelled) + { + return -EINTR; + } + return 0; } @@ -174,7 +190,15 @@ long sched_cancellable_sleep_on(ktqueue_t *queue) */ void sched_cancel(kthread_t *thr) { - NOT_YET_IMPLEMENTED("PROCS: sched_cancel"); + // NOT_YET_IMPLEMENTED("PROCS: sched_cancel"); + + thr->kt_cancelled = 1; + + if (thr->kt_state == KT_SLEEP_CANCELLABLE) + { + ktqueue_remove(thr->kt_wchan, thr); + sched_make_runnable(thr); + } } /* @@ -210,7 +234,21 @@ void sched_cancel(kthread_t *thr) */ void sched_switch(ktqueue_t *queue) { - NOT_YET_IMPLEMENTED("PROCS: sched_switch"); + // NOT_YET_IMPLEMENTED("PROCS: sched_switch"); + + // KASSERT(intr_getipl == IPL_HIGH); + intr_disable(); + int oldIPL = intr_setipl(IPL_LOW); // allow interrupts to wake up the idling core + + KASSERT(curthr->kt_state != KT_ON_CPU); + + curcore.kc_queue = queue; + last_thread_context = &curthr->kt_ctx; + + context_switch(&curthr->kt_ctx, &curcore.kc_ctx); + + intr_enable(); + intr_setipl(oldIPL); } /* @@ -236,7 +274,23 @@ void sched_yield() */ void sched_make_runnable(kthread_t *thr) { - NOT_YET_IMPLEMENTED("PROCS: sched_make_runnable"); + // NOT_YET_IMPLEMENTED("PROCS: sched_make_runnable"); + + dbg(DBG_SCHED, "Making thread with proc pid %d runnable\n in thread\n", thr->kt_proc->p_pid); + if (curthr) + { + dbg(DBG_SCHED, "I did this ^^ with thread %d\n", curthr->kt_proc->p_pid); + } else { + dbg(DBG_SCHED, "I did this ^^ with a null thread!\n"); + } + + KASSERT(thr != curthr); + KASSERT(thr->kt_state != KT_RUNNABLE); + + int oldIPL = intr_setipl(IPL_HIGH); + thr->kt_state = KT_RUNNABLE; + ktqueue_enqueue(&kt_runq, thr); + intr_setipl(oldIPL); } /* @@ -255,7 +309,12 @@ void sched_make_runnable(kthread_t *thr) */ void sched_sleep_on(ktqueue_t *q) { - NOT_YET_IMPLEMENTED("PROCS: sched_sleep_on"); + // NOT_YET_IMPLEMENTED("PROCS: sched_sleep_on"); + + int oldIPL = intr_setipl(IPL_HIGH); + curthr->kt_state = KT_SLEEP; + sched_switch(q); + intr_setipl(oldIPL); } /* @@ -271,7 +330,26 @@ void sched_sleep_on(ktqueue_t *q) */ void sched_wakeup_on(ktqueue_t *q, kthread_t **ktp) { - NOT_YET_IMPLEMENTED("PROCS: sched_wakeup_on"); + // NOT_YET_IMPLEMENTED("PROCS: sched_wakeup_on"); + + if (sched_queue_empty(q) || q == NULL) + { + if (ktp) + { + *ktp = NULL; + } + return; + } + + int oldIPL = intr_setipl(IPL_HIGH); // don't allow interrupts while modifying the queue + kthread_t *thr = ktqueue_dequeue(q); + if (ktp) + { + *ktp = thr; + } + + sched_make_runnable(thr); + intr_setipl(oldIPL); } /* @@ -279,7 +357,12 @@ void sched_wakeup_on(ktqueue_t *q, kthread_t **ktp) */ void sched_broadcast_on(ktqueue_t *q) { - NOT_YET_IMPLEMENTED("PROCS: sched_broadcast_on"); + // NOT_YET_IMPLEMENTED("PROCS: sched_broadcast_on"); + + while (!sched_queue_empty(q)) + { + sched_make_runnable(ktqueue_dequeue(q)); + } } /*=============== @@ -360,6 +443,9 @@ void core_switch() KASSERT(mapped_paddr == expected_paddr); curthr = next_thread; + + dbg(DBG_THR, "Switching to curthr thread %d\n", curthr->kt_proc->p_pid); + curthr->kt_state = KT_ON_CPU; curproc = curthr->kt_proc; context_switch(&curcore.kc_ctx, &curthr->kt_ctx); |