FW: Override timer interrupt
Rune Torgersen
runet at innovsys.com
Tue Oct 16 08:15:59 EST 2007
> From: Benjamin Herrenschmidt
> > Things have changed a lot since I last delved deep into
> > this to try to
> > ge an accurate freerunning clock (2.6.12).
>
> Hrm... 2.6.18 doesn't have clock sources in the first place,
> what kernel
> are you using ?
>
2.6.18
And I'm starting at the clocksource code right now...
>From jiffies.c:
static int __init init_jiffies_clocksource(void)
{
return clocksource_register(&clocksource_jiffies);
}
module_init(init_jiffies_clocksource);
from: kernel/timer.c
/*
* update_wall_time - Uses the current clocksource to increment the wall
time
*
* Called from the timer interrupt, must hold a write on xtime_lock.
*/
static void update_wall_time(void)
{
cycle_t offset;
/* Make sure we're fully resumed: */
if (unlikely(timekeeping_suspended))
return;
#ifdef CONFIG_GENERIC_TIME
offset = (clocksource_read(clock) - clock->cycle_last) &
clock->mask;
#else
offset = clock->cycle_interval;
#endif
clock->xtime_nsec += (s64)xtime.tv_nsec << clock->shift;
/* normally this loop will run just once, however in the
* case of lost or late ticks, it will accumulate correctly.
*/
while (offset >= clock->cycle_interval) {
/* accumulate one interval */
clock->xtime_nsec += clock->xtime_interval;
clock->cycle_last += clock->cycle_interval;
offset -= clock->cycle_interval;
if (clock->xtime_nsec >= (u64)NSEC_PER_SEC <<
clock->shift) {
clock->xtime_nsec -= (u64)NSEC_PER_SEC <<
clock->shift;
xtime.tv_sec++;
second_overflow();
}
/* interpolator bits */
time_interpolator_update(clock->xtime_interval
>> clock->shift);
/* increment the NTP state machine */
update_ntp_one_tick();
/* accumulate error between NTP and clock interval */
clock->error += current_tick_length();
clock->error -= clock->xtime_interval <<
(TICK_LENGTH_SHIFT - clock->shift);
}
/* correct the clock when NTP error is too big */
clocksource_adjust(clock, offset);
/* store full nanoseconds into xtime */
xtime.tv_nsec = (s64)clock->xtime_nsec >> clock->shift;
clock->xtime_nsec -= (s64)xtime.tv_nsec << clock->shift;
/* check to see if there is a new clocksource to use */
if (change_clocksource()) {
clock->error = 0;
clock->xtime_nsec = 0;
clocksource_calculate_interval(clock, tick_nsec);
}
}
More information about the Linuxppc-dev
mailing list