On Tue, 2005-08-23 at 23:34 +0200, Roman Zippel wrote: > Hi, > > On Tue, 23 Aug 2005, john stultz wrote: > > > In the case above, you're accumulating in fixed cycle intervals. This > > does avoid having to do the mult/shift combo each interrupt, however > > since you do not accumulate the entire interval, and there is some > > sub-tick remainder in cycle_offset. We have to ensure that that sub-tick > > remainder is accumulated at the next interrupt using the same ntp > > adjustment it would use in a call to gettimeofday() just prior to this > > interrupt. > > Look closer and you'll notice that the cycle_offset remainder isn't lost. :)
I'm not saying its lost, but that it is accumulated differently then how it would be used in gettimeofday(). So a somewhat lengthy and exaggerated example with a clock that has 2 cycles per milisecond, HZ=1000 and a 0ppm adjustment to begin with. I'm assuming gettimeofday()/clock_gettime() looks something like: xtime + (get_cycles()-last_update)*(mult+ntp_adj)>>shift Using (1,000,000, 1) for the (mult,shift) pair. So first, the easy case: time(0): gettimeofday: 0 + (0 - 0)*(1M+0)>>1 = 0 ns time(1): gettimeofday: 0 + (1 - 0)*(1M+0)>>1 = 0.5M ns time(2): gettimeofday: 0 + (2 - 0)*(1M+0)>>1 = 1M ns time(2): interrupt time(2): gettimeofday: 1M + (2 - 2)*(1M+0)>>1 = 1M ns time(3): gettimeofday: 1M + (3 - 2)*(1M+0)>>1 = 1.5M ns Now, lets look at how we deal with ticks that arrive late: time(6): gettimeofday: 2M + (6 - 4)*(1M+0)>>1 = 3M ns time(7): gettimeofday: 2M + (7 - 4)*(1M+0)>>1 = 3.5M ns time(7): interrupt time(7): gettimeofday: 3M + (7 - 6)*(1M+0)>>1 = 3.5M ns time(8): gettimeofday: 3M + (8 - 6)*(1M+0)>>1 = 4M ns So everything looks ducky. Now on to when we make NTP adjustments. time(11): gettimeofday: 5M + (11 - 10)*(1M+0)>>1 = 5.5M ns time(12): gettimeofday: 5M + (12 - 10)*(1M+0)>>1 = 6M ns time(12): interrupt (set ntp_adj = 1000 ~= 500ppm) time(12): gettimeofday: 6M + (12 - 12)*(1M+ 1000)>>1 = 6M ns time(13): gettimeofday: 6M + (13 - 12)*(1M+ 1000)>>1 = 6,500,500 ns time(14): gettimeofday: 6M + (14 - 12)*(1M+ 1000)>>1 = 7,001,000 ns Still doing fine. Now lets look at doing NTP adjustments while ticks arrive late: time(15): gettimeofday: 7,001k + (15 - 14)*(1M+ 1000)>>1 = 7,501,500 ns time(16): gettimeofday: 7,001k + (16 - 14)*(1M+ 1000)>>1 = 8,002,000 ns time(17): gettimeofday: 7,001k + (17 - 14)*(1M+ 1000)>>1 = 8,502,500 ns time(17): interrupt, (set ntp_adj = 0ppm) time(17): gettimeofday: 8,002k + (17 - 16)*(1M+ 0)>>1 = 8,502,000 ns And bang, we have a 500 ns time inconsistency! And that was only with a tick arriving 1/2 a tick late. I've dealt with systems that on occasion miss 30ms worth of ticks due to SMI crazyness. This is why I accumulate the entire interval with NTP adjustments consistently between the timer tick and gettimeofday. Right now I'm not sure how to work around this issue with your proposal, but let me know if you have an idea or I'm missing some other subtlety. thanks -john - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/