diff options
Diffstat (limited to 'sched')
| -rw-r--r-- | sched/scheduler.c | 449 | ||||
| -rw-r--r-- | sched/scheduler.h | 65 | 
2 files changed, 0 insertions, 514 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; -} diff --git a/sched/scheduler.h b/sched/scheduler.h deleted file mode 100644 index fc92ff3..0000000 --- a/sched/scheduler.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef SCHEDULER_H -#define SCHEDULER_H -#include <fs/ext2.h> -#include <fs/vfs.h> -#include <halts.h> -#include <mmu.h> -#include <signal.h> - -#define MAX_PATH 256 -#define KEYBOARD_HALT 0 -#define WAIT_CHILD_HALT 1 - -int fork(void); -int exec(const char *filename, char **argv); -void switch_task(); -void tasking_init(void); -void exit(int status); - -void *mmap(void *addr, size_t length, int prot, int flags, int fd, -           size_t offset); -int munmap(void *addr, size_t length); -int msync(void *addr, size_t length, int flags); -int kill(pid_t pid, int sig); -void set_signal_handler(int sig, void (*handler)(int)); - -typedef struct { -  void *u_address; -  void *k_address; -  uint32_t length; -  int fd; -} MemoryMap; - -typedef struct Process process_t; - -struct Process { -  uint32_t pid; -  char program_name[100]; -  char current_working_directory[MAX_PATH]; -  uint32_t eip, esp, ebp; -  uint8_t incoming_signal; -  uint32_t signal_handler_stack; -  void *signal_handlers[20]; -  PageDirectory *cr3; -  vfs_fd_t *file_descriptors[100]; -  vfs_inode_t *read_halt_inode[100]; -  vfs_inode_t *write_halt_inode[100]; -  vfs_inode_t *disconnect_halt_inode[100]; -  uint32_t halts[2]; -  struct Halt *halt_list; -  void *data_segment_end; -  process_t *next; -  process_t *parent; -  // TODO: Create a linkedlist of childs so that the parent process -  // can do stuff such as reap zombies and get status. -  process_t *child; -  MemoryMap *maps[100]; -  uint32_t sleep_until; -  int child_rc; -  int dead; -}; - -process_t *get_current_task(void); -int get_free_fd(process_t *p, int allocate); -void free_process(void); -#endif  |