tasking: implement task_kill function, thanks deepseek
This commit is contained in:
+57
-57
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user