Better cleanup of dead threads
This commit is contained in:
+33
@@ -1,4 +1,6 @@
|
||||
#include "sys/amd64/context.h"
|
||||
#include "sys/amd64/mm/pool.h"
|
||||
#include "sys/amd64/mm/phys.h"
|
||||
#include "sys/amd64/hw/irq.h"
|
||||
#include "sys/amd64/hw/idt.h"
|
||||
#include "sys/user/signum.h"
|
||||
@@ -8,6 +10,7 @@
|
||||
#include "sys/thread.h"
|
||||
#include "sys/sched.h"
|
||||
#include "sys/debug.h"
|
||||
#include "sys/heap.h"
|
||||
#include "sys/mm.h"
|
||||
|
||||
void yield(void);
|
||||
@@ -146,6 +149,12 @@ void sched_debug_cycle(uint64_t delta_ms) {
|
||||
struct thread *thr = queue_head;
|
||||
extern struct thread user_init;
|
||||
|
||||
struct heap_stat st;
|
||||
struct amd64_phys_stat phys_st;
|
||||
struct amd64_pool_stat pool_st;
|
||||
|
||||
kdebug("--- DEBUG_CYCLE ---\n");
|
||||
|
||||
debugs(DEBUG_DEFAULT, "Process tree:\n");
|
||||
sched_debug_tree(DEBUG_DEFAULT, &user_init, 0);
|
||||
|
||||
@@ -167,6 +176,30 @@ void sched_debug_cycle(uint64_t delta_ms) {
|
||||
} else {
|
||||
kdebug("--- IDLE\n");
|
||||
}
|
||||
|
||||
heap_stat(heap_global, &st);
|
||||
kdebug("Heap stat:\n");
|
||||
kdebug("Allocated blocks: %u\n", st.alloc_count);
|
||||
kdebug("Used %S, free %S, total %S\n", st.alloc_size, st.free_size, st.total_size);
|
||||
|
||||
amd64_phys_stat(&phys_st);
|
||||
kdebug("Physical memory:\n");
|
||||
kdebug("Used %S (%u), free %S (%u), ceiling %p\n",
|
||||
phys_st.pages_used * 0x1000,
|
||||
phys_st.pages_used,
|
||||
phys_st.pages_free * 0x1000,
|
||||
phys_st.pages_free,
|
||||
phys_st.limit);
|
||||
|
||||
amd64_mm_pool_stat(&pool_st);
|
||||
kdebug("Paging pool:\n");
|
||||
kdebug("Used %S (%u), free %S (%u)\n",
|
||||
pool_st.pages_used * 0x1000,
|
||||
pool_st.pages_used,
|
||||
pool_st.pages_free * 0x1000,
|
||||
pool_st.pages_free);
|
||||
|
||||
kdebug("--- ----------- ---\n");
|
||||
}
|
||||
|
||||
void yield(void) {
|
||||
|
||||
+74
-1
@@ -57,6 +57,24 @@ static void thread_add(struct thread *thr) {
|
||||
threads_all_head = thr;
|
||||
}
|
||||
|
||||
static void thread_remove(struct thread *thr) {
|
||||
struct thread *prev = thr->g_prev;
|
||||
struct thread *next = thr->g_next;
|
||||
|
||||
if (prev) {
|
||||
prev->g_next = next;
|
||||
} else {
|
||||
threads_all_head = next;
|
||||
}
|
||||
|
||||
if (next) {
|
||||
next->g_prev = prev;
|
||||
}
|
||||
|
||||
thr->g_next = NULL;
|
||||
thr->g_prev = NULL;
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
static void thread_ioctx_empty(struct thread *thr) {
|
||||
@@ -113,6 +131,32 @@ struct thread *thread_child(struct thread *of, pid_t pid) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void thread_unchild(struct thread *thr) {
|
||||
struct thread *par = thr->parent;
|
||||
_assert(par);
|
||||
|
||||
struct thread *p = NULL;
|
||||
struct thread *c = par->first_child;
|
||||
int found = 0;
|
||||
|
||||
while (c) {
|
||||
if (c == thr) {
|
||||
found = 1;
|
||||
if (p) {
|
||||
p->next_child = thr->next_child;
|
||||
} else {
|
||||
par->first_child = thr->next_child;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
p = c;
|
||||
c = c->next_child;
|
||||
}
|
||||
|
||||
_assert(found);
|
||||
}
|
||||
|
||||
void thread_cleanup(struct thread *thr) {
|
||||
_assert(thr);
|
||||
// Leave only the system context required for hierachy tracking and error code/pid
|
||||
@@ -136,6 +180,30 @@ void thread_cleanup(struct thread *thr) {
|
||||
mm_space_release(thr->space);
|
||||
}
|
||||
|
||||
void thread_free(struct thread *thr) {
|
||||
_assert(thr->flags & THREAD_STOPPED);
|
||||
_assert(thr->flags & THREAD_EMPTY);
|
||||
|
||||
// Free kstack
|
||||
for (size_t i = 0; i < thr->data.rsp0_size / MM_PAGE_SIZE; ++i) {
|
||||
amd64_phys_free(MM_PHYS(i * MM_PAGE_SIZE + thr->data.rsp0_base));
|
||||
}
|
||||
|
||||
// Free page directory (if not mm_kernel)
|
||||
if (thr->space != mm_kernel) {
|
||||
// Make sure we don't shoot a leg off
|
||||
uintptr_t cr3;
|
||||
asm volatile ("movq %%cr3, %0":"=a"(cr3));
|
||||
_assert(MM_VIRTUALIZE(cr3) != (uintptr_t) thr->space);
|
||||
|
||||
mm_space_free(thr->space);
|
||||
}
|
||||
|
||||
// Free thread itself
|
||||
memset(thr, 0, sizeof(struct thread));
|
||||
kfree(thr);
|
||||
}
|
||||
|
||||
int thread_init(struct thread *thr, uintptr_t entry, void *arg, int user) {
|
||||
uintptr_t stack_pages = amd64_phys_alloc_contiguous(2);
|
||||
_assert(stack_pages != MM_NADDR);
|
||||
@@ -552,11 +620,16 @@ int sys_waitpid(pid_t pid, int *status) {
|
||||
thread_check_signal(thr, 0);
|
||||
}
|
||||
|
||||
// Make sure no platform context remains
|
||||
_assert(chld->flags & THREAD_EMPTY);
|
||||
|
||||
if (status) {
|
||||
*status = chld->exit_status;
|
||||
}
|
||||
|
||||
// TODO: Cleanup the child here
|
||||
thread_unchild(chld);
|
||||
thread_remove(chld);
|
||||
thread_free(chld);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user