X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/939c2b22a74142b76a62ba02b9da29ccb20dc5c2..2ac3322ef9bc032ad942753a56696764aa0b0f74:/timing.c diff --git a/timing.c b/timing.c index 6dd8aa5e..abb9b466 100644 --- a/timing.c +++ b/timing.c @@ -97,7 +97,14 @@ long schedule_timer(int ticks, timer_fn_t fn, void *ctx) init_timers(); when = ticks + GETTICKCOUNT(); - assert(when - now > 0); + + /* + * Just in case our various defences against timing skew fail + * us: if we try to schedule a timer that's already in the + * past, we instead schedule it for the immediate future. + */ + if (when - now <= 0) + when = now + 1; t = snew(struct timer); t->fn = fn; @@ -133,6 +140,58 @@ int run_timers(long anow, long *next) init_timers(); +#ifdef TIMING_SYNC + /* + * In this ifdef I put some code which deals with the + * possibility that `anow' disagrees with GETTICKCOUNT by a + * significant margin. Our strategy for dealing with it differs + * depending on platform, because on some platforms + * GETTICKCOUNT is more likely to be right whereas on others + * `anow' is a better gold standard. + */ + { + long tnow = GETTICKCOUNT(); + + if (tnow + TICKSPERSEC/50 - anow < 0 || + anow + TICKSPERSEC/50 - tnow < 0 + ) { +#if defined TIMING_SYNC_ANOW + /* + * If anow is accurate and the tick count is wrong, + * this is likely to be because the tick count is + * derived from the system clock which has changed (as + * can occur on Unix). Therefore, we resolve this by + * inventing an offset which is used to adjust all + * future output from GETTICKCOUNT. + * + * A platform which defines TIMING_SYNC_ANOW is + * expected to have also defined this offset variable + * in (its platform-specific adjunct to) putty.h. + * Therefore we can simply reference it here and assume + * that it will exist. + */ + tickcount_offset += anow - tnow; +#elif defined TIMING_SYNC_TICKCOUNT + /* + * If the tick count is more likely to be accurate, we + * simply use that as our time value, which may mean we + * run no timers in this call (because we got called + * early), or alternatively it may mean we run lots of + * timers in a hurry because we were called late. + */ + anow = tnow; +#else +/* + * Any platform which defines TIMING_SYNC must also define one of the two + * auxiliary symbols TIMING_SYNC_ANOW and TIMING_SYNC_TICKCOUNT, to + * indicate which measurement to trust when the two disagree. + */ +#error TIMING_SYNC definition incomplete +#endif + } + } +#endif + now = anow; while (1) {