diff --git a/Makefile b/Makefile index 691d0bd..2d4aee8 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 core/irq_pit.o +cobj=$(csrc:%.c=%.o) core/cpu_context_switch.o drivers/irq_pit.o deps = $(csrc:%.c=%.d) kernel:$(asmobj) $(cobj) linker.ld diff --git a/core/kthread.c b/core/kthread.c index 339d794..768378d 100644 --- a/core/kthread.c +++ b/core/kthread.c @@ -4,6 +4,7 @@ #include "irq.h" #include "klibc.h" #include "list.h" +#include "time.h" #include "vga.h" static struct kthread *currentThread; @@ -80,7 +81,7 @@ struct kthread *kthreadSelectNext() return nextThread; } -struct cpu_state *switchKthread(struct cpu_state *prevCpu) +struct cpu_state *kthreadSwitch(struct cpu_state *prevCpu) { uint32_t flags; disable_IRQs(flags); diff --git a/core/kthread.h b/core/kthread.h index d2279f9..2317af4 100644 --- a/core/kthread.h +++ b/core/kthread.h @@ -22,6 +22,6 @@ struct kthread *kthreadCreate(const char *name, cpu_kstate_function_arg1_t func, void kthreadDelete(struct kthread *thread); struct kthread *kthreadSelectNext(); -struct cpu_state *switchKthread(struct cpu_state *prevCpu); +struct cpu_state *kthreadSwitch(struct cpu_state *prevCpu); int kthreadYield(); diff --git a/core/main.c b/core/main.c index 03c8ce4..d29fbe2 100644 --- a/core/main.c +++ b/core/main.c @@ -17,6 +17,7 @@ #ifdef RUN_TEST #include "test.h" #endif +#include "time.h" #include "types.h" #include "vga.h" @@ -29,9 +30,8 @@ void cpuid(int code, uint32_t *a, uint32_t *d) void idleThread(void *arg) { (void)arg; - int count = 0; while (1) - printIntDetails(count++, GREEN, BLACK, 0, VGA_HEIGHT - 1); + printIntDetails((jiffies/HZ), GREEN, BLACK, 0, VGA_HEIGHT - 1); } // Multiboot information available here : @@ -47,7 +47,7 @@ void kmain(unsigned long magic, unsigned long addr) gdtSetup(); idtSetup(); irqSetup(); - pitSetup(100); + pitSetup(HZ); if (magic == MULTIBOOT_BOOTLOADER_MAGIC) { // Get loaded by Grub with mutliboot version 1 multiboot_info_t *mbi = (multiboot_info_t *)addr; diff --git a/core/time.c b/core/time.c new file mode 100644 index 0000000..cb0c607 --- /dev/null +++ b/core/time.c @@ -0,0 +1,13 @@ +#include "time.h" + +unsigned long volatile jiffies = INITIAL_JIFFIES; + +unsigned int jiffies_to_msecs(const unsigned long j) +{ + return (1000L / HZ) * j; +} + +unsigned int jiffies_to_usecs(const unsigned long j) +{ + return (1000000L / HZ) * j; +} diff --git a/core/time.h b/core/time.h new file mode 100644 index 0000000..302aa94 --- /dev/null +++ b/core/time.h @@ -0,0 +1,50 @@ +#pragma once + +#define HZ 100 +/* + * Have the 32 bit jiffies value wrap 5 minutes after boot + * so jiffies wrap bugs show up earlier. + */ +//#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ)) +#define INITIAL_JIFFIES 0 + +extern unsigned long volatile jiffies; + + +#define time_after(unknown, known) ((long)(known) - (long)(unknown) < 0) +#define time_before(unknown, known) ((long)(unknown) - (long)(known) < 0) +#define time_after_eq(unknown, known) ((long)(unknown) - (long)(known) >= 0) +#define time_before_eq(unknown, known) ((long)(known) - (long)(unknown) >= 0) + +/* + * Calculate whether a is in the range of [b, c]. + */ +#define time_in_range(a,b,c) \ + (time_after_eq(a,b) && \ + time_before_eq(a,c)) + +/* + * Calculate whether a is in the range of [b, c). + */ +#define time_in_range_open(a,b,c) \ + (time_after_eq(a,b) && \ + time_before(a,c)) + +/* + * These four macros compare jiffies and 'a' for convenience. + */ + +/* time_is_before_jiffies(a) return true if a is before jiffies */ +#define time_is_before_jiffies(a) time_after(jiffies, a) + +/* time_is_after_jiffies(a) return true if a is after jiffies */ +#define time_is_after_jiffies(a) time_before(jiffies, a) + +/* time_is_before_eq_jiffies(a) return true if a is before or equal to jiffies*/ +#define time_is_before_eq_jiffies(a) time_after_eq(jiffies, a) + +/* time_is_after_eq_jiffies(a) return true if a is after or equal to jiffies*/ +#define time_is_after_eq_jiffies(a) time_before_eq(jiffies, a) + +unsigned int jiffies_to_msecs(const unsigned long j); +unsigned int jiffies_to_usecs(const unsigned long j); diff --git a/core/irq_pit.S b/drivers/irq_pit.S similarity index 97% rename from core/irq_pit.S rename to drivers/irq_pit.S index ac7b935..039cb7a 100644 --- a/core/irq_pit.S +++ b/drivers/irq_pit.S @@ -21,7 +21,7 @@ pit_handler: // already got eflags, cs and eip on stack thanks to CPU outb %al, $0x20 pushl %esp - call switchKthread + call pitIrqHandler movl %eax,%esp /* Restore the CPU context */ diff --git a/drivers/pit.c b/drivers/pit.c index f0a3fdf..b79469a 100644 --- a/drivers/pit.c +++ b/drivers/pit.c @@ -1,6 +1,9 @@ #include "pit.h" #include "io.h" #include "irq.h" +#include "kthread.h" +#include "time.h" +#include "klibc.h" int pitSetup(unsigned int freq) { @@ -13,3 +16,9 @@ int pitSetup(unsigned int freq) return 0; } + +struct cpu_state *pitIrqHandler(struct cpu_state *prevCpu) +{ + __atomic_add_fetch(&jiffies, 1, __ATOMIC_RELAXED); + return kthreadSwitch(prevCpu); +} diff --git a/drivers/pit.h b/drivers/pit.h index c72a257..3fc9ce3 100644 --- a/drivers/pit.h +++ b/drivers/pit.h @@ -1,4 +1,5 @@ #pragma once +#include "cpu_context.h" // C.f https://wiki.osdev.org/PIT @@ -13,3 +14,4 @@ // 3 -> low then high 3-1: mode. See https://wiki.osdev.org/PIT int pitSetup(unsigned int freq); +struct cpu_state *pitIrqHandler(struct cpu_state *prevCpu);