]> 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 IMPLEMENT inline int Timer::irq_line() { return -1; }
14
15 IMPLEMENT
16 void
17 Timer::init()
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 = 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 IMPLEMENT inline NEEDS["apic.h"]
45 void
46 Timer::acknowledge()
47 {
48   Apic::irq_ack();
49 }
50
51 IMPLEMENT inline NEEDS["apic.h"]
52 void
53 Timer::enable()
54 {
55   Apic::timer_enable_irq();
56   Apic::irq_ack();
57 }
58
59 IMPLEMENT inline NEEDS["apic.h"]
60 void
61 Timer::disable()
62 {
63   Apic::timer_disable_irq();
64 }
65
66 static
67 void
68 Timer::update_one_shot(Unsigned64 wakeup)
69 {
70   //unsigned cpu = current_cpu();
71   Unsigned32 apic;
72   Unsigned64 now = Kip::k()->clock; //Cpu::cpus.cpu(cpu).time_us();
73   if (EXPECT_FALSE (wakeup <= now))
74     // already expired
75     apic = 1;
76   else
77     {
78       Unsigned64 delta = wakeup - now;
79       if (delta < Config::One_shot_min_interval_us)
80         apic = Apic::us_to_apic(Config::One_shot_min_interval_us);
81       else if (delta > Config::One_shot_max_interval_us)
82         apic = Apic::us_to_apic(Config::One_shot_max_interval_us);
83       else
84         apic = Apic::us_to_apic(delta);
85
86       if (EXPECT_FALSE (apic < 1))
87         // timeout too small
88         apic = 1;
89     }
90
91   Apic::timer_reg_write(apic);
92 }
93
94 IMPLEMENT inline
95 void
96 Timer::update_timer(Unsigned64 wakeup)
97 {
98   if (Config::scheduler_one_shot)
99     update_one_shot(wakeup);
100 }