]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/ia32/timer-apic.cpp
cb302280e736cbd7ff85735461438780d14f30ac
[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(unsigned)
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 PUBLIC static inline
45 void
46 Timer::acknowledge()
47 {}
48
49 static
50 void
51 Timer::update_one_shot(Unsigned64 wakeup)
52 {
53   //unsigned cpu = current_cpu();
54   Unsigned32 apic;
55   Unsigned64 now = Kip::k()->clock; //Cpu::cpus.cpu(cpu).time_us();
56   if (EXPECT_FALSE (wakeup <= now))
57     // already expired
58     apic = 1;
59   else
60     {
61       Unsigned64 delta = wakeup - now;
62       if (delta < Config::One_shot_min_interval_us)
63         apic = Apic::us_to_apic(Config::One_shot_min_interval_us);
64       else if (delta > Config::One_shot_max_interval_us)
65         apic = Apic::us_to_apic(Config::One_shot_max_interval_us);
66       else
67         apic = Apic::us_to_apic(delta);
68
69       if (EXPECT_FALSE (apic < 1))
70         // timeout too small
71         apic = 1;
72     }
73
74   Apic::timer_reg_write(apic);
75 }
76
77 IMPLEMENT inline
78 void
79 Timer::update_timer(Unsigned64 wakeup)
80 {
81   if (Config::Scheduler_one_shot)
82     update_one_shot(wakeup);
83 }