tasking: continue fixing task_kill

This commit is contained in:
2025-06-23 23:41:01 +03:00
parent 29de6e6f43
commit b769ac0a58
6 changed files with 125 additions and 73 deletions
+1
View File
@@ -46,6 +46,7 @@ static inline uint32_t virt_to_phys(void* virt) {
}
//page_alloc.c
int is_page_in_use(uint32_t page_index);
void set_bit(uint32_t page_index);
void clear_bit(uint32_t page_index);
void init_allocator();
+19 -12
View File
@@ -7,6 +7,15 @@
// Каждый бит представляет одну страницу: 0 = свободна, 1 = занята
uint8_t page_bitmap[BITMAP_SIZE];
int is_page_in_use(uint32_t page_index) {
if (page_index >= PAGE_COUNT) {
return 0; // Out of range is considered "not in use by our allocator"
}
uint32_t byte_index = page_index / 8;
uint8_t bit_offset = page_index % 8;
return (page_bitmap[byte_index] & (1 << bit_offset));
}
// Установить бит (пометить страницу как занятую)
void set_bit(uint32_t page_index) {
uint32_t byte_index = page_index / 8; // Номер байта в битовой карте
@@ -21,16 +30,14 @@ void clear_bit(uint32_t page_index) {
return;
}
uint32_t byte_index = page_index / 8;
uint8_t bit_offset = page_index % 8;
//check if this is needed at all except for debug purposes
if(!(page_bitmap[byte_index] & (1 << bit_offset)))
{
printf("clear_bit: page #0x%X already free\n", page_index);
if (!is_page_in_use(page_index)) {
printf("clear_bit: warning, page #0x%X was already free.\n", page_index);
return;
}
uint32_t byte_index = page_index / 8;
uint8_t bit_offset = page_index % 8;
page_bitmap[byte_index] &= ~(1 << bit_offset); // Сбрасываем бит
}
@@ -49,14 +56,14 @@ void* alloc_page() {
//printf("!!!free page at 0x%X!!!\n", i);
for (j = 0; j < 8; j++) {
if (!(page_bitmap[i] & (1 << j))) { // Если этот бит = 0 (свободен)
page_bitmap[i] |= (1 << j); // Помечаем как занятый
// Вычисляем физический адрес страницы
uint32_t page_num = i * 8 + j;
void* addr = (void*)(page_num * PAGE_SIZE);
//printf("allocated page at 0x%X (page #0x%X)\n", addr, page_num);
if(page_num == 0)
continue;
printf("allocating page %X\n", page_num * PAGE_SIZE);
page_bitmap[i] |= (1 << j); // Помечаем как занятый
return (void*)(page_num * PAGE_SIZE);
}
}
+38 -19
View File
@@ -41,8 +41,8 @@ uint32_t setup_tmp_pgdir(uint32_t magic, uint32_t info)
if(!(n % 1024)) {
pd = n / 1024;
uint32_t pt_phys = (uint32_t)page_table - PAGE_OFFSET + (PAGE_SIZE * pd);
kpage_dir[pd] = pt_phys | PAGE_PRESENT | PAGE_RW | PAGE_USER;//TODO: fix, I don't think pd should have DPL3
kpage_dir[GET_PGDIR(PAGE_OFFSET) + pd] = pt_phys | PAGE_PRESENT | PAGE_RW | PAGE_USER;//TODO: fix, I don't think pd should have DPL3
kpage_dir[pd] = pt_phys | PAGE_PRESENT | PAGE_RW;//TODO: fix, I don't think pd should have DPL3
kpage_dir[GET_PGDIR(PAGE_OFFSET) + pd] = pt_phys | PAGE_PRESENT | PAGE_RW;//TODO: fix, I don't think pd should have DPL3
}
}
@@ -134,8 +134,10 @@ uint32_t* create_page_dir()
for(int i = 768; i < 1023; i++)
{
if(current_pd[i] & PAGE_PRESENT) {
new_pd[i] = current_pd[i];
}
}
int vga_pde_index = 0; // Virtual address 0x000B8000 is covered by PDE[0]
if (current_pd[vga_pde_index] & PAGE_PRESENT) {
@@ -147,27 +149,44 @@ 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) {
// 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)));
void destroy_page_dir(uint32_t* page_dir_virt) {
if (page_dir_virt == NULL) {
return;
}
// Free only user-space pages (entries 0-767)
// Iterate through user-space page directory entries (PDEs 0-767).
// Kernel space (768+) is shared and should not be freed.
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);
uint32_t pde = page_dir_virt[i];
// Check if the page directory entry is present
if (pde & PAGE_PRESENT) {
// Get the physical address of the page table
uint32_t pt_phys = pde & ~0xFFF;
if(is_page_in_use(pt_phys / PAGE_SIZE)){
// Convert it to a virtual address the kernel can access
uint32_t* page_table_virt = (uint32_t*)phys_to_virt(pt_phys);
// Iterate through all 1024 entries in this page table
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));
uint32_t pte = page_table_virt[j];
// If the page table entry is present, free the physical page (frame) it points to
if (pte & PAGE_PRESENT) {
printf("freeing page %X\n", pte);
free_page((void*)(pte & ~0xFFF));
}
}
// Restore original page directory
asm volatile("mov %0, %%cr3" : : "r"(orig_cr3));
free_page((void*)virt_to_phys(page_dir));
// After freeing all pages within the table, free the page table itself
free_page((void*)pt_phys);
}
}
}
// Finally, free the page directory itself.
// We need its physical address to pass to the physical memory manager.
printf("freeing PD page %X\n", virt_to_phys(page_dir_virt));
free_page((void*)virt_to_phys(page_dir_virt));
}
+10 -10
View File
@@ -69,16 +69,16 @@ void exec_from_file(const char* filename)
uint8_t* file;
int result = read_file(filename, &file);
debug_log("result: %X\n", result);
debug_log("buffer: %s\n", file);
//debug_log("result: %X\n", result);
//debug_log("buffer: %s\n", file);
Elf32_Ehdr *elf_ehdr = (Elf32_Ehdr*)file;
int program_header_table_entry_count = elf_ehdr->e_phnum;
int program_header_table_entry_size = elf_ehdr->e_phentsize;
debug_log("magic: %X, type: %X, entry: 0x%X\n", elf_ehdr->e_ident, elf_ehdr->e_type, elf_ehdr->e_entry);
debug_log("PHNUM: %X\n", program_header_table_entry_count);
debug_log("PHENTSIZE: %X\n\n", program_header_table_entry_size);
//debug_log("magic: %X, type: %X, entry: 0x%X\n", elf_ehdr->e_ident, elf_ehdr->e_type, elf_ehdr->e_entry);
//debug_log("PHNUM: %X\n", program_header_table_entry_count);
//debug_log("PHENTSIZE: %X\n\n", program_header_table_entry_size);
uint32_t* proc_pd = create_page_dir();
uint32_t proc_pd_phys = (uint32_t)get_physaddr((void*)proc_pd);
@@ -93,15 +93,15 @@ void exec_from_file(const char* filename)
Elf32_Phdr *elf_phdr = (Elf32_Phdr *)((uint32_t)file + elf_ehdr->e_phoff +
i * elf_ehdr->e_phentsize);
debug_log("HEADER %X, type: 0x%X, vaddr: 0x%X, paddr: 0x%X, memsz: 0x%X\n", i, elf_phdr->p_type, elf_phdr->p_vaddr, elf_phdr->p_paddr, elf_phdr->p_memsz);
//debug_log("HEADER %X, type: 0x%X, vaddr: 0x%X, paddr: 0x%X, memsz: 0x%X\n", i, elf_phdr->p_type, elf_phdr->p_vaddr, elf_phdr->p_paddr, elf_phdr->p_memsz);
if(elf_phdr->p_type != PT_LOAD)
{
debug_log("not PT_LOAD, skipping...\n");
//debug_log("not PT_LOAD, skipping...\n");
continue;
}
int pages_needed = DivRoundUp(elf_phdr->p_memsz, 0x1000);//(elf_phdr->p_memsz / 0x1000) + 1;
debug_log("pages needed: %X\n", pages_needed);
//debug_log("pages needed: %X\n", pages_needed);
for(int j = 0; j < pages_needed; j++)
{
@@ -120,8 +120,8 @@ void exec_from_file(const char* filename)
memset((void*)bss_start, 0, bss_end - bss_start);
}
debug_log("p_filesz: 0x%X (%X)\n", elf_phdr->p_filesz, elf_phdr->p_filesz);
debug_log("================================\n\n\n\n");
//debug_log("p_filesz: 0x%X (%X)\n", elf_phdr->p_filesz, elf_phdr->p_filesz);
//debug_log("================================\n\n\n\n");
}
debug_log("setting up the user stack...\n");
+11 -10
View File
@@ -79,9 +79,9 @@ int sys_write(TrapFrame *tf)
//stdin, stdout or stderr
if(tf->ebx == STDOUT_FILENO)
{
debug_log("\n=================SYS_WRITE output to stdout=====================\n");
//debug_log("\n=================SYS_WRITE output to stdout=====================\n");
print((char*)tf->ecx, tf->edx);
debug_log("\n=================END OF THAT SHIT=====================\n");
//debug_log("\n=================END OF THAT SHIT=====================\n");
return tf->edx;
}
}
@@ -103,16 +103,16 @@ int sys_open(TrapFrame *tf)
int fd = -1;
const char* mode_str = flags_to_mode_str(flags);
debug_log("\n====filename: %s\n", filename);
debug_log("\n====mode_str: %s\n", mode_str);
//debug_log("\n====filename: %s\n", filename);
//debug_log("\n====mode_str: %s\n", mode_str);
for(int i = 3; i < MAX_OPEN_FILES; i++)
{
debug_log("\n====i: %X\n", i);
//debug_log("\n====i: %X\n", i);
if(current->file_descriptors[i] == NULL)
{
current->file_descriptors[i] = malloc(sizeof(file_t)); // Kernel malloc
debug_log("\n====FILE_DESCRIPTOR: %X\n", i);
//debug_log("\n====FILE_DESCRIPTOR: %X\n", i);
int result = fat_fopen(current->file_descriptors[i], filename, mode_str);
if (result < 0) {
free(current->file_descriptors[i]); // Free on failure
@@ -130,12 +130,12 @@ int sys_open(TrapFrame *tf)
int sys_close(TrapFrame *tf)
{
int fd = tf->ebx;
debug_log("SYS_CLOSE: fd = 0x%X", fd);
//debug_log("SYS_CLOSE: fd = 0x%X", fd);
if(current->file_descriptors[fd] != NULL)
{
debug_log("SYS_CLOSE: current->file_descriptors[fd] != NULL");
//debug_log("SYS_CLOSE: current->file_descriptors[fd] != NULL");
int result = fat_fclose(current->file_descriptors[fd]);
debug_log("SYS_CLOSE: fat_fclose result: 0x%X", result);
//debug_log("SYS_CLOSE: fat_fclose result: 0x%X", result);
free(current->file_descriptors[fd]);
current->file_descriptors[fd] = NULL;
return result;
@@ -145,11 +145,12 @@ int sys_close(TrapFrame *tf)
void handle_syscall(TrapFrame *tf)
{
/*
debug_log("EAX: %X ", tf->eax);
debug_log("EBX: %X ", tf->ebx);
debug_log("ECX: %s ", tf->ecx);
debug_log("EDX: %X\n", tf->edx);
*/
if(tf->eax == 1)//exit
{
+43 -19
View File
@@ -98,39 +98,63 @@ void scheduler_unlock()
//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;
scheduler_lock();
// 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;
Process* p = queue;
while (p) {
if (p->state == Terminated) {
Process* next_proc = p->next;
// Unlink from the queue
if (prev) {
prev->next = next_proc;
} else {
prev = curr;
curr = curr->next;
queue = next_proc;
}
// If the terminated process is the current one, we must not switch to it.
if (p == current) {
current = NULL;
}
destroy_page_dir(p->pagedir);
free_page((void*)virt_to_phys(p->kstack));
free_page((void*)virt_to_phys(p));
p = next_proc;
} else {
prev = p;
p = p->next;
}
}
Process* next = current->next;
// If 'current' was terminated or this is the first run, find a new process.
if (!current || current->state != Ready) {
current = queue; // Start search from the beginning
}
// Find the next ready process to run
Process* next = current ? current->next : NULL;
if (!next) next = queue;
// Iterate through the list to find a process that is ready to run
Process* start_node = next;
while (next && next->state != Ready) {
next = next->next;
if (!next) next = queue;
if (!next) next = queue; // Wrap around
if (next == start_node) { // Full circle, no ready process
scheduler_unlock();
return;
}
}
if (!next || next == current) return;
if (next && next != current) {
switchProcess(next);
}
scheduler_unlock();
}
void idle()
{
while (1) {}