diff options
author | Lennart Poettering <lennart@poettering.net> | 2009-09-18 04:10:26 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2009-09-18 04:14:38 +0200 |
commit | 05f6236a83414573587c73dbc439e68dae5f529e (patch) | |
tree | 3859bd06816c3b5ec714a4f8fb36e38b43e496a8 | |
parent | fdec460661faa802c1acf9d985990c2d1b4fa1a3 (diff) |
timeval: make pa_timeval_sub saturating
-rw-r--r-- | src/pulse/timeval.c | 50 |
1 files 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 <pulsecore/winsock.h> #include <pulsecore/macro.h> +#include <pulsecore/core-util.h> #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) { |