diff options
author | John Stultz <john.stultz@linaro.org> | 2014-07-16 17:03:59 -0400 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2014-07-23 13:17:53 -0400 |
commit | 49cd6f869984692547c57621bf42697aaa7f5622 (patch) | |
tree | f0bb760b91afa73f12f6f90db14b190728c0780b | |
parent | 361a3bf00582469877f8d18ff20f1efa6b781274 (diff) |
time: More core infrastructure for timespec64
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>
-rw-r--r-- | include/linux/ktime.h | 28 | ||||
-rw-r--r-- | include/linux/time64.h | 28 | ||||
-rw-r--r-- | kernel/time/time.c | 62 |
3 files changed, 118 insertions, 0 deletions
diff --git a/include/linux/ktime.h b/include/linux/ktime.h index 538c283714e1..da6b680c252b 100644 --- a/include/linux/ktime.h +++ b/include/linux/ktime.h | |||
@@ -83,6 +83,12 @@ static inline ktime_t timespec_to_ktime(struct timespec ts) | |||
83 | return ktime_set(ts.tv_sec, ts.tv_nsec); | 83 | return ktime_set(ts.tv_sec, ts.tv_nsec); |
84 | } | 84 | } |
85 | 85 | ||
86 | /* convert a timespec64 to ktime_t format: */ | ||
87 | static inline ktime_t timespec64_to_ktime(struct timespec64 ts) | ||
88 | { | ||
89 | return ktime_set(ts.tv_sec, ts.tv_nsec); | ||
90 | } | ||
91 | |||
86 | /* convert a timeval to ktime_t format: */ | 92 | /* convert a timeval to ktime_t format: */ |
87 | static inline ktime_t timeval_to_ktime(struct timeval tv) | 93 | static inline ktime_t timeval_to_ktime(struct timeval tv) |
88 | { | 94 | { |
@@ -92,6 +98,9 @@ static inline ktime_t timeval_to_ktime(struct timeval tv) | |||
92 | /* Map the ktime_t to timespec conversion to ns_to_timespec function */ | 98 | /* Map the ktime_t to timespec conversion to ns_to_timespec function */ |
93 | #define ktime_to_timespec(kt) ns_to_timespec((kt).tv64) | 99 | #define ktime_to_timespec(kt) ns_to_timespec((kt).tv64) |
94 | 100 | ||
101 | /* Map the ktime_t to timespec conversion to ns_to_timespec function */ | ||
102 | #define ktime_to_timespec64(kt) ns_to_timespec64((kt).tv64) | ||
103 | |||
95 | /* Map the ktime_t to timeval conversion to ns_to_timeval function */ | 104 | /* Map the ktime_t to timeval conversion to ns_to_timeval function */ |
96 | #define ktime_to_timeval(kt) ns_to_timeval((kt).tv64) | 105 | #define ktime_to_timeval(kt) ns_to_timeval((kt).tv64) |
97 | 106 | ||
@@ -213,6 +222,25 @@ static inline __must_check bool ktime_to_timespec_cond(const ktime_t kt, | |||
213 | } | 222 | } |
214 | } | 223 | } |
215 | 224 | ||
225 | /** | ||
226 | * ktime_to_timespec64_cond - convert a ktime_t variable to timespec64 | ||
227 | * format only if the variable contains data | ||
228 | * @kt: the ktime_t variable to convert | ||
229 | * @ts: the timespec variable to store the result in | ||
230 | * | ||
231 | * Return: %true if there was a successful conversion, %false if kt was 0. | ||
232 | */ | ||
233 | static inline __must_check bool ktime_to_timespec64_cond(const ktime_t kt, | ||
234 | struct timespec64 *ts) | ||
235 | { | ||
236 | if (kt.tv64) { | ||
237 | *ts = ktime_to_timespec64(kt); | ||
238 | return true; | ||
239 | } else { | ||
240 | return false; | ||
241 | } | ||
242 | } | ||
243 | |||
216 | /* | 244 | /* |
217 | * The resolution of the clocks. The resolution value is returned in | 245 | * The resolution of the clocks. The resolution value is returned in |
218 | * the clock_getres() system call to give application programmers an | 246 | * the clock_getres() system call to give application programmers an |
diff --git a/include/linux/time64.h b/include/linux/time64.h index e7b499e1cd79..a3831478d9cf 100644 --- a/include/linux/time64.h +++ b/include/linux/time64.h | |||
@@ -33,6 +33,16 @@ struct timespec64 { | |||
33 | 33 | ||
34 | #if __BITS_PER_LONG == 64 | 34 | #if __BITS_PER_LONG == 64 |
35 | 35 | ||
36 | static inline struct timespec timespec64_to_timespec(const struct timespec64 ts64) | ||
37 | { | ||
38 | return ts64; | ||
39 | } | ||
40 | |||
41 | static inline struct timespec64 timespec_to_timespec64(const struct timespec ts) | ||
42 | { | ||
43 | return ts; | ||
44 | } | ||
45 | |||
36 | # define timespec64_equal timespec_equal | 46 | # define timespec64_equal timespec_equal |
37 | # define timespec64_compare timespec_compare | 47 | # define timespec64_compare timespec_compare |
38 | # define set_normalized_timespec64 set_normalized_timespec | 48 | # define set_normalized_timespec64 set_normalized_timespec |
@@ -47,6 +57,24 @@ struct timespec64 { | |||
47 | 57 | ||
48 | #else | 58 | #else |
49 | 59 | ||
60 | static inline struct timespec timespec64_to_timespec(const struct timespec64 ts64) | ||
61 | { | ||
62 | struct timespec ret; | ||
63 | |||
64 | ret.tv_sec = (time_t)ts64.tv_sec; | ||
65 | ret.tv_nsec = ts64.tv_nsec; | ||
66 | return ret; | ||
67 | } | ||
68 | |||
69 | static inline struct timespec64 timespec_to_timespec64(const struct timespec ts) | ||
70 | { | ||
71 | struct timespec64 ret; | ||
72 | |||
73 | ret.tv_sec = ts.tv_sec; | ||
74 | ret.tv_nsec = ts.tv_nsec; | ||
75 | return ret; | ||
76 | } | ||
77 | |||
50 | static inline int timespec64_equal(const struct timespec64 *a, | 78 | static inline int timespec64_equal(const struct timespec64 *a, |
51 | const struct timespec64 *b) | 79 | const struct timespec64 *b) |
52 | { | 80 | { |
diff --git a/kernel/time/time.c b/kernel/time/time.c index 7c7964c33ae7..e8121a67fd74 100644 --- a/kernel/time/time.c +++ b/kernel/time/time.c | |||
@@ -420,6 +420,68 @@ struct timeval ns_to_timeval(const s64 nsec) | |||
420 | } | 420 | } |
421 | EXPORT_SYMBOL(ns_to_timeval); | 421 | EXPORT_SYMBOL(ns_to_timeval); |
422 | 422 | ||
423 | #if BITS_PER_LONG == 32 | ||
424 | /** | ||
425 | * set_normalized_timespec - set timespec sec and nsec parts and normalize | ||
426 | * | ||
427 | * @ts: pointer to timespec variable to be set | ||
428 | * @sec: seconds to set | ||
429 | * @nsec: nanoseconds to set | ||
430 | * | ||
431 | * Set seconds and nanoseconds field of a timespec variable and | ||
432 | * normalize to the timespec storage format | ||
433 | * | ||
434 | * Note: The tv_nsec part is always in the range of | ||
435 | * 0 <= tv_nsec < NSEC_PER_SEC | ||
436 | * For negative values only the tv_sec field is negative ! | ||
437 | */ | ||
438 | void set_normalized_timespec64(struct timespec64 *ts, time64_t sec, s64 nsec) | ||
439 | { | ||
440 | while (nsec >= NSEC_PER_SEC) { | ||
441 | /* | ||
442 | * The following asm() prevents the compiler from | ||
443 | * optimising this loop into a modulo operation. See | ||
444 | * also __iter_div_u64_rem() in include/linux/time.h | ||
445 | */ | ||
446 | asm("" : "+rm"(nsec)); | ||
447 | nsec -= NSEC_PER_SEC; | ||
448 | ++sec; | ||
449 | } | ||
450 | while (nsec < 0) { | ||
451 | asm("" : "+rm"(nsec)); | ||
452 | nsec += NSEC_PER_SEC; | ||
453 | --sec; | ||
454 | } | ||
455 | ts->tv_sec = sec; | ||
456 | ts->tv_nsec = nsec; | ||
457 | } | ||
458 | EXPORT_SYMBOL(set_normalized_timespec64); | ||
459 | |||
460 | /** | ||
461 | * ns_to_timespec64 - Convert nanoseconds to timespec64 | ||
462 | * @nsec: the nanoseconds value to be converted | ||
463 | * | ||
464 | * Returns the timespec64 representation of the nsec parameter. | ||
465 | */ | ||
466 | struct timespec64 ns_to_timespec64(const s64 nsec) | ||
467 | { | ||
468 | struct timespec64 ts; | ||
469 | s32 rem; | ||
470 | |||
471 | if (!nsec) | ||
472 | return (struct timespec64) {0, 0}; | ||
473 | |||
474 | ts.tv_sec = div_s64_rem(nsec, NSEC_PER_SEC, &rem); | ||
475 | if (unlikely(rem < 0)) { | ||
476 | ts.tv_sec--; | ||
477 | rem += NSEC_PER_SEC; | ||
478 | } | ||
479 | ts.tv_nsec = rem; | ||
480 | |||
481 | return ts; | ||
482 | } | ||
483 | EXPORT_SYMBOL(ns_to_timespec64); | ||
484 | #endif | ||
423 | /* | 485 | /* |
424 | * When we convert to jiffies then we interpret incoming values | 486 | * When we convert to jiffies then we interpret incoming values |
425 | * the following way: | 487 | * the following way: |