Index: sys/kern/kern_tc.c =================================================================== --- sys/kern/kern_tc.c +++ sys/kern/kern_tc.c @@ -1761,6 +1761,7 @@ pps_capture(struct pps_state *pps) { struct timehands *th; + struct timecounter *tc; KASSERT(pps != NULL, ("NULL pps pointer in pps_capture")); th = timehands; @@ -1769,17 +1770,18 @@ #ifdef FFCLOCK pps->capffth = fftimehands; #endif - pps->capcount = th->th_counter->tc_get_timecount(th->th_counter); - atomic_thread_fence_acq(); - if (pps->capgen != th->th_generation) - pps->capgen = 0; + tc = th->th_counter; + pps->capcount = tc->tc_get_timecount(tc); } void pps_event(struct pps_state *pps, int event) { + struct timehands *capth; + struct timecounter *captc; + uint64_t capth_scale; struct bintime bt; - struct timespec ts, *tsp, *osp; + struct timespec *tsp, *osp; u_int tcount, *pcount; int foff; pps_seq_t *pseq; @@ -1796,9 +1798,17 @@ /* Nothing to do if not currently set to capture this event type. */ if ((event & pps->ppsparam.mode) == 0) return; + + /* Make a snapshot of the captured timehand */ + capth = pps->capth; + captc = capth->th_counter; + capth_scale = capth->th_scale; + tcount = capth->th_offset_count; + bt = capth->th_bintime; + /* If the timecounter was wound up underneath us, bail out. */ - if (pps->capgen == 0 || pps->capgen != - atomic_load_acq_int(&pps->capth->th_generation)) + atomic_thread_fence_acq(); + if (pps->capgen == 0 || pps->capgen != capth->th_generation) return; /* Things would be easier with arrays. */ @@ -1832,32 +1842,25 @@ #endif } + *pcount = pps->capcount; + /* * If the timecounter changed, we cannot compare the count values, so * we have to drop the rest of the PPS-stuff until the next event. */ - if (pps->ppstc != pps->capth->th_counter) { - pps->ppstc = pps->capth->th_counter; - *pcount = pps->capcount; + if (__predict_false(pps->ppstc != captc)) { + pps->ppstc = captc; pps->ppscount[2] = pps->capcount; return; } - /* Convert the count to a timespec. */ - tcount = pps->capcount - pps->capth->th_offset_count; - tcount &= pps->capth->th_counter->tc_counter_mask; - bt = pps->capth->th_bintime; - bintime_addx(&bt, pps->capth->th_scale * tcount); - bintime2timespec(&bt, &ts); - - /* If the timecounter was wound up underneath us, bail out. */ - atomic_thread_fence_acq(); - if (pps->capgen != pps->capth->th_generation) - return; - - *pcount = pps->capcount; (*pseq)++; - *tsp = ts; + + /* Convert the count to a timespec. */ + tcount = pps->capcount - tcount; + tcount &= captc->tc_counter_mask; + bintime_addx(&bt, capth_scale * tcount); + bintime2timespec(&bt, tsp); if (foff) { timespecadd(tsp, osp, tsp); @@ -1872,14 +1875,14 @@ bt = pps->capffth->tick_time; ffclock_convert_delta(tcount, pps->capffth->cest.period, &bt); bintime_add(&bt, &pps->capffth->tick_time); - bintime2timespec(&bt, &ts); (*pseq_ffc)++; - *tsp_ffc = ts; + bintime2timespec(&bt, tsp_ffc); #endif #ifdef PPS_SYNC if (fhard) { - uint64_t scale; + uint64_t nsec; + uint64_t freq; /* * Feed the NTP PLL/FLL. @@ -1888,15 +1891,12 @@ */ tcount = pps->capcount - pps->ppscount[2]; pps->ppscount[2] = pps->capcount; - tcount &= pps->capth->th_counter->tc_counter_mask; - scale = (uint64_t)1 << 63; - scale /= pps->capth->th_counter->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); + tcount &= captc->tc_counter_mask; + nsec = 1000000000; + nsec *= tcount; + freq = captc->tc_frequency; + nsec = (nsec + freq / 2) / freq; + hardpps(tsp, (long)nsec); } #endif