]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/ia32/timer-apic.cpp
update
[l4.git] / kernel / fiasco / src / kern / ia32 / timer-apic.cpp
1 IMPLEMENTATION [apic_timer]:
2
3 #include <cstdio>
4
5 #include "apic.h"
6 #include "config.h"
7 #include "cpu.h"
8 #include "logdefs.h"
9 #include "pit.h"
10 #include "std_macros.h"
11
12 // no IRQ line for the LAPIC
13 PUBLIC static inline int Timer::irq() { return -1; }
14
15 IMPLEMENT
16 void
17 Timer::init(Cpu_number)
18 {
19   Apic::timer_assign_irq_vector(Config::Apic_timer_vector);
20
21   if (Config::Scheduler_one_shot)
22     {
23       Apic::timer_set_one_shot();
24       Apic::timer_reg_write(0xffffffff);
25     }
26   else
27     {
28       Apic::timer_set_periodic();
29       Apic::timer_reg_write(Apic::us_to_apic(Config::Scheduler_granularity));
30     }
31
32   // make sure that PIT does pull its interrupt line
33   Pit::done();
34
35   if (!Config::Scheduler_one_shot)
36     // from now we can save energy in getchar()
37     Config::getchar_does_hlt_works_ok = false && Config::hlt_works_ok;
38
39   printf ("Using the Local APIC timer on vector %x (%s Mode) for scheduling\n",
40           Config::Apic_timer_vector,
41           Config::Scheduler_one_shot ? "One-Shot" : "Periodic");
42 }
43
44 PUBLIC static inline
45 void
46 Timer::acknowledge()
47 {}
48
49 static
50 void
51 Timer::update_one_shot(Unsigned64 wakeup)
52 {
53   Unsigned32 apic;
54   Unsigned64 now = Kip::k()->clock;
55   if (EXPECT_FALSE (wakeup <= now))
56     // already expired
57     apic = 1;
58   else
59     {
60       Unsigned64 delta = wakeup - now;
61       if (delta < Config::One_shot_min_interval_us)
62         apic = Apic::us_to_apic(Config::One_shot_min_interval_us);
63       else if (delta > Config::One_shot_max_interval_us)
64         apic = Apic::us_to_apic(Config::One_shot_max_interval_us);
65       else
66         apic = Apic::us_to_apic(delta);
67
68       if (EXPECT_FALSE (apic < 1))
69         // timeout too small
70         apic = 1;
71     }
72
73   Apic::timer_reg_write(apic);
74 }
75
76 IMPLEMENT inline
77 void
78 Timer::update_timer(Unsigned64 wakeup)
79 {
80   if (Config::Scheduler_one_shot)
81     update_one_shot(wakeup);
82 }