diff --git a/chrony_timex.h b/chrony_timex.h index 348d01f..38e1146 100644 --- a/chrony_timex.h +++ b/chrony_timex.h @@ -39,6 +39,7 @@ struct timex { #define ADJ_STATUS 0x0010 /* clock status */ #define ADJ_TICK 0x4000 /* tick value */ #define ADJ_OFFSET_SINGLESHOT 0x8001 /* old-fashioned adjtime */ +#define ADJ_OFFSET_SS_READ 0xa001 /* read-only adjtime */ #define SHIFT_USEC 16 /* frequency offset scale (shift) */ diff --git a/sys_linux.c b/sys_linux.c index 969229f..2da7ed5 100644 --- a/sys_linux.c +++ b/sys_linux.c @@ -103,10 +103,11 @@ static int version_major; static int version_minor; static int version_patchlevel; -/* Flag indicating whether adjtimex() with txc.modes equal to zero -returns the remaining time adjustment or not. If not we have to read -the outstanding adjustment by setting it to zero, examining the return -value and setting the outstanding adjustment back again. */ +/* Flag indicating whether adjtimex() returns the remaining time adjustment +or not. If not we have to read the outstanding adjustment by setting it to +zero, examining the return value and setting the outstanding adjustment back +again. If 1, txc.modes equal to zero is used to read the time. If 2, +txc.modes is set to ADJ_OFFSET_SS_READ. */ static int have_readonly_adjtime; @@ -532,11 +533,20 @@ get_offset_correction(struct timeval *raw, double fast_slew_remaining; long offset; - if (have_readonly_adjtime) { - if (TMX_GetOffsetLeft(&offset) < 0) { +again: + if (have_readonly_adjtime == 1) { + if (TMX_GetOffsetLeftOld(&offset) < 0) { CROAK("adjtimex() failed in get_offset_correction"); } + adjtime_left = (double)offset / 1.0e6; + } else if (have_readonly_adjtime == 2) { + if (TMX_GetOffsetLeft(&offset) < 0) { + LOG(LOGS_INFO, LOGF_SysLinux, "adjtimex() doesn't support ADJ_OFFSET_SS_READ"); + have_readonly_adjtime = 0; + goto again; + } + adjtime_left = (double)offset / 1.0e6; } else { offset = 0; @@ -796,13 +806,19 @@ get_version_specific_details(void) case 4: case 5: case 6: + if (minor < 6 || patch < 27) { + /* These seem to be like 2.0.32 */ + freq_scale = (hz==100) ? (128.0 / 128.125) : basic_freq_scale; + have_readonly_adjtime = 0; + break; + } /* Let's be optimistic that these will be the same until proven otherwise :-) */ case 7: case 8: - /* These seem to be like 2.0.32 */ - freq_scale = (hz==100) ? (128.0 / 128.125) : basic_freq_scale; - have_readonly_adjtime = 0; + /* These don't need scaling */ + freq_scale = 1.0; + have_readonly_adjtime = 2; break; default: LOG_FATAL(LOGF_SysLinux, "Kernel version not supported yet, sorry."); diff --git a/wrap_adjtimex.c b/wrap_adjtimex.c index 66e45b3..991a8e9 100644 --- a/wrap_adjtimex.c +++ b/wrap_adjtimex.c @@ -93,7 +93,7 @@ TMX_GetFrequency(double *freq) } int -TMX_GetOffsetLeft(long *offset) +TMX_GetOffsetLeftOld(long *offset) { struct timex txc; int result; @@ -103,6 +103,17 @@ TMX_GetOffsetLeft(long *offset) return result; } +int +TMX_GetOffsetLeft(long *offset) +{ + struct timex txc; + int result; + txc.modes = ADJ_OFFSET_SS_READ; + result = adjtimex(&txc); + *offset = txc.offset; + return result; +} + int TMX_ReadCurrentParams(struct tmx_params *params) { diff --git a/wrap_adjtimex.h b/wrap_adjtimex.h index d7d59b1..187c8fb 100644 --- a/wrap_adjtimex.h +++ b/wrap_adjtimex.h @@ -72,6 +72,7 @@ int TMX_SetTick(long tick); int TMX_ApplyOffset(long *offset); int TMX_SetFrequency(double freq, long tick); int TMX_GetFrequency(double *freq); +int TMX_GetOffsetLeftOld(long *offset); int TMX_GetOffsetLeft(long *offset); int TMX_ReadCurrentParams(struct tmx_params *params); int TMX_SetLeap(int leap);