X-Git-Url: https://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Ftime%2Ftime.h;h=2fc8161e74ebc3696c05ae2f1247987face8d35f;hp=287558d0c735d7150f4d24a9404c711b830b7f62;hb=HEAD;hpb=1b11d06b6d28c65cc38f0091e624e2809e866275 diff --git a/ccan/time/time.h b/ccan/time/time.h index 287558d0..2fc8161e 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 /** @@ -39,7 +42,7 @@ struct timerel { }; /** - * struct timeabs - an absolue time. + * struct timeabs - an absolute time. * @ts: the actual timespec value. * * For example, Midnight UTC January 1st, 1970: ts.tv_sec = 0, ts.tv_nsec = 0 @@ -66,8 +69,10 @@ struct timemono { * Otherwise time_mono() just refers to time_now(). Your code might * test this if you really need a monotonic clock. */ -#if (HAVE_CLOCK_GETTIME || HAVE_CLOCK_GETTIME_IN_LIBRT) && defined(CLOCK_MONOTONIC) +#if HAVE_CLOCK_GETTIME && defined(CLOCK_MONOTONIC) #define TIME_HAVE_MONOTONIC 1 +#else +#define TIME_HAVE_MONOTONIC 0 #endif struct timespec time_check_(struct timespec in, const char *abortstr); @@ -95,7 +100,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 +118,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 * @@ -127,7 +152,7 @@ struct timeabs time_now(void); * This value is only really useful for measuring time intervals. * * See also: - * time_since() + * timemono_since() */ struct timemono time_mono(void); @@ -231,6 +256,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. @@ -320,6 +371,17 @@ static inline struct timerel timemono_between(struct timemono recent, return t; } +/** + * timemono_since - elapsed monotonic time since @old + * @old: a monotonic time from the past. + */ +static inline struct timerel timemono_since(struct timemono old) +{ + struct timemono now = time_mono(); + + return timemono_between(now, TIMEMONO_CHECK(old)); +} + /** * timeabs_sub - subtract a relative time from an absolute time * @abs: the absolute time. @@ -377,6 +439,28 @@ static inline struct timeabs timeabs_add(struct timeabs a, struct timerel b) return t; } +/** + * timemono_add - add a relative to a monotonic time + * @a: the monotonic time. + * @b: a relative time. + * + * The times must not overflow, or the results are undefined. + * + * Example: + * // We do one every second. + * static struct timemono next_timem(void) + * { + * return timemono_add(time_mono(), time_from_msec(1000)); + * } + */ +static inline struct timemono timemono_add(struct timemono a, struct timerel b) +{ + struct timemono t; + + t.ts = time_add_(a.ts, b.ts); + return t; +} + /** * timerel_add - add two relative times * @a: one relative time.