time: More core infrastructure for timespec64
authorJohn Stultz <john.stultz@linaro.org>
Wed, 16 Jul 2014 21:03:59 +0000 (21:03 +0000)
committerJohn Stultz <john.stultz@linaro.org>
Wed, 23 Jul 2014 17:17:53 +0000 (10:17 -0700)
Helper and conversion functions for timespec64.

Signed-off-by: John Stultz <john.stultz@linaro.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: John Stultz <john.stultz@linaro.org>
include/linux/ktime.h
include/linux/time64.h
kernel/time/time.c

index 538c283714e1b2e891a86ad238360fb3b708a677..da6b680c252b0d338072bbdf265bc397b4bd0a04 100644 (file)
@@ -83,6 +83,12 @@ static inline ktime_t timespec_to_ktime(struct timespec ts)
        return ktime_set(ts.tv_sec, ts.tv_nsec);
 }
 
+/* convert a timespec64 to ktime_t format: */
+static inline ktime_t timespec64_to_ktime(struct timespec64 ts)
+{
+       return ktime_set(ts.tv_sec, ts.tv_nsec);
+}
+
 /* convert a timeval to ktime_t format: */
 static inline ktime_t timeval_to_ktime(struct timeval tv)
 {
@@ -92,6 +98,9 @@ static inline ktime_t timeval_to_ktime(struct timeval tv)
 /* Map the ktime_t to timespec conversion to ns_to_timespec function */
 #define ktime_to_timespec(kt)          ns_to_timespec((kt).tv64)
 
+/* Map the ktime_t to timespec conversion to ns_to_timespec function */
+#define ktime_to_timespec64(kt)                ns_to_timespec64((kt).tv64)
+
 /* Map the ktime_t to timeval conversion to ns_to_timeval function */
 #define ktime_to_timeval(kt)           ns_to_timeval((kt).tv64)
 
@@ -213,6 +222,25 @@ static inline __must_check bool ktime_to_timespec_cond(const ktime_t kt,
        }
 }
 
+/**
+ * ktime_to_timespec64_cond - convert a ktime_t variable to timespec64
+ *                         format only if the variable contains data
+ * @kt:                the ktime_t variable to convert
+ * @ts:                the timespec variable to store the result in
+ *
+ * Return: %true if there was a successful conversion, %false if kt was 0.
+ */
+static inline __must_check bool ktime_to_timespec64_cond(const ktime_t kt,
+                                                      struct timespec64 *ts)
+{
+       if (kt.tv64) {
+               *ts = ktime_to_timespec64(kt);
+               return true;
+       } else {
+               return false;
+       }
+}
+
 /*
  * The resolution of the clocks. The resolution value is returned in
  * the clock_getres() system call to give application programmers an
index e7b499e1cd79c86f1eebf64978c4a3129d68b9d7..a3831478d9cf8db848a193fc908f7e54f340ffa8 100644 (file)
@@ -33,6 +33,16 @@ struct timespec64 {
 
 #if __BITS_PER_LONG == 64
 
+static inline struct timespec timespec64_to_timespec(const struct timespec64 ts64)
+{
+       return ts64;
+}
+
+static inline struct timespec64 timespec_to_timespec64(const struct timespec ts)
+{
+       return ts;
+}
+
 # define timespec64_equal              timespec_equal
 # define timespec64_compare            timespec_compare
 # define set_normalized_timespec64     set_normalized_timespec
@@ -47,6 +57,24 @@ struct timespec64 {
 
 #else
 
+static inline struct timespec timespec64_to_timespec(const struct timespec64 ts64)
+{
+       struct timespec ret;
+
+       ret.tv_sec = (time_t)ts64.tv_sec;
+       ret.tv_nsec = ts64.tv_nsec;
+       return ret;
+}
+
+static inline struct timespec64 timespec_to_timespec64(const struct timespec ts)
+{
+       struct timespec64 ret;
+
+       ret.tv_sec = ts.tv_sec;
+       ret.tv_nsec = ts.tv_nsec;
+       return ret;
+}
+
 static inline int timespec64_equal(const struct timespec64 *a,
                                   const struct timespec64 *b)
 {
index 7c7964c33ae764b7f3ee29ed8045222986f6a53e..e8121a67fd7404a9ce45894ba16c92dca5a3cbd1 100644 (file)
@@ -420,6 +420,68 @@ struct timeval ns_to_timeval(const s64 nsec)
 }
 EXPORT_SYMBOL(ns_to_timeval);
 
+#if BITS_PER_LONG == 32
+/**
+ * set_normalized_timespec - set timespec sec and nsec parts and normalize
+ *
+ * @ts:                pointer to timespec variable to be set
+ * @sec:       seconds to set
+ * @nsec:      nanoseconds to set
+ *
+ * Set seconds and nanoseconds field of a timespec variable and
+ * normalize to the timespec storage format
+ *
+ * Note: The tv_nsec part is always in the range of
+ *     0 <= tv_nsec < NSEC_PER_SEC
+ * For negative values only the tv_sec field is negative !
+ */
+void set_normalized_timespec64(struct timespec64 *ts, time64_t sec, s64 nsec)
+{
+       while (nsec >= NSEC_PER_SEC) {
+               /*
+                * The following asm() prevents the compiler from
+                * optimising this loop into a modulo operation. See
+                * also __iter_div_u64_rem() in include/linux/time.h
+                */
+               asm("" : "+rm"(nsec));
+               nsec -= NSEC_PER_SEC;
+               ++sec;
+       }
+       while (nsec < 0) {
+               asm("" : "+rm"(nsec));
+               nsec += NSEC_PER_SEC;
+               --sec;
+       }
+       ts->tv_sec = sec;
+       ts->tv_nsec = nsec;
+}
+EXPORT_SYMBOL(set_normalized_timespec64);
+
+/**
+ * ns_to_timespec64 - Convert nanoseconds to timespec64
+ * @nsec:       the nanoseconds value to be converted
+ *
+ * Returns the timespec64 representation of the nsec parameter.
+ */
+struct timespec64 ns_to_timespec64(const s64 nsec)
+{
+       struct timespec64 ts;
+       s32 rem;
+
+       if (!nsec)
+               return (struct timespec64) {0, 0};
+
+       ts.tv_sec = div_s64_rem(nsec, NSEC_PER_SEC, &rem);
+       if (unlikely(rem < 0)) {
+               ts.tv_sec--;
+               rem += NSEC_PER_SEC;
+       }
+       ts.tv_nsec = rem;
+
+       return ts;
+}
+EXPORT_SYMBOL(ns_to_timespec64);
+#endif
 /*
  * When we convert to jiffies then we interpret incoming values
  * the following way: