From 1a7415a6ab1eecd2f7219501fe609bcf22f1da10 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Tue, 20 Apr 2010 18:29:39 +0200 Subject: [PATCH] Return actual frequency in drv_set_freq functions This is needed to keep sourcestats accurate when the actual frequency is different from the requested frequency due to clamping (or possibly rounding in future system drivers). --- local.c | 29 ++++++++++++++++++++--------- local.h | 6 ++++-- localp.h | 5 +++-- sys_linux.c | 6 ++++-- sys_netbsd.c | 4 +++- sys_solaris.c | 4 +++- sys_sunos.c | 4 +++- tempcomp.c | 2 +- wrap_adjtimex.c | 5 +++-- wrap_adjtimex.h | 2 +- 10 files changed, 45 insertions(+), 22 deletions(-) diff --git a/local.c b/local.c index b967bcd..c5b6383 100644 --- a/local.c +++ b/local.c @@ -394,7 +394,7 @@ LCL_SetAbsoluteFrequency(double afreq_ppm) /* Call the system-specific driver for setting the frequency */ - (*drv_set_freq)(afreq_ppm); + afreq_ppm = (*drv_set_freq)(afreq_ppm); dfreq = (afreq_ppm - current_freq_ppm) / (1.0e6 + current_freq_ppm); @@ -417,6 +417,9 @@ LCL_AccumulateDeltaFrequency(double dfreq) { ChangeListEntry *ptr; struct timeval raw, cooked; + double old_freq_ppm; + + old_freq_ppm = current_freq_ppm; /* Work out new absolute frequency. Note that absolute frequencies are handled in units of ppm, whereas the 'dfreq' argument is in @@ -425,7 +428,8 @@ LCL_AccumulateDeltaFrequency(double dfreq) current_freq_ppm = (1.0 + dfreq) * current_freq_ppm + 1.0e6 * dfreq; /* Call the system-specific driver for setting the frequency */ - (*drv_set_freq)(current_freq_ppm); + current_freq_ppm = (*drv_set_freq)(current_freq_ppm); + dfreq = (current_freq_ppm - old_freq_ppm) / (1.0e6 + old_freq_ppm); LCL_ReadRawTime(&raw); LCL_CookTime(&raw, &cooked, NULL); @@ -510,7 +514,9 @@ LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset) #endif /* Call the system-specific driver for setting the frequency */ - (*drv_set_freq)(current_freq_ppm); + current_freq_ppm = (*drv_set_freq)(current_freq_ppm); + dfreq = (current_freq_ppm - old_freq_ppm) / (1.0e6 + old_freq_ppm); + (*drv_accrue_offset)(doffset); /* Dispatch to all handlers */ @@ -599,25 +605,30 @@ LCL_SetLeap(int leap) /* ================================================== */ -void +double LCL_SetTempComp(double comp) { + double uncomp_freq_ppm; + if (temp_comp_ppm == comp) - return; + return comp; /* Undo previous compensation */ current_freq_ppm = (current_freq_ppm + temp_comp_ppm) / (1.0 - 1.0e-6 * temp_comp_ppm); + uncomp_freq_ppm = current_freq_ppm; + /* Apply new compensation */ current_freq_ppm = current_freq_ppm * (1.0 - 1.0e-6 * comp) - comp; - temp_comp_ppm = comp; - /* Call the system-specific driver for setting the frequency */ - (*drv_set_freq)(current_freq_ppm); + current_freq_ppm = (*drv_set_freq)(current_freq_ppm); - return; + temp_comp_ppm = (uncomp_freq_ppm - current_freq_ppm) / + (1.0e-6 * uncomp_freq_ppm + 1.0); + + return temp_comp_ppm; } /* ================================================== */ diff --git a/local.h b/local.h index 373d246..ce29918 100644 --- a/local.h +++ b/local.h @@ -186,7 +186,9 @@ extern void LCL_SetLeap(int leap); /* Routine to set a frequency correction (in ppm) that should be applied to local clock to compensate for temperature changes. A positive - argument means that the clock frequency should be increased. */ -extern void LCL_SetTempComp(double comp); + argument means that the clock frequency should be increased. Return the + actual compensation (may be different from the requested compensation + due to clamping or rounding). */ +extern double LCL_SetTempComp(double comp); #endif /* GOT_LOCAL_H */ diff --git a/localp.h b/localp.h index 6f78d1d..6d00e9c 100644 --- a/localp.h +++ b/localp.h @@ -40,8 +40,9 @@ typedef double (*lcl_ReadFrequencyDriver)(void); /* System driver to set the current local frequency, in ppm relative to nominal. A positive value indicates that the local clock runs - fast when uncompensated. */ -typedef void (*lcl_SetFrequencyDriver)(double freq_ppm); + fast when uncompensated. Return actual frequency (may be different + from the requested frequency due to clamping or rounding). */ +typedef double (*lcl_SetFrequencyDriver)(double freq_ppm); /* System driver to accrue an offset. A positive argument means slew the clock forwards. */ diff --git a/sys_linux.c b/sys_linux.c index 406b9d6..081a036 100644 --- a/sys_linux.c +++ b/sys_linux.c @@ -562,7 +562,7 @@ apply_step_offset(double offset) convention is that this is called with a positive argument if the local clock runs fast when uncompensated. */ -static void +static double set_frequency(double freq_ppm) { long required_tick; @@ -603,7 +603,7 @@ set_frequency(double freq_ppm) required_tick = slewing_tick; } - if (TMX_SetFrequency(scaled_freq, required_tick) < 0) { + if (TMX_SetFrequency(&scaled_freq, required_tick) < 0) { LOG_FATAL(LOGF_SysLinux, "adjtimex failed for set_frequency, freq_ppm=%10.4e scaled_freq=%10.4e required_tick=%ld", freq_ppm, scaled_freq, required_tick); } @@ -616,6 +616,8 @@ set_frequency(double freq_ppm) current_total_tick; adjust_fast_slew(old_total_tick, old_delta_tick); } + + return dhz * (nominal_tick - current_tick) - scaled_freq / freq_scale; } /* ================================================== */ diff --git a/sys_netbsd.c b/sys_netbsd.c index 4b921e7..04b3f92 100644 --- a/sys_netbsd.c +++ b/sys_netbsd.c @@ -244,12 +244,14 @@ apply_step_offset(double offset) /* ================================================== */ -static void +static double set_frequency(double new_freq_ppm) { stop_adjust(); current_freq = new_freq_ppm * 1.0e-6; start_adjust(); + + return current_freq * 1.0e6; } /* ================================================== */ diff --git a/sys_solaris.c b/sys_solaris.c index 40a863d..4024048 100644 --- a/sys_solaris.c +++ b/sys_solaris.c @@ -273,12 +273,14 @@ apply_step_offset(double offset) /* ================================================== */ -static void +static double set_frequency(double new_freq_ppm) { stop_adjust(); current_freq = new_freq_ppm * 1.0e-6; start_adjust(); + + return current_freq * 1.0e6; } /* ================================================== */ diff --git a/sys_sunos.c b/sys_sunos.c index 6a98f51..4878715 100644 --- a/sys_sunos.c +++ b/sys_sunos.c @@ -260,12 +260,14 @@ apply_step_offset(double offset) /* ================================================== */ -static void +static double set_frequency(double new_freq_ppm) { stop_adjust(); current_freq = new_freq_ppm * 1.0e-6; start_adjust(); + + return current_freq * 1.0e6; } /* ================================================== */ diff --git a/tempcomp.c b/tempcomp.c index d7f02ad..a2b4561 100644 --- a/tempcomp.c +++ b/tempcomp.c @@ -54,7 +54,7 @@ read_timeout(void *arg) /* Don't allow corrections above 10 ppm */ if (fabs(comp) < 10.0) { - LCL_SetTempComp(comp); + comp = LCL_SetTempComp(comp); if (logfileid != -1) { struct timeval now; diff --git a/wrap_adjtimex.c b/wrap_adjtimex.c index f76f71e..13a4440 100644 --- a/wrap_adjtimex.c +++ b/wrap_adjtimex.c @@ -66,13 +66,14 @@ TMX_ApplyOffset(long *offset) } int -TMX_SetFrequency(double freq, long tick) +TMX_SetFrequency(double *freq, long tick) { struct timex txc; txc.modes = ADJ_TICK | ADJ_FREQUENCY | ADJ_STATUS; - txc.freq = (long)(freq * (double)(1 << SHIFT_USEC)); + txc.freq = (long)(*freq * (double)(1 << SHIFT_USEC)); + *freq = txc.freq / (double)(1 << SHIFT_USEC); txc.tick = tick; txc.status = STA_UNSYNC; /* Prevent any of the FLL/PLL stuff coming up */ diff --git a/wrap_adjtimex.h b/wrap_adjtimex.h index 543f832..f88188a 100644 --- a/wrap_adjtimex.h +++ b/wrap_adjtimex.h @@ -70,7 +70,7 @@ struct tmx_params { int TMX_SetTick(long tick); int TMX_ApplyOffset(long *offset); -int TMX_SetFrequency(double freq, long tick); +int TMX_SetFrequency(double *freq, long tick); int TMX_GetFrequency(double *freq); int TMX_GetOffsetLeftOld(long *offset); int TMX_GetOffsetLeft(long *offset);