/* * linux/kernel/time/timekeeping.c * * Kernel timekeeping code and accessor functions * * This code was moved from linux/kernel/timer.c. * Please see that file for copyright and history logs. * */#include<linux/module.h>#include<linux/interrupt.h>#include<linux/percpu.h>#include<linux/init.h>#include<linux/mm.h>#include<linux/sched.h>#include<linux/syscore_ops.h>#include<linux/clocksource.h>#include<linux/jiffies.h>#include<linux/time.h>#include<linux/tick.h>#include<linux/stop_machine.h>/* Structure holding internal timekeeping values. */structtimekeeper{/* Current clocksource used for timekeeping. */structclocksource*clock;/* The shift value of the current clocksource. */intshift;/* Number of clock cycles in one NTP interval. */cycle_tcycle_interval;/* Number of clock shifted nano seconds in one NTP interval. */u64xtime_interval;/* shifted nano seconds left over when rounding cycle_interval */s64xtime_remainder;/* Raw nano seconds accumulated per NTP interval. */u32raw_interval;/* Clock shifted nano seconds remainder not stored in xtime.tv_nsec. */u64xtime_nsec;/* Difference between accumulated time and NTP time in ntp * shifted nano seconds. */s64ntp_error;/* Shift conversion between clock shifted nano seconds and * ntp shifted nano seconds. */intntp_error_shift;/* NTP adjusted clock multiplier */u32mult;};staticstructtimekeepertimekeeper;/** * timekeeper_setup_internals - Set up internals to use clocksource clock. * * @clock: Pointer to clocksource. * * Calculates a fixed cycle/nsec interval for a given clocksource/adjustment * pair and interval request. * * Unless you're the timekeeping code, you should not be using this! */staticvoidtimekeeper_setup_internals(structclocksource*clock){cycle_tinterval;u64tmp,ntpinterval;timekeeper.clock=clock;clock->cycle_last=clock->read(clock);/* Do the ns -> cycle conversion first, using original mult */tmp=NTP_INTERVAL_LENGTH;tmp<<=clock->shift;ntpinterval=tmp;tmp+=clock->mult/2;do_div(tmp,clock->mult);if(tmp==0)tmp=1;interval=(cycle_t)tmp;timekeeper.cycle_interval=interval;/* Go back from cycles -> shifted ns */timekeeper.xtime_interval=(u64)interval*clock->mult;timekeeper.xtime_remainder=ntpinterval-timekeeper.xtime_interval;timekeeper.raw_interval=((u64)interval*clock->mult)>>clock->shift;timekeeper.xtime_nsec=0;timekeeper.shift=clock->shift;timekeeper.ntp_error=0;timekeeper.ntp_error_shift=NTP_SCALE_SHIFT-clock->shift;