mirror of
https://github.com/deadw00d/AROS.git
synced 2025-12-09 16:00:35 +00:00
Using local LONG variable had a side effect of interpreting large unsigned results as signed, reporting wrong value out, as documented in this bug: https://github.com/deadwood2/AROS/issues/157
83 lines
2.2 KiB
C
83 lines
2.2 KiB
C
/*
|
|
* These are often used by timer.device itself, and inlining
|
|
* them saves us from function call overhead.
|
|
*/
|
|
|
|
/* Add, then normalize */
|
|
#define ADDTIME(dest, src) \
|
|
(dest)->tv_micro += (src)->tv_micro; \
|
|
(dest)->tv_secs += (src)->tv_secs; \
|
|
while((dest)->tv_micro > 999999) \
|
|
{ \
|
|
(dest)->tv_secs++; \
|
|
(dest)->tv_micro -= 1000000; \
|
|
}
|
|
|
|
/*
|
|
* Subtraction algorithm:
|
|
* 1. Normalize values
|
|
* 2. Check if wrap around will happen, when subtracting src->tv_micro
|
|
* from dest->tv_micro. If yes, then normalize, by adding 1 sec to
|
|
* micros and subtracting 1 sec from secs. Note: this check must be
|
|
* before subtracting src timeval from dest timeval!
|
|
*/
|
|
#define SUBTIME(dest, src) \
|
|
while ((src)->tv_micro > 999999) \
|
|
{ \
|
|
(src)->tv_secs++; \
|
|
(src)->tv_micro -= 1000000; \
|
|
} \
|
|
while ((dest)->tv_micro > 999999) \
|
|
{ \
|
|
(dest)->tv_secs++; \
|
|
(dest)->tv_micro -= 1000000; \
|
|
} \
|
|
if ((dest)->tv_micro < (src)->tv_micro) \
|
|
{ \
|
|
(dest)->tv_micro += 1000000; \
|
|
(dest)->tv_secs--; \
|
|
} \
|
|
(dest)->tv_micro -= (src)->tv_micro; \
|
|
(dest)->tv_secs -= (src)->tv_secs;
|
|
|
|
static inline LONG CMPTIME(struct timeval *dest, struct timeval *src)
|
|
{
|
|
if (dest->tv_secs > src->tv_secs)
|
|
return -1;
|
|
else if (dest->tv_secs < src->tv_secs)
|
|
return 1;
|
|
else
|
|
{
|
|
if (dest->tv_micro > src->tv_micro)
|
|
return -1;
|
|
else if (dest->tv_micro < src->tv_micro)
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static inline LONG CMPTIME3232(struct timeval32 *dest, struct timeval32 *src)
|
|
{
|
|
return CMPTIME((struct timeval *)dest, (struct timeval *)src);
|
|
}
|
|
|
|
static inline LONG CMPTIMEXX32(struct timeval *dest, struct timeval32 *src)
|
|
{
|
|
return CMPTIME(dest, (struct timeval *)src);
|
|
}
|
|
|
|
/*
|
|
* Add 'diff' EClock ticks to timeval in 'time'.
|
|
* Fraction of second value is stored in in 'frac'.
|
|
* This macro relies on (CPU-specific) tick2usec() implementation
|
|
*/
|
|
#define INCTIME(time, frac, diff) \
|
|
(frac) += diff; \
|
|
if ((frac) >= TimerBase->tb_eclock_rate) \
|
|
{ \
|
|
(frac) -= TimerBase->tb_eclock_rate; \
|
|
(time).tv_secs++; \
|
|
} \
|
|
(time).tv_micro = tick2usec(frac);
|