Per request, the inlined functions
On Sat, Sep 2, 2017 at 12:59 PM, Bruce Korb <[email protected]> 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) {