diff options
Diffstat (limited to 'kc')
| -rw-r--r-- | kc/core/Makefile | 2 | ||||
| -rw-r--r-- | kc/core/cpu/cpu.c | 2 | ||||
| -rw-r--r-- | kc/core/kc_main.c | 2 | ||||
| -rw-r--r-- | kc/core/memory.c | 12 | ||||
| -rw-r--r-- | kc/core/panic.c | 12 | ||||
| -rw-r--r-- | kc/core/panic.h | 6 | ||||
| -rw-r--r-- | kc/core/pic8259.c | 2 | ||||
| -rw-r--r-- | kc/core/pit8253.c | 75 | ||||
| -rw-r--r-- | kc/core/pit8253.h | 11 | ||||
| -rw-r--r-- | kc/core/task.c | 44 | ||||
| -rw-r--r-- | kc/core/timer.c | 8 | ||||
| -rw-r--r-- | kc/core/timer.h | 21 |
12 files changed, 150 insertions, 47 deletions
diff --git a/kc/core/Makefile b/kc/core/Makefile index fd5c984..cd440a1 100644 --- a/kc/core/Makefile +++ b/kc/core/Makefile @@ -13,7 +13,7 @@ SOBJS := GOBJS := entry_x86_64.o reloc_x86_64.o kprint.o serial.o port.o mmu.o \ kc_main.o memory.o memset.o memcpy.o memmove.o memcmp.o cpu.o \ vm_tree.o exceptions.o panic.o msr.o task.o cpu_task.o irq.o \ - kcc_memory.o string.o pic8259.o pic8259_isr.o pit8253.o timer.o + kcc_memory.o string.o pic8259.o pic8259_isr.o pit8253.o IOBJS := # __attribute__((interrupt)) requires -mgeneral-regs-only diff --git a/kc/core/cpu/cpu.c b/kc/core/cpu/cpu.c index 7b48e30..d33d8a4 100644 --- a/kc/core/cpu/cpu.c +++ b/kc/core/cpu/cpu.c @@ -241,7 +241,7 @@ void isr_install(int vec, void (*isr)(void), int trap, unsigned ist) } else if (ist && ist > 7) { - panic(GENERAL_PANIC); + PANIC(GENERAL_PANIC); } } diff --git a/kc/core/kc_main.c b/kc/core/kc_main.c index 6d73cea..1136e0a 100644 --- a/kc/core/kc_main.c +++ b/kc/core/kc_main.c @@ -28,7 +28,7 @@ unsigned long kc_main(struct kc_boot_data *data) kprintf("integer test %d %u\n", 3, 3); memory_init(); pic8259_init(); - pit8253_init(); + pit8253_timer_source.init(); task_init(); return 0; diff --git a/kc/core/memory.c b/kc/core/memory.c index 0319246..2dac707 100644 --- a/kc/core/memory.c +++ b/kc/core/memory.c @@ -320,7 +320,7 @@ static void init_vm_node( else { kputs("fatal: attempt to insert overlapping vm node\n"); - panic(GENERAL_PANIC); + PANIC(GENERAL_PANIC); } } @@ -544,7 +544,7 @@ int anonymous_page_handler(uint32_t code, void *address) kputs("can't fault a present page\n"); // there's no reason a protection violation should happen // in anonymous space - panic(UNHANDLED_FAULT); + PANIC(UNHANDLED_FAULT); } // kernel page mappings are built different if (address >= (void *)&kc_image_base) @@ -567,7 +567,7 @@ int anonymous_page_handler(uint32_t code, void *address) } else { - panic(OUT_OF_MEMORY); + PANIC(OUT_OF_MEMORY); } } @@ -605,13 +605,13 @@ int page_fault_handler(uint8_t vector, uint32_t code) } if (result) { - panic(UNHANDLED_FAULT); + PANIC(UNHANDLED_FAULT); } } else { kputs("didn't find memory object\n"); - panic(UNHANDLED_FAULT); + PANIC(UNHANDLED_FAULT); } return 0; @@ -623,7 +623,7 @@ int general_protection_handler(uint8_t vector, uint32_t code) (void)vector; (void)code; kputs("general protection violation\n"); - panic(UNHANDLED_FAULT); + PANIC(UNHANDLED_FAULT); return 0; } diff --git a/kc/core/panic.c b/kc/core/panic.c index 6fd5581..2f46a6a 100644 --- a/kc/core/panic.c +++ b/kc/core/panic.c @@ -6,17 +6,22 @@ static char const *reason_strings[] = { "general panic", "unhandled fault", - "out of memory" + "out of memory", + "dead-end routine" }; -noreturn void panic(enum panic_reason reason) +noreturn void panic(const char *file, int line, enum panic_reason reason) { // TODO: kprintf() and friends if (reason > sizeof(reason_strings) / sizeof(*reason_strings)) { reason = 0; } - kprintf("kernel panic: %s\n", reason_strings[reason]); + kprintf( + "kernel panic:%s:%u %s\n", + file, + line, + reason_strings[reason]); halt(); } @@ -25,3 +30,4 @@ noreturn void halt(void) __asm__ ("cli\n\t"); while (true) __asm__ ("hlt\n\t"); } + diff --git a/kc/core/panic.h b/kc/core/panic.h index 0cfd7c2..1ace5ba 100644 --- a/kc/core/panic.h +++ b/kc/core/panic.h @@ -2,12 +2,16 @@ #include <stdnoreturn.h> +#define PANIC(reason) panic(__FILE__, __LINE__, reason) + enum panic_reason { GENERAL_PANIC, UNHANDLED_FAULT, OUT_OF_MEMORY, + DEAD_END }; -noreturn void panic(enum panic_reason reason); +noreturn void panic(const char *file, int line, enum panic_reason reason); noreturn void halt(void); + diff --git a/kc/core/pic8259.c b/kc/core/pic8259.c index b1de903..4317d0c 100644 --- a/kc/core/pic8259.c +++ b/kc/core/pic8259.c @@ -184,7 +184,7 @@ void pic8259_irq_begin(uint8_t irq) } else { - kprintf("%s of irq%hhu\n", "unhandled activation", irq); + kprintf("unhandled irq%hhu\n", irq); } pic8259_irq_end(irq); diff --git a/kc/core/pit8253.c b/kc/core/pit8253.c index 0cf5232..4728020 100644 --- a/kc/core/pit8253.c +++ b/kc/core/pit8253.c @@ -3,6 +3,8 @@ #include "port.h" #include "kprint.h" +#include <stdatomic.h> + #define PIT8253_DATA0 0x40 #define PIT8253_CMD 0x43 @@ -13,51 +15,86 @@ #define CONFIG_CHANNEL_0 (SEL_CHANNEL0|ACC_LOHI|MODE_RATE|BIN_COUNT) +#define PIT_IRQ 0 #define PIT_HZ 1193182U +#define PIT_HZ_MIN (PIT_HZ/0xffff) + +static void pit8253_set_divisor(uint16_t divisor); -static uint64_t count = 0; +static atomic_uint_fast64_t count = 0; +static uint16_t divisor = 0; + +const struct timer_source pit8253_timer_source = +{ + "pit8253", + pit8253_init, + pit8253_start, + pit8253_stop, + + pit8253_set_frequency, + pit8253_get_frequency, + + pit8253_nanoseconds_elapsed, + pit8253_nanoseconds_delta +}; int pit8253_callback(uint8_t irq) { (void)irq; count++; - if (!(count % (185))) - { - kprintf("it's been about %lu seconds since starting\n", count / 18); - } - return 0; } void pit8253_init(void) { - kprintf( - "initializing timer to an approximate frequency of %uHz\n", - PIT_HZ / 0xffff); - outb(PIT8253_CMD, CONFIG_CHANNEL_0); - outb(PIT8253_DATA0, 0xff); - outb(PIT8253_DATA0, 0xff); - - pic8259_irq_install(0, pit8253_callback); - pic8259_irq_unmask(0); + pic8259_irq_install(PIT_IRQ, pit8253_callback); } void pit8253_start(void) { + pic8259_irq_unmask(PIT_IRQ); } void pit8253_stop(void) { + pic8259_irq_mask(PIT_IRQ); } -uint64_t pit8253_count(void) +void pit8253_set_frequency(uint32_t frequency) { - return count; + uint32_t d = PIT_HZ / frequency; + + if (d > UINT16_MAX) + { + kprintf("warning: %uHz is too slow for 8253 pit\n", PIT_HZ/d); + d = UINT16_MAX; + kprintf("warning: set timer to minimum frequency\n"); + } + + pit8253_set_divisor(d); +} + +uint32_t pit8253_get_frequency(void) +{ + return PIT_HZ/divisor; +} + +uint64_t pit8253_nanoseconds_elapsed(void) +{ + return pit8253_nanoseconds_delta() * count; +} + +uint64_t pit8253_nanoseconds_delta(void) +{ + return (TIMER_NANOSECOND * divisor)/PIT_HZ; } -void pit8253_set_hz(uint16_t hz) +static void pit8253_set_divisor(uint16_t d) { - (void)hz; + outb(PIT8253_CMD, CONFIG_CHANNEL_0); + outb(PIT8253_DATA0, (uint8_t)d); + outb(PIT8253_DATA0, (uint8_t)(d >> 8)); + divisor = d; } diff --git a/kc/core/pit8253.h b/kc/core/pit8253.h index 25861f7..32cb9b1 100644 --- a/kc/core/pit8253.h +++ b/kc/core/pit8253.h @@ -1,10 +1,17 @@ #pragma once +#include "timer.h" #include <stdint.h> void pit8253_init(void); void pit8253_start(void); void pit8253_stop(void); -uint64_t pit8253_count(void); -void pit8253_set_hz(uint16_t hz); + +void pit8253_set_frequency(uint32_t frequency); +uint32_t pit8253_get_frequency(void); + +uint64_t pit8253_nanoseconds_elapsed(void); +uint64_t pit8253_nanoseconds_delta(void); + +extern const struct timer_source pit8253_timer_source; diff --git a/kc/core/task.c b/kc/core/task.c index 79fae5f..13263d8 100644 --- a/kc/core/task.c +++ b/kc/core/task.c @@ -6,9 +6,16 @@ #include "kprint.h" #include "cpu/irq.h" +#include "pit8253.h" + +#include <stdatomic.h> +#include <stdbool.h> + struct kc_thread *current_task = NULL; struct kc_thread *first_ready_task = NULL; struct kc_thread *last_ready_task = NULL; +struct kc_thread *sleeping_tasks = NULL; +struct kc_thread *blocked_tasks = NULL; static void lock_scheduler(void); static void unlock_scheduler(void); @@ -18,9 +25,14 @@ static void idle_task_thread(void); extern uint64_t *get_tss_rsp0(void); static uint64_t last_count = 0; +const struct timer_source * timesource; + +static atomic_int preempt_switch_count = 0; +static volatile atomic_bool preempt_switch_flag = false; + void update_time_used(void) { - uint64_t current_count = timer_ticks(); + uint64_t current_count = timesource->nanoseconds_elapsed(); uint64_t elapsed = current_count - last_count; last_count = current_count; current_task->time_elapsed += elapsed; @@ -29,13 +41,23 @@ void update_time_used(void) void task_set_thread(struct kc_thread *task) { // wrapper around cpu_set_thread + if (preempt_switch_count) + { + preempt_switch_flag = true; + return; + } uint64_t *rsp0 = get_tss_rsp0(); cpu_set_thread(¤t_task->state, &task->state, rsp0); } void task_schedule(void) { - kprintf("task_schedule() called @%lu ticks\n", last_count); + if (preempt_switch_count) + { + preempt_switch_flag = true; + return; + } + update_time_used(); if (first_ready_task) { @@ -49,10 +71,22 @@ void task_schedule(void) static void lock_scheduler(void) { irq_lock(); + preempt_switch_count++; } static void unlock_scheduler(void) { + if (preempt_switch_count >= 1) + { + preempt_switch_count--; + } + + if (!preempt_switch_count && preempt_switch_flag) + { + preempt_switch_flag = false; + task_schedule(); + } + irq_unlock(); } @@ -94,8 +128,11 @@ static void idle_task_thread(void) noreturn void task_init(void) { lock_scheduler(); + timesource = &pit8253_timer_source; + timesource->start(); char *kernel_rsp0 = vm_alloc(4096); // TODO: make it so this isn't demand-allocated. + // TODO: decouple the task management code from cpu-dependent task code kernel_rsp0[1] = 0; *get_tss_rsp0() = (uintptr_t)kernel_rsp0; char *first_task = vm_alloc(16384); @@ -104,6 +141,7 @@ noreturn void task_init(void) idle_thread->state.stack = (uintptr_t)idle_thread; idle_thread->state.stack_top = (uintptr_t)kernel_rsp0; + // XXX: this is kindof a train wreck __asm__ volatile ( "mov %%cr3, %%rax\n\t" @@ -118,6 +156,6 @@ noreturn void task_init(void) ); // shouldn't ever get here - panic(GENERAL_PANIC); + PANIC(DEAD_END); } diff --git a/kc/core/timer.c b/kc/core/timer.c deleted file mode 100644 index 2b7d5f6..0000000 --- a/kc/core/timer.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "timer.h" -#include "pit8253.h" - -uint64_t timer_ticks(void) -{ - return pit8253_count(); -} - diff --git a/kc/core/timer.h b/kc/core/timer.h index 702d7b6..b70cd70 100644 --- a/kc/core/timer.h +++ b/kc/core/timer.h @@ -1,6 +1,25 @@ #pragma once #include <stdint.h> -uint64_t timer_ticks(void); +#define TIMER_MILLISECOND 1000ULL +#define TIMER_MICROSECOND 1000000ULL +#define TIMER_NANOSECOND 1000000000ULL + +struct timer_source +{ + const char *name; + void (*init)(void); + void (*start)(void); + void (*stop)(void); + + void (*set_frequency)(uint32_t frequency); + uint32_t (*get_frequency)(void); + uint64_t (*nanoseconds_elapsed)(void); + uint64_t (*nanoseconds_delta)(void); +}; + +uint64_t timer_ticks(void); +void timer_sleep(uint64_t usec); +void timer_sleep_until(uint64_t ticks); |
