HomeFreeBSD

pps: Simplify the nsec calculation in pps_event()

Description

pps: Simplify the nsec calculation in pps_event()

Let A be the current calculation of the frequency accumulator (pps_fcount)
update in pps_event()

scale = (uint64_t)1 << 63;
scale /= captc->tc_frequency;
scale *= 2;
bt.sec = 0;
bt.frac = 0;
bintime_addx(&bt, scale * tcount);
bintime2timespec(&bt, &ts);
hardpps(tsp, ts.tv_nsec + 1000000000 * ts.tv_sec);

and hardpps(..., delta_nsec):

u_nsec = delta_nsec;
if (u_nsec > (NANOSECOND >> 1))
        u_nsec -= NANOSECOND;
else if (u_nsec < -(NANOSECOND >> 1))
        u_nsec += NANOSECOND;
pps_fcount += u_nsec;

This change introduces a new calculation which is slightly simpler and more
straight forward. Name it B.

Consider the following sample values with a tcount of 2000000100 and a
tc_frequency of 2000000000 (2GHz).

For A, the scale is 9223372036. Then scale * tcount is 18446744994337203600
which is larger than UINT64_MAX (= 18446744073709551615). The result is
920627651984 == 18446744994337203600 % UINT64_MAX. Since all operands are
unsigned the result is well defined through modulo arithmetic. The result of
bintime2timespec(&bt, &ts) is 49. This is equal to the correct result
1000000049 % NANOSECOND.

In hardpps(), both conditional statements are not executed and pps_fcount is
incremented by 49.

For the new calculation B, we have 1000000000 * tcount is 2000000100000000000
which is less than UINT64_MAX. This yields after the division with tc_frequency
the correct result of 1000000050 for delta_nsec.

In hardpps(), the first conditional statement is executed and pps_fcount is
incremented by 50.

This shows that both methods yield roughly the same results. However, method B
is easier to understand and requires fewer conditional statements.

Reviewed by: imp
Pull Request: https://github.com/freebsd/freebsd-src/pull/604

Details

Provenance
sebastian.huber_embedded-brains.deAuthored on Feb 27 2023, 9:49 PM
impCommitted on Feb 27 2023, 10:10 PM
Parents
rG8a142484d4c1: pps: Directly assign the timestamps in pps_event()
Branches
Unknown
Tags
Unknown