1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
/*
* Soft: Keepalived is a failover program for the LVS project
* <www.linuxvirtualserver.org>. It monitor & manipulate
* a loadbalanced server pool using multi-layer checks.
*
* Part: timer.c include file.
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Copyright (C) 2001-2017 Alexandre Cassen, <acassen@gmail.com>
*/
#ifndef _TIMER_H
#define _TIMER_H
#include <sys/time.h>
#include <limits.h>
#include <string.h>
#include <stdbool.h>
typedef struct timeval timeval_t;
/* Global vars */
extern timeval_t time_now;
#ifdef _TIMER_CHECK_
extern bool do_timer_check;
#endif
/* Some defines */
#define TIMER_HZ 1000000
#define TIMER_HZ_DIGITS 6
#define TIMER_HZ_FLOAT 1000000.0F
#define TIMER_HZ_DOUBLE ((double)1000000.0F)
#define TIMER_CENTI_HZ 10000
#define TIMER_MAX_SEC 1000U
#define TIMER_NEVER ULONG_MAX /* Used with time intervals in TIMER_HZ units */
#define TIMER_DISABLED LONG_MIN /* Value in timeval_t tv_sec */
#define NSEC_PER_SEC 1000000000 /* nanoseconds per second. Avoids typos by having a definition */
#ifdef _TIMER_CHECK_
#define timer_now() timer_now_r((__FILE__), (__func__), (__LINE__))
#define set_time_now() set_time_now_r((__FILE__), (__func__), (__LINE__))
#endif
#define RB_TIMER_CMP(obj, nnn) \
static inline int \
obj##_timer_cmp(const timeval_t *sands, const rb_node_t *a) \
{ \
const obj##_t *r1 = rb_entry_const(a, obj##_t, nnn); \
\
if (sands->tv_sec == TIMER_DISABLED) { \
if (r1->sands.tv_sec == TIMER_DISABLED) \
return 0; \
return 1; \
} \
\
if (r1->sands.tv_sec == TIMER_DISABLED) \
return -1; \
\
if (sands->tv_sec != r1->sands.tv_sec) \
return sands->tv_sec - r1->sands.tv_sec; \
\
return sands->tv_usec - r1->sands.tv_usec; \
}
#define RB_TIMER_LESS(obj, nnn) \
static inline bool \
obj##_timer_less(rb_node_t *a, const rb_node_t *b) \
{ \
const obj##_t *r1 = rb_entry_const(a, obj##_t, nnn); \
const obj##_t *r2 = rb_entry_const(b, obj##_t, nnn); \
\
if (r1->sands.tv_sec == TIMER_DISABLED) \
return false; \
\
if (r2->sands.tv_sec == TIMER_DISABLED) \
return true; \
\
if (r1->sands.tv_sec != r2->sands.tv_sec) \
return r1->sands.tv_sec < r2->sands.tv_sec; \
\
return r1->sands.tv_usec < r2->sands.tv_usec; \
}
/* timer sub from current time */
static inline timeval_t
timer_sub_now(timeval_t a)
{
timersub(&a, &time_now, &a);
return a;
}
/* timer add to current time */
static inline timeval_t
timer_add_now(timeval_t a)
{
timeradd(&time_now, &a, &a);
return a;
}
/* Returns true if time a + diff_hz < time_now */
static inline bool
timer_cmp_now_diff(timeval_t a, unsigned long diff_hz)
{
timeval_t b = { .tv_sec = diff_hz / TIMER_HZ, .tv_usec = diff_hz % TIMER_HZ };
timeradd(&b, &a, &b);
return !!timercmp(&b, &time_now, <);
}
/* Return time as unsigned long */
static inline unsigned long
timer_long(timeval_t a)
{
return (unsigned long)a.tv_sec * TIMER_HZ + (unsigned long)a.tv_usec;
}
#ifdef _INCLUDE_UNUSED_CODE_
/* print timer value */
static inline void
timer_dump(timeval_t a)
{
printf("=> %lu (usecs)\n", timer_tol(a));
}
#endif
/* prototypes */
#ifdef _TIMER_CHECK_
extern timeval_t timer_now_r(const char *, const char *, int);
extern timeval_t set_time_now_r(const char *, const char *, int);
#else
extern timeval_t timer_now(void);
extern timeval_t set_time_now(void);
#endif
extern timeval_t timer_add_long(timeval_t, unsigned long) __attribute__((const));
extern timeval_t timer_sub_long(timeval_t, unsigned long) __attribute__((const));
#endif
|