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
/**
struct timespec ts;
};
+/**
+ * struct timemono - a monotonic time.
+ * @ts: the actual timespec value.
+ *
+ * This comes from the monotonic clock (if available), so it's useful
+ * for measuring intervals as it won't change even if the system clock
+ * is moved for some reason.
+ */
+struct timemono {
+ struct timespec ts;
+};
+
+/**
+ * TIME_HAVE_MONOTONIC - defined if we really have a monotonic clock.
+ *
+ * Otherwise time_mono() just refers to time_now(). Your code might
+ * test this if you really need a monotonic clock.
+ */
+#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);
/**
/**
* 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
*/
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
*
*/
struct timeabs time_now(void);
+/**
+ * time_mono - return the current monotonic time
+ *
+ * This value is only really useful for measuring time intervals.
+ *
+ * See also:
+ * timemono_since()
+ */
+struct timemono time_mono(void);
+
static inline bool time_greater_(struct timespec a, struct timespec b)
{
if (TIME_CHECK(a).tv_sec > TIME_CHECK(b).tv_sec)
&& 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 <sys/types.h>
+ * #include <sys/wait.h>
+ *
+ * // 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.
* exit(0);
* }
* wait(NULL);
- * diff = time_between(start, time_now());
+ * diff = time_between(time_now(), start);
* return timerel_eq(diff, zero);
* }
*/
return t;
}
+/**
+ * timemono_between - time between two monotonic times
+ * @recent: the larger time.
+ * @old: the smaller time.
+ *
+ * This returns a well formed struct timerel of @recent - @old.
+ */
+static inline struct timerel timemono_between(struct timemono recent,
+ struct timemono old)
+{
+ struct timerel t;
+
+ t.ts = time_sub_(recent.ts, old.ts);
+ 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.
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.