]> git.buserror.net Git - polintos/scott/priv.git/blob - kernel/core/time.cc
Switch to a simple X11-style license.
[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 // Permission is hereby granted, free of charge, to any person obtaining a copy of
6 // this software and associated documentation files (the "Software"), to deal with
7 // the Software without restriction, including without limitation the rights to
8 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9 // of the Software, and to permit persons to whom the Software is furnished to do
10 // so, subject to the following condition:
11 // 
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 // 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
21 // SOFTWARE.
22
23 #include <kern/arch.h>
24 #include <kern/time.h>
25 #include <lowlevel/clock.h>
26 #include <System/Exceptions.h>
27
28 namespace Time {
29         using namespace Lock;
30
31         void MonotonicClock::get_time(Time *time)
32         {
33                 if (!time)
34                         throw_idl(InvalidArgument, 0, nullarray);
35         
36                 AutoSpinLockRecIRQ autolock(lock);
37                 s32 nanos = get_nanos(ll_getclock() - last_tick_llclock);
38                 
39                 *time = last_tick_time;
40                 time->nanos += nanos;
41                 
42                 while (time->nanos >= 1000000000) {
43                         time->nanos -= 1000000000;
44                         time->seconds++;
45                 }
46         }
47         
48         void MonotonicClock::get_resolution(Time *res)
49         {
50                 if (!res) 
51                         throw_idl(InvalidArgument, 0, nullarray);
52                 
53                 res->seconds = 0;
54                 
55                 if (llclocks_per_second >= 1000000000)
56                         res->nanos = 1;
57                 else
58                         res->nanos = 1000000000 / llclocks_per_second;
59         }
60         
61         void MonotonicClock::tick()
62         {
63                 unsigned long irq = lock.lock_recirq();
64                 
65                 while (ll_getclock() - last_tick_llclock > llclocks_per_tick) {
66                         last_tick_llclock += llclocks_per_tick;
67                         last_tick_time += clock_tick_increment;
68                 }
69                 
70                 Time next_tick = last_tick_time + clock_tick_increment;
71                 lock.unlock_recirq(irq);
72
73                 tick_timer.arm(next_tick);
74         }
75
76         void MonotonicClock::new_timer(Timer *timer)
77         {
78                 if (!timer)
79                         throw_idl(InvalidArgument, 0, nullarray);
80         
81                 // FIXME
82                 *timer = NULL;
83                 return;
84         }
85         
86         void MonotonicClock::timer_tick(KTimerEntry *entry)
87         {
88                 MonotonicClock *clock = static_cast<MonotonicClock *>(entry->data);
89                 clock->tick();
90         }
91         
92         void MonotonicClock::init_tick_timer()
93         {
94                 tick_timer.mux = monotonic_timers;
95                 tick_timer.func = timer_tick;
96                 tick_timer.data = this;
97
98                 last_tick_llclock = ll_getclock();
99                 last_tick_time.seconds = 0;
100                 last_tick_time.nanos = 0;
101                 
102                 Time next_tick = clock_tick_increment;
103                 tick_timer.arm(next_tick);
104                 
105                 Arch::timer_init();
106         }
107         
108         void HWTimer::get_expiry(Time *EXPIRY, uint8_t *ARMED)
109         {
110                 if (EXPIRY)
111                         *EXPIRY = expiry;
112                 if (ARMED)
113                         *ARMED = armed;
114         }
115         
116         MonotonicClock monotonic_clock;
117         TimerMux *monotonic_timers;
118         HWTimer *hw_timer;
119         
120         void init()
121         {
122                 hw_timer->calibrate();
123                 monotonic_timers = new TimerMux(monotonic_clock, *hw_timer);
124                 monotonic_clock.init_tick_timer();
125         }
126 }
127
128 #include <servers/core/time/footer.cc>