diff --git a/lib/isc/unix/include/isc/time.h b/lib/isc/unix/include/isc/time.h index 850a826fa2..b5a76f1755 100644 --- a/lib/isc/unix/include/isc/time.h +++ b/lib/isc/unix/include/isc/time.h @@ -4,21 +4,93 @@ #include #include +#include -/* - * This structure can be used both to represent absolute times, and to - * to represent intervals. +/*** + *** Intervals + ***/ + +/* + * The contents of this structure are private, and MUST NOT be accessed + * directly by callers. + * + * The contents are exposed only so that callers may avoid dynamic allocation + * and instead just declare a 'struct isc_interval'. + */ +typedef struct isc_interval { + unsigned int seconds; + unsigned int nanoseconds; +} *isc_interval_t; + +void +isc_interval_set(isc_interval_t i, + unsigned int seconds, unsigned int nanoseconds); +/* + * Set 'i' to a value representing an interval of 'seconds' seconds and + * 'nanoseconds' nanoseconds, suitable for use in isc_time_add() and + * isc_time_subtract(). + * + * Requires: + * + * 't' is a valid. + * + * nanoseconds < 1000000000 + */ + +isc_boolean_t +isc_interval_iszero(isc_interval_t i); +/* + * Returns ISC_TRUE iff. 'i' is the zero interval. + * + * Requires: + * + * 't' is a valid. + * + */ + +/*** + *** Absolute Times + ***/ + +/* + * The contents of this structure are private, and MUST NOT be accessed + * directly by callers. + * + * The contents are exposed only so that callers may avoid dynamic allocation + * and instead just declare a 'struct isc_time'. */ typedef struct isc_time { - time_t seconds; - long nanoseconds; + time_t seconds; + unsigned int nanoseconds; } *isc_time_t; +void +isc_time_settoepoch(isc_time_t t); +/* + * Set 't' to the time of the epoch. + * + * Requires: + * + * 't' is a valid. + * + */ + +isc_boolean_t +isc_time_isepoch(isc_time_t t); +/* + * Returns ISC_TRUE iff. 't' is the epoch ("time zero"). + * + * Requires: + * + * 't' is a valid. + * + */ + isc_result_t isc_time_get(isc_time_t t); /* - * Set 't' to the current absolute time (secs + nsec since January 1, 1970). + * Set 't' to the current absolute time. * * Requires: * @@ -47,25 +119,73 @@ isc_time_compare(isc_time_t t1, isc_time_t t2); */ void -isc_time_add(isc_time_t t1, isc_time_t t2, isc_time_t t3); +isc_time_add(isc_time_t t, isc_interval_t i, isc_time_t result); /* - * Add 't1' to 't2', storing the result in 't3'. + * Add 'i' to 't', storing the result in 'result'. * * Requires: * - * 't1', 't2', and 't3' are valid. + * 't', 'i', and 'result' are valid. */ void -isc_time_subtract(isc_time_t t1, isc_time_t t2, isc_time_t t3); +isc_time_subtract(isc_time_t t, isc_interval_t t2, isc_time_t result); /* - * Subtract 't2' from 't1', storing the result in 't3'. + * Subtract 'i' from 't', storing the result in 'result'. * * Requires: * - * 't1', 't2', and 't3' are valid. + * 't', 'i', and 'result' are valid. + * + * t >= epoch + i (comparing times, not pointers) + */ + +/*** + *** UNIX-only + ***/ + +void +isc_time_fromtimeval(isc_time_t t, struct timeval *tv); +/* + * Set 't' to the time given by 'ts'. + * + * Requires: + * + * 't' and 'tv' are a valid. + * + */ + +void +isc_time_totimeval(isc_time_t t, struct timeval *tv); +/* + * Convert 't' to a UNIX timeval. + * + * Requires: + * + * 't' and 'tv' are a valid. + * + */ + +void +isc_time_fromtimespec(isc_time_t t, struct timespec *ts); +/* + * Set 't' to the time given by 'ts'. + * + * Requires: + * + * 't' and 'ts' are a valid. + * + */ + +void +isc_time_totimespec(isc_time_t t, struct timespec *ts); +/* + * Convert 't' to a UNIX timespec. + * + * Requires: + * + * 't' and 'ts' are a valid. * - * t1 >= t2 (comparing times, not pointers) */ #endif /* ISC_TIME_H */ diff --git a/lib/isc/unix/time.c b/lib/isc/unix/time.c index 4dfac9e249..62559e22ba 100644 --- a/lib/isc/unix/time.c +++ b/lib/isc/unix/time.c @@ -11,30 +11,98 @@ #include #include +/*** + *** Intervals + ***/ + +void +isc_interval_set(isc_interval_t i, + unsigned int seconds, unsigned int nanoseconds) { + + /* + * Set 'i' to a value representing an interval of 'seconds' seconds + * and 'nanoseconds' nanoseconds, suitable for use in isc_time_add() + * and isc_time_subtract(). + */ + + REQUIRE(i != NULL); + REQUIRE(nanoseconds < 1000000000); + + i->seconds = seconds; + i->nanoseconds = nanoseconds; +} + +isc_boolean_t +isc_interval_iszero(isc_interval_t i) { + + /* + * Returns ISC_TRUE iff. 'i' is the zero interval. + */ + + REQUIRE(i != NULL); + + if (i->seconds == 0 && i->nanoseconds == 0) + return (ISC_TRUE); + + return (ISC_FALSE); +} + + +/*** + *** Absolute Times + ***/ + +void +isc_time_settoepoch(isc_time_t t) { + /* + * Set 't' to the time of the epoch. + */ + + REQUIRE(t != NULL); + + t->seconds = 0; + t->nanoseconds = 0; +} + +isc_boolean_t +isc_time_isepoch(isc_time_t t) { + + /* + * Returns ISC_TRUE iff. 't' is the epoch ("time zero"). + */ + + REQUIRE(t != NULL); + + if (t->seconds == 0 && t->nanoseconds == 0) + return (ISC_TRUE); + + return (ISC_FALSE); +} + isc_result -isc_time_get(isc_time_t timep) { +isc_time_get(isc_time_t t) { struct timeval tv; /* - * Set *timep to the current absolute time (secs + nsec since - * January 1, 1970). + * Set *t to the current absolute time. */ - REQUIRE(timep != NULL); + REQUIRE(t != NULL); if (gettimeofday(&tv, NULL) == -1) { UNEXPECTED_ERROR(__FILE__, __LINE__, strerror(errno)); return (ISC_R_UNEXPECTED); } - timep->seconds = tv.tv_sec; - timep->nanoseconds = tv.tv_usec * 1000; + t->seconds = tv.tv_sec; + t->nanoseconds = tv.tv_usec * 1000; return (ISC_R_SUCCESS); } int isc_time_compare(isc_time_t t1, isc_time_t t2) { + /* * Compare the times referenced by 't1' and 't2' */ @@ -53,37 +121,94 @@ isc_time_compare(isc_time_t t1, isc_time_t t2) { } void -isc_time_add(isc_time_t t1, isc_time_t t2, isc_time_t t3) +isc_time_add(isc_time_t t, isc_interval_t i, isc_time_t result) { /* - * Add 't1' to 't2', storing the result in 't3'. + * Add 't' to 'i', storing the result in 'result'. */ - REQUIRE(t1 != NULL && t2 != NULL && t3 != NULL); + REQUIRE(t != NULL && i != NULL && result != NULL); - t3->seconds = t1->seconds + t2->seconds; - t3->nanoseconds = t1->nanoseconds + t2->nanoseconds; - if (t3->nanoseconds > 1000000000) { - t3->seconds++; - t3->nanoseconds -= 1000000000; + result->seconds = t->seconds + i->seconds; + result->nanoseconds = t->nanoseconds + i->nanoseconds; + if (result->nanoseconds > 1000000000) { + result->seconds++; + result->nanoseconds -= 1000000000; } } void -isc_time_subtract(isc_time_t t1, isc_time_t t2, isc_time_t t3) { +isc_time_subtract(isc_time_t t, isc_interval_t i, isc_time_t result) { /* - * Subtract 't2' from 't1', storing the result in 't1'. + * Subtract 'i' from 't', storing the result in 'result'. */ - REQUIRE(t1 != NULL && t2 != NULL && t3 != NULL); - REQUIRE(isc_time_compare(t1, t2) >= 0); + REQUIRE(t != NULL && i != NULL && result != NULL); - t3->seconds = t1->seconds - t2->seconds; - if (t1->nanoseconds >= t2->nanoseconds) - t3->nanoseconds = t1->nanoseconds - t2->nanoseconds; + result->seconds = t->seconds - i->seconds; + if (t->nanoseconds >= i->nanoseconds) + result->nanoseconds = t->nanoseconds - i->nanoseconds; else { - t3->nanoseconds = 1000000000 - t2->nanoseconds + - t1->nanoseconds; - t3->seconds--; + result->nanoseconds = 1000000000 - i->nanoseconds + + t->nanoseconds; + result->seconds--; } } + + +/*** + *** UNIX-only + ***/ + + +void +isc_time_fromtimeval(isc_time_t t, struct timeval *tv) { + + /* + * Set 't' to the time given by 'ts'. + */ + + REQUIRE(t != NULL && tv != NULL); + + t->seconds = tv->tv_sec; + t->nanoseconds = tv->tv_usec * 1000; +} + +void +isc_time_totimeval(isc_time_t t, struct timeval *tv) { + + /* + * Convert 't' to a UNIX timeval. + */ + + REQUIRE(t != NULL && tv != NULL); + + tv->tv_sec = t->seconds; + tv->tv_usec = t->nanoseconds / 1000; +} + +void +isc_time_fromtimespec(isc_time_t t, struct timespec *ts) { + + /* + * Set 't' to the time given by 'ts'. + */ + + REQUIRE(t != NULL && ts != NULL); + + t->seconds = ts->tv_sec; + t->nanoseconds = ts->tv_nsec; +} + +void +isc_time_totimespec(isc_time_t t, struct timespec *ts) { + + /* + * Convert 't' to a UNIX timespec. + */ + + REQUIRE(t != NULL && ts != NULL); + + ts->tv_sec = t->seconds; + ts->tv_nsec = t->nanoseconds; +}