From e349ec2435a094bbb9f053bb8fbe3bb7f43bb466 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 8 Apr 2014 21:31:12 +1000 Subject: [PATCH] Add a slew of timer helper functions to libckpool --- configure.ac | 2 +- src/ckpool.h | 3 + src/libckpool.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++- src/libckpool.h | 22 +++++- 4 files changed, 198 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 46a09ff5..f9db932c 100644 --- a/configure.ac +++ b/configure.ac @@ -32,7 +32,7 @@ AC_FUNC_ALLOCA PKG_PROG_PKG_CONFIG() AC_CHECK_HEADERS(stdio.h stdlib.h fcntl.h sys/time.h unistd.h) -AC_CHECK_HEADERS(ctype.h errno.h byteswap.h string.h) +AC_CHECK_HEADERS(ctype.h errno.h byteswap.h string.h time.h) AC_CHECK_HEADERS(endian.h sys/endian.h arpa/inet.h) AC_CHECK_HEADERS(alloca.h pthread.h) AC_CHECK_HEADERS(sys/types.h sys/socket.h) diff --git a/src/ckpool.h b/src/ckpool.h index 5be7fb14..017525d1 100644 --- a/src/ckpool.h +++ b/src/ckpool.h @@ -70,6 +70,9 @@ /* Typedefs are evil but we use this one so often... */ typedef unsigned char uchar; +typedef struct timeval tv_t; +typedef struct timespec ts_t; + static inline void swap_256(void *dest_p, const void *src_p) { uint32_t *dest = dest_p; diff --git a/src/libckpool.c b/src/libckpool.c index e9f78aa4..ff502a58 100644 --- a/src/libckpool.c +++ b/src/libckpool.c @@ -18,6 +18,9 @@ #include #include #include +#include +#include +#include #include "ckpool.h" #include "libckpool.h" @@ -160,7 +163,7 @@ void b58tobin(uchar *b58bin, const uchar *b58) } } -void address_to_pubkeyhash(uchar *pkh, const uchar *addr) +void address_to_pubkeytxn(uchar *pkh, const uchar *addr) { uchar b58bin[25]; @@ -192,3 +195,172 @@ int ser_number(uchar *s, int32_t val) s[0] = len++; return len; } + +/* For testing a le encoded 256 byte hash against a target */ +bool fulltest(const uchar *hash, const uchar *target) +{ + uint32_t *hash32 = (uint32_t *)hash; + uint32_t *target32 = (uint32_t *)target; + bool ret = true; + int i; + + for (i = 28 / 4; i >= 0; i--) { + uint32_t h32tmp = le32toh(hash32[i]); + uint32_t t32tmp = le32toh(target32[i]); + + if (h32tmp > t32tmp) { + ret = false; + break; + } + if (h32tmp < t32tmp) { + ret = true; + break; + } + } + return ret; +} + +void copy_tv(tv_t *dest, const tv_t *src) +{ + memcpy(dest, src, sizeof(tv_t)); +} + +void ts_to_tv(tv_t *val, const ts_t *spec) +{ + val->tv_sec = spec->tv_sec; + val->tv_usec = spec->tv_nsec / 1000; +} + +void tv_to_ts(ts_t *spec, const tv_t *val) +{ + spec->tv_sec = val->tv_sec; + spec->tv_nsec = val->tv_usec * 1000; +} + +void us_to_tv(tv_t *val, int64_t us) +{ + lldiv_t tvdiv = lldiv(us, 1000000); + + val->tv_sec = tvdiv.quot; + val->tv_usec = tvdiv.rem; +} + +void us_to_ts(ts_t *spec, int64_t us) +{ + lldiv_t tvdiv = lldiv(us, 1000000); + + spec->tv_sec = tvdiv.quot; + spec->tv_nsec = tvdiv.rem * 1000; +} + +void ms_to_ts(ts_t *spec, int64_t ms) +{ + lldiv_t tvdiv = lldiv(ms, 1000); + + spec->tv_sec = tvdiv.quot; + spec->tv_nsec = tvdiv.rem * 1000000; +} + +void ms_to_tv(tv_t *val, int64_t ms) +{ + lldiv_t tvdiv = lldiv(ms, 1000); + + val->tv_sec = tvdiv.quot; + val->tv_usec = tvdiv.rem * 1000; +} + +void tv_time(tv_t *tv) +{ + gettimeofday(tv, NULL); +} + +void ts_time(ts_t *ts) +{ + clock_gettime(CLOCK_MONOTONIC, ts); +} + +void cksleep_prepare_r(ts_t *ts) +{ + ts_time(ts); +} + +void nanosleep_abstime(ts_t *ts_end) +{ + int ret; + + do { + ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, ts_end, NULL); + } while (ret == EINTR); +} + +void timeraddspec(ts_t *a, const ts_t *b) +{ + a->tv_sec += b->tv_sec; + a->tv_nsec += b->tv_nsec; + if (a->tv_nsec >= 1000000000) { + a->tv_nsec -= 1000000000; + a->tv_sec++; + } +} + +/* Reentrant version of cksleep functions allow start time to be set separately + * from the beginning of the actual sleep, allowing scheduling delays to be + * counted in the sleep. */ +void cksleep_ms_r(ts_t *ts_start, int ms) +{ + ts_t ts_end; + + ms_to_ts(&ts_end, ms); + timeraddspec(&ts_end, ts_start); + nanosleep_abstime(&ts_end); +} + +void cksleep_us_r(ts_t *ts_start, int64_t us) +{ + ts_t ts_end; + + us_to_ts(&ts_end, us); + timeraddspec(&ts_end, ts_start); + nanosleep_abstime(&ts_end); +} + +void cksleep_ms(int ms) +{ + ts_t ts_start; + + cksleep_prepare_r(&ts_start); + cksleep_ms_r(&ts_start, ms); +} + +void cksleep_us(int64_t us) +{ + ts_t ts_start; + + cksleep_prepare_r(&ts_start); + cksleep_us_r(&ts_start, us); +} + +/* Returns the microseconds difference between end and start times as a double */ +double us_tvdiff(tv_t *end, tv_t *start) +{ + /* Sanity check. We should only be using this for small differences so + * limit the max to 60 seconds. */ + if (unlikely(end->tv_sec - start->tv_sec > 60)) + return 60000000; + return (end->tv_sec - start->tv_sec) * 1000000 + (end->tv_usec - start->tv_usec); +} + +/* Returns the milliseconds difference between end and start times */ +int ms_tvdiff(tv_t *end, tv_t *start) +{ + /* Like us_tdiff, limit to 1 hour. */ + if (unlikely(end->tv_sec - start->tv_sec > 3600)) + return 3600000; + return (end->tv_sec - start->tv_sec) * 1000 + (end->tv_usec - start->tv_usec) / 1000; +} + +/* Returns the seconds difference between end and start times as a double */ +double tvdiff(tv_t *end, tv_t *start) +{ + return end->tv_sec - start->tv_sec + (end->tv_usec - start->tv_usec) / 1000000.0; +} diff --git a/src/libckpool.h b/src/libckpool.h index a0b8cc76..7b7dadbf 100644 --- a/src/libckpool.h +++ b/src/libckpool.h @@ -20,7 +20,27 @@ void __bin2hex(uchar *s, const uchar *p, size_t len); void *bin2hex(const uchar *p, size_t len); bool hex2bin(uchar *p, const uchar *hexstr, size_t len); void b58tobin(uchar *b58bin, const uchar *b58); -void address_to_pubkeyhash(uchar *pkh, const uchar *addr); +void address_to_pubkeytxn(uchar *pkh, const uchar *addr); int ser_number(uchar *s, int32_t val); +bool fulltest(const uchar *hash, const uchar *target); +void copy_tv(tv_t *dest, const tv_t *src); +void ts_to_tv(tv_t *val, const ts_t *spec); +void tv_to_ts(ts_t *spec, const tv_t *val); +void us_to_tv(tv_t *val, int64_t us); +void us_to_ts(ts_t *spec, int64_t us); +void ms_to_ts(ts_t *spec, int64_t ms); +void ms_to_tv(tv_t *val, int64_t ms); +void tv_time(tv_t *tv); +void ts_time(ts_t *ts); +void cksleep_prepare_r(ts_t *ts); +void nanosleep_abstime(ts_t *ts_end); +void timeraddspec(ts_t *a, const ts_t *b); +void cksleep_ms_r(ts_t *ts_start, int ms); +void cksleep_us_r(ts_t *ts_start, int64_t us); +void cksleep_ms(int ms); +void cksleep_us(int64_t us); +double us_tvdiff(tv_t *end, tv_t *start); +int ms_tvdiff(tv_t *end, tv_t *start); +double tvdiff(tv_t *end, tv_t *start); #endif /* LIBCKPOOL_H */