static void accrue_offset(double offset, double corr_rate) { struct timeval newadj, oldadj; double doldadj; UTI_DoubleToTimeval(-offset, &newadj); if (PRV_AdjustTime(&newadj, &oldadj) < 0) LOG_FATAL("adjtime() failed"); /* Add the old remaining adjustment if not zero */ doldadj = UTI_TimevalToDouble(&oldadj); if (doldadj != 0.0) { UTI_DoubleToTimeval(-offset + doldadj, &newadj); if (PRV_AdjustTime(&newadj, NULL) < 0) LOG_FATAL("adjtime() failed"); } }
static void start_adjust(void) { struct timeval newadj, oldadj; struct timeval T1; double elapsed, accrued_error; double adjust_required; struct timeval exact_newadj; long delta, tickdelta; double rounding_error; double old_adjust_remaining; /* Determine the amount of error built up since the last adjustment */ if (gettimeofday(&T1, NULL) < 0) { LOG_FATAL(LOGF_SysNetBSD, "gettimeofday() failed"); } UTI_DiffTimevalsToDouble(&elapsed, &T1, &T0); accrued_error = elapsed * current_freq; adjust_required = - (accrued_error + offset_register); UTI_DoubleToTimeval(adjust_required, &exact_newadj); /* At this point, we need to round the required adjustment the same way the kernel does. */ delta = exact_newadj.tv_sec * 1000000 + exact_newadj.tv_usec; if (delta > kern_bigadj || delta < -kern_bigadj) tickdelta = 10 * kern_tickadj; else tickdelta = kern_tickadj; if (delta % tickdelta) delta = delta / tickdelta * tickdelta; newadj.tv_sec = 0; newadj.tv_usec = delta; UTI_NormaliseTimeval(&newadj); /* Add rounding error back onto offset register. */ UTI_DiffTimevalsToDouble(&rounding_error, &newadj, &exact_newadj); if (adjtime(&newadj, &oldadj) < 0) { LOG_FATAL(LOGF_SysNetBSD, "adjtime() failed"); } UTI_TimevalToDouble(&oldadj, &old_adjust_remaining); offset_register = rounding_error - old_adjust_remaining; T0 = T1; UTI_TimevalToDouble(&newadj, &adjustment_requested); }