X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=timing.c;h=abb9b466b2aa5df7256fe55d2fe881f725bd202c;hb=c1a9dbef1306f6f52ee843dd9b74552ce5f395d9;hp=6dd8aa5e689dd10fe59cbb7dab98beef86683692;hpb=68d88605ae9da91af0d281f35e54545b0ef37d01;p=PuTTY.git 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) {