tasking: continue fixing task_kill
This commit is contained in:
@@ -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
@@ -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
@@ -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,7 +134,9 @@ uint32_t* create_page_dir()
|
||||
|
||||
for(int i = 768; i < 1023; i++)
|
||||
{
|
||||
new_pd[i] = current_pd[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]
|
||||
@@ -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);
|
||||
for (int j = 0; j < 1024; j++) {
|
||||
if (pt[j] & PAGE_PRESENT) {
|
||||
free_page((void*)(pt[j] & ~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++) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
// After freeing all pages within the table, free the page table itself
|
||||
free_page((void*)pt_phys);
|
||||
}
|
||||
free_page((void*)(page_dir[i] & ~0xFFF));
|
||||
}
|
||||
}
|
||||
|
||||
// Restore original page directory
|
||||
asm volatile("mov %0, %%cr3" : : "r"(orig_cr3));
|
||||
free_page((void*)virt_to_phys(page_dir));
|
||||
// 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));
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
{
|
||||
|
||||
+42
-18
@@ -98,37 +98,61 @@ 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;
|
||||
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 {
|
||||
queue = next_proc;
|
||||
}
|
||||
|
||||
destroy_page_dir(curr->pagedir);
|
||||
free_page((void*)virt_to_phys(curr->kstack));
|
||||
free_page((void*)virt_to_phys(curr));
|
||||
// If the terminated process is the current one, we must not switch to it.
|
||||
if (p == current) {
|
||||
current = NULL;
|
||||
}
|
||||
|
||||
curr = next;
|
||||
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 = curr;
|
||||
curr = curr->next;
|
||||
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;
|
||||
|
||||
switchProcess(next);
|
||||
if (next && next != current) {
|
||||
switchProcess(next);
|
||||
}
|
||||
|
||||
scheduler_unlock();
|
||||
}
|
||||
|
||||
void idle()
|
||||
|
||||
Reference in New Issue
Block a user