#include <lunaix/spike.h>
#include <lunaix/syslog.h>
#include <lunaix/timer.h>
+#include <lunaix/sched.h>
#define LVT_ENTRY_TIMER(vector, mode) (LVT_DELIVERY_FIXED | mode | vector)
static volatile uint32_t rtc_counter = 0;
static volatile uint8_t apic_timer_done = 0;
+static volatile uint32_t sched_ticks = 0;
+static volatile uint32_t sched_ticks_counter = 0;
+
#define APIC_CALIBRATION_CONST 0x100000
void
timer_ctx->active_timers =
(struct lx_timer*)lxmalloc(sizeof(struct lx_timer));
llist_init_head(timer_ctx->active_timers);
+
}
void
// Setup APIC timer
// Setup a one-shot timer, we will use this to measure the bus speed. So we
- // can
- // then calibrate apic timer to work at *nearly* accurate hz
+ // can then calibrate apic timer to work at *nearly* accurate hz
apic_write_reg(APIC_TIMER_LVT,
LVT_ENTRY_TIMER(APIC_TIMER_IV, LVT_TIMER_ONESHOT));
step 4: Startup RTC timer
step 5: Write a large value, v, to APIC_TIMER_ICR to start APIC timer (this must be
followed immediately after step 4)
- step 6: issue a write to EOI and clean up.
+ step 6: issue a write to EOI and clean up.
When the APIC ICR counting down to 0 #APIC_TIMER_IV triggered, save the
rtc timer's counter, k, and disable RTC timer immediately (although the
*/
+ #ifdef __LUNAIXOS_DEBUG__
+ if (frequency < 1000) {
+ kprintf(KWARN "Frequency too low. Millisecond timer might be dodgy.");
+ }
+ #endif
+
timer_ctx->base_frequency = 0;
rtc_counter = 0;
apic_timer_done = 0;
wait_until(apic_timer_done);
- // cpu_disable_interrupt();
assert_msg(timer_ctx->base_frequency, "Fail to initialize timer (NOFREQ)");
kprintf(KINFO "Base frequency: %u Hz\n", timer_ctx->base_frequency);
timer_ctx->running_frequency = frequency;
- timer_ctx->tps = timer_ctx->base_frequency / frequency;
+ timer_ctx->tphz = timer_ctx->base_frequency / frequency;
// cleanup
intr_unsubscribe(APIC_TIMER_IV, temp_intr_routine_apic_timer);
LVT_ENTRY_TIMER(APIC_TIMER_IV, LVT_TIMER_PERIODIC));
intr_subscribe(APIC_TIMER_IV, timer_update);
- apic_write_reg(APIC_TIMER_ICR, timer_ctx->tps);
+ apic_write_reg(APIC_TIMER_ICR, timer_ctx->tphz);
+
+ sched_ticks = timer_ctx->running_frequency / 1000 * SCHED_TIME_SLICE;
+ sched_ticks_counter = 0;
}
-int
+struct lx_timer*
timer_run_second(uint32_t second, void (*callback)(void*), void* payload, uint8_t flags)
{
return timer_run(second * timer_ctx->running_frequency, callback, payload, flags);
}
-int
+struct lx_timer*
timer_run_ms(uint32_t millisecond, void (*callback)(void*), void* payload, uint8_t flags)
{
return timer_run(timer_ctx->running_frequency / 1000 * millisecond, callback, payload, flags);
}
-int
+struct lx_timer*
timer_run(ticks_t ticks, void (*callback)(void*), void* payload, uint8_t flags)
{
struct lx_timer* timer = (struct lx_timer*)lxmalloc(sizeof(struct lx_timer));
- if (!timer) return 0;
+ if (!timer) return NULL;
timer->callback = callback;
timer->counter = ticks;
llist_append(timer_ctx->active_timers, &timer->link);
- return 1;
+ return timer;
}
static void
llist_for_each(pos, n, &timer_list_head->link, link)
{
- if (--pos->counter) {
+ if (!pos->counter) {
+ llist_delete(&pos->link);
+ lxfree(pos);
+ continue;
+ }
+
+ if (--(pos->counter)) {
continue;
}
pos->callback ? pos->callback(pos->payload) : 1;
- if (pos->flags & TIMER_MODE_PERIODIC) {
+ if ((pos->flags & TIMER_MODE_PERIODIC)) {
pos->counter = pos->deadline;
- } else {
- llist_delete(&pos->link);
- lxfree(pos);
}
}
+
+ sched_ticks_counter++;
+
+ if (sched_ticks_counter >= sched_ticks) {
+ sched_ticks_counter = 0;
+ schedule();
+ }
}
static void