FreeBSD/sys/kern/kern_tc.c
/*
 * Adjust the fftimehands when the timecounter is changed. Stating the obvious,
 * the old and new hardware counter cannot be read simultaneously. tc_windup()
 * does read the two counters 'back to back', but a few cycles are effectively
 * lost, and not accumulated in tick_ffcount. This is a fairly radical
 * operation for a feed-forward synchronization daemon, and it is its job to not
 * pushing irrelevant data to the kernel. Because there is no locking here,
 * simply force to ignore pending or next update to give daemon a chance to
 * realize the counter has changed.
 */
Adjust the fftimehands when the timecounter is changed. Stating the obvious,
the old and new hardware counter cannot be read simultaneously. tc_windup()
does read the two counters 'back to back', but a few cycles are effectively
lost, and not accumulated in tick_ffcount. This is a fairly radical
operation for a feed-forward synchronization daemon, and it is its job to not
pushing irrelevant data to the kernel. Because there is no locking here,
simply force to ignore pending or next update to give daemon a chance to
realize the counter has changed.
Adjust the fftimehands when the timecounter is changed . Stating the obvious the old and new hardware counter cannot be read simultaneously . tc_windup () does read the two counters ' back to back ' but a few cycles are effectively lost and not accumulated in tick_ffcount . This is a fairly radical operation for a feed - forward synchronization daemon and it is its job to not pushing irrelevant data to the kernel . Because there is no locking here simply force to ignore pending or next update to give daemon a chance to realize the counter has changed .
static void
ffclock_change_tc(struct timehands *th)
{
	struct fftimehands *ffth;
	struct ffclock_estimate *cest;
	struct timecounter *tc;
	uint8_t ogen;
	tc = th->th_counter;
	ffth = fftimehands->next;
	ogen = ffth->gen;
	ffth->gen = 0;
	cest = &ffth->cest;
	bcopy(&(fftimehands->cest), cest, sizeof(struct ffclock_estimate));
	cest->period = ((1ULL << 63) / tc->tc_frequency ) << 1;
	cest->errb_abs = 0;
	cest->errb_rate = 0;
	cest->status |= FFCLOCK_STA_UNSYNC;
	ffth->tick_ffcount = fftimehands->tick_ffcount;
	ffth->tick_time_lerp = fftimehands->tick_time_lerp;
	ffth->tick_time = fftimehands->tick_time;
	ffth->period_lerp = cest->period;
	ffclock_updated--;
	if (++ogen == 0)
		ogen = 1;
	ffth->gen = ogen;
	fftimehands = ffth;
}
static void ffclock_change_tc ( struct timehands * th ) { struct fftimehands * ffth ; struct ffclock_estimate * cest ; struct timecounter * tc ; uint8_t ogen ; tc = th -> th_counter ; ffth = fftimehands -> next ; ogen = ffth -> gen ; ffth -> gen = 0 ; cest = & ffth -> cest ; bcopy ( & ( fftimehands -> cest ) , cest , sizeof ( struct ffclock_estimate ) ) ; cest -> period = ( ( 1ULL << 63 ) / tc -> tc_frequency ) << 1 ; cest -> errb_abs = 0 ; cest -> errb_rate = 0 ; cest -> status |= FFCLOCK_STA_UNSYNC ; ffth -> tick_ffcount = fftimehands -> tick_ffcount ; ffth -> tick_time_lerp = fftimehands -> tick_time_lerp ; ffth -> tick_time = fftimehands -> tick_time ; ffth -> period_lerp = cest -> period ; ffclock_updated -- ; if ( ++ ogen == 0 ) ogen = 1 ; ffth -> gen = ogen ; fftimehands = ffth ; }
Adjust the fftimehands when the timecounter is changed.
Adjust the fftimehands when the timecounter is changed .
/* Do not lock but ignore next update from synchronization daemon. */