aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/riscv64/kernel/proc.c6
-rw-r--r--arch/riscv64/kernel/vmem.c7
-rw-r--r--include/arch/tcb.h7
-rw-r--r--include/kmi/tcb.h16
-rw-r--r--src/orphanage.c7
-rw-r--r--src/tcb.c28
6 files changed, 50 insertions, 21 deletions
diff --git a/arch/riscv64/kernel/proc.c b/arch/riscv64/kernel/proc.c
index f1a62c4..a4746b4 100644
--- a/arch/riscv64/kernel/proc.c
+++ b/arch/riscv64/kernel/proc.c
@@ -28,6 +28,7 @@ void run_init(struct tcb *t, vm_t fdt, vm_t initrd)
* Could be fixed with a separate pure asm run_init, but I guess this
* works for now.
*/
+ vm_t stack_top = t->thread_stack + t->thread_stack_size;
bkl_unlock();
__asm__ volatile ("mv sp, %0\n"
"mv a0, %1\n"
@@ -35,7 +36,7 @@ void run_init(struct tcb *t, vm_t fdt, vm_t initrd)
"mv a2, %3\n"
"sret\n"
:
- : "r" (t->thread_stack_top), "r" (t->tid), "r" (fdt),
+ : "r" (stack_top), "r" (t->tid), "r" (fdt),
"r" (initrd)
: "memory");
/* we should never reach this */
@@ -66,8 +67,7 @@ void set_thread(struct tcb *t)
struct riscv_regs *r = (struct riscv_regs *)(t->regs) - 1;
/* insert important values into register slots */
- r->sp = (long)t->thread_stack_top;
- r->tp = (long)t->thread_storage;
+ r->sp = (long)t->thread_stack + t->thread_stack_size;
}
void set_stack(struct tcb *t, vm_t s)
diff --git a/arch/riscv64/kernel/vmem.c b/arch/riscv64/kernel/vmem.c
index f717771..00752c1 100644
--- a/arch/riscv64/kernel/vmem.c
+++ b/arch/riscv64/kernel/vmem.c
@@ -551,11 +551,18 @@ void destroy_rpc_stack(struct tcb *t)
}
}
+void reset_rpc_stack(struct tcb *t)
+{
+ t->rpc_stack = RPC_STACK_BASE + (BASE_PAGE_SIZE * rpc_pages);
+ t->arch.rpc_idx = rpc_pages;
+}
+
bool rpc_stack_empty(pm_t addr)
{
return addr == RPC_STACK_BASE + (BASE_PAGE_SIZE * rpc_pages);
}
+
vm_t rpc_position(struct tcb *t)
{
/** @todo we assume rpc_idx is updated on every segfault of the rpc stack */
diff --git a/include/arch/tcb.h b/include/arch/tcb.h
index 931b800..b8b0961 100644
--- a/include/arch/tcb.h
+++ b/include/arch/tcb.h
@@ -42,6 +42,13 @@ void setup_rpc_stack(struct tcb *t);
void destroy_rpc_stack(struct tcb *t);
/**
+ * Reset RPC stack to top.
+ *
+ * @param t Thread whose RPC stack should be reset.
+ */
+void reset_rpc_stack(struct tcb *t);
+
+/**
* @return Max size of one individual RPC stack instance.
*/
size_t max_rpc_size();
diff --git a/include/kmi/tcb.h b/include/kmi/tcb.h
index b7fd3d6..a06d801 100644
--- a/include/kmi/tcb.h
+++ b/include/kmi/tcb.h
@@ -122,18 +122,13 @@ struct tcb {
vm_t thread_stack;
/** Address of this thread's stack top. */
- vm_t thread_stack_top;
+ vm_t thread_stack_size;
/** Current address of usable rpc stack. */
vm_t rpc_stack;
- /** \todo Check if each thread should be allowed more than just one
- * region of thread local storage. */
- /** Possible thread local storage. */
- vm_t thread_storage;
-
/** Reference count to process. */
- atomic_int_fast32_t refcount;
+ long refcount;
/** Process context of thread. */
struct tcb_ctx proc;
@@ -322,6 +317,13 @@ struct tcb *get_tcb(id_t tid);
stat_t alloc_stack(struct tcb *t);
/**
+ * Free thread stack.
+ *
+ * @param t Thread whose stack to free.
+ */
+void free_stack(struct tcb *t);
+
+/**
* Set address to jump to when returning to userspace.
*
* @param t Thread return address to set.
diff --git a/src/orphanage.c b/src/orphanage.c
index 4760f73..9da6f8b 100644
--- a/src/orphanage.c
+++ b/src/orphanage.c
@@ -34,9 +34,14 @@ void unorphanize(struct tcb *t)
t->pid = 1;
t->eid = 1;
+ free_stack(t);
+ reset_rpc_stack(t);
+
t->proc = init->proc;
- t->rpc_stack = RPC_STACK_BASE;
use_vmem(t->proc.vmem);
+ alloc_stack(t);
+
+ clear_bits(t->state, TCB_ORPHAN);
catastrophic_assert(init->callback);
set_args3(t, 0, SYS_USER_ORPHANED, t->tid);
diff --git a/src/tcb.c b/src/tcb.c
index 51aa939..45c31ce 100644
--- a/src/tcb.c
+++ b/src/tcb.c
@@ -107,11 +107,17 @@ stat_t alloc_stack(struct tcb *t)
return ERR_OOMEM;
/** \todo this only allows for a global stack size, what if a user wants
- * per thread stack sizes? */
- t->thread_stack_top = t->thread_stack + __thread_stack_size;
+ * per thread stack sizes? I guess allocate them yourself in userspace
+ * or something? */
+ t->thread_stack_size = __thread_stack_size;
return OK;
}
+void free_stack(struct tcb *t)
+{
+ free_uvmem(t, t->thread_stack);
+}
+
struct tcb *create_thread(struct tcb *p)
{
hard_assert(tcbs, 0);
@@ -171,7 +177,7 @@ static stat_t __copy_proc(struct tcb *p, struct tcb *n)
n->exec = p->exec;
n->callback = p->callback;
n->thread_stack = p->thread_stack;
- n->thread_stack_top = p->thread_stack_top;
+ n->thread_stack_size = p->thread_stack_size;
copy_regs(n, p);
copy_caps(n->caps, p->caps);
@@ -188,7 +194,7 @@ struct tcb *create_proc(struct tcb *p)
return 0;
if (p)
- __copy_proc(p, n); /* we have a parent thread */
+ __copy_proc(p, n); /* we have a parent process i.e. fork */
return n;
}
@@ -203,12 +209,6 @@ static stat_t __destroy_thread_data(struct tcb *t)
{
catastrophic_assert(t->refcount == 0);
- /* free memory backing rpc stack */
- destroy_rpc_stack(t);
-
- /* free rpc vmem */
- destroy_vmem(t->rpc.vmem);
-
/* remove ourselves from the thread pool */
/** @todo this should be at the top of the function, and be wrapped in
* some kind of lock that checks that nobody reads the value while we're
@@ -241,6 +241,14 @@ stat_t destroy_thread(struct tcb *t)
/* remove reference to root process */
unreference_proc(get_rproc(t));
+ free_stack(t);
+
+ /* free memory backing rpc stack */
+ destroy_rpc_stack(t);
+
+ /* free rpc vmem */
+ destroy_vmem(t->rpc.vmem);
+
unqueue_ipi(t);
/** @todo timers, irqs? theoretically we could allow them to stay and