]> git.ozlabs.org Git - ccan/blobdiff - ccan/time/time.h
base64: fix for unsigned chars (e.g. ARM).
[ccan] / ccan / time / time.h
index 287558d0c735d7150f4d24a9404c711b830b7f62..2fc8161e74ebc3696c05ae2f1247987face8d35f 100644 (file)
@@ -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 <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.
@@ -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.