From: Rusty Russell Date: Mon, 31 Oct 2016 00:32:32 +0000 (+1030) Subject: time: make timemono a first-class citizen. X-Git-Url: http://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=88ed9bfe13c4bd2c72b0a2513cecf9ec0f19b792 time: make timemono a first-class citizen. Include assert checks, implement timemono_eq(). Signed-off-by: Rusty Russell --- diff --git a/ccan/time/test/run-check.c b/ccan/time/test/run-check.c index 11bcc576..c134afc3 100644 --- a/ccan/time/test/run-check.c +++ b/ccan/time/test/run-check.c @@ -17,10 +17,11 @@ void abort(void) int main(void) { struct timeabs t1, t2, epoch = { { 0, 0 } }; + struct timemono t1m, t2m; struct timerel t3, t4, zero = { { 0, 0 } }; int fds[2]; - plan_tests(64); + plan_tests(69); /* Test time_now */ t1 = time_now(); @@ -43,6 +44,21 @@ int main(void) ok1(timerel_eq(t3, t3)); ok1(!timerel_eq(t3, zero)); + /* Test time_mono */ + t1m = time_mono(); + t2m = time_mono(); + + ok1(!time_less_(t2m.ts, t1m.ts)); + + t3.ts.tv_sec = 1; + t3.ts.tv_nsec = 0; + + ok1(time_less(timemono_between(t2m, t1m), t3)); + ok1(time_less(timemono_since(t1m), t3)); + + ok1(timemono_add(t1m, t3).ts.tv_sec == t1m.ts.tv_sec + 1); + ok1(timemono_add(t2m, t3).ts.tv_nsec == t2m.ts.tv_nsec); + /* Make sure t2 > t1. */ t3.ts.tv_sec = 0; t3.ts.tv_nsec = 1; diff --git a/ccan/time/time.c b/ccan/time/time.c index d0542f56..27f0d52a 100644 --- a/ccan/time/time.c +++ b/ccan/time/time.c @@ -33,7 +33,7 @@ struct timemono time_mono(void) #else /* Best we can do */ ret.ts = time_now().ts; #endif /* !HAVE_TIME_MONOTONIC */ - return ret; + return TIMEMONO_CHECK(ret); } struct timerel time_divide(struct timerel t, unsigned long div) @@ -128,3 +128,11 @@ struct timeabs timeabs_check(struct timeabs t, const char *abortstr) ret.ts = time_check_(t.ts, abortstr); return ret; } + +struct timemono timemono_check(struct timemono t, const char *abortstr) +{ + struct timemono ret; + + ret.ts = time_check_(t.ts, abortstr); + return ret; +} diff --git a/ccan/time/time.h b/ccan/time/time.h index f2b335cf..70ebdc9a 100644 --- a/ccan/time/time.h +++ b/ccan/time/time.h @@ -22,10 +22,13 @@ struct timespec { timerel_check((t), __FILE__ ":" stringify(__LINE__) " (" stringify(t) ") ") #define TIMEABS_CHECK(t) \ timeabs_check((t), __FILE__ ":" stringify(__LINE__) " (" stringify(t) ") ") +#define TIMEMONO_CHECK(t) \ + timemono_check((t), __FILE__ ":" stringify(__LINE__) " (" stringify(t) ") ") #else #define TIME_CHECK(t) (t) #define TIMEREL_CHECK(t) (t) #define TIMEABS_CHECK(t) (t) +#define TIMEMONO_CHECK(t) (t) #endif /** @@ -95,7 +98,7 @@ struct timerel timerel_check(struct timerel in, const char *abortstr); /** * timeabs_check - check if an absolute time is malformed. - * @in: the relative time to check (returned) + * @in: the absolute 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 @@ -113,6 +116,26 @@ struct timerel timerel_check(struct timerel in, const char *abortstr); */ struct timeabs timeabs_check(struct timeabs in, const char *abortstr); +/** + * timemono_check - check if a monotonic time is malformed. + * @in: the monotonic 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 timemono 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 mono start\n", + * (long)timemono_check(time_mono(), "time_mono failed?").ts.tv_sec); + */ +struct timemono timemono_check(struct timemono in, const char *abortstr); + /** * time_now - return the current time * @@ -231,6 +254,32 @@ static inline bool timeabs_eq(struct timeabs a, struct timeabs b) && a.ts.tv_nsec == b.ts.tv_nsec; } +/** + * timemono_eq - is a equal to b? + * @a: one monotonic time. + * @b: another monotonic time. + * + * Example: + * #include + * #include + * + * // Can we fork in under a nanosecond? + * static bool fast_fork(void) + * { + * struct timemono start = time_mono(); + * if (fork() != 0) { + * exit(0); + * } + * wait(NULL); + * return timemono_eq(start, time_mono()); + * } + */ +static inline bool timemono_eq(struct timemono a, struct timemono b) +{ + return TIMEMONO_CHECK(a).ts.tv_sec == TIMEMONO_CHECK(b).ts.tv_sec + && a.ts.tv_nsec == b.ts.tv_nsec; +} + /** * timerel_eq - is a equal to b? * @a: one relative time. @@ -328,7 +377,7 @@ static inline struct timerel timemono_since(struct timemono old) { struct timemono now = time_mono(); - return timemono_between(now, old); + return timemono_between(now, TIMEMONO_CHECK(old)); } /**