Add thread cleanup after termination
This commit is contained in:
@@ -11,6 +11,8 @@ struct amd64_thread {
|
||||
|
||||
uintptr_t stack3_base;
|
||||
uintptr_t stack3_size;
|
||||
|
||||
uint32_t data_flags;
|
||||
};
|
||||
|
||||
void amd64_thread_set_ip(struct thread *t, uintptr_t ip);
|
||||
|
||||
@@ -45,3 +45,4 @@ int thread_init(struct thread *t,
|
||||
size_t stack3_size,
|
||||
uint32_t flags,
|
||||
void *arg);
|
||||
void thread_cleanup(struct thread *t);
|
||||
|
||||
+6
-1
@@ -282,7 +282,7 @@ int mm_space_fork(mm_space_t dst_pml4, const mm_space_t src_pml4, uint32_t flags
|
||||
}
|
||||
|
||||
void mm_space_release(mm_space_t pml4) {
|
||||
for (size_t pml4i = 0; pml4i < 255; ++pml4i) {
|
||||
for (size_t pml4i = 0; pml4i < AMD64_PML4I_USER_END; ++pml4i) {
|
||||
if (!(pml4[pml4i] & 1)) {
|
||||
continue;
|
||||
}
|
||||
@@ -324,6 +324,11 @@ void mm_space_release(mm_space_t pml4) {
|
||||
}
|
||||
}
|
||||
|
||||
void mm_space_free(mm_space_t pml4) {
|
||||
mm_space_release(pml4);
|
||||
amd64_mm_pool_free(pml4);
|
||||
}
|
||||
|
||||
static void amd64_mm_describe_range(const mm_space_t pml4, uintptr_t start_addr, uintptr_t end_addr) {
|
||||
uintptr_t addr = AMD64_MM_STRIPSX(start_addr);
|
||||
|
||||
|
||||
@@ -230,6 +230,8 @@ void sched_remove_from(int cpu, struct thread *thr) {
|
||||
thr->next = NULL;
|
||||
thr->prev = NULL;
|
||||
|
||||
thread_cleanup(thr);
|
||||
|
||||
// TODO: make other cpus schedule a new thread if they're running a stopped one
|
||||
}
|
||||
|
||||
|
||||
@@ -28,12 +28,16 @@ int thread_init(
|
||||
size_t rsp3_size,
|
||||
uint32_t flags,
|
||||
void *arg) {
|
||||
t->data.data_flags = 0;
|
||||
|
||||
if (!rsp0_base) {
|
||||
void *kstack = kmalloc(THREAD_KSTACK_SIZE);
|
||||
_assert(kstack);
|
||||
|
||||
rsp0_base = (uintptr_t) kstack;
|
||||
rsp0_size = THREAD_KSTACK_SIZE;
|
||||
} else {
|
||||
t->data.data_flags |= 1 /* Don't free kstack */;
|
||||
}
|
||||
|
||||
if (!(flags & THREAD_KERNEL) && !rsp3_base) {
|
||||
@@ -44,6 +48,8 @@ int thread_init(
|
||||
rsp3_size = 4 * 0x1000;
|
||||
|
||||
kdebug("Allocated user stack: %p\n", ustack);
|
||||
} else if (rsp3_base) {
|
||||
t->data.data_flags |= 2 /* Don't free ustack */;
|
||||
}
|
||||
|
||||
t->data.stack0_base = rsp0_base;
|
||||
@@ -112,6 +118,29 @@ int thread_init(
|
||||
return 0;
|
||||
}
|
||||
|
||||
void thread_cleanup(struct thread *t) {
|
||||
_assert(t);
|
||||
|
||||
// Release files
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
if (t->fds[i].vnode) {
|
||||
vfs_close(&t->ioctx, &t->fds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Release stacks
|
||||
if (!(t->data.data_flags & 1)) {
|
||||
kfree((void *) t->data.stack0_base);
|
||||
}
|
||||
|
||||
if (t->space != mm_kernel) {
|
||||
mm_space_free(t->space);
|
||||
}
|
||||
|
||||
memset(t, 0, sizeof(struct thread));
|
||||
kfree(t);
|
||||
}
|
||||
|
||||
int sys_execve(const char *filename, const char *const argv[], const char *const envp[]) {
|
||||
asm volatile ("cli");
|
||||
struct thread *thr = get_cpu()->thread;
|
||||
@@ -211,6 +240,7 @@ int sys_fork(void) {
|
||||
struct amd64_thread *dst_data = &thr_dst->data;
|
||||
_assert(dst_kstack);
|
||||
|
||||
dst_data->data_flags |= 1 /* Don't free kstack */;
|
||||
dst_data->stack0_base = (uintptr_t) dst_kstack;
|
||||
dst_data->stack0_size = THREAD_KSTACK_SIZE;
|
||||
dst_data->stack3_base = thr_src->data.stack3_base;
|
||||
|
||||
@@ -67,6 +67,9 @@ void vnode_ref(vnode_t *vn) {
|
||||
// vfs_vnode_path(buf, vn);
|
||||
// printf("++refcount for %s\n", buf);
|
||||
_assert(vn);
|
||||
if (vn->type == VN_BLK || vn->type == VN_CHR) {
|
||||
return;
|
||||
}
|
||||
_assert(vn->fs);
|
||||
_assert(vn->fs->cls);
|
||||
|
||||
@@ -86,6 +89,10 @@ void vnode_ref(vnode_t *vn) {
|
||||
|
||||
void vnode_unref(vnode_t *vn) {
|
||||
_assert(vn);
|
||||
if (vn->type == VN_BLK || vn->type == VN_CHR) {
|
||||
return;
|
||||
}
|
||||
|
||||
_assert(vn->fs);
|
||||
_assert(vn->fs->cls);
|
||||
|
||||
|
||||
+16
-4
@@ -868,12 +868,24 @@ int vfs_open_node(struct vfs_ioctx *ctx, struct ofile *of, vnode_t *vn, int opt)
|
||||
|
||||
void vfs_close(struct vfs_ioctx *ctx, struct ofile *of) {
|
||||
_assert(of);
|
||||
kinfo("vfs_close %p\n", of);
|
||||
vnode_t *vn = of->vnode;
|
||||
_assert(vn && vn->op);
|
||||
switch (vn->type) {
|
||||
case VN_REG:
|
||||
case VN_DIR:
|
||||
_assert(vn);
|
||||
|
||||
if (vn->op->close) {
|
||||
vn->op->close(of);
|
||||
if (vn->op->close) {
|
||||
vn->op->close(of);
|
||||
}
|
||||
break;
|
||||
|
||||
// TODO: maybe call something special for that
|
||||
case VN_CHR:
|
||||
case VN_BLK:
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("Unhandled vnode type\n");
|
||||
}
|
||||
|
||||
vnode_unref(of->vnode);
|
||||
|
||||
Reference in New Issue
Block a user