refactor: Move the kernel post init stage into proc0
[lunaix-os.git] / lunaix-os / kernel / time / timer.c
index 73bc0d5b8f25fdab712ae0be0c5b81b573da3cab..981b64565fc458121e3f071d4ba65a1540621876 100644 (file)
@@ -16,6 +16,7 @@
 #include <lunaix/spike.h>
 #include <lunaix/syslog.h>
 #include <lunaix/timer.h>
 #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)
 
 
 #define LVT_ENTRY_TIMER(vector, mode) (LVT_DELIVERY_FIXED | mode | vector)
 
@@ -38,6 +39,9 @@ static volatile struct lx_timer_context* timer_ctx = NULL;
 static volatile uint32_t rtc_counter = 0;
 static volatile uint8_t apic_timer_done = 0;
 
 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
 #define APIC_CALIBRATION_CONST 0x100000
 
 void
@@ -51,6 +55,7 @@ timer_init_context()
     timer_ctx->active_timers =
       (struct lx_timer*)lxmalloc(sizeof(struct lx_timer));
     llist_init_head(timer_ctx->active_timers);
     timer_ctx->active_timers =
       (struct lx_timer*)lxmalloc(sizeof(struct lx_timer));
     llist_init_head(timer_ctx->active_timers);
+
 }
 
 void
 }
 
 void
@@ -63,8 +68,7 @@ timer_init(uint32_t frequency)
     // Setup APIC timer
 
     // Setup a one-shot timer, we will use this to measure the bus speed. So we
     // 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));
 
     apic_write_reg(APIC_TIMER_LVT,
                    LVT_ENTRY_TIMER(APIC_TIMER_IV, LVT_TIMER_ONESHOT));
 
@@ -81,7 +85,7 @@ timer_init(uint32_t frequency)
          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 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
 
         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
@@ -94,6 +98,12 @@ timer_init(uint32_t frequency)
 
     */
 
 
     */
 
+    #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;
     timer_ctx->base_frequency = 0;
     rtc_counter = 0;
     apic_timer_done = 0;
@@ -109,14 +119,13 @@ timer_init(uint32_t frequency)
 
     wait_until(apic_timer_done);
 
 
     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;
 
     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);
 
     // cleanup
     intr_unsubscribe(APIC_TIMER_IV, temp_intr_routine_apic_timer);
@@ -126,27 +135,30 @@ timer_init(uint32_t frequency)
                    LVT_ENTRY_TIMER(APIC_TIMER_IV, LVT_TIMER_PERIODIC));
     intr_subscribe(APIC_TIMER_IV, timer_update);
 
                    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);
 }
 
 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);
 }
 
 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));
 
 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;
 
     timer->callback = callback;
     timer->counter = ticks;
@@ -156,7 +168,7 @@ timer_run(ticks_t ticks, void (*callback)(void*), void* payload, uint8_t flags)
 
     llist_append(timer_ctx->active_timers, &timer->link);
 
 
     llist_append(timer_ctx->active_timers, &timer->link);
 
-    return 1;
+    return timer;
 }
 
 static void
 }
 
 static void
@@ -167,19 +179,29 @@ timer_update(const isr_param* param)
 
     llist_for_each(pos, n, &timer_list_head->link, link)
     {
 
     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;
 
             continue;
         }
 
         pos->callback ? pos->callback(pos->payload) : 1;
 
-        if (pos->flags & TIMER_MODE_PERIODIC) {
+        if ((pos->flags & TIMER_MODE_PERIODIC)) {
             pos->counter = pos->deadline;
             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
 }
 
 static void