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