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 /src | |
| parent | fdec460661faa802c1acf9d985990c2d1b4fa1a3 (diff) | |
timeval: make pa_timeval_sub saturating
Diffstat (limited to 'src')
| -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) { | 
