mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 13:25:43 +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-take.o \
|
||||||
ccan-tal-grab_file.o \
|
ccan-tal-grab_file.o \
|
||||||
ccan-tal-str.o \
|
ccan-tal-str.o \
|
||||||
ccan-tal.o
|
ccan-tal.o \
|
||||||
|
ccan-time.o
|
||||||
|
|
||||||
# For tests
|
# For tests
|
||||||
CCAN_EXTRA_OBJS := \
|
CCAN_EXTRA_OBJS := \
|
||||||
@ -139,6 +140,7 @@ CCAN_HEADERS := \
|
|||||||
$(CCANDIR)/ccan/tal/tal.h \
|
$(CCANDIR)/ccan/tal/tal.h \
|
||||||
$(CCANDIR)/ccan/tal/talloc/talloc.h \
|
$(CCANDIR)/ccan/tal/talloc/talloc.h \
|
||||||
$(CCANDIR)/ccan/tcon/tcon.h \
|
$(CCANDIR)/ccan/tcon/tcon.h \
|
||||||
|
$(CCANDIR)/ccan/time/time.h \
|
||||||
$(CCANDIR)/ccan/typesafe_cb/typesafe_cb.h
|
$(CCANDIR)/ccan/typesafe_cb/typesafe_cb.h
|
||||||
|
|
||||||
TEST_CLI_HEADERS := test-cli/gather_updates.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 $@ $<
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
ccan-isaac64.o: $(CCANDIR)/ccan/isaac/isaac64.c
|
ccan-isaac64.o: $(CCANDIR)/ccan/isaac/isaac64.c
|
||||||
$(CC) $(CFLAGS) -c -o $@ $<
|
$(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