tasking: implement task_kill function, thanks deepseek

This commit is contained in:
2025-06-23 00:25:23 +03:00
parent 70d6aacb91
commit c047dd687b
6 changed files with 86 additions and 77 deletions
+4
View File
@@ -41,6 +41,10 @@ uint32_t phys_to_virt(uint32_t phys);
uint32_t* create_page_dir(); uint32_t* create_page_dir();
void destroy_page_dir(uint32_t* 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 //page_alloc.c
void set_bit(uint32_t page_index); void set_bit(uint32_t page_index);
void clear_bit(uint32_t page_index); void clear_bit(uint32_t page_index);
+3 -2
View File
@@ -63,13 +63,14 @@ typedef struct Process
struct Process* next; // Следующий процесс struct Process* next; // Следующий процесс
file_t* file_descriptors[MAX_OPEN_FILES]; file_t* file_descriptors[MAX_OPEN_FILES];
uint8_t zombie;
} Process; } Process;
extern Process* current; extern Process* current;
Process* task_create(uint32_t func, uint32_t user_esp, uint32_t ring, uint32_t* pagedir); 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 scheduler_init();
void schedule(); void schedule();
+1 -1
View File
@@ -17,7 +17,7 @@ void set_bit(uint32_t page_index) {
// Сбросить бит (пометить страницу как свободную) // Сбросить бит (пометить страницу как свободную)
void clear_bit(uint32_t page_index) { void clear_bit(uint32_t page_index) {
if (page_index >= PAGE_COUNT) { 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; return;
} }
+16 -15
View File
@@ -147,26 +147,27 @@ uint32_t* create_page_dir()
return new_pd; 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) { void destroy_page_dir(uint32_t* page_dir) {
// Iterate through all page directory entries // Temporarily switch to target PD for freeing
for (int i = 0; i < 1024; i++) { uint32_t orig_cr3;
if (page_dir[i] & 1) { // If page table exists asm volatile("mov %%cr3, %0" : "=r"(orig_cr3));
uint32_t* page_table = (uint32_t*)(page_dir[i] & 0xFFFFF000); asm volatile("mov %0, %%cr3" : : "r"(virt_to_phys(page_dir)));
// Free all user pages (0-767) // Free only user-space pages (entries 0-767)
if (i < 768) { for (int i = 0; i < 768; i++) {
for (int j = 0; j < 1024; j++) { if (page_dir[i] & PAGE_PRESENT) {
if (page_table[j] & 1) { uint32_t* pt = (uint32_t*)phys_to_virt(page_dir[i] & ~0xFFF);
free_page((void*)(page_table[j] & 0xFFFFF000)); for (int j = 0; j < 1024; j++) {
} if (pt[j] & PAGE_PRESENT) {
free_page((void*)(pt[j] & ~0xFFF));
} }
} }
free_page((void*)(page_dir[i] & ~0xFFF));
// Free the page table itself
free_page(page_table);
} }
} }
// Free the page directory // Restore original page directory
free_page(page_dir); asm volatile("mov %0, %%cr3" : : "r"(orig_cr3));
free_page((void*)virt_to_phys(page_dir));
} }
+4 -1
View File
@@ -49,8 +49,11 @@ const char* flags_to_mode_str(int flags) {
int sys_exit(TrapFrame *tf) int sys_exit(TrapFrame *tf)
{ {
int error_code = tf->ebx; int error_code = tf->ebx;
printf("killing task\n");
task_kill(current); task_kill(current);
asm("sti");
while(1){}
printf("wtf??");
return error_code; return error_code;
} }
+55 -55
View File
@@ -8,6 +8,7 @@
Process* current = 0; Process* current = 0;
Process* queue = 0; Process* queue = 0;
Process* zombie_list = 0;
uint32_t irq_disable_counter = 0; uint32_t irq_disable_counter = 0;
uint32_t pid_counter; uint32_t pid_counter;
@@ -18,7 +19,8 @@ uint32_t task_count;
extern void trapret(void); extern void trapret(void);
extern void switchProcess(Process* next); extern void switchProcess(Process* next);
extern Process* queue; //extern Process* queue;
extern uint32_t pid_counter; extern uint32_t pid_counter;
extern uint32_t task_count; extern uint32_t task_count;
@@ -108,18 +110,40 @@ void scheduler_unlock()
asm volatile("sti"); asm volatile("sti");
} }
void schedule() //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
if (!current) void schedule() {
return; 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; Process* next = current->next;
if (!next) if (!next) next = queue;
next = queue; while (next && next->state != Ready) {
if (next != current) next = next->next;
{ if (!next) next = queue;
switchProcess(next);
} }
if (!next || next == current) return;
switchProcess(next);
} }
void idle() void idle()
@@ -149,59 +173,35 @@ void scheduler_init()
task_create((uint32_t)idle, 0, 0, kernel_tasks_pagedir); task_create((uint32_t)idle, 0, 0, kernel_tasks_pagedir);
} }
void task_exit() void task_kill(Process* proc) {
{ //that proc != current is sus
task_kill(current); if (!proc || proc != current) return;
}
void task_kill(Process* proc)
{
scheduler_lock(); scheduler_lock();
proc->state = Terminated;
// Remove process from scheduler queue // Remove from process queue
Process* prev = NULL; if (queue == proc) {
Process* curr = queue; queue = proc->next;
} else {
while (curr) { Process* prev = queue;
if (curr == proc) { while (prev && prev->next != proc) prev = prev->next;
if (prev) { if (prev) prev->next = proc->next;
prev->next = curr->next;
} else {
queue = curr->next;
}
break;
}
prev = curr;
curr = curr->next;
} }
for (int i = 0; i < MAX_OPEN_FILES; i++) { // Schedule next process
if (proc->file_descriptors[i] != NULL) { Process* next = queue;
fat_fclose(proc->file_descriptors[i]); while (next && next->state != Ready) next = next->next;
free(proc->file_descriptors[i]); if (!next) next = queue; // Fallback to idle if needed
proc->file_descriptors[i] = NULL;
}
}
// Free kernel stack current = next;
if (proc->kstack) { set_page_dir(virt_to_phys(next->pagedir));
uint32_t kstack_phys = (uint32_t)proc->kstack - 0xC0000000;
free_page((void*)kstack_phys);
}
// Free process structure // Free resources safely from new context
uint32_t proc_phys = (uint32_t)proc - 0xC0000000;
free_page((void*)proc_phys);
// Destroy page directory and free user pages
destroy_page_dir(proc->pagedir); destroy_page_dir(proc->pagedir);
free_page((void*)virt_to_phys(proc->kstack));
// Update task count and current process if needed free_page((void*)virt_to_phys(proc));
task_count--;
if (proc == current) {
current = NULL;
schedule(); // Switch to another process
}
scheduler_unlock(); scheduler_unlock();
switchProcess(next);
} }