]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/timer_tick.cpp
update
[l4.git] / kernel / fiasco / src / kern / timer_tick.cpp
1 INTERFACE:
2
3 #include "irq_chip.h"
4 #include "thread.h"
5
6 class Timer_tick : public Irq_base
7 {
8 public:
9   enum Mode
10   {
11     Any_cpu, ///< Might hit on any CPU
12     Sys_cpu, ///< Hit only on the CPU that manages the system time
13     App_cpu, ///< Hit only on application CPUs
14   };
15   /// Create a timer IRQ object
16   explicit Timer_tick(Mode mode)
17   {
18     switch (mode)
19       {
20       case Any_cpu: set_hit(&handler_all); break;
21       case Sys_cpu: set_hit(&handler_sys_time); break;
22       case App_cpu: set_hit(&handler_app); break;
23       }
24   }
25
26   static void setup(Cpu_number cpu);
27   static void enable(Cpu_number cpu);
28   static void disable(Cpu_number cpu);
29
30 protected:
31   static bool allocate_irq(Irq_base *irq, unsigned irqnum);
32
33 private:
34   // we do not support triggering modes
35   void switch_mode(unsigned) {}
36 };
37
38 // ------------------------------------------------------------------------
39 INTERFACE [debug]:
40
41 #include "tb_entry.h"
42
43 EXTENSION class Timer_tick
44 {
45 public:
46   struct Log : public Tb_entry
47   {
48     Irq_base *obj;
49     Address user_ip;
50     unsigned print(int, char *) const;
51   };
52 };
53
54 // ------------------------------------------------------------------------
55 IMPLEMENTATION:
56
57 #include "timer.h"
58
59 #include "kernel_console.h"
60 #include "vkey.h"
61
62 PRIVATE static inline NEEDS["thread.h", "timer.h", "kernel_console.h", "vkey.h"]
63 void
64 Timer_tick::handle_timer(Irq_base *_s, Upstream_irq const *ui,
65                          Thread *t, Cpu_number cpu)
66 {
67   Timer_tick *self = nonull_static_cast<Timer_tick *>(_s);
68   self->ack();
69   ui->ack();
70   Timer::update_system_clock(cpu);
71   if (Config::esc_hack && cpu == Cpu_number::boot_cpu())
72     {
73       if (Kconsole::console()->char_avail() && !Vkey::check_())
74         kdb_ke("SERIAL_ESC");
75     }
76   self->log_timer();
77   t->handle_timer_interrupt();
78 }
79
80 PUBLIC static inline NEEDS[Timer_tick::handle_timer]
81 void
82 Timer_tick::handler_all(Irq_base *_s, Upstream_irq const *ui)
83 {
84   Thread *t = current_thread();
85   handle_timer(_s, ui, t, t->cpu(true));
86 }
87
88 PUBLIC static inline NEEDS[Timer_tick::handle_timer]
89 void
90 Timer_tick::handler_sys_time(Irq_base *_s, Upstream_irq const *ui)
91 {
92   // assume the boot CPU to be the CPU that manages the system time
93   handle_timer(_s, ui, current_thread(), Cpu_number::boot_cpu());
94 }
95
96 PUBLIC static inline NEEDS["thread.h", "timer.h"]
97 void
98 Timer_tick::handler_app(Irq_base *_s, Upstream_irq const *ui)
99 {
100   Timer_tick *self = nonull_static_cast<Timer_tick *>(_s);
101   self->ack();
102   ui->ack();
103   self->log_timer();
104   current_thread()->handle_timer_interrupt();
105 }
106
107 // --------------------------------------------------------------------------
108 IMPLEMENTATION [!debug]:
109
110 PUBLIC static inline
111 void
112 Timer_tick::log_timer()
113 {}
114
115 // --------------------------------------------------------------------------
116 IMPLEMENTATION [debug]:
117
118 #include "logdefs.h"
119 #include "irq_chip.h"
120
121 IMPLEMENT
122 unsigned
123 Timer_tick::Log::print(int maxlen, char *buf) const
124 {
125   return snprintf(buf, maxlen, "u-ip=0x%lx", user_ip);
126 }
127
128 PUBLIC inline NEEDS["logdefs.h"]
129 void
130 Timer_tick::log_timer()
131 {
132   Context *c = current();
133   LOG_TRACE("Timer IRQs (kernel scheduling)", "timer", c, Log,
134       l->user_ip  = c->regs()->ip();
135       l->obj      = this;
136   );
137 }