sched.h: create_new_process - correct function to create a new process in an available spot
This commit is contained in:
parent
ef854fba54
commit
61017db51c
28
kernel.c
28
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
17
kernel.h
17
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();
|
||||
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user