Per request, the inlined functions On Sat, Sep 2, 2017 at 12:59 PM, Bruce Korb <bruce.k...@gmail.com> wrote: > I know about all these theoretical possibilities of numbers behaving > in strange ways when arithmetic optimizations assume that signed > overflow won't occur when they actually might. Yep, it creates subtle > bugs. The warning is worthwhile. Still and all: > > 485 tvdiff = abs_tval(sub_tval(timetv, tvlast)); > 486 if (tvdiff.tv_sec != 0) { > > systime.c: In function 'step_systime': > systime.c:486:5: warning: assuming signed overflow does not occur when > simplifying conditional to constant [-Wstrict-overflow] > > What possible optimization might be going on to cause an overflow > problem when I simply want to know if the "tv_sec" field is zero or > not? (BTW, in current source, "tvdiff" is a structure that is returned > by abs_tval()) > > $ gcc --version > gcc (SUSE Linux) 4.8.5 > Copyright (C) 2015 Free Software Foundation, Inc. > This is free software; see the source for copying conditions. There is NO > warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
/* make sure microseconds are in nominal range */ static inline struct timeval normalize_tval( struct timeval x ) { long z; if (x.tv_usec < -3l * MICROSECONDS || x.tv_usec > 3l * MICROSECONDS ) { z = x.tv_usec / MICROSECONDS; x.tv_usec -= z * MICROSECONDS; x.tv_sec += z; } if (x.tv_usec < 0) do { x.tv_usec += MICROSECONDS; x.tv_sec--; } while (x.tv_usec < 0); else if (x.tv_usec >= MICROSECONDS) do { x.tv_usec -= MICROSECONDS; x.tv_sec++; } while (x.tv_usec >= MICROSECONDS); return x; } /* x = a - b */ static inline struct timeval sub_tval( struct timeval a, struct timeval b ) { struct timeval x; x = a; x.tv_sec -= b.tv_sec; x.tv_usec -= b.tv_usec; return normalize_tval(x); } /* x = abs(a) */ static inline struct timeval abs_tval( struct timeval a ) { struct timeval c; c = normalize_tval(a); if (c.tv_sec < 0) { if (c.tv_usec != 0) { c.tv_sec = -c.tv_sec - 1; c.tv_usec = MICROSECONDS - c.tv_usec; } else { c.tv_sec = -c.tv_sec; } } return c; } And the larger code fragment: /* get the current time as l_fp (without fuzz) and as struct timeval */ get_ostime(&timets); fp_sys = tspec_stamp_to_lfp(timets); tvlast.tv_sec = timets.tv_sec; tvlast.tv_usec = (timets.tv_nsec + 500) / 1000; /* get the target time as l_fp */ L_ADD(&fp_sys, &fp_ofs); /* unfold the new system time */ timetv = lfp_stamp_to_tval(fp_sys, &pivot); /* now set new system time */ if (ntp_set_tod(&timetv, NULL) != 0) { msyslog(LOG_ERR, "step-systime: %m"); if (enable_panic_check && allow_panic) { msyslog(LOG_ERR, "step_systime: allow_panic is TRUE!"); } return FALSE; } /* <--- time-critical path ended with 'ntp_set_tod()' <--- */ sys_residual = 0; lamport_violated = (step < 0); if (step_callback) (*step_callback)(); tvdiff = abs_tval(sub_tval(timetv, tvlast)); if (tvdiff.tv_sec != 0) {