259 lines
6.0 KiB
C
259 lines
6.0 KiB
C
#ifndef INCLUDED_C_TIMESPEC_H
|
|||
|
|
#define INCLUDED_C_TIMESPEC_H
|
||
|
|
|
||
|
|
#ifndef INCLUDED_C_TYPES_H
|
||
|
|
#include <c_Types.h>
|
||
|
|
#endif /*INCLUDED_C_TYPES_H*/
|
||
|
|
|
||
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
||
|
|
/* */
|
||
|
|
|
||
|
|
#define C_NSEC_PER_USEC 1000L
|
||
|
|
#define C_USEC_PER_MSEC 1000L
|
||
|
|
#define C_MSEC_PER_SEC 1000L
|
||
|
|
#define C_NSEC_PER_MSEC 1000000L
|
||
|
|
#define C_USEC_PER_SEC 1000000L
|
||
|
|
#define C_NSEC_PER_SEC 1000000000L
|
||
|
|
|
||
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
||
|
|
/* */
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
struct timespec c_timespec_normalise(struct timespec ts)
|
||
|
|
{
|
||
|
|
while(ts.tv_nsec >= C_NSEC_PER_SEC)
|
||
|
|
{
|
||
|
|
++(ts.tv_sec);
|
||
|
|
ts.tv_nsec -= C_NSEC_PER_SEC;
|
||
|
|
}
|
||
|
|
|
||
|
|
while(ts.tv_nsec <= -C_NSEC_PER_SEC)
|
||
|
|
{
|
||
|
|
--(ts.tv_sec);
|
||
|
|
ts.tv_nsec += C_NSEC_PER_SEC;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(ts.tv_nsec < 0)
|
||
|
|
{
|
||
|
|
/* Negative nanoseconds isn't valid according to POSIX.
|
||
|
|
* Decrement tv_sec and roll tv_nsec over.
|
||
|
|
*/
|
||
|
|
|
||
|
|
--(ts.tv_sec);
|
||
|
|
ts.tv_nsec = (C_NSEC_PER_SEC + ts.tv_nsec);
|
||
|
|
}
|
||
|
|
|
||
|
|
return ts;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
||
|
|
/* */
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
struct timespec c_timespec_add(struct timespec ts1, struct timespec ts2)
|
||
|
|
{
|
||
|
|
/* Normalise inputs to prevent tv_nsec rollover if whole-second values
|
||
|
|
* are packed in it.
|
||
|
|
*/
|
||
|
|
ts1 = c_timespec_normalise(ts1);
|
||
|
|
ts2 = c_timespec_normalise(ts2);
|
||
|
|
|
||
|
|
ts1.tv_sec += ts2.tv_sec;
|
||
|
|
ts1.tv_nsec += ts2.tv_nsec;
|
||
|
|
|
||
|
|
return c_timespec_normalise(ts1);
|
||
|
|
}
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
struct timespec c_timespec_sub(struct timespec ts1, struct timespec ts2)
|
||
|
|
{
|
||
|
|
/* Normalise inputs to prevent tv_nsec rollover if whole-second values
|
||
|
|
* are packed in it.
|
||
|
|
*/
|
||
|
|
ts1 = c_timespec_normalise(ts1);
|
||
|
|
ts2 = c_timespec_normalise(ts2);
|
||
|
|
|
||
|
|
ts1.tv_sec -= ts2.tv_sec;
|
||
|
|
ts1.tv_nsec -= ts2.tv_nsec;
|
||
|
|
|
||
|
|
return c_timespec_normalise(ts1);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
||
|
|
/* */
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
int c_timespec_cmp(struct timespec ts1, struct timespec ts2)
|
||
|
|
{
|
||
|
|
ts1 = c_timespec_normalise(ts1);
|
||
|
|
ts2 = c_timespec_normalise(ts2);
|
||
|
|
|
||
|
|
if(ts1.tv_sec == ts2.tv_sec && ts1.tv_nsec == ts2.tv_nsec)
|
||
|
|
{
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
else if((ts1.tv_sec > ts2.tv_sec)
|
||
|
|
|| (ts1.tv_sec == ts2.tv_sec && ts1.tv_nsec > ts2.tv_nsec))
|
||
|
|
{
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
bool c_timespec_eq(struct timespec ts1, struct timespec ts2)
|
||
|
|
{
|
||
|
|
ts1 = c_timespec_normalise(ts1);
|
||
|
|
ts2 = c_timespec_normalise(ts2);
|
||
|
|
|
||
|
|
return (ts1.tv_sec == ts2.tv_sec && ts1.tv_nsec == ts2.tv_nsec);
|
||
|
|
}
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
bool c_timespec_gt(struct timespec ts1, struct timespec ts2)
|
||
|
|
{
|
||
|
|
ts1 = c_timespec_normalise(ts1);
|
||
|
|
ts2 = c_timespec_normalise(ts2);
|
||
|
|
|
||
|
|
return (ts1.tv_sec > ts2.tv_sec || (ts1.tv_sec == ts2.tv_sec && ts1.tv_nsec > ts2.tv_nsec));
|
||
|
|
}
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
bool c_timespec_ge(struct timespec ts1, struct timespec ts2)
|
||
|
|
{
|
||
|
|
ts1 = c_timespec_normalise(ts1);
|
||
|
|
ts2 = c_timespec_normalise(ts2);
|
||
|
|
|
||
|
|
return (ts1.tv_sec > ts2.tv_sec || (ts1.tv_sec == ts2.tv_sec && ts1.tv_nsec >= ts2.tv_nsec));
|
||
|
|
}
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
bool c_timespec_lt(struct timespec ts1, struct timespec ts2)
|
||
|
|
{
|
||
|
|
ts1 = c_timespec_normalise(ts1);
|
||
|
|
ts2 = c_timespec_normalise(ts2);
|
||
|
|
|
||
|
|
return (ts1.tv_sec < ts2.tv_sec || (ts1.tv_sec == ts2.tv_sec && ts1.tv_nsec < ts2.tv_nsec));
|
||
|
|
}
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
bool c_timespec_le(struct timespec ts1, struct timespec ts2)
|
||
|
|
{
|
||
|
|
ts1 = c_timespec_normalise(ts1);
|
||
|
|
ts2 = c_timespec_normalise(ts2);
|
||
|
|
|
||
|
|
return (ts1.tv_sec < ts2.tv_sec || (ts1.tv_sec == ts2.tv_sec && ts1.tv_nsec <= ts2.tv_nsec));
|
||
|
|
}
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
struct timespec c_timespec_min(struct timespec ts1, struct timespec ts2) {
|
||
|
|
if(c_timespec_le(ts1, ts2)) {
|
||
|
|
return ts1;
|
||
|
|
} else {
|
||
|
|
return ts2;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
struct timespec c_timespec_max(struct timespec ts1, struct timespec ts2) {
|
||
|
|
if(c_timespec_ge(ts1, ts2)) {
|
||
|
|
return ts1;
|
||
|
|
} else {
|
||
|
|
return ts2;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
struct timespec c_timespec_clamp(struct timespec ts, struct timespec min, struct timespec max) {
|
||
|
|
if(c_timespec_gt(ts, max)) {
|
||
|
|
return max;
|
||
|
|
}
|
||
|
|
if(c_timespec_lt(ts, min)) {
|
||
|
|
return min;
|
||
|
|
}
|
||
|
|
return ts;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
||
|
|
/* */
|
||
|
|
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
struct timespec c_timespec_from_double(double s)
|
||
|
|
{
|
||
|
|
struct timespec ts = {
|
||
|
|
.tv_sec = s,
|
||
|
|
.tv_nsec = (s - (long)(s)) * C_NSEC_PER_SEC,
|
||
|
|
};
|
||
|
|
|
||
|
|
return c_timespec_normalise(ts);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
double c_timespec_to_double(struct timespec ts)
|
||
|
|
{
|
||
|
|
return ((double)(ts.tv_sec) + ((double)(ts.tv_nsec) / C_NSEC_PER_SEC));
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
||
|
|
/* */
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
struct timespec c_timespec_from_timeval(struct timeval tv)
|
||
|
|
{
|
||
|
|
struct timespec ts = {
|
||
|
|
.tv_sec = tv.tv_sec,
|
||
|
|
.tv_nsec = tv.tv_usec * C_NSEC_PER_USEC
|
||
|
|
};
|
||
|
|
|
||
|
|
return c_timespec_normalise(ts);
|
||
|
|
}
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
struct timeval c_timespec_to_timeval(struct timespec ts)
|
||
|
|
{
|
||
|
|
ts = c_timespec_normalise(ts);
|
||
|
|
|
||
|
|
struct timeval tv = {
|
||
|
|
.tv_sec = ts.tv_sec,
|
||
|
|
.tv_usec = ts.tv_nsec / C_NSEC_PER_USEC,
|
||
|
|
};
|
||
|
|
|
||
|
|
return tv;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
||
|
|
/* */
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
struct timespec c_timespec_from_ms(long milliseconds)
|
||
|
|
{
|
||
|
|
struct timespec ts = {
|
||
|
|
.tv_sec = (milliseconds / C_MSEC_PER_SEC),
|
||
|
|
.tv_nsec = (milliseconds % C_MSEC_PER_SEC) * C_NSEC_PER_MSEC,
|
||
|
|
};
|
||
|
|
|
||
|
|
return c_timespec_normalise(ts);
|
||
|
|
}
|
||
|
|
|
||
|
|
C_STATIC_FORCE_INLINE
|
||
|
|
long c_timespec_to_ms(struct timespec ts)
|
||
|
|
{
|
||
|
|
return (ts.tv_sec * C_MSEC_PER_SEC) + (ts.tv_nsec / C_NSEC_PER_MSEC);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
||
|
|
/* */
|
||
|
|
|
||
|
|
struct timespec c_timespec_mod(struct timespec ts1, struct timespec ts2);
|
||
|
|
|
||
|
|
#endif /*INCLUDED_C_TIMESPEC_H*/
|