X-Git-Url: http://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Ftime%2Ftime.h;h=5bb1ad5b5cfaafc103cd780fb485fe406e40c820;hp=6fb622c6224b86d5daeeddcf73fb721398598a99;hb=6abc867fce8c3eba40eb26092d31e34b47dd9165;hpb=2012d45e273c3016dbd09b2606efc9ffab07c57f diff --git a/ccan/time/time.h b/ccan/time/time.h index 6fb622c6..5bb1ad5b 100644 --- a/ccan/time/time.h +++ b/ccan/time/time.h @@ -14,6 +14,34 @@ struct timespec { #include #include +#ifdef DEBUG +#include +#define TIME_CHECK(t) \ + time_check((t), __FILE__ ":" stringify(__LINE__) " (" stringify(t) ") ") +#else +#define TIME_CHECK(t) (t) +#endif + +/** + * time_check - check if a time is malformed. + * @in: the time to check (returned) + * @abortstr: the string to print to stderr before aborting (if set). + * + * This can be used to make sure a time isn't negative and doesn't + * have a tv_nsec >= 1000000000. If it is, and @abortstr is non-NULL, + * that will be printed and abort() is called. Otherwise, if + * @abortstr is NULL then the returned timespec will be normalized and + * tv_sec set to 0 if it was negative. + * + * Note that if ccan/time is compiled with DEBUG, then it will call this + * for all passed and returned times. + * + * Example: + * printf("Now is %lu seconds since epoch\n", + * (long)time_check(time_now(), "time_now() failed?").tv_sec); + */ +struct timespec time_check(struct timespec in, const char *abortstr); + /** * time_now - return the current time * @@ -34,7 +62,15 @@ struct timespec time_now(void); * return time_greater(time_now(), time_add(*start, TIMEOUT)); * } */ -bool time_greater(struct timespec a, struct timespec b); +static inline bool time_greater(struct timespec a, struct timespec b) +{ + if (TIME_CHECK(a).tv_sec > TIME_CHECK(b).tv_sec) + return true; + else if (a.tv_sec < b.tv_sec) + return false; + + return a.tv_nsec > b.tv_nsec; +} /** * time_less - is a before b? @@ -48,7 +84,15 @@ bool time_greater(struct timespec a, struct timespec b); * return time_less(time_now(), time_add(*start, TIMEOUT)); * } */ -bool time_less(struct timespec a, struct timespec b); +static inline bool time_less(struct timespec a, struct timespec b) +{ + if (TIME_CHECK(a).tv_sec < TIME_CHECK(b).tv_sec) + return true; + else if (a.tv_sec > b.tv_sec) + return false; + + return a.tv_nsec < b.tv_nsec; +} /** * time_eq - is a equal to b? @@ -59,7 +103,7 @@ bool time_less(struct timespec a, struct timespec b); * #include * #include * - * // Can we fork in under a microsecond? + * // Can we fork in under a nanosecond? * static bool fast_fork(void) * { * struct timespec start = time_now(); @@ -70,7 +114,11 @@ bool time_less(struct timespec a, struct timespec b); * return time_eq(start, time_now()); * } */ -bool time_eq(struct timespec a, struct timespec b); +static inline bool time_eq(struct timespec a, struct timespec b) +{ + return TIME_CHECK(a).tv_sec == TIME_CHECK(b).tv_sec + && a.tv_nsec == b.tv_nsec; +} /** * time_sub - subtract two times @@ -85,7 +133,20 @@ bool time_eq(struct timespec a, struct timespec b); * return time_sub(time_now(), *start).tv_sec < 1; * } */ -struct timespec time_sub(struct timespec recent, struct timespec old); +static inline struct timespec time_sub(struct timespec recent, + struct timespec old) +{ + struct timespec diff; + + diff.tv_sec = TIME_CHECK(recent).tv_sec - TIME_CHECK(old).tv_sec; + if (old.tv_nsec > recent.tv_nsec) { + diff.tv_sec--; + diff.tv_nsec = 1000000000 + recent.tv_nsec - old.tv_nsec; + } else + diff.tv_nsec = recent.tv_nsec - old.tv_nsec; + + return TIME_CHECK(diff); +} /** * time_add - add two times @@ -101,7 +162,18 @@ struct timespec time_sub(struct timespec recent, struct timespec old); * return time_add(time_now(), time_from_msec(1000)); * } */ -struct timespec time_add(struct timespec a, struct timespec b); +static inline struct timespec time_add(struct timespec a, struct timespec b) +{ + struct timespec sum; + + sum.tv_sec = TIME_CHECK(a).tv_sec + TIME_CHECK(b).tv_sec; + sum.tv_nsec = a.tv_nsec + b.tv_nsec; + if (sum.tv_nsec >= 1000000000) { + sum.tv_sec++; + sum.tv_nsec -= 1000000000; + } + return TIME_CHECK(sum); +} /** * time_divide - divide a time by a value. @@ -151,7 +223,13 @@ struct timespec time_multiply(struct timespec t, unsigned long mult); * printf("Forking time is %u msec\n", * (unsigned)time_to_msec(forking_time())); */ -uint64_t time_to_msec(struct timespec t); +static inline uint64_t time_to_msec(struct timespec t) +{ + uint64_t msec; + + msec = TIME_CHECK(t).tv_nsec / 1000000 + (uint64_t)t.tv_sec * 1000; + return msec; +} /** * time_to_usec - return number of microseconds @@ -167,7 +245,13 @@ uint64_t time_to_msec(struct timespec t); * (unsigned)time_to_usec(forking_time())); * */ -uint64_t time_to_usec(struct timespec t); +static inline uint64_t time_to_usec(struct timespec t) +{ + uint64_t usec; + + usec = TIME_CHECK(t).tv_nsec / 1000 + (uint64_t)t.tv_sec * 1000000; + return usec; +} /** * time_to_nsec - return number of nanoseconds @@ -183,7 +267,13 @@ uint64_t time_to_usec(struct timespec t); * (unsigned)time_to_nsec(forking_time())); * */ -uint64_t time_to_nsec(struct timespec t); +static inline uint64_t time_to_nsec(struct timespec t) +{ + uint64_t nsec; + + nsec = TIME_CHECK(t).tv_nsec + (uint64_t)t.tv_sec * 1000000000; + return nsec; +} /** * time_from_msec - convert milliseconds to a timespec @@ -193,7 +283,14 @@ uint64_t time_to_nsec(struct timespec t); * // 1/2 second timeout * #define TIMEOUT time_from_msec(500) */ -struct timespec time_from_msec(uint64_t msec); +static inline struct timespec time_from_msec(uint64_t msec) +{ + struct timespec t; + + t.tv_nsec = (msec % 1000) * 1000000; + t.tv_sec = msec / 1000; + return TIME_CHECK(t); +} /** * time_from_usec - convert microseconds to a timespec @@ -203,7 +300,14 @@ struct timespec time_from_msec(uint64_t msec); * // 1/2 second timeout * #define TIMEOUT time_from_usec(500000) */ -struct timespec time_from_usec(uint64_t usec); +static inline struct timespec time_from_usec(uint64_t usec) +{ + struct timespec t; + + t.tv_nsec = (usec % 1000000) * 1000; + t.tv_sec = usec / 1000000; + return TIME_CHECK(t); +} /** * time_from_nsec - convert nanoseconds to a timespec @@ -213,7 +317,14 @@ struct timespec time_from_usec(uint64_t usec); * // 1/2 second timeout * #define TIMEOUT time_from_nsec(500000000) */ -struct timespec time_from_nsec(uint64_t nsec); +static inline struct timespec time_from_nsec(uint64_t nsec) +{ + struct timespec t; + + t.tv_nsec = nsec % 1000000000; + t.tv_sec = nsec / 1000000000; + return TIME_CHECK(t); +} /** * timespec_to_timeval - convert a timespec to a timeval. @@ -223,6 +334,7 @@ struct timespec time_from_nsec(uint64_t nsec); * struct timeval tv; * * tv = timespec_to_timeval(time_now()); + * printf("time = %lu.%06u\n", (long)tv.tv_sec, (int)tv.tv_usec); */ static inline struct timeval timespec_to_timeval(struct timespec ts) { @@ -241,6 +353,7 @@ static inline struct timeval timespec_to_timeval(struct timespec ts) * struct timespec ts; * * ts = timeval_to_timespec(tv); + * printf("timespec = %lu.%09lu\n", (long)ts.tv_sec, (long)ts.tv_nsec); */ static inline struct timespec timeval_to_timespec(struct timeval tv) {