diff options
Diffstat (limited to 'sched/scheduler.c')
-rw-r--r-- | sched/scheduler.c | 449 |
1 files changed, 0 insertions, 449 deletions
diff --git a/sched/scheduler.c b/sched/scheduler.c deleted file mode 100644 index a6ace7d..0000000 --- a/sched/scheduler.c +++ /dev/null @@ -1,449 +0,0 @@ -#include <assert.h> -#include <cpu/io.h> -#include <defs.h> -#include <drivers/pit.h> -#include <elf.h> -#include <errno.h> -#include <fs/vfs.h> - -#define STACK_LOCATION ((void *)0x90000000) -#define STACK_SIZE 0x80000 -#define HEAP_SIZE 0x400000 -#define HEAP_LOCATION (STACK_LOCATION - STACK_SIZE - HEAP_SIZE) - -process_t *ready_queue; -process_t *current_task = NULL; -uint32_t next_pid = 0; - -extern uint32_t read_eip(void); - -process_t *get_current_task(void) { return current_task; } - -void set_signal_handler(int sig, void (*handler)(int)) { - if (sig >= 20 || sig < 0) - return; - if (9 == sig) - return; - current_task->signal_handlers[sig] = handler; -} - -process_t *create_process(process_t *p) { - process_t *r; - r = ksbrk(sizeof(process_t)); - r->dead = 0; - r->pid = next_pid++; - r->esp = r->ebp = 0; - r->eip = 0; - r->sleep_until = 0; - if (!p) { - assert(1 == next_pid); - strncpy(r->program_name, "[kernel]", sizeof(current_task->program_name)); - } else - strncpy(r->program_name, "[Not yet named]", - sizeof(current_task->program_name)); - - r->cr3 = (p) ? clone_directory(get_active_pagedirectory()) - : get_active_pagedirectory(); - r->next = 0; - r->incoming_signal = 0; - r->parent = p; - r->child = NULL; - r->halt_list = NULL; - - mmu_allocate_region((void *)(0x80000000 - 0x1000), 0x1000, MMU_FLAG_RW, - r->cr3); - r->signal_handler_stack = 0x80000000; - - strcpy(r->current_working_directory, "/"); - r->data_segment_end = (p) ? p->data_segment_end : NULL; - memset((void *)r->halts, 0, 2 * sizeof(uint32_t)); - for (int i = 0; i < 100; i++) { - if (p) { - r->file_descriptors[i] = p->file_descriptors[i]; - if (r->file_descriptors[i]) { - r->file_descriptors[i]->reference_count++; - } - } - if (i < 20) - r->signal_handlers[i] = NULL; - r->read_halt_inode[i] = NULL; - r->write_halt_inode[i] = NULL; - r->disconnect_halt_inode[i] = NULL; - r->maps[i] = NULL; - } - return r; -} - -int get_free_fd(process_t *p, int allocate) { - if (!p) - p = (process_t *)current_task; - int i; - for (i = 0; i < 100; i++) - if (!p->file_descriptors[i]) - break; - if (p->file_descriptors[i]) - return -1; - if (allocate) { - vfs_fd_t *fd = p->file_descriptors[i] = kmalloc(sizeof(vfs_fd_t)); - fd->inode = kmalloc(sizeof(vfs_inode_t)); - } - return i; -} - -void tasking_init(void) { current_task = ready_queue = create_process(NULL); } - -int i = 0; -void __attribute__((optimize("O0"))) free_process(void) { - kprintf("Exiting process: %s\n", get_current_task()->program_name); - // free_process() will purge all contents such as allocated frames - // out of the current process. This will be called by exit() and - // exec*(). - - // Do a special free for shared memory which avoids labeling - // underlying frames as "unused". - for (int i = 0; i < 100; i++) { - vfs_close(i); - if (!current_task->maps[i]) - continue; - MemoryMap *m = current_task->maps[i]; - mmu_remove_virtual_physical_address_mapping(m->u_address, m->length); - } - - // NOTE: Kernel stuff begins at 0x90000000 - mmu_free_address_range((void *)0x1000, 0x90000000); -} - -void exit(int status) { - assert(current_task->pid != 1); - if (current_task->parent) { - current_task->parent->halts[WAIT_CHILD_HALT] = 0; - current_task->parent->child_rc = status; - } - process_t *new_task = current_task; - for (; new_task == current_task;) { - if (!new_task->next) - new_task = ready_queue; - new_task = new_task->next; - } - - free_process(); - // Remove current_task from list - for (process_t *tmp = ready_queue; tmp;) { - if (tmp == current_task) // current_task is ready_queue(TODO: - // Figure out whether this could even - // happen) - { - ready_queue = current_task->next; - break; - } - if (tmp->next == current_task) { - tmp->next = tmp->next->next; - break; - } - tmp = tmp->next; - } - current_task->dead = 1; - // This function will enable interrupts - switch_task(); -} - -uint32_t setup_stack(uint32_t stack_pointer, int argc, char **argv) { - mmu_allocate_region(STACK_LOCATION - STACK_SIZE, STACK_SIZE, MMU_FLAG_RW, - NULL); - flush_tlb(); - - uint32_t ptr = stack_pointer; - - char *argv_ptrs[argc + 1]; - for (int i = 0; i < argc; i++) { - char *s = argv[i]; - size_t l = strlen(s); - ptr -= l + 1; - char *b = (char *)ptr; - memcpy(b, s, l); - b[l] = '\0'; - argv_ptrs[i] = b; - } - - char **ptrs[argc + 1]; - for (int i = argc; i >= 0; i--) { - ptr -= sizeof(char *); - ptrs[i] = (char **)ptr; - if (i != argc) { - *(ptrs[i]) = argv_ptrs[i]; - } else { - *(ptrs[i]) = NULL; - } - } - - char *s = (char *)ptr; - ptr -= sizeof(char **); - *(char ***)ptr = (char **)s; - - ptr -= sizeof(int); - *(int *)ptr = argc; - return ptr; -} - -int exec(const char *filename, char **argv) { - // exec() will "takeover" the process by loading the file specified in - // filename into memory, change from ring 0 to ring 3 and jump to the - // files entry point as decided by the ELF header of the file. - int argc = 0; - for (; argv[argc];) { - argc++; - } - - uint32_t end_of_code; - void *entry = load_elf_file(filename, &end_of_code); - if (!entry) { - return 0; - } - - strncpy(current_task->program_name, filename, - sizeof(current_task->program_name)); - - current_task->data_segment_end = align_page((void *)end_of_code); - - uint32_t ptr = setup_stack(0x90000000, argc, argv); - - jump_usermode((void (*)())(entry), ptr); - ASSERT_NOT_REACHED; - return 0; -} - -int __attribute__((optimize("O0"))) fork(void) { - process_t *parent_task = (process_t *)current_task; - - process_t *new_task = create_process(parent_task); - - process_t *tmp_task = (process_t *)ready_queue; - for (; tmp_task->next;) - tmp_task = tmp_task->next; - - tmp_task->next = new_task; - - uint32_t eip = read_eip(); - - if (current_task != parent_task) { - return 0; - } - - new_task->child_rc = -1; - new_task->parent = current_task; - current_task->child = new_task; - - new_task->eip = eip; - asm("\ - mov %%esp, %0;\ - mov %%ebp, %1;" - : "=r"(new_task->esp), "=r"(new_task->ebp)); - asm("sti"); - return new_task->pid; -} - -int is_halted(process_t *process) { - for (int i = 0; i < 2; i++) - if (process->halts[i]) - return 1; - - if (isset_fdhalt(process->read_halt_inode, process->write_halt_inode, - process->disconnect_halt_inode)) { - return 1; - } - return 0; -} - -extern PageDirectory *active_directory; - -process_t *next_task(process_t *c) { - for (;;) { - c = c->next; - if (!c) - c = ready_queue; - if (c->incoming_signal) - break; - if (c->sleep_until > pit_num_ms()) - continue; - if (is_halted(c) || c->dead) - continue; - break; - } - return c; -} - -int task_save_state(void) { - asm("mov %%esp, %0" : "=r"(current_task->esp)); - asm("mov %%ebp, %0" : "=r"(current_task->ebp)); - - uint32_t eip = read_eip(); - - if (0x1 == eip) { - // Should the returned value from read_eip be equal to one it - // means that we have just switched over to this task after we - // saved the state(since the switch_task() function changes the - // eax register to 1). - return 0; - } - - current_task->eip = eip; - return 1; -} - -int kill(pid_t pid, int sig) { - process_t *p = current_task; - p = p->next; - if (!p) - p = ready_queue; - for (; p->pid != pid;) { - if (p == current_task) - break; - p = p->next; - if (!p) - p = ready_queue; - } - if (p->pid != pid) - return -ESRCH; - p->incoming_signal = sig; - return 0; -} - -void jump_signal_handler(void *func, uint32_t esp); -void switch_task() { - if (!current_task) - return; - - if (0 == task_save_state()) { - return; - } - - current_task = next_task((process_t *)current_task); - - active_directory = current_task->cr3; - - if (current_task->incoming_signal) { - uint8_t sig = current_task->incoming_signal; - current_task->incoming_signal = 0; - asm("mov %0, %%cr3" ::"r"(current_task->cr3->physical_address)); - - void *handler = current_task->signal_handlers[sig]; - if (9 == sig) { - klog("Task recieved SIGKILL", LOG_NOTE); - exit(0); - } - if (!handler) { - klog("Task recieved unhandeled signal. Killing process.", LOG_WARN); - exit(1); - } - jump_signal_handler(handler, current_task->signal_handler_stack); - } else { - asm(" \ - mov %0, %%esp; \ - mov %1, %%ebp; \ - mov %2, %%ecx; \ - mov %3, %%cr3; \ - mov $0x1, %%eax; \ - jmp *%%ecx" ::"r"(current_task->esp), - "r"(current_task->ebp), "r"(current_task->eip), - "r"(current_task->cr3->physical_address)); - } -} - -MemoryMap **get_free_map(void) { - for (int i = 0; i < 100; i++) - if (!(current_task->maps[i])) - return &(current_task->maps[i]); - assert(0); - return NULL; -} - -void *get_free_virtual_memory(size_t length) { - void *n = - (void *)((uintptr_t)(get_current_task()->data_segment_end) + length); - - void *rc = get_current_task()->data_segment_end; - get_current_task()->data_segment_end = align_page(n); - return rc; -} - -void *allocate_virtual_user_memory(size_t length, int prot, int flags) { - (void)prot; - (void)flags; - void *rc = get_free_virtual_memory(length); - if ((void *)-1 == rc) - return (void *)-1; - - mmu_allocate_region(rc, length, MMU_FLAG_RW, NULL); - return rc; -} - -void *user_kernel_mapping(void *kernel_addr, size_t length) { - void *rc = get_free_virtual_memory(length); - if ((void *)-1 == rc) - return (void *)-1; - - mmu_map_directories(rc, NULL, kernel_addr, NULL, length); - return rc; -} - -void *create_physical_mapping(void **physical_addresses, size_t length) { - void *rc = get_free_virtual_memory(length); - if ((void *)-1 == rc) - return (void *)-1; - int n = (uintptr_t)align_page((void *)length) / 0x1000; - for (int i = 0; i < n; i++) { - mmu_map_physical(rc + (i * 0x1000), NULL, physical_addresses[i], 0x1000); - } - return rc; -} - -void *mmap(void *addr, size_t length, int prot, int flags, int fd, - size_t offset) { - (void)addr; - if (0 == length) { - kprintf("EINVAL\n"); - return (void *)-EINVAL; - } - - MemoryMap **ptr = get_free_map(); - if (!ptr) { - klog("mmap(): No free memory map.", LOG_WARN); - return (void *)-1; - } - *ptr = kmalloc(sizeof(MemoryMap)); - MemoryMap *free_map = *ptr; - - if (fd == -1) { - void *rc = allocate_virtual_user_memory(length, prot, flags); - if ((void *)-1 == rc) { - kprintf("ENOMEM\n"); - return (void *)-ENOMEM; - } - free_map->u_address = rc; - free_map->k_address = NULL; - free_map->length = length; - free_map->fd = -1; - return rc; - } - - vfs_vm_object_t *vmobject = vfs_get_vm_object(fd, length, offset); - if (!vmobject) { - kprintf("ENODEV\n"); - return (void *)-ENODEV; - } - - if (vmobject->size < length) { - kprintf("EOVERFLOW\n"); - return (void *)-EOVERFLOW; // TODO: Check if this is the correct - // code. - } - - if (length > vmobject->size) - length = vmobject->size; - void *rc = create_physical_mapping(vmobject->object, length); - free_map->u_address = rc; - free_map->k_address = NULL; - free_map->length = length; - free_map->fd = fd; - return rc; -} |