diff --git a/kernel-src/arch/x86-64/apic.c b/kernel-src/arch/x86-64/apic.c index 8ce93224..104319ee 100644 --- a/kernel-src/arch/x86-64/apic.c +++ b/kernel-src/arch/x86-64/apic.c @@ -194,7 +194,7 @@ void arch_apic_eoi() { writelapic(APIC_REG_EOI, 0); } -static time_t stoptimer() { +static time_t stoptimer(timer_t *) { time_t remaining = readlapic(APIC_TIMER_COUNT); time_t initial = readlapic(APIC_TIMER_INITIALCOUNT); @@ -203,11 +203,18 @@ static time_t stoptimer() { return initial - remaining; } +static time_t time_passed(timer_t *) { + time_t remaining = readlapic(APIC_TIMER_COUNT); + time_t initial = readlapic(APIC_TIMER_INITIALCOUNT); + + return initial - remaining; +} + static void timerisr(isr_t *isr, context_t *context) { timer_isr(current_cpu()->timer, context); } -static void armtimer(time_t ticks) { +static void armtimer(timer_t *, time_t ticks) { writelapic(APIC_TIMER_INITIALCOUNT, ticks); } @@ -237,7 +244,7 @@ void arch_apic_timerinit() { writelapic(APIC_LVT_TIMER, vec); - current_cpu()->timer = timer_new(ticksperus, armtimer, stoptimer, 0xffffffff); + current_cpu()->timer = timer_new(ticksperus, armtimer, stoptimer, time_passed, 0xffffffff); __assert(current_cpu()->timer); } diff --git a/kernel-src/include/kernel/timer.h b/kernel-src/include/kernel/timer.h index e42ee7ed..46cebc68 100644 --- a/kernel-src/include/kernel/timer.h +++ b/kernel-src/include/kernel/timer.h @@ -17,23 +17,25 @@ typedef struct timerentry_t { bool fired; } timerentry_t; -typedef struct { +typedef struct timer_t { spinlock_t lock; time_t tick_limit; time_t ticksperus; time_t tickcurrent; time_t current_target; bool running; - void (*arm)(time_t); - time_t (*stop)(); + void (*arm)(struct timer_t *, time_t); + time_t (*stop)(struct timer_t *); + time_t (*time_passed)(struct timer_t *); timerentry_t *queue; } timer_t; +time_t timer_get_ticks(timer_t *timer); void timer_resume(timer_t *timer); void timer_stop(timer_t *timer); void timer_isr(timer_t *timer, context_t *context); void timer_insert(timer_t *timer, timerentry_t *entry, dpcfn_t fn, dpcarg_t arg, time_t us, bool repeating); -uintmax_t timer_remove(timer_t *timer, timerentry_t *entry); -timer_t *timer_new(time_t ticksperus, void (*arm)(time_t), time_t (*stop)(), time_t tick_limit); +time_t timer_remove(timer_t *timer, timerentry_t *entry); +timer_t *timer_new(time_t ticksperus, void (*arm)(timer_t *, time_t), time_t (*stop)(timer_t *), time_t (*time_passed)(timer_t *), time_t tick_limit); #endif diff --git a/kernel-src/sys/timer.c b/kernel-src/sys/timer.c index 0542cd64..7969ef99 100644 --- a/kernel-src/sys/timer.c +++ b/kernel-src/sys/timer.c @@ -45,7 +45,7 @@ static inline void arm_for_next_target(timer_t *timer) { target = timer->tick_limit; timer->current_target = timer->tickcurrent + target; - timer->arm(target); + timer->arm(timer, target); } // expects IPL to be at least IPL_TIMER @@ -96,6 +96,16 @@ void timer_isr(timer_t *timer, context_t *context) { spinlock_release(&timer->lock); } +time_t timer_get_ticks(timer_t *timer) { + long ipl = spinlock_acquireraiseipl(&timer->lock, IPL_TIMER); + + time_t ticks = timer->tickcurrent + timer->time_passed(timer); + + spinlock_releaseloweripl(&timer->lock, ipl); + + return ticks; +} + void timer_resume(timer_t *timer) { long oldipl = interrupt_raiseipl(IPL_TIMER); spinlock_acquire(&timer->lock); @@ -147,7 +157,7 @@ void timer_insert(timer_t *timer, timerentry_t *entry, dpcfn_t fn, dpcarg_t arg, interrupt_loweripl(oldipl); } -uintmax_t timer_remove(timer_t *timer, timerentry_t *entry) { +time_t timer_remove(timer_t *timer, timerentry_t *entry) { long oldipl = interrupt_raiseipl(IPL_TIMER); spinlock_acquire(&timer->lock); @@ -191,7 +201,7 @@ uintmax_t timer_remove(timer_t *timer, timerentry_t *entry) { return timeremaining; } -timer_t *timer_new(time_t ticksperus, void (*arm)(time_t), time_t (*stop)(), time_t tick_limit) { +timer_t *timer_new(time_t ticksperus, void (*arm)(timer_t *, time_t), time_t (*stop)(timer_t *), time_t (*time_passed)(timer_t *), time_t tick_limit) { timer_t *timer = alloc(sizeof(timer_t)); if (timer == NULL) return NULL; @@ -201,6 +211,7 @@ timer_t *timer_new(time_t ticksperus, void (*arm)(time_t), time_t (*stop)(), tim timer->tick_limit = tick_limit; timer->arm = arm; timer->stop = stop; + timer->time_passed = time_passed; SPINLOCK_INIT(timer->lock); return timer;