mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 23:18:21 +00:00
per cpu timer queue
This commit is contained in:
@@ -190,22 +190,27 @@ void apic_timerinterruptset(uint8_t vector){
|
|||||||
lapic_writereg(APIC_TIMER_LVT, vector);
|
lapic_writereg(APIC_TIMER_LVT, vector);
|
||||||
}
|
}
|
||||||
|
|
||||||
void apic_timerstop(){
|
size_t apic_timerstop(){
|
||||||
|
|
||||||
|
size_t ticksremaining = lapic_readreg(APIC_TIMER_COUNT);
|
||||||
|
|
||||||
lapic_writereg(APIC_TIMER_INITIALCOUNT, 0);
|
lapic_writereg(APIC_TIMER_INITIALCOUNT, 0);
|
||||||
|
|
||||||
|
return ticksremaining;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t apic_timercalibrate(size_t ms){
|
size_t apic_timercalibrate(size_t us){
|
||||||
|
|
||||||
lapic_writereg(APIC_TIMER_INITIALCOUNT, 0xFFFFFFFF);
|
lapic_writereg(APIC_TIMER_INITIALCOUNT, 0xFFFFFFFF);
|
||||||
lapic_writereg(APIC_TIMER_DIVIDE, 0b111); // no divider
|
lapic_writereg(APIC_TIMER_DIVIDE, 0b111); // no divider
|
||||||
|
|
||||||
hpet_wait_ms(ms);
|
hpet_wait_ms(us);
|
||||||
|
|
||||||
size_t ticks = 0xFFFFFFFF - lapic_readreg(APIC_TIMER_COUNT);
|
size_t ticks = 0xFFFFFFFF - lapic_readreg(APIC_TIMER_COUNT);
|
||||||
|
|
||||||
apic_timerstop();
|
apic_timerstop();
|
||||||
|
|
||||||
return ticks;
|
return ticks / 1000;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#include <arch/cputimer.h>
|
||||||
|
#include <arch/apic.h>
|
||||||
|
#include <arch/idt.h>
|
||||||
|
|
||||||
|
size_t arch_cputimer_init(){
|
||||||
|
// XXX invariant TSC?
|
||||||
|
|
||||||
|
size_t ticks = apic_timercalibrate(1);
|
||||||
|
|
||||||
|
apic_timerinterruptset(VECTOR_TIMER);
|
||||||
|
|
||||||
|
return ticks;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t arch_cputimer_stop(){
|
||||||
|
return apic_timerstop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void arch_cputimer_fire(size_t ticks){
|
||||||
|
apic_timerstart(ticks);
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
#include <arch/gdt.h>
|
#include <arch/gdt.h>
|
||||||
#include <arch/ist.h>
|
#include <arch/ist.h>
|
||||||
|
|
||||||
static void setseg(segdesc __seg_gs *seg, uint32_t limit, uint32_t offset, uint8_t flags, uint8_t access){
|
static void setseg(segdesc *seg, uint32_t limit, uint32_t offset, uint8_t flags, uint8_t access){
|
||||||
|
|
||||||
seg->limit = limit & 0xFFFF;
|
seg->limit = limit & 0xFFFF;
|
||||||
seg->offset1 = offset & 0xFFFF;
|
seg->offset1 = offset & 0xFFFF;
|
||||||
@@ -14,7 +14,7 @@ static void setseg(segdesc __seg_gs *seg, uint32_t limit, uint32_t offset, uint8
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setsys64(sys64 __seg_gs *e, uint32_t limit, uint64_t offset, uint8_t flags, uint8_t access){
|
static void setsys64(sys64 *e, uint32_t limit, uint64_t offset, uint8_t flags, uint8_t access){
|
||||||
|
|
||||||
e->limit = limit & 0xFFFF;
|
e->limit = limit & 0xFFFF;
|
||||||
e->offset1 = offset & 0xFFFF;
|
e->offset1 = offset & 0xFFFF;
|
||||||
@@ -32,14 +32,14 @@ gdtr_t gdtr;
|
|||||||
|
|
||||||
static void reloadgdtr(){
|
static void reloadgdtr(){
|
||||||
|
|
||||||
gdtr.offset = (uint64_t)&cls->gdt + arch_getcls();
|
gdtr.offset = &arch_getcls()->gdt;
|
||||||
gdtr.size = sizeof(gdt_t) - 1;
|
gdtr.size = sizeof(gdt_t) - 1;
|
||||||
asm("lgdt (%%rax)" : : "a"(&gdtr) : "memory");
|
asm("lgdt (%%rax)" : : "a"(&gdtr) : "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
void gdt_init(){
|
void gdt_init(){
|
||||||
|
|
||||||
gdt_t __seg_gs *gdt = &cls->gdt;
|
gdt_t* gdt = &arch_getcls()->gdt;
|
||||||
|
|
||||||
setseg(&gdt->null, 0, 0, 0, 0);
|
setseg(&gdt->null, 0, 0, 0, 0);
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
|
|
||||||
void apic_sendipi(uint8_t cpu, uint8_t vec, uint8_t dest, uint8_t mode, uint8_t level);
|
void apic_sendipi(uint8_t cpu, uint8_t vec, uint8_t dest, uint8_t mode, uint8_t level);
|
||||||
void apic_eoi();
|
void apic_eoi();
|
||||||
void apic_timerstop();
|
size_t apic_timerstop();
|
||||||
void apic_timerstart(size_t ticks);
|
void apic_timerstart(size_t ticks);
|
||||||
void apic_timerinterruptset(uint8_t vector);
|
void apic_timerinterruptset(uint8_t vector);
|
||||||
size_t apic_timercalibrate(size_t ms);
|
size_t apic_timercalibrate(size_t us);
|
||||||
void apic_lapicinit();
|
void apic_lapicinit();
|
||||||
void apic_init();
|
void apic_init();
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <arch/regs.h>
|
#include <arch/regs.h>
|
||||||
#include <kernel/vmm.h>
|
#include <kernel/vmm.h>
|
||||||
#include <kernel/sched.h>
|
#include <kernel/sched.h>
|
||||||
|
#include <kernel/timer.h>
|
||||||
|
|
||||||
// cpu level storage
|
// cpu level storage
|
||||||
// this will be pointed to by GS and will contain per cpu info
|
// this will be pointed to by GS and will contain per cpu info
|
||||||
@@ -19,7 +20,8 @@ typedef struct{
|
|||||||
arch_regs *laststate;
|
arch_regs *laststate;
|
||||||
vmm_context *context;
|
vmm_context *context;
|
||||||
thread_t* thread;
|
thread_t* thread;
|
||||||
size_t schedtimerticksperms;
|
size_t timerticksperus;
|
||||||
|
timer_req* timerfirstreq;
|
||||||
} cls_t;
|
} cls_t;
|
||||||
|
|
||||||
void bsp_setcls();
|
void bsp_setcls();
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef _CPUTIMER_H_INCLUDE
|
||||||
|
#define _CPUTIMER_H_INCLUDE
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
size_t arch_cputimer_init();
|
||||||
|
size_t arch_cputimer_stop();
|
||||||
|
void arch_cputimer_fire(size_t ticks);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <arch/panic.h>
|
#include <arch/panic.h>
|
||||||
#include <kernel/vmm.h>
|
#include <kernel/vmm.h>
|
||||||
#include <arch/apic.h>
|
#include <arch/apic.h>
|
||||||
|
#include <kernel/timer.h>
|
||||||
|
|
||||||
void isr_general(arch_regs *reg){
|
void isr_general(arch_regs *reg){
|
||||||
_panic("Unhandled interrupt", reg);
|
_panic("Unhandled interrupt", reg);
|
||||||
@@ -30,5 +31,6 @@ void isr_mmuinval(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void isr_timer(arch_regs* reg){
|
void isr_timer(arch_regs* reg){
|
||||||
|
timer_irq(reg);
|
||||||
apic_eoi();
|
apic_eoi();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <arch/pci.h>
|
#include <arch/pci.h>
|
||||||
#include <arch/hpet.h>
|
#include <arch/hpet.h>
|
||||||
#include <arch/smp.h>
|
#include <arch/smp.h>
|
||||||
|
#include <kernel/timer.h>
|
||||||
|
|
||||||
static volatile struct limine_terminal_request liminettyr = {
|
static volatile struct limine_terminal_request liminettyr = {
|
||||||
.id = LIMINE_TERMINAL_REQUEST,
|
.id = LIMINE_TERMINAL_REQUEST,
|
||||||
@@ -42,7 +43,9 @@ void kmain(){
|
|||||||
console_setwritehook(liminewrite);
|
console_setwritehook(liminewrite);
|
||||||
|
|
||||||
bsp_setcls();
|
bsp_setcls();
|
||||||
|
|
||||||
gdt_init();
|
gdt_init();
|
||||||
|
|
||||||
idt_bspinit();
|
idt_bspinit();
|
||||||
|
|
||||||
pmm_init();
|
pmm_init();
|
||||||
@@ -62,6 +65,8 @@ void kmain(){
|
|||||||
|
|
||||||
hpet_init();
|
hpet_init();
|
||||||
|
|
||||||
|
timer_init();
|
||||||
|
|
||||||
vfs_init();
|
vfs_init();
|
||||||
|
|
||||||
printf("Mounting tmpfs in /\n");
|
printf("Mounting tmpfs in /\n");
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ static void apstartup(struct limine_smp_info *info){
|
|||||||
|
|
||||||
apic_lapicinit();
|
apic_lapicinit();
|
||||||
|
|
||||||
|
timer_init();
|
||||||
|
|
||||||
printf("CPU %lu ready!\n", info->lapic_id);
|
printf("CPU %lu ready!\n", info->lapic_id);
|
||||||
|
|
||||||
sem_signal(sem);
|
sem_signal(sem);
|
||||||
@@ -62,6 +64,8 @@ void smp_init(){
|
|||||||
|
|
||||||
apcls = pmm_hhdmalloc(sizeof(cls_t)*cpucount/PAGE_SIZE+1);
|
apcls = pmm_hhdmalloc(sizeof(cls_t)*cpucount/PAGE_SIZE+1);
|
||||||
|
|
||||||
|
memset(apcls, 0, sizeof(cls_t)*cpucount/PAGE_SIZE+1);
|
||||||
|
|
||||||
printf("System has %lu CPUs\n", cpucount);
|
printf("System has %lu CPUs\n", cpucount);
|
||||||
|
|
||||||
sem = sem_init(-cpucount + 2, 0);
|
sem = sem_init(-cpucount + 2, 0);
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef _TIMER_H_INCLUDE
|
||||||
|
#define _TIMER_H_INCLUDE
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <arch/regs.h>
|
||||||
|
|
||||||
|
typedef struct _timer_req{
|
||||||
|
// values callee should care about
|
||||||
|
void* (*func)(arch_regs*, void*);
|
||||||
|
void* argptr;
|
||||||
|
// internal values
|
||||||
|
struct _timer_req* next;
|
||||||
|
size_t ticks;
|
||||||
|
} timer_req;
|
||||||
|
|
||||||
|
void timer_init();
|
||||||
|
void timer_add(timer_req* req, size_t us);
|
||||||
|
void timer_resume();
|
||||||
|
void timer_stop();
|
||||||
|
void timer_irq(arch_regs* ctx);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
#include <kernel/timer.h>
|
||||||
|
#include <arch/cputimer.h>
|
||||||
|
#include <arch/cls.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void timer_init(){
|
||||||
|
cls_t* cls = arch_getcls();
|
||||||
|
cls->timerticksperus = arch_cputimer_init();
|
||||||
|
printf("CPU%d: CPUTIMER tick: %lu per us\n", cls->lapicid, cls->timerticksperus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_irq(arch_regs* ctx){
|
||||||
|
timer_req* pendingreq = arch_getcls()->timerfirstreq;
|
||||||
|
timer_req* iter = pendingreq->next;
|
||||||
|
|
||||||
|
arch_getcls()->timerfirstreq = iter;
|
||||||
|
|
||||||
|
while(iter){
|
||||||
|
iter->ticks -= pendingreq->ticks;
|
||||||
|
iter = iter->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
pendingreq->func(ctx, pendingreq->argptr);
|
||||||
|
|
||||||
|
if(!arch_getcls()->timerfirstreq) return;
|
||||||
|
|
||||||
|
arch_cputimer_fire(arch_getcls()->timerfirstreq->ticks);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_resume(){
|
||||||
|
arch_cputimer_fire(arch_getcls()->timerfirstreq->ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_stop(){
|
||||||
|
|
||||||
|
size_t remainingticks = arch_cputimer_stop();
|
||||||
|
timer_req* iter = arch_getcls()->timerfirstreq;
|
||||||
|
size_t subticks = iter->ticks - remainingticks;
|
||||||
|
while(iter){
|
||||||
|
iter->ticks -= subticks;
|
||||||
|
iter = iter->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_add(timer_req* req, size_t us){
|
||||||
|
|
||||||
|
size_t remainingticks = arch_cputimer_stop();
|
||||||
|
|
||||||
|
timer_req* iter = arch_getcls()->timerfirstreq;
|
||||||
|
|
||||||
|
|
||||||
|
req->ticks = us*arch_getcls()->timerticksperus;
|
||||||
|
|
||||||
|
if(!iter){
|
||||||
|
arch_getcls()->timerfirstreq = req;
|
||||||
|
req->next = NULL;
|
||||||
|
arch_cputimer_fire(req->ticks);
|
||||||
|
printf("ticks3: %lu", req->ticks);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t subticks = iter->ticks - remainingticks;
|
||||||
|
|
||||||
|
while(iter){
|
||||||
|
iter->ticks -= subticks;
|
||||||
|
iter = iter->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
iter = arch_getcls()->timerfirstreq;
|
||||||
|
|
||||||
|
if(iter->ticks > req->ticks){
|
||||||
|
req->next = arch_getcls()->timerfirstreq;
|
||||||
|
arch_getcls()->timerfirstreq = req;
|
||||||
|
arch_cputimer_fire(req->ticks);
|
||||||
|
printf("ticks2: %lu", req->ticks);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(iter->next && iter->next->ticks <= req->ticks)
|
||||||
|
iter = iter->next;
|
||||||
|
|
||||||
|
req->next = iter->next;
|
||||||
|
iter->next = req;
|
||||||
|
|
||||||
|
printf("ticks: %lu", arch_getcls()->timerfirstreq->ticks);
|
||||||
|
arch_cputimer_fire(arch_getcls()->timerfirstreq->ticks);
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user