From 05f6236a83414573587c73dbc439e68dae5f529e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Sep 2009 04:10:26 +0200 Subject: timeval: make pa_timeval_sub saturating --- src/pulse/timeval.c | 50 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/src/pulse/timeval.c b/src/pulse/timeval.c index 376cf13c..1a0d3cef 100644 --- a/src/pulse/timeval.c +++ b/src/pulse/timeval.c @@ -33,6 +33,7 @@ #include #include +#include #include "timeval.h" @@ -54,9 +55,9 @@ struct timeval *pa_gettimeofday(struct timeval *tv) { #define EPOCHFILETIME (116444736000000000LL) #endif - FILETIME ft; - LARGE_INTEGER li; - __int64 t; + FILETIME ft; + LARGE_INTEGER li; + int64_t t; pa_assert(tv); @@ -128,40 +129,65 @@ pa_usec_t pa_timeval_age(const struct timeval *tv) { } struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) { - unsigned long secs; + time_t secs; pa_assert(tv); - secs = (unsigned long) (v/PA_USEC_PER_SEC); - tv->tv_sec += (time_t) secs; - v -= ((pa_usec_t) secs) * PA_USEC_PER_SEC; + secs = (time_t) (v/PA_USEC_PER_SEC); + if (PA_UNLIKELY(tv->tv_sec > PA_INT_TYPE_MAX(time_t) - secs)) + goto overflow; + + tv->tv_sec += secs; + v -= (pa_usec_t) secs * PA_USEC_PER_SEC; tv->tv_usec += (suseconds_t) v; /* Normalize */ - while ((unsigned) tv->tv_usec >= PA_USEC_PER_SEC) { + while ((pa_usec_t) tv->tv_usec >= PA_USEC_PER_SEC) { + + if (PA_UNLIKELY(tv->tv_sec >= PA_INT_TYPE_MAX(time_t))) + goto overflow; + tv->tv_sec++; tv->tv_usec -= (suseconds_t) PA_USEC_PER_SEC; } return tv; + +overflow: + tv->tv_sec = PA_INT_TYPE_MAX(time_t); + tv->tv_usec = (suseconds_t) (PA_USEC_PER_SEC-1); + return tv; } struct timeval* pa_timeval_sub(struct timeval *tv, pa_usec_t v) { - unsigned long secs; + time_t secs; pa_assert(tv); - secs = (unsigned long) (v/PA_USEC_PER_SEC); - tv->tv_sec -= (time_t) secs; - v -= ((pa_usec_t) secs) * PA_USEC_PER_SEC; + secs = (time_t) (v/PA_USEC_PER_SEC); + + if (PA_UNLIKELY(tv->tv_sec < secs)) + goto underflow; + + tv->tv_sec -= secs; + v -= (pa_usec_t) secs * PA_USEC_PER_SEC; if (tv->tv_usec >= (suseconds_t) v) tv->tv_usec -= (suseconds_t) v; else { + + if (PA_UNLIKELY(tv->tv_sec <= 0)) + goto underflow; + tv->tv_sec --; tv->tv_usec += (suseconds_t) (PA_USEC_PER_SEC - v); } return tv; + +underflow: + tv->tv_sec = 0; + tv->tv_usec = 0; + return tv; } struct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v) { -- cgit v1.2.3