fix(net): improve network stability and resource management

This commit is contained in:
boreddevnl
2026-05-10 21:56:23 +02:00
parent 2d40ca30af
commit 6784b2139f
6 changed files with 152 additions and 132 deletions

View File

@@ -10,7 +10,7 @@
extern void serial_print(const char *s);
extern void serial_write(const char *str);
uint64_t elf_load(const char *path, uint64_t user_pml4, size_t *out_load_size) {
uint64_t elf_load(const char *path, uint64_t user_pml4, size_t *out_load_size, struct process *proc) {
if (out_load_size) *out_load_size = 0;
FAT32_FileHandle *file = fat32_open(path, "r");
if (!file || !file->valid) {
@@ -76,15 +76,11 @@ uint64_t elf_load(const char *path, uint64_t user_pml4, size_t *out_load_size) {
// Calculate boundaries for bulk allocation
uintptr_t align_offset = p_vaddr & 0xFFF;
uintptr_t start_page = p_vaddr & ~0xFFFFFFFFFFFFF000ULL; // Wait, mask should be ~0xFFF
uintptr_t start_page = p_vaddr & ~0xFFFFFFFFFFFFF000ULL;
start_page = p_vaddr & ~0xFFFULL;
size_t total_needed = (p_memsz + align_offset + 4095) & ~4095ULL;
size_t num_pages = total_needed / 4096;
// Bulk allocate physical memory for the entire segment
// Note: We allocate page by page but map them sequentially.
// A better way is to allocate a large contiguous block if possible,
// but our kmalloc_aligned handles arbitrary sizes.
void* bulk_phys = kmalloc_aligned(total_needed, 4096);
if (!bulk_phys) {
serial_write("[ELF] Error: Out of memory bulk allocating segment\n");
@@ -107,6 +103,14 @@ uint64_t elf_load(const char *path, uint64_t user_pml4, size_t *out_load_size) {
uint64_t phys_addr = v2p((uint64_t)bulk_phys + (p * 4096));
paging_map_page(user_pml4, vaddr, phys_addr, 0x07);
}
if (proc) {
// Track physical segments so they can be freed on process exit.
// This resolves the memory leak where process binaries remained in RAM forever.
extern void process_add_elf_segment(struct process *proc, void *ptr);
process_add_elf_segment(proc, bulk_phys);
}
if (out_load_size) *out_load_size += total_needed;
}
}

View File

@@ -118,6 +118,7 @@ typedef struct __attribute__((packed)) {
// Loads the ELF executable at 'path' using fat32 into the pagemap given by user_pml4.
// Returns entry point address on success, or 0 on failure.
uint64_t elf_load(const char *path, uint64_t user_pml4, size_t *out_load_size);
struct process;
uint64_t elf_load(const char *path, uint64_t user_pml4, size_t *out_load_size, struct process *proc);
#endif

View File

@@ -236,6 +236,13 @@ process_t* process_create(void (*entry_point)(void), bool is_user) {
return new_proc;
}
void process_add_elf_segment(process_t *proc, void *ptr) {
if (!proc || !ptr) return;
if (proc->elf_segment_count < 4) {
proc->elf_segments[proc->elf_segment_count++] = ptr;
}
}
process_t* process_create_elf(const char* filepath, const char* args_str, bool terminal_proc, int tty_id) {
uint64_t rflags = spinlock_acquire_irqsave(&runqueue_lock);
process_t *new_proc = NULL;
@@ -255,6 +262,7 @@ process_t* process_create_elf(const char* filepath, const char* args_str, bool t
new_proc->pid = next_pid++;
new_proc->is_user = true;
new_proc->elf_segment_count = 0;
spinlock_release_irqrestore(&runqueue_lock, rflags);
// 1. Setup Page Table
@@ -294,7 +302,7 @@ process_t* process_create_elf(const char* filepath, const char* args_str, bool t
// 2. Load ELF executable
size_t elf_load_size = 0;
uint64_t entry_point = elf_load(filepath, new_proc->pml4_phys, &elf_load_size);
uint64_t entry_point = elf_load(filepath, new_proc->pml4_phys, &elf_load_size, new_proc);
if (entry_point == 0) {
serial_write("[PROC] Failed to load ELF: ");
serial_write(filepath);
@@ -742,14 +750,22 @@ void process_terminate_with_status(process_t *to_delete, int status) {
to_delete->exited = true;
to_delete->exit_status = status;
// Reclaim all process resources
if (to_delete->user_stack_alloc) kfree(to_delete->user_stack_alloc);
if (to_delete->kernel_stack_alloc) kfree(to_delete->kernel_stack_alloc);
extern void paging_destroy_user_pml4_phys(uint64_t pml4_phys);
// Free the process's page table structure
if (to_delete->pml4_phys && to_delete->is_user) {
paging_destroy_user_pml4_phys(to_delete->pml4_phys);
}
// Free the physical memory occupied by the executable binary
for (uint32_t i = 0; i < to_delete->elf_segment_count; i++) {
if (to_delete->elf_segments[i]) kfree(to_delete->elf_segments[i]);
to_delete->elf_segments[i] = NULL;
}
to_delete->elf_segment_count = 0;
to_delete->user_stack_alloc = NULL;
to_delete->kernel_stack_alloc = NULL;
to_delete->pml4_phys = 0;
@@ -926,8 +942,15 @@ int process_exec_replace_current(registers_t *regs, const char* filepath, const
uint64_t new_pml4 = paging_create_user_pml4_phys();
if (!new_pml4) return -1;
// Free old segments
for (uint32_t i = 0; i < proc->elf_segment_count; i++) {
if (proc->elf_segments[i]) kfree(proc->elf_segments[i]);
proc->elf_segments[i] = NULL;
}
proc->elf_segment_count = 0;
size_t elf_load_size = 0;
uint64_t entry_point = elf_load(filepath, new_pml4, &elf_load_size);
uint64_t entry_point = elf_load(filepath, new_pml4, &elf_load_size, proc);
if (entry_point == 0) {
extern void paging_destroy_user_pml4_phys(uint64_t pml4_phys);
paging_destroy_user_pml4_phys(new_pml4);

View File

@@ -90,8 +90,18 @@ typedef struct process {
uint64_t signal_handlers[MAX_SIGNALS];
uint64_t signal_action_mask[MAX_SIGNALS];
int signal_action_flags[MAX_SIGNALS];
// Tracking for ELF executable segments to allow full memory reclamation on exit.
void *elf_segments[4];
uint32_t elf_segment_count;
} __attribute__((aligned(16))) process_t;
// Loads the ELF executable at 'path' using fat32 into the pagemap given by user_pml4.
// If 'proc' is provided, the physical segments are tracked for later reclamation.
// Returns entry point address on success, or 0 on failure.
struct process;
uint64_t elf_load(const char *path, uint64_t user_pml4, size_t *out_load_size, struct process *proc);
typedef struct {
uint32_t pid;
char name[64];
@@ -110,6 +120,9 @@ void process_set_current_for_cpu(uint32_t cpu_id, process_t* p);
process_t* process_get_current_for_cpu(uint32_t cpu_id);
uint64_t process_schedule(uint64_t current_rsp);
uint64_t process_terminate_current(void);
// Records an allocated ELF segment pointer so it can be freed when the process exits.
void process_add_elf_segment(struct process *proc, void *ptr);
void process_terminate(process_t *proc);
void process_terminate_with_status(process_t *proc, int status);
process_t* process_get_by_pid(uint32_t pid);