mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
ccan: import time module.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
e97e8988f8
commit
4163935bbb
6
Makefile
6
Makefile
@ -86,7 +86,8 @@ CCAN_OBJS := \
|
||||
ccan-take.o \
|
||||
ccan-tal-grab_file.o \
|
||||
ccan-tal-str.o \
|
||||
ccan-tal.o
|
||||
ccan-tal.o \
|
||||
ccan-time.o
|
||||
|
||||
# For tests
|
||||
CCAN_EXTRA_OBJS := \
|
||||
@ -139,6 +140,7 @@ CCAN_HEADERS := \
|
||||
$(CCANDIR)/ccan/tal/tal.h \
|
||||
$(CCANDIR)/ccan/tal/talloc/talloc.h \
|
||||
$(CCANDIR)/ccan/tcon/tcon.h \
|
||||
$(CCANDIR)/ccan/time/time.h \
|
||||
$(CCANDIR)/ccan/typesafe_cb/typesafe_cb.h
|
||||
|
||||
TEST_CLI_HEADERS := test-cli/gather_updates.h
|
||||
@ -363,3 +365,5 @@ ccan-isaac.o: $(CCANDIR)/ccan/isaac/isaac.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
ccan-isaac64.o: $(CCANDIR)/ccan/isaac/isaac64.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
ccan-time.o: $(CCANDIR)/ccan/time/time.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
1
ccan/ccan/time/LICENSE
Symbolic link
1
ccan/ccan/time/LICENSE
Symbolic link
@ -0,0 +1 @@
|
||||
../../licenses/BSD-MIT
|
57
ccan/ccan/time/_info
Normal file
57
ccan/ccan/time/_info
Normal file
@ -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;
|
||||
}
|
204
ccan/ccan/time/test/run-check.c
Normal file
204
ccan/ccan/time/test/run-check.c
Normal file
@ -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();
|
||||
}
|
24
ccan/ccan/time/test/run-monotonic.c
Normal file
24
ccan/ccan/time/test/run-monotonic.c
Normal file
@ -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();
|
||||
}
|
163
ccan/ccan/time/test/run.c
Normal file
163
ccan/ccan/time/test/run.c
Normal file
@ -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();
|
||||
}
|
130
ccan/ccan/time/time.c
Normal file
130
ccan/ccan/time/time.c
Normal file
@ -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;
|
||||
}
|
669
ccan/ccan/time/time.h
Normal file
669
ccan/ccan/time/time.h
Normal file
@ -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
Block a user