]> git.buserror.net Git - polintos/scott/priv.git/blob - kernel/core/time.cc
Initial checkin from Perforce.
[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 conditions:
11 // 
12 //     * Redistributions of source code must retain the above copyright notice,
13 //       this list of conditions and the following disclaimers.
14 // 
15 //     * Redistributions in binary form must reproduce the above copyright notice,
16 //       this list of conditions and the following disclaimers in the
17 //       documentation and/or other materials provided with the distribution.
18 // 
19 //     * The names of the Software's authors and/or contributors
20 //       may not be used to endorse or promote products derived from
21 //       this Software without specific prior written permission.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
25 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
26 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
29 // SOFTWARE.
30
31 #include <kern/arch.h>
32 #include <kern/time.h>
33 #include <lowlevel/clock.h>
34 #include <System/Exceptions.h>
35
36 namespace Time {
37         using namespace Lock;
38
39         void MonotonicClock::get_time(Time *time)
40         {
41                 if (!time)
42                         throw_idl(InvalidArgument, 0, nullarray);
43         
44                 AutoSpinLockRecIRQ autolock(lock);
45                 s32 nanos = get_nanos(ll_getclock() - last_tick_llclock);
46                 
47                 *time = last_tick_time;
48                 time->nanos += nanos;
49                 
50                 while (time->nanos >= 1000000000) {
51                         time->nanos -= 1000000000;
52                         time->seconds++;
53                 }
54         }
55         
56         void MonotonicClock::get_resolution(Time *res)
57         {
58                 if (!res) 
59                         throw_idl(InvalidArgument, 0, nullarray);
60                 
61                 res->seconds = 0;
62                 
63                 if (llclocks_per_second >= 1000000000)
64                         res->nanos = 1;
65                 else
66                         res->nanos = 1000000000 / llclocks_per_second;
67         }
68         
69         void MonotonicClock::tick()
70         {
71                 unsigned long irq = lock.lock_recirq();
72                 
73                 while (ll_getclock() - last_tick_llclock > llclocks_per_tick) {
74                         last_tick_llclock += llclocks_per_tick;
75                         last_tick_time += clock_tick_increment;
76                 }
77                 
78                 Time next_tick = last_tick_time + clock_tick_increment;
79                 lock.unlock_recirq(irq);
80
81                 tick_timer.arm(next_tick);
82         }
83
84         void MonotonicClock::new_timer(Timer *timer)
85         {
86                 if (!timer)
87                         throw_idl(InvalidArgument, 0, nullarray);
88         
89                 // FIXME
90                 *timer = NULL;
91                 return;
92         }
93         
94         void MonotonicClock::timer_tick(KTimerEntry *entry)
95         {
96                 MonotonicClock *clock = static_cast<MonotonicClock *>(entry->data);
97                 clock->tick();
98         }
99         
100         void MonotonicClock::init_tick_timer()
101         {
102                 tick_timer.mux = monotonic_timers;
103                 tick_timer.func = timer_tick;
104                 tick_timer.data = this;
105
106                 last_tick_llclock = ll_getclock();
107                 last_tick_time.seconds = 0;
108                 last_tick_time.nanos = 0;
109                 
110                 Time next_tick = clock_tick_increment;
111                 tick_timer.arm(next_tick);
112                 
113                 Arch::timer_init();
114         }
115         
116         void HWTimer::get_expiry(Time *EXPIRY, uint8_t *ARMED)
117         {
118                 if (EXPIRY)
119                         *EXPIRY = expiry;
120                 if (ARMED)
121                         *ARMED = armed;
122         }
123         
124         MonotonicClock monotonic_clock;
125         TimerMux *monotonic_timers;
126         HWTimer *hw_timer;
127         
128         void init()
129         {
130                 hw_timer->calibrate();
131                 monotonic_timers = new TimerMux(monotonic_clock, *hw_timer);
132                 monotonic_clock.init_tick_timer();
133         }
134 }
135
136 #include <servers/core/time/footer.cc>