From 2c0f54926d7c2dbf905f13d1b9d2cc66c453832d Mon Sep 17 00:00:00 2001 From: Mathieu Maret Date: Thu, 23 Apr 2020 00:49:09 +0200 Subject: [PATCH] Initial kthread implementation --- Makefile | 2 +- core/cpu_context_switch.S | 4 +-- core/interrupt.h | 1 + core/irq_pit.S | 38 ++++++++++++++++++++++ core/klibc.c | 34 ++++++++++++++++++-- core/klibc.h | 6 ++-- core/kthread.c | 67 +++++++++++++++++++++++++++++++++++++++ core/kthread.h | 26 +++++++++++++++ core/main.c | 19 ++++++++++- core/stack.c | 2 -- core/stack.h | 3 ++ 11 files changed, 191 insertions(+), 11 deletions(-) create mode 100644 core/irq_pit.S create mode 100644 core/kthread.c create mode 100644 core/kthread.h diff --git a/Makefile b/Makefile index f4ec520..6d006f6 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ CPPFLAGS += $(foreach dir, $(SUBDIRS), -I$(dir)) asmsrc=$(wildcard *.asm) asmobj=$(asmsrc:%.asm=%.o) csrc=$(shell find $(SUBDIRS) -type f -name "*.c")# $(wildcard *.c) -cobj=$(csrc:%.c=%.o) core/cpu_context_switch.o +cobj=$(csrc:%.c=%.o) core/cpu_context_switch.o core/irq_pit.o deps = $(csrc:%.c=%.d) kernel:$(asmobj) $(cobj) linker.ld diff --git a/core/cpu_context_switch.S b/core/cpu_context_switch.S index aa7e5f5..f26c376 100644 --- a/core/cpu_context_switch.S +++ b/core/cpu_context_switch.S @@ -12,8 +12,8 @@ cpu_context_switch: pushf // (eflags) esp+56 pushl %cs // (cs) esp+52 pushl $resume_pc // (ip) esp+48 - pushl $0 // (error code) esp+44 - pushal // (general reg) esp+12+8*4 + pushl $0 // (error code) esp+12+8x4 + pushal // (general reg) esp+12 subl $2, %esp // (alignment) esp+10 pushw %ss // esp+8 pushw %ds // esp+6 diff --git a/core/interrupt.h b/core/interrupt.h index 50ac724..14d8dc7 100644 --- a/core/interrupt.h +++ b/core/interrupt.h @@ -16,6 +16,7 @@ void print_handler(struct interrupt_frame *frame, ulong error_code); void pagefault_handler(struct interrupt_frame *frame, ulong error_code); // IRQ +void pit_handler(struct interrupt_frame *frame); void keyboard_handler(struct interrupt_frame *frame); void timer_handler(struct interrupt_frame *frame); void serial_handler(struct interrupt_frame *frame); diff --git a/core/irq_pit.S b/core/irq_pit.S new file mode 100644 index 0000000..6684618 --- /dev/null +++ b/core/irq_pit.S @@ -0,0 +1,38 @@ +.file "irq_pit.S" + +.text + +.extern selectNextThread + +.globl pit_handler +.type pit_handler, @function +pit_handler: // already got eflags, cs and eip on stack thanks to CPU + pushl $0 // err_code esp+12+8*4=44 + pushal // (general reg) esp+12 + subl $2, %esp // (alignment) esp+10 + pushw %ss // esp+8 + pushw %ds // esp+6 + pushw %es // esp+4 + pushw %fs // esp+2 + pushw %gs // esp + + /* Send EOI to PIC */ + movb $0x20, %al + outb %al, $0x20 + + pushl %esp + call selectNextThread + movl %eax,%esp + + /* Restore the CPU context */ + popw %gs + popw %fs + popw %es + popw %ds + popw %ss + addl $2,%esp + popal + addl $4, %esp /* Ignore "error code" */ + + /* This restores the eflags, the cs and the eip registers */ + iret /* equivalent to: popfl ; ret */ diff --git a/core/klibc.c b/core/klibc.c index fcd64f3..9dffb29 100644 --- a/core/klibc.c +++ b/core/klibc.c @@ -80,7 +80,7 @@ void reverse(char s[]) } /* K&R */ -int strlen(char s[]) +int strlen(const char s[]) { int i = 0; while (s[i] != '\0') @@ -90,7 +90,7 @@ int strlen(char s[]) /* K&R * Returns <0 if s10 if s1>s2 */ -int strcmp(char s1[], char s2[]) +int strcmp(const char s1[], const char s2[]) { int i; for (i = 0; s1[i] == s2[i]; i++) { @@ -100,6 +100,33 @@ int strcmp(char s1[], char s2[]) return s1[i] - s2[i]; } +unsigned int strnlen(const char *s, size_t count) +{ + const char *sc; + + for (sc = s; count-- && *sc != '\0'; ++sc) + /* nothing */ continue; + + return sc - s; +} + +char *strzcpy(register char *dst, register const char *src, register int len) +{ + int i; + + if (len <= 0) + return dst; + + for (i = 0; i < len; i++) { + dst[i] = src[i]; + if (src[i] == '\0') + return dst; + } + + dst[len - 1] = '\0'; + return dst; +} + void printf(const char *format, ...) { va_list ap; @@ -115,7 +142,8 @@ void puts(const char *str) } } -void putc(const char str){ +void putc(const char str) +{ VGAputc(str); serialPutc(str); } diff --git a/core/klibc.h b/core/klibc.h index d7bdc83..e50b33e 100644 --- a/core/klibc.h +++ b/core/klibc.h @@ -14,8 +14,10 @@ void *memcpy(void *dest, const void *src, size_t n); void *memset(void *s, int c, size_t n); char *itoa(int value, char *str, int base); void reverse(char s[]); -int strlen(char s[]); -int strcmp(char s1[], char s2[]); +int strlen(const char s[]); +unsigned int strnlen(const char * s, size_t count); +int strcmp(const char s1[], const char s2[]); +char *strzcpy(char *dst, const char *src, int len); void puts(const char *str); void putc(const char str); void printInt(int integer); diff --git a/core/kthread.c b/core/kthread.c new file mode 100644 index 0000000..8ae0978 --- /dev/null +++ b/core/kthread.c @@ -0,0 +1,67 @@ +#include "kthread.h" +#include "list.h" +#include "alloc.h" +#include "klibc.h" + +static struct kthread *currentThread; + +void _kthread_exit(){ + //TODO + return; +} + +int kthreadSetup(vaddr_t mainStack, size_t mainStackSize){ + struct kthread * current = (struct kthread *)malloc(sizeof(struct kthread)); + strzcpy(current->name, "[KINIT]", KTHREAD_NAME_MAX_LENGTH); + current->stackAddr = mainStack; + current->stackSize = mainStackSize; + + list_singleton(currentThread, current); + + return 0; +} + +struct kthread *createKthread(const char *name, cpu_kstate_function_arg1_t func, + void *args) +{ + struct kthread *thread = (struct kthread *)malloc(sizeof(struct kthread)); + if (!thread) + return NULL; + + thread->stackAddr = (vaddr_t) malloc(KTHREAD_DEFAULT_STACK_SIZE); + thread->stackSize = KTHREAD_DEFAULT_STACK_SIZE; + + if(!thread->stackAddr) + goto free_mem; + + if(name) + strzcpy(thread->name, name, KTHREAD_NAME_MAX_LENGTH); + else + strzcpy(thread->name, "[UNKNOW]", KTHREAD_NAME_MAX_LENGTH); + + if(cpu_kstate_init(&thread->cpuState, (cpu_kstate_function_arg1_t *)func, (vaddr_t)args, + thread->stackAddr, thread->stackSize, + (cpu_kstate_function_arg1_t *)_kthread_exit, 0)) + goto free_mem; + + list_add_tail(currentThread, thread); + return thread; +free_mem: + free((void *)thread->stackAddr); + free((void *)thread); + return NULL; +} + +void deleteKthread(struct kthread *thread){ + list_delete(currentThread, thread); + + free((void *)thread->stackAddr); + free((void *)thread); +} + +struct cpu_state *selectNextThread(struct cpu_state *prevCpu){ + currentThread->cpuState = prevCpu; + struct kthread *nextThread = currentThread->next; + currentThread = nextThread; + return nextThread->cpuState; +} diff --git a/core/kthread.h b/core/kthread.h new file mode 100644 index 0000000..178fb82 --- /dev/null +++ b/core/kthread.h @@ -0,0 +1,26 @@ +#pragma once + +#include "cpu_context.h" +#include "mem.h" + +#define KTHREAD_NAME_MAX_LENGTH 32 +#define KTHREAD_DEFAULT_STACK_SIZE PAGE_SIZE + +struct kthread { + char name[KTHREAD_NAME_MAX_LENGTH]; + struct cpu_state *cpuState; + vaddr_t stackAddr; + size_t stackSize; + struct kthread *next; + struct kthread *prev; +}; + + +int kthreadSetup(vaddr_t mainStack, size_t mainStackSize); + +struct kthread *createKthread(const char *name, cpu_kstate_function_arg1_t func, + void *args); + +void deleteKthread(struct kthread *thread); + +struct cpu_state *selectNextThread(struct cpu_state *prev_cpu); diff --git a/core/main.c b/core/main.c index c958b59..84b7ba3 100644 --- a/core/main.c +++ b/core/main.c @@ -6,11 +6,13 @@ #include "io.h" #include "irq.h" #include "klibc.h" +#include "kthread.h" #include "mem.h" #include "multiboot.h" #include "paging.h" #include "pit.h" #include "serial.h" +#include "stack.h" #include "stdarg.h" #ifdef RUN_TEST #include "test.h" @@ -24,6 +26,18 @@ void cpuid(int code, uint32_t *a, uint32_t *d) asm volatile("cpuid" : "=a"(*a), "=d"(*d) : "0"(code) : "ebx", "ecx"); } +void idleThread(void *arg){ + (void)arg; + while(1) + printf("."); +} + +void dashThread(void *arg){ + (void)arg; + while(1) + printf("-"); +} + // Multiboot information available here : // https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#kernel_002ec // https://www.gnu.org/software/grub/manual/multiboot/html_node/Boot-information-format.html#Boot%20information%20format @@ -99,7 +113,6 @@ void kmain(unsigned long magic, unsigned long addr) printf("Setting up IRQ handlers\n"); irqSetRoutine(IRQ_KEYBOARD, keyboard_handler); - irqSetRoutine(IRQ_TIMER, timer_handler); printf("Enabling HW interrupts\n"); exceptionSetRoutine(EXCEPTION_DOUBLE_FAULT, print_handler); @@ -110,6 +123,10 @@ void kmain(unsigned long magic, unsigned long addr) printf("Setting up Serial link (115200)\n"); serialSetup(115200); allocInit(); + kthreadSetup(_stack_bottom, (_stack_top - _stack_bottom + 1)); + createKthread("idle", idleThread, NULL); + createKthread("dash", dashThread, NULL); + irqSetRoutine(IRQ_TIMER, pit_handler); #ifdef RUN_TEST run_test(); #endif diff --git a/core/stack.c b/core/stack.c index 21c4ba9..e29037f 100644 --- a/core/stack.c +++ b/core/stack.c @@ -2,8 +2,6 @@ #include "types.h" #include "klibc.h" -extern vaddr_t _stack_bottom; -extern vaddr_t _stack_top; void printStackTrace(unsigned int maxFrames) { #ifdef DEBUG diff --git a/core/stack.h b/core/stack.h index a0265cd..a0d6136 100644 --- a/core/stack.h +++ b/core/stack.h @@ -1,3 +1,6 @@ #pragma once +#include "types.h" +extern vaddr_t _stack_bottom; +extern vaddr_t _stack_top; void printStackTrace(unsigned int maxFrame);