Rusty Russell
9 years ago
8 changed files with 1253 additions and 1 deletions
@ -0,0 +1 @@ |
|||||
|
../../licenses/BSD-MIT |
@ -0,0 +1,57 @@ |
|||||
|
#include "config.h" |
||||
|
#include <stdio.h> |
||||
|
#include <string.h> |
||||
|
|
||||
|
/** |
||||
|
* time - routines for dealing with time |
||||
|
* |
||||
|
* This code provides convenient functions for working with time, in the |
||||
|
* form of 'struct timerel' for durations and 'struct timeabs' for timestamps |
||||
|
* which are light wrappers around struct timespec. |
||||
|
* |
||||
|
* Author: Rusty Russell <rusty@rustcorp.com.au> |
||||
|
* License: BSD-MIT |
||||
|
* |
||||
|
* Example: |
||||
|
* #include <ccan/time/time.h> |
||||
|
* #include <stdlib.h> |
||||
|
* #include <stdio.h> |
||||
|
* #include <err.h> |
||||
|
* |
||||
|
* int main(int argc, char *argv[]) |
||||
|
* { |
||||
|
* struct timeabs t; |
||||
|
* |
||||
|
* if (argc != 2) |
||||
|
* errx(1, "Usage: %s <diff in millisec>", argv[0]); |
||||
|
* |
||||
|
* t = time_now(); |
||||
|
* if (argv[1][0] == '-') |
||||
|
* t = timeabs_sub(t, time_from_msec(atol(argv[1]+1))); |
||||
|
* else |
||||
|
* t = timeabs_add(t, time_from_msec(atol(argv[1]))); |
||||
|
* |
||||
|
* printf("%lu.%09u\n", |
||||
|
* (unsigned long)t.ts.tv_sec, (unsigned)t.ts.tv_nsec); |
||||
|
* return 0; |
||||
|
* } |
||||
|
*/ |
||||
|
int main(int argc, char *argv[]) |
||||
|
{ |
||||
|
/* Expect exactly one argument */ |
||||
|
if (argc != 2) |
||||
|
return 1; |
||||
|
|
||||
|
if (strcmp(argv[1], "depends") == 0) { |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
#if HAVE_CLOCK_GETTIME_IN_LIBRT |
||||
|
if (strcmp(argv[1], "libs") == 0) { |
||||
|
printf("rt\n"); |
||||
|
return 0; |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
return 1; |
||||
|
} |
@ -0,0 +1,204 @@ |
|||||
|
#define DEBUG |
||||
|
#include <ccan/time/time.h> |
||||
|
#include <ccan/time/time.c> |
||||
|
#include <ccan/tap/tap.h> |
||||
|
#include <unistd.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <signal.h> |
||||
|
#include <sys/types.h> |
||||
|
#include <sys/wait.h> |
||||
|
|
||||
|
/* If we really abort, we don't get coverage info! */ |
||||
|
void abort(void) |
||||
|
{ |
||||
|
exit(7); |
||||
|
} |
||||
|
|
||||
|
int main(void) |
||||
|
{ |
||||
|
struct timeabs t1, t2, epoch = { { 0, 0 } }; |
||||
|
struct timerel t3, t4, zero = { { 0, 0 } }; |
||||
|
int fds[2]; |
||||
|
|
||||
|
plan_tests(64); |
||||
|
|
||||
|
/* Test time_now */ |
||||
|
t1 = time_now(); |
||||
|
t2 = time_now(); |
||||
|
|
||||
|
/* Test time_between. */ |
||||
|
t3 = time_between(t2, t1); |
||||
|
ok1(t3.ts.tv_sec > 0 || t3.ts.tv_nsec >= 0); |
||||
|
t3 = time_between(t2, t2); |
||||
|
ok1(t3.ts.tv_sec == 0 && t3.ts.tv_nsec == 0); |
||||
|
t3 = time_between(t1, t1); |
||||
|
ok1(t3.ts.tv_sec == 0 && t3.ts.tv_nsec == 0); |
||||
|
|
||||
|
/* Test timeabs_eq / timerel_eq */ |
||||
|
ok1(timeabs_eq(t1, t1)); |
||||
|
ok1(timeabs_eq(t2, t2)); |
||||
|
ok1(!timeabs_eq(t1, epoch)); |
||||
|
ok1(!timeabs_eq(t2, epoch)); |
||||
|
t3.ts.tv_sec = 1; |
||||
|
ok1(timerel_eq(t3, t3)); |
||||
|
ok1(!timerel_eq(t3, zero)); |
||||
|
|
||||
|
/* Make sure t2 > t1. */ |
||||
|
t3.ts.tv_sec = 0; |
||||
|
t3.ts.tv_nsec = 1; |
||||
|
t2 = timeabs_add(t2, t3); |
||||
|
|
||||
|
/* Test time_before and time_after. */ |
||||
|
ok1(!timeabs_eq(t1, t2)); |
||||
|
ok1(!time_after(t1, t2)); |
||||
|
ok1(time_before(t1, t2)); |
||||
|
ok1(time_after(t2, t1)); |
||||
|
ok1(!time_before(t2, t1)); |
||||
|
t3.ts.tv_sec = 0; |
||||
|
t3.ts.tv_nsec = 999999999; |
||||
|
t2 = timeabs_add(t2, t3); |
||||
|
ok1(!timeabs_eq(t1, t2)); |
||||
|
ok1(!time_after(t1, t2)); |
||||
|
ok1(time_before(t1, t2)); |
||||
|
ok1(time_after(t2, t1)); |
||||
|
ok1(!time_before(t2, t1)); |
||||
|
|
||||
|
t3 = time_between(t2, epoch); |
||||
|
ok1(t2.ts.tv_sec == t3.ts.tv_sec && t2.ts.tv_nsec == t3.ts.tv_nsec); |
||||
|
t3 = time_between(t2, t2); |
||||
|
ok1(timerel_eq(t3, zero)); |
||||
|
|
||||
|
/* time_from_msec / time_to_msec */ |
||||
|
t3 = time_from_msec(500); |
||||
|
ok1(t3.ts.tv_sec == 0); |
||||
|
ok1(t3.ts.tv_nsec == 500000000); |
||||
|
ok1(time_to_msec(t3) == 500); |
||||
|
|
||||
|
t3 = time_from_msec(1000); |
||||
|
ok1(t3.ts.tv_sec == 1); |
||||
|
ok1(t3.ts.tv_nsec == 0); |
||||
|
ok1(time_to_msec(t3) == 1000); |
||||
|
|
||||
|
t3 = time_from_msec(1500); |
||||
|
ok1(t3.ts.tv_sec == 1); |
||||
|
ok1(t3.ts.tv_nsec == 500000000); |
||||
|
ok1(time_to_msec(t3) == 1500); |
||||
|
|
||||
|
/* time_from_usec */ |
||||
|
t3 = time_from_usec(500000); |
||||
|
ok1(t3.ts.tv_sec == 0); |
||||
|
ok1(t3.ts.tv_nsec == 500000000); |
||||
|
ok1(time_to_usec(t3) == 500000); |
||||
|
|
||||
|
t3 = time_from_usec(1000000); |
||||
|
ok1(t3.ts.tv_sec == 1); |
||||
|
ok1(t3.ts.tv_nsec == 0); |
||||
|
ok1(time_to_usec(t3) == 1000000); |
||||
|
|
||||
|
t3 = time_from_usec(1500000); |
||||
|
ok1(t3.ts.tv_sec == 1); |
||||
|
ok1(t3.ts.tv_nsec == 500000000); |
||||
|
ok1(time_to_usec(t3) == 1500000); |
||||
|
|
||||
|
/* time_from_nsec */ |
||||
|
t3 = time_from_nsec(500000000); |
||||
|
ok1(t3.ts.tv_sec == 0); |
||||
|
ok1(t3.ts.tv_nsec == 500000000); |
||||
|
ok1(time_to_nsec(t3) == 500000000); |
||||
|
|
||||
|
t3 = time_from_nsec(1000000000); |
||||
|
ok1(t3.ts.tv_sec == 1); |
||||
|
ok1(t3.ts.tv_nsec == 0); |
||||
|
ok1(time_to_nsec(t3) == 1000000000); |
||||
|
|
||||
|
t3 = time_from_nsec(1500000000); |
||||
|
ok1(t3.ts.tv_sec == 1); |
||||
|
ok1(t3.ts.tv_nsec == 500000000); |
||||
|
ok1(time_to_nsec(t3) == 1500000000); |
||||
|
|
||||
|
/* Test wrapunder */ |
||||
|
t1 = timeabs_sub(timeabs_sub(t2, time_from_msec(500)), |
||||
|
time_from_msec(500)); |
||||
|
ok1(t1.ts.tv_sec == t2.ts.tv_sec - 1); |
||||
|
ok1(t1.ts.tv_nsec == t2.ts.tv_nsec); |
||||
|
|
||||
|
/* time_divide and time_multiply */ |
||||
|
t4.ts.tv_nsec = 100; |
||||
|
t4.ts.tv_sec = 100; |
||||
|
|
||||
|
t3 = time_divide(t4, 2); |
||||
|
ok1(t3.ts.tv_sec == 50); |
||||
|
ok1(t3.ts.tv_nsec == 50); |
||||
|
|
||||
|
t3 = time_divide(t4, 100); |
||||
|
ok1(t3.ts.tv_sec == 1); |
||||
|
ok1(t3.ts.tv_nsec == 1); |
||||
|
|
||||
|
t3 = time_multiply(t3, 100); |
||||
|
ok1(timerel_eq(t3, t4)); |
||||
|
|
||||
|
t3 = time_divide(t4, 200); |
||||
|
ok1(t3.ts.tv_sec == 0); |
||||
|
ok1(t3.ts.tv_nsec == 500000000); |
||||
|
|
||||
|
/* Divide by huge number. */ |
||||
|
t4.ts.tv_sec = (1U << 31) - 1; |
||||
|
t4.ts.tv_nsec = 999999999; |
||||
|
t3 = time_divide(t4, 1 << 30); |
||||
|
/* Allow us to round either way. */ |
||||
|
ok1((t3.ts.tv_sec == 2 && t3.ts.tv_nsec == 0) |
||||
|
|| (t3.ts.tv_sec == 1 && t3.ts.tv_nsec == 999999999)); |
||||
|
|
||||
|
/* Multiply by huge number. */ |
||||
|
t4.ts.tv_sec = 0; |
||||
|
t4.ts.tv_nsec = 1; |
||||
|
t3 = time_multiply(t4, 1UL << 31); |
||||
|
ok1(t3.ts.tv_sec == 2); |
||||
|
ok1(t3.ts.tv_nsec == 147483648); |
||||
|
|
||||
|
pipe(fds); |
||||
|
|
||||
|
fflush(stdout); |
||||
|
switch (fork()) { |
||||
|
case 0: |
||||
|
close(fds[0]); |
||||
|
dup2(fds[1], 1); |
||||
|
dup2(fds[1], 2); |
||||
|
t1.ts.tv_sec = 7; |
||||
|
t1.ts.tv_nsec = 1000000001; |
||||
|
t2 = timeabs_check(t1, NULL); |
||||
|
if (t2.ts.tv_sec != 8 || t2.ts.tv_nsec != 1) |
||||
|
exit(1); |
||||
|
t1.ts.tv_sec = -1; |
||||
|
t1.ts.tv_nsec = 5; |
||||
|
t2 = timeabs_check(t1, NULL); |
||||
|
if (t2.ts.tv_sec != 0 || t2.ts.tv_nsec != 5) |
||||
|
exit(1); |
||||
|
t1.ts.tv_sec = 8; |
||||
|
t1.ts.tv_nsec = 1000000002; |
||||
|
/* We expect this to abort! */ |
||||
|
t2 = timeabs_check(t1, "abortstr"); |
||||
|
exit(1); |
||||
|
|
||||
|
default: { |
||||
|
char readbuf[1024]; |
||||
|
int r, len = 0; |
||||
|
|
||||
|
close(fds[1]); |
||||
|
while ((r = read(fds[0], readbuf + len, 1023 - len)) > 0) |
||||
|
len += r; |
||||
|
readbuf[len] = '\0'; |
||||
|
ok1(strcmp(readbuf, |
||||
|
"WARNING: malformed time" |
||||
|
" 7 seconds 1000000001 ns converted to 8.000000001.\n" |
||||
|
"WARNING: malformed time" |
||||
|
" -1 seconds 5 ns converted to 0.000000005.\n" |
||||
|
"abortstr: malformed time 8.1000000002\n") == 0); |
||||
|
ok1(wait(&r) != -1); |
||||
|
ok1(WIFEXITED(r)); |
||||
|
ok1(WEXITSTATUS(r) == 7); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return exit_status(); |
||||
|
} |
@ -0,0 +1,24 @@ |
|||||
|
#include <ccan/time/time.h> |
||||
|
#include <ccan/time/time.c> |
||||
|
#include <ccan/tap/tap.h> |
||||
|
|
||||
|
int main(void) |
||||
|
{ |
||||
|
struct timemono t1, t2; |
||||
|
struct timerel t3; |
||||
|
|
||||
|
plan_tests(2); |
||||
|
|
||||
|
/* Test time_mono */ |
||||
|
t1 = time_mono(); |
||||
|
t2 = time_mono(); |
||||
|
|
||||
|
ok1(!time_less_(t2.ts, t1.ts)); |
||||
|
|
||||
|
t3.ts.tv_sec = 1; |
||||
|
t3.ts.tv_nsec = 0; |
||||
|
|
||||
|
ok1(time_less(timemono_between(t1, t2), t3)); |
||||
|
|
||||
|
return exit_status(); |
||||
|
} |
@ -0,0 +1,163 @@ |
|||||
|
#include <ccan/time/time.h> |
||||
|
#include <ccan/time/time.c> |
||||
|
#include <ccan/tap/tap.h> |
||||
|
|
||||
|
int main(void) |
||||
|
{ |
||||
|
struct timeabs t1, t2; |
||||
|
struct timerel t3, t4, zero = { { 0, 0 } }; |
||||
|
|
||||
|
plan_tests(66); |
||||
|
|
||||
|
/* Test time_now */ |
||||
|
t1 = time_now(); |
||||
|
t2 = time_now(); |
||||
|
|
||||
|
/* Test time_between. */ |
||||
|
t3 = time_between(t2, t1); |
||||
|
ok1(t3.ts.tv_sec > 0 || t3.ts.tv_nsec >= 0); |
||||
|
t3 = time_between(t2, t2); |
||||
|
ok1(t3.ts.tv_sec == 0 && t3.ts.tv_nsec == 0); |
||||
|
t3 = time_between(t1, t1); |
||||
|
ok1(t3.ts.tv_sec == 0 && t3.ts.tv_nsec == 0); |
||||
|
|
||||
|
/* Test timeabs_eq / timerel_eq */ |
||||
|
ok1(timeabs_eq(t1, t1)); |
||||
|
ok1(timeabs_eq(t2, t2)); |
||||
|
t3.ts.tv_sec = 0; |
||||
|
t3.ts.tv_nsec = 1; |
||||
|
ok1(!timerel_eq(t3, zero)); |
||||
|
ok1(!timerel_eq(t3, zero)); |
||||
|
|
||||
|
/* Make sure t2 > t1. */ |
||||
|
t2 = timeabs_add(t2, t3); |
||||
|
|
||||
|
/* Test time_after and time_before. */ |
||||
|
ok1(!timeabs_eq(t1, t2)); |
||||
|
ok1(!time_after(t1, t2)); |
||||
|
ok1(time_before(t1, t2)); |
||||
|
ok1(time_after(t2, t1)); |
||||
|
ok1(!time_before(t2, t1)); |
||||
|
t3.ts.tv_sec = 0; |
||||
|
t3.ts.tv_nsec = 999999999; |
||||
|
t2 = timeabs_add(t2, t3); |
||||
|
ok1(!timeabs_eq(t1, t2)); |
||||
|
ok1(!time_after(t1, t2)); |
||||
|
ok1(time_before(t1, t2)); |
||||
|
ok1(time_after(t2, t1)); |
||||
|
ok1(!time_before(t2, t1)); |
||||
|
|
||||
|
/* Test time_less and time_greater. */ |
||||
|
ok1(time_less(zero, t3)); |
||||
|
ok1(!time_greater(zero, t3)); |
||||
|
ok1(!time_less(t3, zero)); |
||||
|
ok1(time_greater(t3, zero)); |
||||
|
|
||||
|
/* Test time_sub */ |
||||
|
t3 = time_sub(t3, t3); |
||||
|
ok1(timerel_eq(t3, zero)); |
||||
|
|
||||
|
/* Test time_between */ |
||||
|
t3 = time_between(t2, t2); |
||||
|
ok1(timerel_eq(t3, zero)); |
||||
|
t3.ts.tv_sec = 0; |
||||
|
t3.ts.tv_nsec = 999999999; |
||||
|
t1 = timeabs_add(t2, t3); |
||||
|
t3 = time_between(t1, t2); |
||||
|
ok1(t3.ts.tv_sec == 0 && t3.ts.tv_nsec == 999999999); |
||||
|
|
||||
|
/* time_from_sec / time_to_sec */ |
||||
|
t3 = time_from_sec(500); |
||||
|
ok1(t3.ts.tv_sec == 500); |
||||
|
ok1(t3.ts.tv_nsec == 0); |
||||
|
ok1(time_to_sec(t3) == 500); |
||||
|
|
||||
|
/* time_from_msec / time_to_msec */ |
||||
|
t3 = time_from_msec(500); |
||||
|
ok1(t3.ts.tv_sec == 0); |
||||
|
ok1(t3.ts.tv_nsec == 500000000); |
||||
|
ok1(time_to_msec(t3) == 500); |
||||
|
|
||||
|
t3 = time_from_msec(1000); |
||||
|
ok1(t3.ts.tv_sec == 1); |
||||
|
ok1(t3.ts.tv_nsec == 0); |
||||
|
ok1(time_to_msec(t3) == 1000); |
||||
|
|
||||
|
t3 = time_from_msec(1500); |
||||
|
ok1(t3.ts.tv_sec == 1); |
||||
|
ok1(t3.ts.tv_nsec == 500000000); |
||||
|
ok1(time_to_msec(t3) == 1500); |
||||
|
|
||||
|
/* time_from_usec */ |
||||
|
t3 = time_from_usec(500000); |
||||
|
ok1(t3.ts.tv_sec == 0); |
||||
|
ok1(t3.ts.tv_nsec == 500000000); |
||||
|
ok1(time_to_usec(t3) == 500000); |
||||
|
|
||||
|
t3 = time_from_usec(1000000); |
||||
|
ok1(t3.ts.tv_sec == 1); |
||||
|
ok1(t3.ts.tv_nsec == 0); |
||||
|
ok1(time_to_usec(t3) == 1000000); |
||||
|
|
||||
|
t3 = time_from_usec(1500000); |
||||
|
ok1(t3.ts.tv_sec == 1); |
||||
|
ok1(t3.ts.tv_nsec == 500000000); |
||||
|
ok1(time_to_usec(t3) == 1500000); |
||||
|
|
||||
|
/* time_from_nsec */ |
||||
|
t3 = time_from_nsec(500000000); |
||||
|
ok1(t3.ts.tv_sec == 0); |
||||
|
ok1(t3.ts.tv_nsec == 500000000); |
||||
|
ok1(time_to_nsec(t3) == 500000000); |
||||
|
|
||||
|
t3 = time_from_nsec(1000000000); |
||||
|
ok1(t3.ts.tv_sec == 1); |
||||
|
ok1(t3.ts.tv_nsec == 0); |
||||
|
ok1(time_to_nsec(t3) == 1000000000); |
||||
|
|
||||
|
t3 = time_from_nsec(1500000000); |
||||
|
ok1(t3.ts.tv_sec == 1); |
||||
|
ok1(t3.ts.tv_nsec == 500000000); |
||||
|
ok1(time_to_nsec(t3) == 1500000000); |
||||
|
|
||||
|
/* Test wrapunder */ |
||||
|
t1 = timeabs_sub(timeabs_sub(t2, time_from_msec(500)), time_from_msec(500)); |
||||
|
ok1(t1.ts.tv_sec == t2.ts.tv_sec - 1); |
||||
|
ok1(t1.ts.tv_nsec == t2.ts.tv_nsec); |
||||
|
|
||||
|
/* time_divide and time_multiply */ |
||||
|
t4.ts.tv_nsec = 100; |
||||
|
t4.ts.tv_sec = 100; |
||||
|
|
||||
|
t3 = time_divide(t4, 2); |
||||
|
ok1(t3.ts.tv_sec == 50); |
||||
|
ok1(t3.ts.tv_nsec == 50); |
||||
|
|
||||
|
t3 = time_divide(t4, 100); |
||||
|
ok1(t3.ts.tv_sec == 1); |
||||
|
ok1(t3.ts.tv_nsec == 1); |
||||
|
|
||||
|
t3 = time_multiply(t3, 100); |
||||
|
ok1(timerel_eq(t3, t4)); |
||||
|
|
||||
|
t3 = time_divide(t4, 200); |
||||
|
ok1(t3.ts.tv_sec == 0); |
||||
|
ok1(t3.ts.tv_nsec == 500000000); |
||||
|
|
||||
|
/* Divide by huge number. */ |
||||
|
t4.ts.tv_sec = (1U << 31) - 1; |
||||
|
t4.ts.tv_nsec = 999999999; |
||||
|
t3 = time_divide(t4, 1 << 30); |
||||
|
/* Allow us to round either way. */ |
||||
|
ok1((t3.ts.tv_sec == 2 && t3.ts.tv_nsec == 0) |
||||
|
|| (t3.ts.tv_sec == 1 && t3.ts.tv_nsec == 999999999)); |
||||
|
|
||||
|
/* Multiply by huge number. */ |
||||
|
t4.ts.tv_sec = 0; |
||||
|
t4.ts.tv_nsec = 1; |
||||
|
t3 = time_multiply(t4, 1UL << 31); |
||||
|
ok1(t3.ts.tv_sec == 2); |
||||
|
ok1(t3.ts.tv_nsec == 147483648); |
||||
|
|
||||
|
return exit_status(); |
||||
|
} |
@ -0,0 +1,130 @@ |
|||||
|
/* Licensed under BSD-MIT - see LICENSE file for details */ |
||||
|
#include <ccan/time/time.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <stdio.h> |
||||
|
|
||||
|
#if !HAVE_CLOCK_GETTIME |
||||
|
#include <sys/time.h> |
||||
|
|
||||
|
struct timeabs time_now(void) |
||||
|
{ |
||||
|
struct timeval now; |
||||
|
struct timeabs ret; |
||||
|
gettimeofday(&now, NULL); |
||||
|
ret.ts.tv_sec = now.tv_sec; |
||||
|
ret.ts.tv_nsec = now.tv_usec * 1000; |
||||
|
return TIMEABS_CHECK(ret); |
||||
|
} |
||||
|
#else |
||||
|
#include <time.h> |
||||
|
struct timeabs time_now(void) |
||||
|
{ |
||||
|
struct timeabs ret; |
||||
|
clock_gettime(CLOCK_REALTIME, &ret.ts); |
||||
|
return TIMEABS_CHECK(ret); |
||||
|
} |
||||
|
#endif /* HAVE_CLOCK_GETTIME */ |
||||
|
|
||||
|
struct timemono time_mono(void) |
||||
|
{ |
||||
|
struct timemono ret; |
||||
|
#ifdef TIME_HAVE_MONOTONIC |
||||
|
clock_gettime(CLOCK_MONOTONIC, &ret.ts); |
||||
|
#else /* Best we can do */ |
||||
|
ret.ts = time_now().ts; |
||||
|
#endif /* !HAVE_TIME_MONOTONIC */ |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
struct timerel time_divide(struct timerel t, unsigned long div) |
||||
|
{ |
||||
|
struct timerel res; |
||||
|
uint64_t rem, ns; |
||||
|
|
||||
|
/* Dividing seconds is simple. */ |
||||
|
res.ts.tv_sec = TIMEREL_CHECK(t).ts.tv_sec / div; |
||||
|
rem = t.ts.tv_sec % div; |
||||
|
|
||||
|
/* If we can't fit remainder * 1,000,000,000 in 64 bits? */ |
||||
|
#if 0 /* ilog is great, but we use fp for multiply anyway. */
|
||||
|
bits = ilog64(rem); |
||||
|
if (bits + 30 >= 64) { |
||||
|
/* Reduce accuracy slightly */ |
||||
|
rem >>= (bits - (64 - 30)); |
||||
|
div >>= (bits - (64 - 30)); |
||||
|
} |
||||
|
#endif |
||||
|
if (rem & ~(((uint64_t)1 << 30) - 1)) { |
||||
|
/* FIXME: fp is cheating! */ |
||||
|
double nsec = rem * 1000000000.0 + t.ts.tv_nsec; |
||||
|
res.ts.tv_nsec = nsec / div; |
||||
|
} else { |
||||
|
ns = rem * 1000000000 + t.ts.tv_nsec; |
||||
|
res.ts.tv_nsec = ns / div; |
||||
|
} |
||||
|
return TIMEREL_CHECK(res); |
||||
|
} |
||||
|
|
||||
|
struct timerel time_multiply(struct timerel t, unsigned long mult) |
||||
|
{ |
||||
|
struct timerel res; |
||||
|
|
||||
|
/* Are we going to overflow if we multiply nsec? */ |
||||
|
if (mult & ~((1UL << 30) - 1)) { |
||||
|
/* FIXME: fp is cheating! */ |
||||
|
double nsec = (double)t.ts.tv_nsec * mult; |
||||
|
|
||||
|
res.ts.tv_sec = nsec / 1000000000.0; |
||||
|
res.ts.tv_nsec = nsec - (res.ts.tv_sec * 1000000000.0); |
||||
|
} else { |
||||
|
uint64_t nsec = t.ts.tv_nsec * mult; |
||||
|
|
||||
|
res.ts.tv_nsec = nsec % 1000000000; |
||||
|
res.ts.tv_sec = nsec / 1000000000; |
||||
|
} |
||||
|
res.ts.tv_sec += TIMEREL_CHECK(t).ts.tv_sec * mult; |
||||
|
return TIMEREL_CHECK(res); |
||||
|
} |
||||
|
|
||||
|
struct timespec time_check_(struct timespec t, const char *abortstr) |
||||
|
{ |
||||
|
if (t.tv_sec < 0 || t.tv_nsec >= 1000000000) { |
||||
|
if (abortstr) { |
||||
|
fprintf(stderr, "%s: malformed time %li.%09li\n", |
||||
|
abortstr, |
||||
|
(long)t.tv_sec, (long)t.tv_nsec); |
||||
|
abort(); |
||||
|
} else { |
||||
|
struct timespec old = t; |
||||
|
|
||||
|
if (t.tv_nsec >= 1000000000) { |
||||
|
t.tv_sec += t.tv_nsec / 1000000000; |
||||
|
t.tv_nsec %= 1000000000; |
||||
|
} |
||||
|
if (t.tv_sec < 0) |
||||
|
t.tv_sec = 0; |
||||
|
|
||||
|
fprintf(stderr, "WARNING: malformed time" |
||||
|
" %li seconds %li ns converted to %li.%09li.\n", |
||||
|
(long)old.tv_sec, (long)old.tv_nsec, |
||||
|
(long)t.tv_sec, (long)t.tv_nsec); |
||||
|
} |
||||
|
} |
||||
|
return t; |
||||
|
} |
||||
|
|
||||
|
struct timerel timerel_check(struct timerel t, const char *abortstr) |
||||
|
{ |
||||
|
struct timerel ret; |
||||
|
|
||||
|
ret.ts = time_check_(t.ts, abortstr); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
struct timeabs timeabs_check(struct timeabs t, const char *abortstr) |
||||
|
{ |
||||
|
struct timeabs ret; |
||||
|
|
||||
|
ret.ts = time_check_(t.ts, abortstr); |
||||
|
return ret; |
||||
|
} |
@ -0,0 +1,669 @@ |
|||||
|
/* Licensed under BSD-MIT - see LICENSE file for details */ |
||||
|
#ifndef CCAN_TIME_H |
||||
|
#define CCAN_TIME_H |
||||
|
#include "config.h" |
||||
|
#include <sys/time.h> |
||||
|
#if HAVE_STRUCT_TIMESPEC |
||||
|
#include <time.h> |
||||
|
#else |
||||
|
struct timespec { |
||||
|
time_t tv_sec; /* seconds */ |
||||
|
long tv_nsec; /* nanoseconds */ |
||||
|
}; |
||||
|
#endif |
||||
|
#include <stdint.h> |
||||
|
#include <stdbool.h> |
||||
|
|
||||
|
#ifdef DEBUG |
||||
|
#include <ccan/str/str.h> |
||||
|
#define TIME_CHECK(t) \ |
||||
|
time_check_((t), __FILE__ ":" stringify(__LINE__) " (" stringify(t) ") ") |
||||
|
#define TIMEREL_CHECK(t) \ |
||||
|
timerel_check((t), __FILE__ ":" stringify(__LINE__) " (" stringify(t) ") ") |
||||
|
#define TIMEABS_CHECK(t) \ |
||||
|
timeabs_check((t), __FILE__ ":" stringify(__LINE__) " (" stringify(t) ") ") |
||||
|
#else |
||||
|
#define TIME_CHECK(t) (t) |
||||
|
#define TIMEREL_CHECK(t) (t) |
||||
|
#define TIMEABS_CHECK(t) (t) |
||||
|
#endif |
||||
|
|
||||
|
/**
|
||||
|
* struct timerel - a relative time. |
||||
|
* @ts: the actual timespec value. |
||||
|
* |
||||
|
* For example, 1 second: ts.tv_sec = 1, ts.tv_nsec = 0 |
||||
|
*/ |
||||
|
struct timerel { |
||||
|
struct timespec ts; |
||||
|
}; |
||||
|
|
||||
|
/**
|
||||
|
* struct timeabs - an absolue time. |
||||
|
* @ts: the actual timespec value. |
||||
|
* |
||||
|
* For example, Midnight UTC January 1st, 1970: ts.tv_sec = 0, ts.tv_nsec = 0 |
||||
|
*/ |
||||
|
struct timeabs { |
||||
|
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 |
||||
|
#endif |
||||
|
|
||||
|
struct timespec time_check_(struct timespec in, const char *abortstr); |
||||
|
|
||||
|
/**
|
||||
|
* timerel_check - check if a relative time is malformed. |
||||
|
* @in: the relative 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 timerel 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("Time to calc this was %lu nanoseconds\n", |
||||
|
* (long)timerel_check(time_between(time_now(), time_now()), |
||||
|
* "time_now() failed?").ts.tv_nsec); |
||||
|
*/ |
||||
|
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) |
||||
|
* @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 timeabs 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 epoch\n", |
||||
|
* (long)timeabs_check(time_now(), "time_now failed?").ts.tv_sec); |
||||
|
*/ |
||||
|
struct timeabs timeabs_check(struct timeabs in, const char *abortstr); |
||||
|
|
||||
|
/**
|
||||
|
* time_now - return the current time |
||||
|
* |
||||
|
* Example: |
||||
|
* printf("Now is %lu seconds since epoch\n", (long)time_now().ts.tv_sec); |
||||
|
*/ |
||||
|
struct timeabs time_now(void); |
||||
|
|
||||
|
/**
|
||||
|
* time_mono - return the current monotonic time |
||||
|
* |
||||
|
* This value is only really useful for measuring time intervals. |
||||
|
* |
||||
|
* See also: |
||||
|
* time_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) |
||||
|
return true; |
||||
|
else if (a.tv_sec < b.tv_sec) |
||||
|
return false; |
||||
|
|
||||
|
return a.tv_nsec > b.tv_nsec; |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* time_after - is a after b? |
||||
|
* @a: one abstime. |
||||
|
* @b: another abstime. |
||||
|
* |
||||
|
* Example: |
||||
|
* static bool timed_out(const struct timeabs *start) |
||||
|
* { |
||||
|
* #define TIMEOUT time_from_msec(1000) |
||||
|
* return time_after(time_now(), timeabs_add(*start, TIMEOUT)); |
||||
|
* } |
||||
|
*/ |
||||
|
static inline bool time_after(struct timeabs a, struct timeabs b) |
||||
|
{ |
||||
|
return time_greater_(a.ts, b.ts); |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* time_greater - is a greater than b? |
||||
|
* @a: one reltime. |
||||
|
* @b: another reltime. |
||||
|
*/ |
||||
|
static inline bool time_greater(struct timerel a, struct timerel b) |
||||
|
{ |
||||
|
return time_greater_(a.ts, b.ts); |
||||
|
} |
||||
|
|
||||
|
static inline bool time_less_(struct timespec a, struct timespec b) |
||||
|
{ |
||||
|
if (TIME_CHECK(a).tv_sec < TIME_CHECK(b).tv_sec) |
||||
|
return true; |
||||
|
else if (a.tv_sec > b.tv_sec) |
||||
|
return false; |
||||
|
|
||||
|
return a.tv_nsec < b.tv_nsec; |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* time_before - is a before b? |
||||
|
* @a: one absolute time. |
||||
|
* @b: another absolute time. |
||||
|
* |
||||
|
* Example: |
||||
|
* static bool still_valid(const struct timeabs *start) |
||||
|
* { |
||||
|
* #define TIMEOUT time_from_msec(1000) |
||||
|
* return time_before(time_now(), timeabs_add(*start, TIMEOUT)); |
||||
|
* } |
||||
|
*/ |
||||
|
static inline bool time_before(struct timeabs a, struct timeabs b) |
||||
|
{ |
||||
|
return time_less_(a.ts, b.ts); |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* time_less - is a before b? |
||||
|
* @a: one relative time. |
||||
|
* @b: another relative time. |
||||
|
*/ |
||||
|
static inline bool time_less(struct timerel a, struct timerel b) |
||||
|
{ |
||||
|
return time_less_(a.ts, b.ts); |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* timeabs_eq - is a equal to b? |
||||
|
* @a: one absolute time. |
||||
|
* @b: another absolute time. |
||||
|
* |
||||
|
* Example: |
||||
|
* #include <sys/types.h> |
||||
|
* #include <sys/wait.h> |
||||
|
* |
||||
|
* // Can we fork in under a nanosecond?
|
||||
|
* static bool fast_fork(void) |
||||
|
* { |
||||
|
* struct timeabs start = time_now(); |
||||
|
* if (fork() != 0) { |
||||
|
* exit(0); |
||||
|
* } |
||||
|
* wait(NULL); |
||||
|
* return timeabs_eq(start, time_now()); |
||||
|
* } |
||||
|
*/ |
||||
|
static inline bool timeabs_eq(struct timeabs a, struct timeabs b) |
||||
|
{ |
||||
|
return TIMEABS_CHECK(a).ts.tv_sec == TIMEABS_CHECK(b).ts.tv_sec |
||||
|
&& a.ts.tv_nsec == b.ts.tv_nsec; |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* timerel_eq - is a equal to b? |
||||
|
* @a: one relative time. |
||||
|
* @b: another relative time. |
||||
|
* |
||||
|
* Example: |
||||
|
* #include <sys/types.h> |
||||
|
* #include <sys/wait.h> |
||||
|
* |
||||
|
* // Can we fork in under a nanosecond?
|
||||
|
* static bool fast_fork(void) |
||||
|
* { |
||||
|
* struct timeabs start = time_now(); |
||||
|
* struct timerel diff, zero = { .ts = { 0, 0 } }; |
||||
|
* if (fork() != 0) { |
||||
|
* exit(0); |
||||
|
* } |
||||
|
* wait(NULL); |
||||
|
* diff = time_between(time_now(), start); |
||||
|
* return timerel_eq(diff, zero); |
||||
|
* } |
||||
|
*/ |
||||
|
static inline bool timerel_eq(struct timerel a, struct timerel b) |
||||
|
{ |
||||
|
return TIMEREL_CHECK(a).ts.tv_sec == TIMEREL_CHECK(b).ts.tv_sec |
||||
|
&& a.ts.tv_nsec == b.ts.tv_nsec; |
||||
|
} |
||||
|
|
||||
|
static inline struct timespec time_sub_(struct timespec recent, |
||||
|
struct timespec old) |
||||
|
{ |
||||
|
struct timespec diff; |
||||
|
|
||||
|
diff.tv_sec = TIME_CHECK(recent).tv_sec - TIME_CHECK(old).tv_sec; |
||||
|
if (old.tv_nsec > recent.tv_nsec) { |
||||
|
diff.tv_sec--; |
||||
|
diff.tv_nsec = 1000000000 + recent.tv_nsec - old.tv_nsec; |
||||
|
} else |
||||
|
diff.tv_nsec = recent.tv_nsec - old.tv_nsec; |
||||
|
|
||||
|
return TIME_CHECK(diff); |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* time_sub - subtract two relative times |
||||
|
* @a: the larger time. |
||||
|
* @b: the smaller time. |
||||
|
* |
||||
|
* This returns a well formed struct timerel of @a - @b. |
||||
|
*/ |
||||
|
static inline struct timerel time_sub(struct timerel a, struct timerel b) |
||||
|
{ |
||||
|
struct timerel t; |
||||
|
|
||||
|
t.ts = time_sub_(a.ts, b.ts); |
||||
|
return t; |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* time_between - time between two absolute times |
||||
|
* @recent: the larger time. |
||||
|
* @old: the smaller time. |
||||
|
* |
||||
|
* This returns a well formed struct timerel of @a - @b. |
||||
|
*/ |
||||
|
static inline struct timerel time_between(struct timeabs recent, struct timeabs old) |
||||
|
{ |
||||
|
struct timerel t; |
||||
|
|
||||
|
t.ts = time_sub_(recent.ts, old.ts); |
||||
|
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; |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* timeabs_sub - subtract a relative time from an absolute time |
||||
|
* @abs: the absolute time. |
||||
|
* @rel: the relative time. |
||||
|
* |
||||
|
* This returns a well formed struct timeabs of @a - @b. |
||||
|
* |
||||
|
* Example: |
||||
|
* // We do one every second.
|
||||
|
* static struct timeabs previous_time(void) |
||||
|
* { |
||||
|
* return timeabs_sub(time_now(), time_from_msec(1000)); |
||||
|
* } |
||||
|
*/ |
||||
|
static inline struct timeabs timeabs_sub(struct timeabs abs, struct timerel rel) |
||||
|
{ |
||||
|
struct timeabs t; |
||||
|
|
||||
|
t.ts = time_sub_(abs.ts, rel.ts); |
||||
|
return t; |
||||
|
} |
||||
|
|
||||
|
static inline struct timespec time_add_(struct timespec a, struct timespec b) |
||||
|
{ |
||||
|
struct timespec sum; |
||||
|
|
||||
|
sum.tv_sec = TIME_CHECK(a).tv_sec + TIME_CHECK(b).tv_sec; |
||||
|
sum.tv_nsec = a.tv_nsec + b.tv_nsec; |
||||
|
if (sum.tv_nsec >= 1000000000) { |
||||
|
sum.tv_sec++; |
||||
|
sum.tv_nsec -= 1000000000; |
||||
|
} |
||||
|
return TIME_CHECK(sum); |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* timeabs_add - add a relative to an absolute time |
||||
|
* @a: the absolute time. |
||||
|
* @b: a relative time. |
||||
|
* |
||||
|
* The times must not overflow, or the results are undefined. |
||||
|
* |
||||
|
* Example: |
||||
|
* // We do one every second.
|
||||
|
* static struct timeabs next_time(void) |
||||
|
* { |
||||
|
* return timeabs_add(time_now(), time_from_msec(1000)); |
||||
|
* } |
||||
|
*/ |
||||
|
static inline struct timeabs timeabs_add(struct timeabs a, struct timerel b) |
||||
|
{ |
||||
|
struct timeabs t; |
||||
|
|
||||
|
t.ts = time_add_(a.ts, b.ts); |
||||
|
return t; |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* timerel_add - add two relative times |
||||
|
* @a: one relative time. |
||||
|
* @b: another relative time. |
||||
|
* |
||||
|
* The times must not overflow, or the results are undefined. |
||||
|
* |
||||
|
* Example: |
||||
|
* static struct timerel double_time(struct timerel a) |
||||
|
* { |
||||
|
* return timerel_add(a, a); |
||||
|
* } |
||||
|
*/ |
||||
|
static inline struct timerel timerel_add(struct timerel a, struct timerel b) |
||||
|
{ |
||||
|
struct timerel t; |
||||
|
|
||||
|
t.ts = time_add_(a.ts, b.ts); |
||||
|
return t; |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* time_divide - divide a time by a value. |
||||
|
* @t: a time. |
||||
|
* @div: number to divide it by. |
||||
|
* |
||||
|
* Example: |
||||
|
* // How long does it take to do a fork?
|
||||
|
* static struct timerel forking_time(void) |
||||
|
* { |
||||
|
* struct timeabs start = time_now(); |
||||
|
* unsigned int i; |
||||
|
* |
||||
|
* for (i = 0; i < 1000; i++) { |
||||
|
* if (fork() != 0) { |
||||
|
* exit(0); |
||||
|
* } |
||||
|
* wait(NULL); |
||||
|
* } |
||||
|
* return time_divide(time_between(time_now(), start), i); |
||||
|
* } |
||||
|
*/ |
||||
|
struct timerel time_divide(struct timerel t, unsigned long div); |
||||
|
|
||||
|
/**
|
||||
|
* time_multiply - multiply a time by a value. |
||||
|
* @t: a relative time. |
||||
|
* @mult: number to multiply it by. |
||||
|
* |
||||
|
* Example: |
||||
|
* ... |
||||
|
* printf("Time to do 100000 forks would be %u sec\n", |
||||
|
* (unsigned)time_multiply(forking_time(), 1000000).ts.tv_sec); |
||||
|
*/ |
||||
|
struct timerel time_multiply(struct timerel t, unsigned long mult); |
||||
|
|
||||
|
/**
|
||||
|
* time_to_sec - return number of seconds |
||||
|
* @t: a time |
||||
|
* |
||||
|
* It's often more convenient to deal with time values as seconds. |
||||
|
* Note that this will fit into an unsigned 32-bit variable if it's a |
||||
|
* time of less than about 136 years. |
||||
|
* |
||||
|
* Example: |
||||
|
* ... |
||||
|
* printf("Forking time is %u sec\n", |
||||
|
* (unsigned)time_to_sec(forking_time())); |
||||
|
*/ |
||||
|
static inline uint64_t time_to_sec(struct timerel t) |
||||
|
{ |
||||
|
return t.ts.tv_sec; |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* time_to_msec - return number of milliseconds |
||||
|
* @t: a relative time |
||||
|
* |
||||
|
* It's often more convenient to deal with time values as |
||||
|
* milliseconds. Note that this will fit into a 32-bit variable if |
||||
|
* it's a time difference of less than ~7 weeks. |
||||
|
* |
||||
|
* Example: |
||||
|
* ... |
||||
|
* printf("Forking time is %u msec\n", |
||||
|
* (unsigned)time_to_msec(forking_time())); |
||||
|
*/ |
||||
|
static inline uint64_t time_to_msec(struct timerel t) |
||||
|
{ |
||||
|
uint64_t msec; |
||||
|
|
||||
|
msec = TIMEREL_CHECK(t).ts.tv_nsec/1000000 + (uint64_t)t.ts.tv_sec*1000; |
||||
|
return msec; |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* time_to_usec - return number of microseconds |
||||
|
* @t: a relative time |
||||
|
* |
||||
|
* It's often more convenient to deal with time values as |
||||
|
* microseconds. Note that this will fit into a 32-bit variable if |
||||
|
* it's a time difference of less than ~1 hour. |
||||
|
* |
||||
|
* Example: |
||||
|
* ... |
||||
|
* printf("Forking time is %u usec\n", |
||||
|
* (unsigned)time_to_usec(forking_time())); |
||||
|
* |
||||
|
*/ |
||||
|
static inline uint64_t time_to_usec(struct timerel t) |
||||
|
{ |
||||
|
uint64_t usec; |
||||
|
|
||||
|
usec = TIMEREL_CHECK(t).ts.tv_nsec/1000 + (uint64_t)t.ts.tv_sec*1000000; |
||||
|
return usec; |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* time_to_nsec - return number of nanoseconds |
||||
|
* @t: a relative time |
||||
|
* |
||||
|
* It's sometimes more convenient to deal with time values as |
||||
|
* nanoseconds. Note that this will fit into a 32-bit variable if |
||||
|
* it's a time difference of less than ~4 seconds. |
||||
|
* |
||||
|
* Example: |
||||
|
* ... |
||||
|
* printf("Forking time is %u nsec\n", |
||||
|
* (unsigned)time_to_nsec(forking_time())); |
||||
|
* |
||||
|
*/ |
||||
|
static inline uint64_t time_to_nsec(struct timerel t) |
||||
|
{ |
||||
|
uint64_t nsec; |
||||
|
|
||||
|
nsec = TIMEREL_CHECK(t).ts.tv_nsec + (uint64_t)t.ts.tv_sec * 1000000000; |
||||
|
return nsec; |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* time_from_sec - convert seconds to a relative time |
||||
|
* @msec: time in seconds |
||||
|
* |
||||
|
* Example: |
||||
|
* // 1 minute timeout
|
||||
|
* #define TIMEOUT time_from_sec(60) |
||||
|
*/ |
||||
|
static inline struct timerel time_from_sec(uint64_t sec) |
||||
|
{ |
||||
|
struct timerel t; |
||||
|
|
||||
|
t.ts.tv_nsec = 0; |
||||
|
t.ts.tv_sec = sec; |
||||
|
return TIMEREL_CHECK(t); |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* time_from_msec - convert milliseconds to a relative time |
||||
|
* @msec: time in milliseconds |
||||
|
* |
||||
|
* Example: |
||||
|
* // 1/2 second timeout
|
||||
|
* #define TIMEOUT time_from_msec(500) |
||||
|
*/ |
||||
|
static inline struct timerel time_from_msec(uint64_t msec) |
||||
|
{ |
||||
|
struct timerel t; |
||||
|
|
||||
|
t.ts.tv_nsec = (msec % 1000) * 1000000; |
||||
|
t.ts.tv_sec = msec / 1000; |
||||
|
return TIMEREL_CHECK(t); |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* time_from_usec - convert microseconds to a relative time |
||||
|
* @usec: time in microseconds |
||||
|
* |
||||
|
* Example: |
||||
|
* // 1/2 second timeout
|
||||
|
* #define TIMEOUT time_from_usec(500000) |
||||
|
*/ |
||||
|
static inline struct timerel time_from_usec(uint64_t usec) |
||||
|
{ |
||||
|
struct timerel t; |
||||
|
|
||||
|
t.ts.tv_nsec = (usec % 1000000) * 1000; |
||||
|
t.ts.tv_sec = usec / 1000000; |
||||
|
return TIMEREL_CHECK(t); |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* time_from_nsec - convert nanoseconds to a relative time |
||||
|
* @nsec: time in nanoseconds |
||||
|
* |
||||
|
* Example: |
||||
|
* // 1/2 second timeout
|
||||
|
* #define TIMEOUT time_from_nsec(500000000) |
||||
|
*/ |
||||
|
static inline struct timerel time_from_nsec(uint64_t nsec) |
||||
|
{ |
||||
|
struct timerel t; |
||||
|
|
||||
|
t.ts.tv_nsec = nsec % 1000000000; |
||||
|
t.ts.tv_sec = nsec / 1000000000; |
||||
|
return TIMEREL_CHECK(t); |
||||
|
} |
||||
|
|
||||
|
static inline struct timeval timespec_to_timeval(struct timespec ts) |
||||
|
{ |
||||
|
struct timeval tv; |
||||
|
tv.tv_sec = ts.tv_sec; |
||||
|
tv.tv_usec = ts.tv_nsec / 1000; |
||||
|
return tv; |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* timerel_to_timeval - convert a relative time to a timeval. |
||||
|
* @t: a relative time. |
||||
|
* |
||||
|
* Example: |
||||
|
* struct timerel t = { { 100, 0 } }; // 100 seconds
|
||||
|
* struct timeval tv; |
||||
|
* |
||||
|
* tv = timerel_to_timeval(t); |
||||
|
* printf("time = %lu.%06u\n", (long)tv.tv_sec, (int)tv.tv_usec); |
||||
|
*/ |
||||
|
static inline struct timeval timerel_to_timeval(struct timerel t) |
||||
|
{ |
||||
|
return timespec_to_timeval(t.ts); |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* timeabs_to_timeval - convert an absolute time to a timeval. |
||||
|
* @t: an absolute time. |
||||
|
* |
||||
|
* Example: |
||||
|
* struct timeval tv; |
||||
|
* |
||||
|
* tv = timeabs_to_timeval(time_now()); |
||||
|
* printf("time = %lu.%06u\n", (long)tv.tv_sec, (int)tv.tv_usec); |
||||
|
*/ |
||||
|
static inline struct timeval timeabs_to_timeval(struct timeabs t) |
||||
|
{ |
||||
|
return timespec_to_timeval(t.ts); |
||||
|
} |
||||
|
|
||||
|
static inline struct timespec timeval_to_timespec(struct timeval tv) |
||||
|
{ |
||||
|
struct timespec ts; |
||||
|
ts.tv_sec = tv.tv_sec; |
||||
|
ts.tv_nsec = tv.tv_usec * 1000; |
||||
|
return ts; |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* timeval_to_timerel - convert a timeval to a relative time. |
||||
|
* @tv: a timeval. |
||||
|
* |
||||
|
* Example: |
||||
|
* struct timeval tv = { 0, 500 }; |
||||
|
* struct timerel t; |
||||
|
* |
||||
|
* t = timeval_to_timerel(tv); |
||||
|
* printf("timerel = %lu.%09lu\n", (long)t.ts.tv_sec, (long)t.ts.tv_nsec); |
||||
|
*/ |
||||
|
static inline struct timerel timeval_to_timerel(struct timeval tv) |
||||
|
{ |
||||
|
struct timerel t; |
||||
|
t.ts = timeval_to_timespec(tv); |
||||
|
return TIMEREL_CHECK(t); |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* timeval_to_timeabs - convert a timeval to an absolute time. |
||||
|
* @tv: a timeval. |
||||
|
* |
||||
|
* Example: |
||||
|
* struct timeval tv = { 1401762008, 500 }; |
||||
|
* struct timeabs t; |
||||
|
* |
||||
|
* t = timeval_to_timeabs(tv); |
||||
|
* printf("timeabs = %lu.%09lu\n", (long)t.ts.tv_sec, (long)t.ts.tv_nsec); |
||||
|
*/ |
||||
|
static inline struct timeabs timeval_to_timeabs(struct timeval tv) |
||||
|
{ |
||||
|
struct timeabs t; |
||||
|
t.ts = timeval_to_timespec(tv); |
||||
|
return TIMEABS_CHECK(t); |
||||
|
} |
||||
|
#endif /* CCAN_TIME_H */ |
Loading…
Reference in new issue