From c0929a4eeab0fbf00d187eeb01c38c79da46ed26 Mon Sep 17 00:00:00 2001 From: pjht Date: Thu, 30 Jul 2020 21:58:23 -0500 Subject: [PATCH] Add preemptive multitasking --- Makefile | 5 +++-- kernel/cpu/i386/isr.c | 2 +- kernel/kernel.c | 17 ++++++++++------- kernel/timer/pit/timer.c | 26 ++++++++++++++++++++++++++ kernel/timer/timer.h | 14 ++++++++++++++ kernel/timer_handler.c | 14 ++++++++++++++ psinfo/i386/timer_type.txt | 1 + 7 files changed, 69 insertions(+), 10 deletions(-) create mode 100644 kernel/timer/pit/timer.c create mode 100644 kernel/timer/timer.h create mode 100644 kernel/timer_handler.c create mode 100644 psinfo/i386/timer_type.txt diff --git a/Makefile b/Makefile index 615a3bc..0151f65 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ PLAT=i386 -C_SOURCES = $(wildcard kernel/*.c kernel/cpu/$(PLAT)/*.c kernel/cpu/*.c) -C_HEADERS = $(wildcard kernel/*.h kernel/cpu/$(PLAT)/*.h kernel/cpu/*.h) +TIMER_TYPE=$(shell cat psinfo/$(PLAT)/timer_type.txt) +C_SOURCES = $(wildcard kernel/*.c kernel/cpu/$(PLAT)/*.c kernel/cpu/*.c kernel/timer/$(TIMER_TYPE)/*.c) +C_HEADERS = $(wildcard kernel/*.h kernel/cpu/$(PLAT)/*.h kernel/cpu/*.h kernel/timer/$(TIMER_TYPE)/*.h) ASM = $(wildcard kernel/cpu/$(PLAT)/*.asm) S_ASM = $(wildcard kernel/cpu/$(PLAT)/*.s) LIBC_SOURCES = $(wildcard libc/*.c libc/*/*.c) diff --git a/kernel/cpu/i386/isr.c b/kernel/cpu/i386/isr.c index 2774a29..2728cb4 100644 --- a/kernel/cpu/i386/isr.c +++ b/kernel/cpu/i386/isr.c @@ -294,7 +294,7 @@ void irq_handler(registers_t* r) { port_byte_out(0x20,0x20); /* master */ /* Handle the interrupt in a more modular way */ if (irq_handlers[r->int_no-32] != NULL) { - isr_t handler = irq_handlers[r->int_no]; + isr_t handler = irq_handlers[r->int_no-32]; handler(r); } } diff --git a/kernel/kernel.c b/kernel/kernel.c index db46312..f8f4fed 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -11,6 +11,7 @@ #include #include #include +#include "timer/timer.h" /** * REspresents a TAR file header @@ -66,6 +67,7 @@ void kmain(struct multiboot_boot_header_tag* hdr) { asm volatile("sti"); tasking_init(); vga_init((char*)0xC00B8000); + timer_init(1000); read_initrd(tags); int pos=0; size_t datapos; @@ -115,13 +117,14 @@ void kmain(struct multiboot_boot_header_tag* hdr) { copy_data(address_space,ptr,pheader.memsz,(void*)pheader.vaddr); } create_proc((void*)header.entry,address_space,NULL,NULL); - for (int i=0;i<4;i++) { - yield(); - } - unblock_thread(1,0); - for (int i=0;i<4;i++) { - yield(); - } + // for (int i=0;i<4;i++) { + // yield(); + // } + // unblock_thread(1,0); + // for (int i=0;i<4;i++) { + // yield(); + // } + // for (;;); exit(0); } } diff --git a/kernel/timer/pit/timer.c b/kernel/timer/pit/timer.c new file mode 100644 index 0000000..7684234 --- /dev/null +++ b/kernel/timer/pit/timer.c @@ -0,0 +1,26 @@ +#include "../../cpu/isr.h" +#include "../../tasking.h" +#include "../../cpu/serial.h" +#include + +void timer_handler(registers_t* r); + +void timer_init(int freq) { + int div=1193180/freq; + if (div>65535) { + serial_printf("Frequency of %dHz too slow, min freq is 18 Hz\n"); + div=65535; + freq=18; + if (div==0) { + serial_printf("Frequency of %dHz too slow, max freq is 1193180 Hz\n"); + div=1; + freq=1193180; + } + } else { + serial_printf("Setting PIT to %dHz using divisor of %d\n",freq,div); + } + isr_register_handler(0,timer_handler); + port_byte_out(0x43,(div>>8)&0xFF); + port_byte_out(0x40,div&0xFF); + port_byte_out(0x40,0x2E); +} diff --git a/kernel/timer/timer.h b/kernel/timer/timer.h new file mode 100644 index 0000000..f73f3a1 --- /dev/null +++ b/kernel/timer/timer.h @@ -0,0 +1,14 @@ +/** + * \file +*/ + +#ifndef TIMER_H +#define TIMER_H + +/** + * Initialize the timer + * \param freq The freqency to set the timer to +*/ +void timer_init(int freq); + +#endif diff --git a/kernel/timer_handler.c b/kernel/timer_handler.c new file mode 100644 index 0000000..1136a8b --- /dev/null +++ b/kernel/timer_handler.c @@ -0,0 +1,14 @@ +/** + * \file +*/ + +#include "tasking.h" +#include "cpu/isr.h" + +/** + * Interrupt handler for the timer interrupt + * \param r The saved state of the CPU when the interrupt occured +*/ +void timer_handler(registers_t* r) { + tasking_yield(); +} diff --git a/psinfo/i386/timer_type.txt b/psinfo/i386/timer_type.txt new file mode 100644 index 0000000..9aae856 --- /dev/null +++ b/psinfo/i386/timer_type.txt @@ -0,0 +1 @@ +pit