aboutsummaryrefslogtreecommitdiff
path: root/kernel/proc
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/proc')
-rw-r--r--kernel/proc/kthread.c54
-rw-r--r--kernel/proc/proc.c225
-rw-r--r--kernel/proc/sched.c100
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);