]> git.buserror.net Git - polintos/scott/priv.git/blob - kernel/core/time.cc
Lots of stuff.
[polintos/scott/priv.git] / kernel / core / time.cc
1 // core/time.cc -- Clocks and timers
2 //
3 // This software is copyright (c) 2006 Scott Wood <scott@buserror.net>.
4 // 
5 // This software is provided 'as-is', without any express or implied warranty.
6 // In no event will the authors or contributors be held liable for any damages
7 // arising from the use of this software.
8 // 
9 // Permission is hereby granted to everyone, free of charge, to use, copy,
10 // modify, prepare derivative works of, publish, distribute, perform,
11 // sublicense, and/or sell copies of the Software, provided that the above
12 // copyright notice and disclaimer of warranty be included in all copies or
13 // substantial portions of this software.
14
15 #include <kern/arch.h>
16 #include <kern/time.h>
17 #include <lowlevel/clock.h>
18 #include <System/Exceptions.h>
19
20 namespace Time {
21         using namespace Lock;
22
23         void MonotonicClock::get_time(Time *time)
24         {
25                 if (!time)
26                         throw_idl(InvalidArgument, 0, nullarray);
27         
28                 AutoSpinLockRecIRQ autolock(lock);
29                 s32 nanos = get_nanos(ll_getclock() - last_tick_llclock);
30                 
31                 *time = last_tick_time;
32                 time->nanos += nanos;
33                 
34                 while (time->nanos >= 1000000000) {
35                         time->nanos -= 1000000000;
36                         time->seconds++;
37                 }
38         }
39         
40         void MonotonicClock::get_resolution(Time *res)
41         {
42                 if (!res) 
43                         throw_idl(InvalidArgument, 0, nullarray);
44                 
45                 res->seconds = 0;
46                 
47                 if (llclocks_per_second >= 1000000000)
48                         res->nanos = 1;
49                 else
50                         res->nanos = 1000000000 / llclocks_per_second;
51         }
52         
53         void MonotonicClock::tick()
54         {
55                 unsigned long irq = lock.lock_recirq();
56                 
57                 while (ll_getclock() - last_tick_llclock > llclocks_per_tick) {
58                         last_tick_llclock += llclocks_per_tick;
59                         last_tick_time += clock_tick_increment;
60                 }
61                 
62                 Time next_tick = last_tick_time + clock_tick_increment;
63                 lock.unlock_recirq(irq);
64
65                 tick_timer.arm(next_tick);
66         }
67
68         void MonotonicClock::new_timer(Timer *timer)
69         {
70                 if (!timer)
71                         throw_idl(InvalidArgument, 0, nullarray);
72         
73                 // FIXME
74                 *timer = NULL;
75                 return;
76         }
77         
78         void MonotonicClock::timer_tick(KTimerEntry *entry)
79         {
80                 MonotonicClock *clock = static_cast<MonotonicClock *>(entry->data);
81                 clock->tick();
82         }
83         
84         void MonotonicClock::init_tick_timer()
85         {
86                 tick_timer.mux = monotonic_timers;
87                 tick_timer.func = timer_tick;
88                 tick_timer.data = this;
89
90                 last_tick_llclock = ll_getclock();
91                 last_tick_time.seconds = 0;
92                 last_tick_time.nanos = 0;
93                 
94                 Time next_tick = clock_tick_increment;
95                 tick_timer.arm(next_tick);
96                 
97                 Arch::timer_init();
98         }
99         
100         void HWTimer::get_expiry(Time *EXPIRY, uint8_t *ARMED)
101         {
102                 if (EXPIRY)
103                         *EXPIRY = expiry;
104                 if (ARMED)
105                         *ARMED = armed;
106         }
107         
108         MonotonicClock monotonic_clock;
109         TimerMux *monotonic_timers;
110         HWTimer *hw_timer;
111         
112         void init()
113         {
114                 hw_timer->calibrate();
115                 monotonic_timers = new TimerMux(monotonic_clock, *hw_timer);
116                 monotonic_clock.init_tick_timer();
117         }
118 }
119
120 #include <servers/core/time/footer.cc>