]> 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 IMPLEMENT
13 void
14 Timer::init()
15 {
16   Apic::timer_assign_irq_vector(Config::scheduler_irq_vector);
17
18   if (Config::scheduler_one_shot)
19     {
20       Apic::timer_set_one_shot();
21       Apic::timer_reg_write(0xffffffff);
22     }
23   else
24     {
25       Apic::timer_set_periodic();
26       Apic::timer_reg_write(Apic::us_to_apic(Config::scheduler_granularity));
27     }
28
29   // make sure that PIT does pull its interrupt line
30   Pit::done();
31
32   if (!Config::scheduler_one_shot)
33     // from now we can save energy in getchar()
34     Config::getchar_does_hlt_works_ok = Config::hlt_works_ok;
35
36   printf ("Using the Local APIC timer on vector %x (%s Mode) for scheduling\n",
37           Config::scheduler_irq_vector,
38           Config::scheduler_one_shot ? "One-Shot" : "Periodic");
39 }
40
41 IMPLEMENT inline NEEDS["apic.h"]
42 void
43 Timer::acknowledge()
44 {
45   Apic::irq_ack();
46 }
47
48 IMPLEMENT inline NEEDS["apic.h"]
49 void
50 Timer::enable()
51 {
52   Apic::timer_enable_irq();
53   Apic::irq_ack();
54 }
55
56 IMPLEMENT inline NEEDS["apic.h"]
57 void
58 Timer::disable()
59 {
60   Apic::timer_disable_irq();
61 }
62
63 static
64 void
65 Timer::update_one_shot(Unsigned64 wakeup)
66 {
67   //unsigned cpu = current_cpu();
68   Unsigned32 apic;
69   Unsigned64 now = Kip::k()->clock; //Cpu::cpus.cpu(cpu).time_us();
70   if (EXPECT_FALSE (wakeup <= now))
71     // already expired
72     apic = 1;
73   else
74     {
75       Unsigned64 delta = wakeup - now;
76       if (delta < Config::One_shot_min_interval_us)
77         apic = Apic::us_to_apic(Config::One_shot_min_interval_us);
78       else if (delta > Config::One_shot_max_interval_us)
79         apic = Apic::us_to_apic(Config::One_shot_max_interval_us);
80       else
81         apic = Apic::us_to_apic(delta);
82
83       if (EXPECT_FALSE (apic < 1))
84         // timeout too small
85         apic = 1;
86     }
87
88   Apic::timer_reg_write(apic);
89 }
90
91 IMPLEMENT inline
92 void
93 Timer::update_timer(Unsigned64 wakeup)
94 {
95   if (Config::scheduler_one_shot)
96     update_one_shot(wakeup);
97 }