mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
per cpu timer queue
This commit is contained in:
+10
-5
@@ -190,22 +190,27 @@ void apic_timerinterruptset(uint8_t 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);
|
||||
|
||||
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_DIVIDE, 0b111); // no divider
|
||||
|
||||
hpet_wait_ms(ms);
|
||||
hpet_wait_ms(us);
|
||||
|
||||
size_t ticks = 0xFFFFFFFF - lapic_readreg(APIC_TIMER_COUNT);
|
||||
|
||||
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/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->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->offset1 = offset & 0xFFFF;
|
||||
@@ -32,14 +32,14 @@ gdtr_t gdtr;
|
||||
|
||||
static void reloadgdtr(){
|
||||
|
||||
gdtr.offset = (uint64_t)&cls->gdt + arch_getcls();
|
||||
gdtr.offset = &arch_getcls()->gdt;
|
||||
gdtr.size = sizeof(gdt_t) - 1;
|
||||
asm("lgdt (%%rax)" : : "a"(&gdtr) : "memory");
|
||||
}
|
||||
|
||||
void gdt_init(){
|
||||
|
||||
gdt_t __seg_gs *gdt = &cls->gdt;
|
||||
gdt_t* gdt = &arch_getcls()->gdt;
|
||||
|
||||
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_eoi();
|
||||
void apic_timerstop();
|
||||
size_t apic_timerstop();
|
||||
void apic_timerstart(size_t ticks);
|
||||
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_init();
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <arch/regs.h>
|
||||
#include <kernel/vmm.h>
|
||||
#include <kernel/sched.h>
|
||||
#include <kernel/timer.h>
|
||||
|
||||
// cpu level storage
|
||||
// this will be pointed to by GS and will contain per cpu info
|
||||
@@ -19,7 +20,8 @@ typedef struct{
|
||||
arch_regs *laststate;
|
||||
vmm_context *context;
|
||||
thread_t* thread;
|
||||
size_t schedtimerticksperms;
|
||||
size_t timerticksperus;
|
||||
timer_req* timerfirstreq;
|
||||
} cls_t;
|
||||
|
||||
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 <kernel/vmm.h>
|
||||
#include <arch/apic.h>
|
||||
#include <kernel/timer.h>
|
||||
|
||||
void isr_general(arch_regs *reg){
|
||||
_panic("Unhandled interrupt", reg);
|
||||
@@ -30,5 +31,6 @@ void isr_mmuinval(){
|
||||
}
|
||||
|
||||
void isr_timer(arch_regs* reg){
|
||||
timer_irq(reg);
|
||||
apic_eoi();
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <arch/pci.h>
|
||||
#include <arch/hpet.h>
|
||||
#include <arch/smp.h>
|
||||
#include <kernel/timer.h>
|
||||
|
||||
static volatile struct limine_terminal_request liminettyr = {
|
||||
.id = LIMINE_TERMINAL_REQUEST,
|
||||
@@ -42,7 +43,9 @@ void kmain(){
|
||||
console_setwritehook(liminewrite);
|
||||
|
||||
bsp_setcls();
|
||||
|
||||
gdt_init();
|
||||
|
||||
idt_bspinit();
|
||||
|
||||
pmm_init();
|
||||
@@ -62,6 +65,8 @@ void kmain(){
|
||||
|
||||
hpet_init();
|
||||
|
||||
timer_init();
|
||||
|
||||
vfs_init();
|
||||
|
||||
printf("Mounting tmpfs in /\n");
|
||||
@@ -76,7 +81,7 @@ void kmain(){
|
||||
pci_enumerate();
|
||||
|
||||
smp_init();
|
||||
|
||||
|
||||
_panic("End of kmain()", 0);
|
||||
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ static void apstartup(struct limine_smp_info *info){
|
||||
arch_mmu_apinit();
|
||||
|
||||
apic_lapicinit();
|
||||
|
||||
timer_init();
|
||||
|
||||
printf("CPU %lu ready!\n", info->lapic_id);
|
||||
|
||||
@@ -62,6 +64,8 @@ void smp_init(){
|
||||
|
||||
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);
|
||||
|
||||
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