From 99d16e98e04c73e108160d7d70244bafdb33b6fc Mon Sep 17 00:00:00 2001 From: Jake Mannens Date: Wed, 11 Jul 2018 00:18:49 +1000 Subject: Implemented a basic scheduler using an array of task structures in which each structure has a TSS inside, as well as several descriptor entries in the GDT pointing to each task's TSS. Task switching is performed in hardware by means of far jumping to the new task's TSS descriptor in the GDT. Task states are saved manually by copying the saved state from the interrupt handler's stack, back into the task's TSS. Added the function save_state() to sched.c which can be called from assembly to copy the state information of the suspended task from the current stack, to it's respective task structure. NOTE: this assumes that the pointer cstate has been set ahead of time to point to the state information on the stack, and that the pointer ctask has not yet been modified. Added the function reschedule() which is currently called from the timer's tick handler. Currently, this function merely alternates between the two tasks created in sched_init(), but in future, will be expanded to decided independently which task will run next. The function userspace_init() was renamed to the more appropriate sched_init(). Moved most of the code from the original userspace_init() to the new function create_proc() which sets up a virtual address space and state information, copies the specified binary into the new address space, then returns a pointer to the newly created tasks entry in the task table. Defined the type pid_t in unistd.h as a 16-bit unsigned integer. Added two new debugging system calls for checking which task is currently active. The getpid() system calls returns the caller's PID whilst the getpdir() call returns the physical location of the caller's page directory (the value of CR3). The getpdir() call can be used as a fallback to determine which task is *actually* running if the information in ctask or the getpid() call is faulty. Added two new subroutines; set_tss() and clear_tss() (whose prototypes are defined in asm/system.h) for managing the task-state descriptor entries in the GDT. set_tss() initializes a TSS descriptor and sets it's base pointer to the supplied TSS pointer whilst clear_tss() simply marks a TSS descriptor as 'not present' without clearing it. --- include/kernel/sched.h | 33 +++++++++++++++++++++++++-------- include/kernel/sys.h | 6 ++++-- 2 files changed, 29 insertions(+), 10 deletions(-) (limited to 'include/kernel') diff --git a/include/kernel/sched.h b/include/kernel/sched.h index afced68..a3d95e0 100644 --- a/include/kernel/sched.h +++ b/include/kernel/sched.h @@ -2,27 +2,44 @@ #define _SCHED_H #include +#include -struct task_state { - uint32_t ss; - uint32_t esp; - uint32_t eflags; - uint32_t cs; +struct tss_struct { + uint32_t prevt; + uint32_t esp0; + uint32_t ss0; + uint32_t esp1; + uint32_t ss1; + uint32_t esp2; + uint32_t ss2; + uint32_t cr3; uint32_t eip; + uint32_t eflags; uint32_t eax; uint32_t ecx; uint32_t edx; uint32_t ebx; - uint32_t esp_garbage; + uint32_t esp; uint32_t ebp; uint32_t esi; uint32_t edi; + uint32_t es; + uint32_t cs; + uint32_t ss; + uint32_t ds; + uint32_t fs; + uint32_t gs; + uint32_t ldt; + uint32_t io_map; } __attribute__((packed)); struct task_struct { - struct task_state state; + pid_t pid; + struct tss_struct state; } __attribute__((packed)); -void userspace_init(void); +extern struct task_struct *ctask; + +void sched_init(void); #endif diff --git a/include/kernel/sys.h b/include/kernel/sys.h index 7c129d2..248a93b 100644 --- a/include/kernel/sys.h +++ b/include/kernel/sys.h @@ -2,13 +2,15 @@ typedef int (*syscall_t) (void); extern int sys_puts(void); extern int sys_time(void); +extern int sys_getpid(void); +extern int sys_getpdir(void); extern int sys_dummy(void); syscall_t call_table[256] = { [0] = &sys_puts, [1] = &sys_time, - [2] = &sys_dummy, - [3] = &sys_dummy, + [2] = &sys_getpid, + [3] = &sys_getpdir, [4] = &sys_dummy, [5] = &sys_dummy, [6] = &sys_dummy, -- cgit v1.3