From c047dd687b3ab513a3dd4b1df885e14e4f2e927a Mon Sep 17 00:00:00 2001 From: Ruslan Isaev Date: Mon, 23 Jun 2025 00:05:21 +0300 Subject: [PATCH] tasking: implement task_kill function, thanks deepseek --- include/paging.h | 4 ++ include/task.h | 5 +- src/mm/page_alloc.c | 2 +- src/mm/paging.c | 33 ++++++------ src/tasking/syscalls.c | 5 +- src/tasking/task.c | 114 ++++++++++++++++++++--------------------- 6 files changed, 86 insertions(+), 77 deletions(-) diff --git a/include/paging.h b/include/paging.h index 44c640b..01baa0a 100644 --- a/include/paging.h +++ b/include/paging.h @@ -41,6 +41,10 @@ uint32_t phys_to_virt(uint32_t phys); uint32_t* create_page_dir(); void destroy_page_dir(uint32_t* page_dir); +static inline uint32_t virt_to_phys(void* virt) { + return (uint32_t)virt - 0xC0000000; +} + //page_alloc.c void set_bit(uint32_t page_index); void clear_bit(uint32_t page_index); diff --git a/include/task.h b/include/task.h index 24ddccd..561ccb4 100644 --- a/include/task.h +++ b/include/task.h @@ -63,13 +63,14 @@ typedef struct Process struct Process* next; // Следующий процесс file_t* file_descriptors[MAX_OPEN_FILES]; + uint8_t zombie; } Process; extern Process* current; Process* task_create(uint32_t func, uint32_t user_esp, uint32_t ring, uint32_t* pagedir); -void task_kill(Process* proc); -void task_exit(); + +void task_kill(Process* proc); void scheduler_init(); void schedule(); diff --git a/src/mm/page_alloc.c b/src/mm/page_alloc.c index bb16eb9..6d3a217 100644 --- a/src/mm/page_alloc.c +++ b/src/mm/page_alloc.c @@ -17,7 +17,7 @@ void set_bit(uint32_t page_index) { // Сбросить бит (пометить страницу как свободную) void clear_bit(uint32_t page_index) { if (page_index >= PAGE_COUNT) { - printf("clear_bit: address out of range\n"); + printf("clear_bit: address %X out of range\n", page_index); return; } diff --git a/src/mm/paging.c b/src/mm/paging.c index 80fc346..d458f92 100644 --- a/src/mm/paging.c +++ b/src/mm/paging.c @@ -147,26 +147,27 @@ uint32_t* create_page_dir() return new_pd; } +//TODO: this function is somehow messes up addresses so free_page passes page_nums like 0xF000F into clear_bit void destroy_page_dir(uint32_t* page_dir) { - // Iterate through all page directory entries - for (int i = 0; i < 1024; i++) { - if (page_dir[i] & 1) { // If page table exists - uint32_t* page_table = (uint32_t*)(page_dir[i] & 0xFFFFF000); - - // Free all user pages (0-767) - if (i < 768) { - for (int j = 0; j < 1024; j++) { - if (page_table[j] & 1) { - free_page((void*)(page_table[j] & 0xFFFFF000)); - } + // Temporarily switch to target PD for freeing + uint32_t orig_cr3; + asm volatile("mov %%cr3, %0" : "=r"(orig_cr3)); + asm volatile("mov %0, %%cr3" : : "r"(virt_to_phys(page_dir))); + + // Free only user-space pages (entries 0-767) + for (int i = 0; i < 768; i++) { + if (page_dir[i] & PAGE_PRESENT) { + uint32_t* pt = (uint32_t*)phys_to_virt(page_dir[i] & ~0xFFF); + for (int j = 0; j < 1024; j++) { + if (pt[j] & PAGE_PRESENT) { + free_page((void*)(pt[j] & ~0xFFF)); } } - - // Free the page table itself - free_page(page_table); + free_page((void*)(page_dir[i] & ~0xFFF)); } } - // Free the page directory - free_page(page_dir); + // Restore original page directory + asm volatile("mov %0, %%cr3" : : "r"(orig_cr3)); + free_page((void*)virt_to_phys(page_dir)); } \ No newline at end of file diff --git a/src/tasking/syscalls.c b/src/tasking/syscalls.c index 3c62043..053bb83 100644 --- a/src/tasking/syscalls.c +++ b/src/tasking/syscalls.c @@ -49,8 +49,11 @@ const char* flags_to_mode_str(int flags) { int sys_exit(TrapFrame *tf) { int error_code = tf->ebx; - + printf("killing task\n"); task_kill(current); + asm("sti"); + while(1){} + printf("wtf??"); return error_code; } diff --git a/src/tasking/task.c b/src/tasking/task.c index 1967f96..196820a 100644 --- a/src/tasking/task.c +++ b/src/tasking/task.c @@ -8,6 +8,7 @@ Process* current = 0; Process* queue = 0; +Process* zombie_list = 0; uint32_t irq_disable_counter = 0; uint32_t pid_counter; @@ -18,7 +19,8 @@ uint32_t task_count; extern void trapret(void); extern void switchProcess(Process* next); -extern Process* queue; +//extern Process* queue; + extern uint32_t pid_counter; extern uint32_t task_count; @@ -108,18 +110,40 @@ void scheduler_unlock() asm volatile("sti"); } -void schedule() -{ - if (!current) - return; +//TODO: there's an issue with this. If there's only one task in the queue (or is it there really?), +//the scheduler doesn't switch the context to it, but just does nothing +void schedule() { + if (!current) return; + + // Clean any terminated processes in queue + Process* prev = NULL; + Process* curr = queue; + while (curr) { + if (curr->state == Terminated) { + Process* next = curr->next; + if (prev) prev->next = next; + else queue = next; + + destroy_page_dir(curr->pagedir); + free_page((void*)virt_to_phys(curr->kstack)); + free_page((void*)virt_to_phys(curr)); + + curr = next; + } else { + prev = curr; + curr = curr->next; + } + } Process* next = current->next; - if (!next) - next = queue; - if (next != current) - { - switchProcess(next); + if (!next) next = queue; + while (next && next->state != Ready) { + next = next->next; + if (!next) next = queue; } + if (!next || next == current) return; + + switchProcess(next); } void idle() @@ -149,59 +173,35 @@ void scheduler_init() task_create((uint32_t)idle, 0, 0, kernel_tasks_pagedir); } -void task_exit() -{ - task_kill(current); -} +void task_kill(Process* proc) { + //that proc != current is sus + if (!proc || proc != current) return; -void task_kill(Process* proc) -{ scheduler_lock(); + proc->state = Terminated; - // Remove process from scheduler queue - Process* prev = NULL; - Process* curr = queue; + // Remove from process queue + if (queue == proc) { + queue = proc->next; + } else { + Process* prev = queue; + while (prev && prev->next != proc) prev = prev->next; + if (prev) prev->next = proc->next; + } + + // Schedule next process + Process* next = queue; + while (next && next->state != Ready) next = next->next; + if (!next) next = queue; // Fallback to idle if needed - while (curr) { - if (curr == proc) { - if (prev) { - prev->next = curr->next; - } else { - queue = curr->next; - } - break; - } - prev = curr; - curr = curr->next; - } - - for (int i = 0; i < MAX_OPEN_FILES; i++) { - if (proc->file_descriptors[i] != NULL) { - fat_fclose(proc->file_descriptors[i]); - free(proc->file_descriptors[i]); - proc->file_descriptors[i] = NULL; - } - } - - // Free kernel stack - if (proc->kstack) { - uint32_t kstack_phys = (uint32_t)proc->kstack - 0xC0000000; - free_page((void*)kstack_phys); - } + current = next; + set_page_dir(virt_to_phys(next->pagedir)); - // Free process structure - uint32_t proc_phys = (uint32_t)proc - 0xC0000000; - free_page((void*)proc_phys); - - // Destroy page directory and free user pages + // Free resources safely from new context destroy_page_dir(proc->pagedir); + free_page((void*)virt_to_phys(proc->kstack)); + free_page((void*)virt_to_phys(proc)); - // Update task count and current process if needed - task_count--; - if (proc == current) { - current = NULL; - schedule(); // Switch to another process - } - scheduler_unlock(); + switchProcess(next); } \ No newline at end of file