diff options
Diffstat (limited to 'lib/qtime.h')
-rw-r--r-- | lib/qtime.h | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/lib/qtime.h b/lib/qtime.h new file mode 100644 index 00000000..a9e635d1 --- /dev/null +++ b/lib/qtime.h @@ -0,0 +1,213 @@ +/* Quagga Realtime Clock handling -- header + * Copyright (C) 2009 Chris Hall (GMCH), Highwayman + * + * This file is part of GNU Zebra. + * + * GNU Zebra 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, or (at your + * option) any later version. + * + * GNU Zebra 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. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ZEBRA_QTIME_H +#define _ZEBRA_QTIME_H + +#include <stdint.h> +#include <stdlib.h> +#include <time.h> +#include <sys/time.h> +#include <unistd.h> + +#include "zassert.h" +#include "config.h" + +#ifndef Inline +#define Inline static inline +#endif + +/*============================================================================== + * qtime_t -- signed 64-bit integer. + * + * The various time functions work in terms of the structures: + * + * timespec -- tv_secs seconds + * tv_nsecs nano-seconds + * + * timeval -- tv_secs seconds + * tv_usecs micro-seconds + * + * Given a 64-bit integer it is much easier to do operations on a 64 bit + * (signed) nano-second value. That gives 34 bits for the seconds count, which + * is > 290 years. + */ + +typedef int64_t qtime_t ; + +/* A qtime_t second 123456789 -- nano-seconds */ +#define QTIME_SECOND 1000000000 +#define TIMESPEC_SECOND 1000000000 +#define TIMEVAL_SECOND 1000000 + +/* Macro to convert time in seconds to a qtime_t */ +#define QTIME(s) ((qtime_t)((s) * QTIME_SECOND)) + +Inline qtime_t +timespec2qtime(struct timespec* p_ts) ; + +Inline qtime_t +timeval2qtime(struct timeval* p_tv) ; + +Inline struct timespec* +qtime2timespec(struct timespec* p_ts, qtime_t qt) ; + +Inline struct timeval* +qtime2timeval(struct timeval* p_tv, qtime_t qt) ; + +/*============================================================================== + * Clocks. + * + * Here is support for: + * + * * System Clock + * + * This can be read using either clock_gettime(CLOCK_REALTIME, &ts) or + * gettimeofday(&tv, NULL) -- which (are believed to) return the same clock, + * but in different units. + * + * * Monotonic Clock + * + * Using clock_gettime(CLOCK_MONOTONIC, &ts) if it is available, otherwise + * a manufactured equivalent using times(). + */ + +Inline qtime_t +qt_get_timeofday(void) ; /* gettimeofday(&tv, NULL) */ + +Inline qtime_t +qt_get_realtime(void) ; /* clock_gettime(CLOCK_REALTIME, &ts) */ + +Inline qtime_t +qt_get_monotonic(void) ; /* clock_gettime(CLOCK_MONOTONIC, &ts */ + /* OR equivalent using times() */ + +/* Function to manufacture a monotonic clock. */ +extern qtime_t qt_craft_monotonic(void) ; + +/*============================================================================== + * Inline conversion functions + */ + +/* Convert timespec to qtime_t + * + * Returns qtime_t value. + */ +Inline qtime_t +timespec2qtime(struct timespec* p_ts) +{ + return ((qtime_t)(p_ts->tv_sec) * QTIME_SECOND) + p_ts->tv_nsec ; +} ; + +/* Convert timeval to qtime_t + * + * Returns qtime_t value. + */ +Inline qtime_t +timeval2qtime(struct timeval* p_tv) +{ + return ((qtime_t)(p_tv->tv_sec) * QTIME_SECOND) + (p_tv->tv_usec * 1000) ; +} ; + +/* Convert qtime_t to timespec + * + * Takes address of struct timespec and returns that address. + */ +Inline struct timespec* +qtime2timespec(struct timespec* p_ts, qtime_t qt) +{ + lldiv_t imd = lldiv(qt, QTIME_SECOND) ; + p_ts->tv_sec = imd.quot ; + p_ts->tv_nsec = imd.rem ; + + return p_ts ; +} ; + +/* Convert timespec to qtime_t + * + * Takes address of struct timespec and returns that address. + */ +Inline struct timeval* +qtime2timeval(struct timeval* p_tv, qtime_t qt) +{ + lldiv_t imd = lldiv(qt, QTIME_SECOND) ; + p_tv->tv_sec = imd.quot ; + p_tv->tv_usec = imd.rem / 1000 ; + + return p_tv ; +} ; + +/*============================================================================== + * Inline Clock Functions. + */ + +/* Read given clock & return a qtime_t value. + * + * Crunch, zabbort_errno, if fails: cannot continue with broken time value ! + */ + +Inline qtime_t +qt_clock_gettime(clockid_t clock_id) +{ + struct timespec ts ; + + if (clock_gettime(clock_id, &ts) != 0) + zabort_errno("clock_gettime failed") ; + + return timespec2qtime(&ts) ; +} ; + +/* gettimeofday(&tv, NULL) -- returning qtime_t value + */ +Inline qtime_t +qt_get_timeofday(void) +{ + struct timeval tv ; + gettimeofday(&tv, NULL) ; + return timeval2qtime(&tv) ; +} + +/* clock_gettime(CLOCK_REALTIME, &ts) -- returning qtime_t value + * + * Crunch, zabbort_errno, if fails: cannot continue with broken time value ! + */ +Inline qtime_t +qt_get_realtime(void) +{ + return qt_clock_gettime(CLOCK_REALTIME) ; +} ; + +/* clock_gettime(CLOCK_MONOTONIC, &ts) OR qt_craft_monotonic() + * -- returning qtime_t value + * + * Crunch, zabbort_errno, if fails: cannot continue with broken time value ! + */ +Inline qtime_t +qt_get_monotonic(void) +{ +#ifdef HAVE_CLOCK_MONOTONIC + return qt_clock_gettime(CLOCK_MONOTONIC) ; +#else + return qt_craft_monotonic() ; +#endif +} ; + +#endif /* _ZEBRA_QTIME_H */ |