----- On Nov 9, 2018, at 10:37 AM, Jonathan Rajotte jonathan.rajotte-jul...@efficios.com wrote:
> Problem: > > The previous algorithm was not *wrong* but was prone to C type conversion > error. > > Previous algorithm: > > ((A.sec - B.sec) * MSEC_PER_SEC) + ((A.nsec - B.nsec) / NSEC_PER_SEC) > > ((A.sec - B.sec) * 1000000ULL) + ((A.nsec - B.nsec) / 1000000ULL) > > Note that "(A.nsec - B.nsec)" can be negative. > > A *quick* fix here could be to cast the NSEC_PER_SEC to long allowing a > valid division operation. > > The problem was introduced by 395d6b02dda3db1acd08936f49c1dc8efc48e613. > > Solution: > > Perform the time diff using a temporary timespec struct and perform the > carry operation manually. This prevent negative value for nsec and > helps prevent C type promotion problems. > > Signed-off-by: Jonathan Rajotte <jonathan.rajotte-jul...@efficios.com> > --- > > I initially misplaced the issue. > As mentioned in the commit message, we can also cast NSEC_PER_SEC to long to > fix > the issue. I prefer the use of a timespec struct for expressiveness. > > Also the case were we pass a time_b > time_a is handled by returning a > difference of zero. We might want to assert here since it should never happen. > > src/common/sessiond-comm/inet.c | 28 ++++++++++++++++++++-------- > src/common/sessiond-comm/inet6.c | 28 ++++++++++++++++++++-------- > 2 files changed, 40 insertions(+), 16 deletions(-) > > diff --git a/src/common/sessiond-comm/inet.c b/src/common/sessiond-comm/inet.c > index e0b3e7a96..94a3c3a67 100644 > --- a/src/common/sessiond-comm/inet.c > +++ b/src/common/sessiond-comm/inet.c > @@ -119,16 +119,28 @@ static > unsigned long time_diff_ms(struct timespec *time_a, > struct timespec *time_b) > { > - time_t sec_diff; > - long nsec_diff; > - unsigned long result_ms; > + struct timespec diff; > > - sec_diff = time_a->tv_sec - time_b->tv_sec; > - nsec_diff = time_a->tv_nsec - time_b->tv_nsec; > + diff.tv_sec = time_a->tv_sec - time_b->tv_sec; > + diff.tv_nsec = time_a->tv_nsec - time_b->tv_nsec; > > - result_ms = sec_diff * MSEC_PER_SEC; > - result_ms += nsec_diff / NSEC_PER_MSEC; > - return result_ms; > + if (diff.tv_nsec < 0) { > + /* Perform borrow operation */ > + diff.tv_sec -= 1; > + diff.tv_nsec += NSEC_PER_SEC; > + } > + > + if (diff.tv_sec < 0) { > + /* We went back in time. Put all to zero */ > + diff.tv_sec = 0; > + diff.tv_nsec = 0; > + } Why would a diff operation implicitly floor everything to 0 when time_a < time_b ? > + > + /* > + * Transform into MSEC, diff.tv_nsec is always positive due to borrow > + * operation. diff.tb_sec is always positive. tb_sec -> tv_nsec > + */ > + return (diff.tv_sec * MSEC_PER_SEC) + (diff.tv_nsec / NSEC_PER_MSEC); How do we handle time delta difference that overflows unsigned long ? > } > > static > diff --git a/src/common/sessiond-comm/inet6.c > b/src/common/sessiond-comm/inet6.c > index dfb5fc5d1..07043e93f 100644 > --- a/src/common/sessiond-comm/inet6.c > +++ b/src/common/sessiond-comm/inet6.c > @@ -117,16 +117,28 @@ static > unsigned long time_diff_ms(struct timespec *time_a, > struct timespec *time_b) This should be moved to a common implementation file. It's a cut and paste from inet.c. Thanks, Mathieu > { > - time_t sec_diff; > - long nsec_diff; > - unsigned long result_ms; > + struct timespec diff; > > - sec_diff = time_a->tv_sec - time_b->tv_sec; > - nsec_diff = time_a->tv_nsec - time_b->tv_nsec; > + diff.tv_sec = time_a->tv_sec - time_b->tv_sec; > + diff.tv_nsec = time_a->tv_nsec - time_b->tv_nsec; > > - result_ms = sec_diff * MSEC_PER_SEC; > - result_ms += nsec_diff / NSEC_PER_MSEC; > - return result_ms; > + if (diff.tv_nsec < 0) { > + /* Perform borrow operation */ > + diff.tv_sec -= 1; > + diff.tv_nsec += NSEC_PER_SEC; > + } > + > + if (diff.tv_sec < 0) { > + /* We went back in time. Put all to zero */ > + diff.tv_sec = 0; > + diff.tv_nsec = 0; > + } > + > + /* > + * Transform into MSEC, diff.tv_nsec is always positive due to borrow > + * operation. diff.tb_sec is always positive. > + */ > + return (diff.tv_sec * MSEC_PER_SEC) + (diff.tv_nsec / NSEC_PER_MSEC); > } > > static > -- > 2.17.1 > > _______________________________________________ > lttng-dev mailing list > lttng-dev@lists.lttng.org > https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev -- Mathieu Desnoyers EfficiOS Inc. http://www.efficios.com _______________________________________________ lttng-dev mailing list lttng-dev@lists.lttng.org https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev