CeDOS - Commit fb3b4a8c

sched: Use kernel entry as idle process Previously, we created a new page directory for the entry process and had a whole lot of if statements in the scheduler to treat the idle process specially. Instead, we now just use the page directory we got from the bootloader, and enter the idle process from the kernel main. That way, we don't waste pages, we keep the startup context on the idle process stack, and have a cleared-up scheduler function that does not occlude what happens in PID 0.
Celina Sophie Kalus
Tue, 26 Dec 2023 21:56:13 +0100
6 files changed, 55 insertions(+), 41 deletions(-)
M kernel/link.txtkernel/link.txt

@@ -36,3 +36,4 @@ __REALMD_VMA = ADDR(REALMD);

__REALMD_SIZE = SIZEOF(REALMD); __KERNEL_STACK_ADDR = 0xC0400000; +__SCHED_STACK_ADDR = 0xC0200000;
M kernel/main.ckernel/main.c

@@ -128,22 +128,31 @@ }

int os_main(void) { infodump(); + + printk("Starting scheduler.\n"); + sched_start(); - // create test tasks printk("Creating tasks.\n"); - + /** + * Here, the kernel "forks" into the idle process and + * the shell. + * + * The idle process is executed whenever, duh, all + * processes are out of work and idling. + * + * The shell is where the user can give commands and + * start her own processes. It is an executable that + * is read from disk. + */ int pid = sched_spawn("shelf", "Hello World!", 0); assert(pid != -1); - //sched_spawn("fibonacci.o", "Hello World!"); - //sched_spawn("fibonacci.o", "Hello World!"); - - printk("Starting scheduler.\n"); - sched_start(); - //kpanic("SIMULATED KERNEL PANIC"); + // here is where the idle process (PID 0) starts. + sched_idle(NULL); - // won't be executed - printk("Main procedure terminating.\n"); + // this should never happen. + kpanic("Returned from idle process!"); + return 0; }
M kernel/mm/paging.hkernel/mm/paging.h

@@ -37,6 +37,13 @@ "Nd" (pd_new));

return (void*)pd_old; } +__attribute__((always_inline)) inline PHYS_ADDR get_current_page_dir(void) { + uint32_t pd_old; + __asm__ volatile ( "mov %%cr3, %0" : + "=a" (pd_old) : ); + return (void*)pd_old; +} + /*! * Invalidates all pages, forces buffer reload. */
M kernel/sched/sched.ckernel/sched/sched.c

@@ -45,7 +45,7 @@

int sched_dispatcher(void); -void entry_idle(char *args) { +void sched_idle(char *args) { while (1) { hlt(); }

@@ -61,10 +61,8 @@ PRINT_DBG("process name: %s\n", name);

PRINT_DBG("process args: %s\n", args); PRINT_DBG("process flags: %i\n", flags); - if (name != NULL) { - int fd = file_open(name, 0); - if (fd == -1) { return -1; } - } + int fd = file_open(name, 0); + if (fd == -1) { return -1; } PHYS_ADDR page_dir = create_empty_page_dir();

@@ -75,12 +73,7 @@ p->ebp = USER_STACK;

p->esp = USER_STACK - sizeof(SCHED_FRAME); p->eflags = PROCESS_STD_EFLAGS; p->entry = (PROCESS_MAIN*)(0xDEADBEEF); - - if (name == NULL) { - p->eip = entry_idle; - } else { - p->eip = sched_dispatcher; - } + p->eip = sched_dispatcher; if (flags != 0) { p->stdin = (int)(flags & 0xFF);

@@ -138,15 +131,13 @@ PROCESS* current = get_process(current_pid);

alarm_tick(); - if (current_pid != 0) { - current->esp = (VIRT_ADDR)(frame); - current->ebp = (VIRT_ADDR)(ebp); - current->eip = (VIRT_ADDR)frame->eip; - current->eflags = frame->eflags; + current->esp = (VIRT_ADDR)(frame); + current->ebp = (VIRT_ADDR)(ebp); + current->eip = (VIRT_ADDR)frame->eip; + current->eflags = frame->eflags; - // save stack checksum - stack_compute_checksum(&(current->checksum), current->esp, current->ebp); - } + // save stack checksum + stack_compute_checksum(&(current->checksum), current->esp, current->ebp); PRINT_DBG("esp: %p\n", current->esp); PRINT_DBG("ebp: %p\n", current->ebp);

@@ -181,13 +172,11 @@ // prepare stack

frame = (volatile SCHED_FRAME*)(next->esp); ebp = next->ebp; - if (current_pid == 0) { - frame->cs = 0x18; - frame->eip = next->eip; - frame->eflags = (uint32_t)(next->eflags); - frame->esp = (uint32_t)(next->esp); - frame->ebp = (uint32_t)(next->ebp); - } + frame->cs = 0x18; + frame->eip = next->eip; + frame->eflags = (uint32_t)(next->eflags); + frame->esp = (uint32_t)(next->esp); + frame->ebp = (uint32_t)(next->ebp); PRINT_DBG("esp: %p, ebp: %p, eip: %p, eflags: %p\n", frame->esp, frame->ebp, frame->eip, frame->eflags);

@@ -207,11 +196,14 @@

current_pid = 0; // create idle process - PROCESS_ID idle_pid = sched_spawn(NULL, NULL, 0); + PROCESS *idle = get_slot(); + assert(idle != NULL); + + PROCESS_ID idle_pid = add_process(idle, NULL); assert(idle_pid == 0); - PROCESS *idle = get_process(idle_pid); - assert(idle != NULL); + idle->page_dir = get_current_page_dir(); + idle->state = PSTATE_RUNNING; idle->state = PSTATE_READY;
M kernel/sched/sched.hkernel/sched/sched.h

@@ -46,6 +46,11 @@ * Initializes the scheduler.

*/ int sched_init(void); +/** + * Idle process main function (PID 0). +*/ +void sched_idle(char *args); + /*! * Starts the scheduler. * \return 1 on success, 0 on failure.
M kernel/sched/sched.skernel/sched/sched.s

@@ -9,8 +9,8 @@

// switch to scheduler stack mov %esp, %eax mov %ebp, %ebx - mov $0xC0400000, %esp - mov $0xC0400000, %ebp + mov $__SCHED_STACK_ADDR, %esp + mov $__SCHED_STACK_ADDR, %ebp // pass process stack as arguments push %ebx