mirror of
https://github.com/JannisHeydemann/BoredOS.git
synced 2026-05-30 02:16:58 +00:00
fix(net): improve network stability and resource management
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user