diff --git a/kernel.c b/kernel.c index a4102a7..017bc81 100644 --- a/kernel.c +++ b/kernel.c @@ -5,10 +5,12 @@ #include "io.h" #include "malloc.h" -void create_processes_from_bin_table(); +void read_binary_table(); extern ProcessControlBlock processes[PROCESS_COUNT]; +// this array is populated when the memory image is built, therefore it should +// resign in a section which is not overwritten with zeros on startup loaded_binary binary_table[NUM_BINARIES] __attribute__ ((section (".data"))); extern void memset(unsigned int, void*, void*); @@ -19,20 +21,20 @@ extern void init() dbgln("Kernel started!", 15); - create_processes_from_bin_table(); + read_binary_table(); scheduler_run_next(); } -void create_processes_from_bin_table() +void read_binary_table() { char msg[28] = "found bin with id 0 at pos 0"; - ProcessControlBlock* next_process = processes; malloc_info info; info.allocate_memory_end = (void*) 0xFF0000; info.allocate_memory_start = (void*) 0; + // calculate the end of loaded binaries for (int i = 0; i < NUM_BINARIES; i++) { if (binary_table[i].binid == 0) break; @@ -50,21 +52,9 @@ void create_processes_from_bin_table() if (binary_table[i].binid == 0) break; - - optional_voidptr stack_top = malloc_stack(1<<12); // allocate 4Kib stack - if (has_error(stack_top)) { - dbgln("Error while allocating stack for initial process", 48); - continue; - } - - next_process->status = PROC_RDY; - next_process->pid = binary_table[i].binid; - next_process->pc = binary_table[i].entrypoint; - - next_process->regs[1] = (int) stack_top.value; // set stack top, put 32 bytes of zeros there - next_process++; - dbgln("enabled process from table", 26); - + // create a new process for each binary found + // it should have around 4kb stack + create_new_process(binary_table+i, 1<<12); } } diff --git a/kernel.h b/kernel.h index 5cfa869..3c4a2cd 100644 --- a/kernel.h +++ b/kernel.h @@ -11,23 +11,6 @@ // scheduler settings #define TIME_SLICE_LEN 100 // number of cpu time ticks per slice - -/* This struct holds information about binaries which are currently loaded into - * memory. Currently the kernel is not able to load binaries into memory, as - * no file system layer is implemented. When the memory image is built, the - * list of loaded binaries is populated aswell. - */ -typedef struct loaded_binary { - int binid; - int entrypoint; - void* bounds[2]; -} loaded_binary; - -// create a global table holding all loaded binaries. -// this is either populated at runtime when binaries are loaded dynamically -// or when a memory image is created. -extern loaded_binary binary_table[NUM_BINARIES]; - // init function extern __attribute__((__noreturn__)) void init(); diff --git a/kinclude/ktypes.h b/kinclude/ktypes.h index 6551a49..54302f3 100644 --- a/kinclude/ktypes.h +++ b/kinclude/ktypes.h @@ -25,6 +25,8 @@ enum process_status { // process structure: typedef struct ProcessControlBlock ProcessControlBlock; +struct loaded_binary; + struct ProcessControlBlock { int pid; int pc; @@ -32,10 +34,24 @@ struct ProcessControlBlock { int exit_code; // scheduling information enum process_status status; - ProcessControlBlock *waiting_for_process; + ProcessControlBlock* waiting_for_process; + struct loaded_binary* binary; unsigned long long int asleep_until; }; + +/* This struct holds information about binaries which are currently loaded into + * memory. Currently the kernel is not able to load binaries into memory, as + * no file system layer is implemented. When the memory image is built, the + * list of loaded binaries is populated aswell. + */ +typedef struct loaded_binary { + int binid; + int entrypoint; + void* bounds[2]; +} loaded_binary; + + /* * Optionals * diff --git a/kinclude/sched.c b/kinclude/sched.c index 450eeed..9dde2f8 100644 --- a/kinclude/sched.c +++ b/kinclude/sched.c @@ -2,6 +2,7 @@ #include "sched.h" #include "csr.h" #include "io.h" +#include "malloc.h" // scheduling data: @@ -9,6 +10,7 @@ ProcessControlBlock processes[PROCESS_COUNT]; ProcessControlBlock* current_process; unsigned long long int scheduling_interrupted_start; unsigned long long int next_interrupt_scheduled_for; +int next_process_id = 1; void scheduler_run_next () { @@ -153,4 +155,55 @@ void set_next_interrupt() void mark_ecall_entry() { scheduling_interrupted_start = read_time(); -} \ No newline at end of file +} + +optional_pcbptr find_available_pcb_slot() { + static int index = 0; + int start_index = index; + ProcessControlBlock* pcb = processes + index; + + while (pcb->status != PROC_DEAD) { + index = (index + 1) % PROCESS_COUNT; + if (index == start_index) + return (optional_pcbptr) { .error = ENOBUFS }; + pcb = processes + index; + } + return (optional_pcbptr) { .value = pcb }; +} + +int create_new_process(loaded_binary* bin, int stack_size) +{ + // try to get a position in the processes list + optional_pcbptr slot_or_err = find_available_pcb_slot(); + // if that failed, we cannot creat a new process + if (has_error(slot_or_err)) { + dbgln("No more process structs!", 24); + return slot_or_err.error; + } + + // allocate stack for the new process + optional_voidptr stack_top_or_err = malloc_stack(stack_size); // allocate 4Kib stack + // if that failed, we also can't create a new process + if (has_error(stack_top_or_err)) { + dbgln("Error while allocating stack for process", 40); + return stack_top_or_err.error; + } + + ProcessControlBlock* pcb = slot_or_err.value; + + // determine next pid + int pid = next_process_id++; + + // mark process as ready + pcb->status = PROC_RDY; + pcb->pid = pid; + pcb->pc = bin->entrypoint; + pcb->binary = bin; + // load stack top into stack pointer register + pcb->regs[1] = (int) stack_top_or_err.value; + // load pid into a0 register + pcb->regs[9] = pid; + + dbgln("Created new process!", 20); + +} diff --git a/kinclude/sched.h b/kinclude/sched.h index a808c7a..a4937fe 100644 --- a/kinclude/sched.h +++ b/kinclude/sched.h @@ -18,4 +18,7 @@ int scheduler_index_from_pid(int pid); int* get_current_process_registers(); ProcessControlBlock* get_current_process(); void mark_ecall_entry(); + +int create_new_process(loaded_binary* bin, int stack_size); + #endif \ No newline at end of file