Commit df1d1855 authored by William Ahern's avatar William Ahern

sync refactoring work

parent f301bdf3
all: timer all: timer
CPPFLAGS = -DTIMER_DEBUG -DTIMER_MAIN WHEEL_BIT = 6
WHEEL_NUM = 4
CPPFLAGS = -DTIMER_DEBUG -DTIMER_MAIN -DWHEEL_BIT=$(WHEEL_BIT) -DWHEEL_NUM=$(WHEEL_NUM)
CFLAGS = -O2 -g -Wall -Wextra CFLAGS = -O2 -g -Wall -Wextra
......
...@@ -33,6 +33,8 @@ ...@@ -33,6 +33,8 @@
#include <sys/queue.h> #include <sys/queue.h>
#include <sys/param.h> #include <sys/param.h>
#include "timer.h"
/* /*
* D E B U G R O U T I N E S * D E B U G R O U T I N E S
...@@ -43,6 +45,8 @@ ...@@ -43,6 +45,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#undef TIMER_DEBUG
#define TIMER_DEBUG 1
#define DEBUG_LEVEL timer_debug #define DEBUG_LEVEL timer_debug
static int timer_debug; static int timer_debug;
...@@ -59,6 +63,8 @@ static int timer_debug; ...@@ -59,6 +63,8 @@ static int timer_debug;
_Exit(EXIT_FAILURE); \ _Exit(EXIT_FAILURE); \
} while (0) } while (0)
#else #else
#undef TIMER_DEBUG
#define TIMER_DEBUG 0
#define DEBUG_LEVEL 0 #define DEBUG_LEVEL 0
#define SAYit(...) (void)0 #define SAYit(...) (void)0
...@@ -115,6 +121,9 @@ static inline char *bin64_(char *buf, uint64_t n) { ...@@ -115,6 +121,9 @@ static inline char *bin64_(char *buf, uint64_t n) {
#define countof(a) (sizeof (a) / sizeof *(a)) #define countof(a) (sizeof (a) / sizeof *(a))
#define endof(a) (&(a)[countof(a)]) #define endof(a) (&(a)[countof(a)])
#if !defined MIN
#define MIN(a, b) (((a) < (b))? (a) : (b))
#endif
#define CIRCLEQ_CONCAT(head1, head2, field) do { \ #define CIRCLEQ_CONCAT(head1, head2, field) do { \
if (!CIRCLEQ_EMPTY(head2)) { \ if (!CIRCLEQ_EMPTY(head2)) { \
...@@ -136,7 +145,78 @@ static inline char *bin64_(char *buf, uint64_t n) { ...@@ -136,7 +145,78 @@ static inline char *bin64_(char *buf, uint64_t n) {
} while (0) } while (0)
static inline uint64_t rotl(const uint64_t v, int c) { /*
* B I T M A N I P U L A T I O N R O U T I N E S
*
* These routines implement wheel parameterization.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#define TIMER_BIT (sizeof (timer_t) * CHAR_BIT)
#if !defined WHEEL_BIT
#define WHEEL_BIT 6
#endif
#if !defined WHEEL_NUM
#define WHEEL_NUM 4
#endif
#define WHEEL_LEN (1U << WHEEL_BIT)
#define WHEEL_MAX (WHEEL_LEN - 1)
#define WHEEL_MASK (WHEEL_LEN - 1)
#define TIMEOUT_MAX ((TIMER_C(1) << (WHEEL_BIT * WHEEL_NUM)) - 1)
#if WHEEL_BIT == 6
#define WHEEL_C(n) UINT64_C(n)
#define WHEEL_PRIu PRIu64
#define WHEEL_PRIx PRIx64
typedef uint64_t wheel_t;
#define ctz(n) __builtin_ctzll(n)
#define fls(n) ((1 << WHEEL_BIT) - __builtin_clzll(n))
#elif WHEEL_BIT == 5
#define WHEEL_C(n) UINT32_C(n)
#define WHEEL_PRIu PRIu32
#define WHEEL_PRIx PRIx32
typedef uint32_t wheel_t;
#define ctz(n) __builtin_ctzl(n)
#define fls(n) ((1 << WHEEL_BIT) - __builtin_clzl(n))
#elif WHEEL_BIT == 4
#define WHEEL_C(n) UINT16_C(n)
#define WHEEL_PRIu PRIu16
#define WHEEL_PRIx PRIx16
typedef uint16_t wheel_t;
#define ctz(n) __builtin_ctz(n)
#define fls(n) ((1 << WHEEL_BIT) - __builtin_clz(n))
#elif WHEEL_BIT == 3
#define WHEEL_C(n) UINT8_C(n)
#define WHEEL_PRIu PRIu8
#define WHEEL_PRIx PRIx8
typedef uint8_t wheel_t;
#define ctz(n) __builtin_ctz(n)
#define fls(n) ((1 << WHEEL_BIT) - __builtin_clz(n))
#else
#error invalid WHEEL_BIT value
#endif
static inline wheel_t rotl(const wheel_t v, int c) {
if (!(c &= (sizeof v * CHAR_BIT - 1))) if (!(c &= (sizeof v * CHAR_BIT - 1)))
return v; return v;
...@@ -144,7 +224,7 @@ static inline uint64_t rotl(const uint64_t v, int c) { ...@@ -144,7 +224,7 @@ static inline uint64_t rotl(const uint64_t v, int c) {
} /* rotl() */ } /* rotl() */
static inline uint64_t rotr(const uint64_t v, int c) { static inline wheel_t rotr(const wheel_t v, int c) {
if (!(c &= (sizeof v * CHAR_BIT - 1))) if (!(c &= (sizeof v * CHAR_BIT - 1)))
return v; return v;
...@@ -152,66 +232,14 @@ static inline uint64_t rotr(const uint64_t v, int c) { ...@@ -152,66 +232,14 @@ static inline uint64_t rotr(const uint64_t v, int c) {
} /* rotr() */ } /* rotr() */
/* static inline int timeout_wheel(timeout_t timeout) {
* From http://groups.google.com/group/comp.lang.c/msg/0cef41f343f0e875. return (fls(MIN(timeout, TIMEOUT_MAX)) - 1) / WHEEL_BIT;
* } /* timeout_wheel() */
* The bitwise pattern 0x43147259a7abb7e can derive every permutation of 0
* to 2^6-1, each permutation overlapping bitwise in the pattern, offset by
* 1 bit. Multiplying by a power of 2 shifts one of the permutations into
* the high 6 bits of the word, which is then shifted down 58 bits and
* reduced modulo 2^6.
*
* The constant was found by brute force search with a sieve to quickly
* discard invalid patterns. The following program generates constants for
* mapping words of length 2^N (0 <= N <= 6), although it's not exhaustive.
* Decode with `sed -e 's/^ \* //' | uudecode -p | gunzip -c`.
*
* begin 644 -
* M'XL(`+J'&E$``\53VV[30!!]SG[%M%'3W=:T<5-%2$XL`4\(@9"@3S2*XAM=
* MD:PC7Q"H[;]S=G;=NB$2[1-6K'CG<F;F[)FA-NFZS7*:U4VF37-V$]/Y"5V]
* M__1U>KE\1RUL^&CHY%P,^[%KG=C8IT9=6IL%V%9(+.1$V40AAEE>:)/3QS=?
* M/DB3Z*8.2"N24G:59*AH-B/G5(I>$0PCDEJI7O;G+GFS^JY3QK@6Y)\^.)`Y
* M!/49@^(8MG"G1/>)&D+4S:K1*2W?EN6:RA^KWS(M3=T\4N!K.BN,Y++I5@P>
* M8NH\-S2G<4`)FHR$&!1EA0X0K:T]PA]:X$9<.BRGIPPR2!"QP\??(^\$:!4A
* M4Q<DN?2($H7SH,J;MC*HAP,[[N:4X'"/CKPOC,2]O2H>U=^3Y^!GJ3/4V[Z`
* M`7M"QK?IY>+Y4Z,YF_.,(1>`T2\"]@H\I*,L.`RX-[U0%F+;-NG-JI+'U^98
* M>1+LL'LX@.PRN7_\!VM1MB;[ARPV@65?\#TQ"L4TIM'(D>]Q.UW>]KH?_SHZ
* M>\TOS6/"'-S-Y&+9J`XHILF%ZCN<\"-'[E-P:W37[[6P`8L.![NVNXQ^$+N*
* M"-^CSDTWTX%,`,!,*$L^\^9P$18&SD5W=BNZ3E"<`Z#,,/J_K;`$.-!KP*E9
* >&VE5P#?"7JPU?E-N_G'#O(`0[;+_`)GB4OE4!0``
* `
* end
*/
#define FFS64_HASH UINT64_C(0x43147259a7abb7e)
#define FFS64_MLEN 6
#define FFS64_INDEX(v) (((UINT64_C(1) << FFS64_MLEN) - 1) & ((((v) & -(v)) * FFS64_HASH) >> ((UINT64_C(1) << FFS64_MLEN) - FFS64_MLEN)))
static inline int ffs64(const uint64_t v) {
static const int map[] = {
63, 0, 1, 6, 2, 12, 7, 18, 3, 24, 13, 27, 8, 33, 19, 39,
4, 16, 25, 37, 14, 45, 28, 47, 9, 30, 34, 53, 20, 49, 40, 56,
62, 5, 11, 17, 23, 26, 32, 38, 15, 36, 44, 46, 29, 52, 48, 55,
61, 10, 22, 31, 35, 43, 51, 54, 60, 21, 42, 50, 59, 41, 58, 57,
};
return (v)? map[FFS64_INDEX(v)] + 1 : 0;
} /* ffs64() */
static inline int fls64(const uint64_t v) {
#if 0
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v |= v >> 32;
v++;
#endif
return (v)? ((sizeof v * CHAR_BIT) - 1) - __builtin_clzll(v) : 0; static inline int timer_slot(int wheel, timer_t expires) {
} /* fls64 */ return WHEEL_MASK & ((expires >> (wheel * WHEEL_BIT)) - !!wheel);
} /* timer_slot() */
/* /*
...@@ -224,15 +252,21 @@ CIRCLEQ_HEAD(timeouts, timeout); ...@@ -224,15 +252,21 @@ CIRCLEQ_HEAD(timeouts, timeout);
#define TIMEOUT_INITIALIZER { 0, 0, { 0, 0 } } #define TIMEOUT_INITIALIZER { 0, 0, { 0, 0 } }
struct timeout { struct timeout {
uint64_t expires; int flags;
timer_t expires;
struct timeouts *pending; struct timeouts *pending;
CIRCLEQ_ENTRY(timeout) cqe; CIRCLEQ_ENTRY(timeout) cqe;
}; /* struct timeout */ }; /* struct timeout */
static inline struct timeout *timeout_init(struct timeout *to) { struct timeout *timeout_init(struct timeout *to, int flags) {
return memset(to, 0, sizeof *to); memset(to, 0, sizeof *to);
to->flags = flags;
return to;
} /* timeout_init() */ } /* timeout_init() */
...@@ -241,34 +275,17 @@ static inline struct timeout *timeout_init(struct timeout *to) { ...@@ -241,34 +275,17 @@ static inline struct timeout *timeout_init(struct timeout *to) {
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#define PERIOD_BIT 6
#define PERIOD_LEN (1 << PERIOD_BIT)
#define PERIOD_MAX (PERIOD_LEN - 1)
#define PERIOD_NUM 4
#define PERIOD_MASK (PERIOD_LEN - 1)
#define ELAPSED_MAX ((UINT64_C(1) << (PERIOD_BIT * PERIOD_NUM)) - 1)
#define TIMEOUT_PERIOD(elapsed) (fls64(MIN(ELAPSED_MAX, elapsed)) / PERIOD_BIT)
#define TIMEOUT_MINUTE(period, curtime, elapsed) (PERIOD_MASK & (((curtime) >> ((period) * PERIOD_BIT)) + ((elapsed) >> ((period) * PERIOD_BIT))))
static uint64_t timeout_minute(uint64_t period, uint64_t expires) {
return PERIOD_MASK & ((expires >> (period * PERIOD_BIT)) - !!period);
} /* timeout_minute() */
#undef TIMEOUT_MINUTE
#define TIMEOUT_MINUTE(...) timeout_minute(__VA_ARGS__)
struct timer { struct timer {
struct timeouts wheel[4][64], expired; struct timeouts wheel[WHEEL_NUM][WHEEL_LEN], expired;
uint64_t pending[4]; wheel_t pending[WHEEL_NUM];
uint64_t curtime; timer_t curtime;
uint64_t hertz; timer_t hertz;
}; /* struct timer */ }; /* struct timer */
struct timer *timer_init(struct timer *T) { struct timer *timer_init(struct timer *T, timer_t hz) {
unsigned i, j; unsigned i, j;
for (i = 0; i < countof(T->wheel); i++) { for (i = 0; i < countof(T->wheel); i++) {
...@@ -284,6 +301,7 @@ struct timer *timer_init(struct timer *T) { ...@@ -284,6 +301,7 @@ struct timer *timer_init(struct timer *T) {
} }
T->curtime = 0; T->curtime = 0;
T->hertz = (hz)? hz : TIMER_mHZ;
return T; return T;
} /* timer_init() */ } /* timer_init() */
...@@ -293,10 +311,10 @@ void timer_del(struct timer *T, struct timeout *to) { ...@@ -293,10 +311,10 @@ void timer_del(struct timer *T, struct timeout *to) {
if (to->pending) { if (to->pending) {
if (to->pending != &T->expired && CIRCLEQ_EMPTY(to->pending)) { if (to->pending != &T->expired && CIRCLEQ_EMPTY(to->pending)) {
ptrdiff_t index = to->pending - &T->wheel[0][0]; ptrdiff_t index = to->pending - &T->wheel[0][0];
int period = index / 64; int wheel = index / WHEEL_LEN;
int minute = index % 64; int slot = index % WHEEL_LEN;
T->pending[period] &= ~(UINT64_C(1) << minute); T->pending[wheel] &= ~(WHEEL_C(1) << slot);
} }
CIRCLEQ_REMOVE(to->pending, to, cqe); CIRCLEQ_REMOVE(to->pending, to, cqe);
...@@ -305,14 +323,14 @@ void timer_del(struct timer *T, struct timeout *to) { ...@@ -305,14 +323,14 @@ void timer_del(struct timer *T, struct timeout *to) {
} /* timer_del() */ } /* timer_del() */
static inline uint64_t timer_rem(struct timer *T, struct timeout *to) { static inline timeout_t timer_rem(struct timer *T, struct timeout *to) {
return to->expires - T->curtime; return to->expires - T->curtime;
} /* timer_rem() */ } /* timer_rem() */
void timer_add(struct timer *T, struct timeout *to, uint64_t expires) { void timer_add(struct timer *T, struct timeout *to, timer_t expires) {
uint64_t rem; timeout_t rem;
unsigned period, minute; int wheel, slot;
timer_del(T, to); timer_del(T, to);
...@@ -321,16 +339,16 @@ void timer_add(struct timer *T, struct timeout *to, uint64_t expires) { ...@@ -321,16 +339,16 @@ void timer_add(struct timer *T, struct timeout *to, uint64_t expires) {
if (expires > T->curtime) { if (expires > T->curtime) {
rem = timer_rem(T, to); rem = timer_rem(T, to);
period = TIMEOUT_PERIOD(rem); wheel = timeout_wheel(rem);
minute = TIMEOUT_MINUTE(period, to->expires); slot = timer_slot(wheel, to->expires);
SAY("%llu rem:%llu period:%u (fls:%d) minute:%u", expires, timer_rem(T, to), period, fls64(timer_rem(T, to)), minute); SAY("%llu rem:%llu wheel:%d (fls:%d) slot:%d", expires, timer_rem(T, to), wheel, fls(timer_rem(T, to)) - 1, slot);
SAY("clock: %s", fmt(expires)); SAY("clock: %s", fmt(expires));
to->pending = &T->wheel[period][minute]; to->pending = &T->wheel[wheel][slot];
CIRCLEQ_INSERT_HEAD(to->pending, to, cqe); CIRCLEQ_INSERT_HEAD(to->pending, to, cqe);
T->pending[period] |= UINT64_C(1) << minute; T->pending[wheel] |= WHEEL_C(1) << slot;
} else { } else {
to->pending = &T->expired; to->pending = &T->expired;
CIRCLEQ_INSERT_HEAD(to->pending, to, cqe); CIRCLEQ_INSERT_HEAD(to->pending, to, cqe);
...@@ -338,56 +356,59 @@ void timer_add(struct timer *T, struct timeout *to, uint64_t expires) { ...@@ -338,56 +356,59 @@ void timer_add(struct timer *T, struct timeout *to, uint64_t expires) {
} /* timer_add() */ } /* timer_add() */
void timer_step(struct timer *T, uint64_t curtime) { void timeout_add(struct timer *T, struct timeout *to, timeout_t timeout) {
uint64_t elapsed = curtime - T->curtime; timer_add(T, to, T->curtime + timeout);
} /* timeout_add() */
void timer_step(struct timer *T, timer_t curtime) {
timeout_t elapsed = curtime - T->curtime;
struct timeouts todo; struct timeouts todo;
unsigned period; int wheel, slot;
wheel_t _elapsed;
CIRCLEQ_INIT(&todo); CIRCLEQ_INIT(&todo);
#if defined DEBUG_LEVEL
if (DEBUG_LEVEL > 1) {
fputc('\n', stderr);
SAY("== step =========================================");
SAY("%llu -> %llu", T->curtime, curtime);
SAY("%s -> %s", fmt(T->curtime), fmt(curtime));
}
#endif
for (period = 0; period < PERIOD_NUM; period++) {
uint64_t pending;
//SAY("newtime: %llu elapsed:%llu", curtime, elapsed); SAY("\n");
SAY("-- period (%u) -----------------------------------", period); SAY("== step =========================================");
if ((elapsed >> (period * PERIOD_BIT)) > PERIOD_MAX) { SAY("%" TIMER_PRIu " -> %" TIMER_PRIu, T->curtime, curtime);
pending = ~UINT64_C(0); SAY("%s -> %s", fmt(T->curtime), fmt(curtime));
for (wheel = 0; wheel < WHEEL_NUM; wheel++) {
wheel_t pending;
SAYit(2, "-- wheel (%u) ------------------------------------", wheel);
if ((elapsed >> (wheel * WHEEL_BIT)) > WHEEL_MAX) {
pending = ~WHEEL_C(0);
} else { } else {
uint64_t _elapsed = PERIOD_MASK & (elapsed >> (period * PERIOD_BIT)); _elapsed = WHEEL_MASK & (elapsed >> (wheel * WHEEL_BIT));
uint64_t _minute = PERIOD_MASK & (T->curtime >> (period * PERIOD_BIT));
SAY("period:%u _elapsed:%llu _minute:%llu", period, _elapsed, _minute); slot = WHEEL_MASK & (T->curtime >> (wheel * WHEEL_BIT));
// pending = rotl(rotl(((UINT64_C(1) << (_elapsed + 1)) - 1), TIMEOUT_MINUTE(period, T->curtime)), 1); SAYit(2, "wheel:%u _elapsed:%llu slot:%d", wheel, _elapsed, slot);
// pending = rotl(((UINT64_C(1) << _elapsed) - 1)|1, TIMEOUT_MINUTE(period, curtime)); pending = rotl(((UINT64_C(1) << _elapsed) - 1), slot);
pending = rotl(((UINT64_C(1) << _elapsed) - 1), _minute);
uint64_t _minute1 = PERIOD_MASK & (curtime >> (period * PERIOD_BIT)); slot = WHEEL_MASK & (curtime >> (wheel * WHEEL_BIT));
SAY("_minute1: %llu", _minute1); SAYit(2, "slot: %d", slot);
pending |= UINT64_C(1) << _minute1; pending |= WHEEL_C(1) << slot;
pending |= rotr(rotl(((UINT64_C(1) << _elapsed) - 1), _minute1), _elapsed); pending |= rotr(rotl(((WHEEL_C(1) << _elapsed) - 1), slot), _elapsed);
SAYit(2, "rotl:%.8x%.8x pending:%.8x%.8x", (unsigned)(((UINT64_C(1) << _elapsed) - 1) >> 32), (unsigned)((UINT64_C(1) << _elapsed) - 1), (unsigned)(pending >> 32), (unsigned)pending); SAYit(2, "rotl:%.*" TIMEOUT_PRIx " pending:%.*" WHEEL_PRIx, (int)(sizeof _elapsed * CHAR_BIT / 4), ((TIMEOUT_C(1) << _elapsed) - 1), (int)(sizeof pending * CHAR_BIT / 4), pending);
} }
SAYit(2, "pending:%.8x%.8x & populated:%.8x%.8x", (unsigned)(pending >> 32), (unsigned)pending, (unsigned)(T->pending[period] >> 32), (unsigned)T->pending[period]); SAYit(2, "pending : %s", bin64(pending));
SAYit(2, "pending : %s", bin64(pending)); SAYit(2, "populated : %s", bin64(T->pending[wheel]));
SAYit(2, "populated : %s", bin64(T->pending[period]));
while (pending & T->pending[period]) { while (pending & T->pending[wheel]) {
int minute = ffs64(pending & T->pending[period]) - 1; int slot = ctz(pending & T->pending[wheel]);
CIRCLEQ_CONCAT(&todo, &T->wheel[period][minute], cqe); CIRCLEQ_CONCAT(&todo, &T->wheel[wheel][slot], cqe);
T->pending[period] &= ~(UINT64_C(1) << minute); T->pending[wheel] &= ~(UINT64_C(1) << slot);
} }
// if (!((UINT64_C(1) << 63) & pending))
if (!(0x1 & pending)) if (!(0x1 & pending))
break; /* break if we didn't reach end of period */ break; /* break if we didn't reach end of wheel */
/* if we're continuing, the next period must tick at least once */ /* if we're continuing, the next wheel must tick at least once */
elapsed = MAX(elapsed, (UINT64_C(64) << (period * PERIOD_BIT))); elapsed = MAX(elapsed, (WHEEL_LEN << (wheel * WHEEL_BIT)));
} }
T->curtime = curtime; T->curtime = curtime;
...@@ -405,13 +426,51 @@ SAYit(2, "populated : %s", bin64(T->pending[period])); ...@@ -405,13 +426,51 @@ SAYit(2, "populated : %s", bin64(T->pending[period]));
} /* timer_step() */ } /* timer_step() */
struct timeout *timer_expired(struct timer *T) { bool timer_pending(struct timer *T) {
wheel_t pending = 0;
int wheel;
for (wheel = 0; wheel < WHEEL_NUM; wheel++) {
pending |= T->pending[wheel];
}
return !!pending;
} /* timer_pending() */
timeout_t timer_timeout(struct timer *T) {
timeout_t timeout = ~TIMEOUT_C(0), _timeout;
timer_t relmask;
int wheel, slot;
if (!CIRCLEQ_EMPTY(&T->expired))
return 0;
relmask = 0;
for (wheel = 0; wheel < WHEEL_NUM; wheel++) {
if (T->pending[wheel]) {
slot = WHEEL_MASK & (T->curtime >> (wheel * WHEEL_BIT));
_timeout = (ctz(rotr(T->pending[wheel], slot)) + !!wheel) << (wheel * WHEEL_BIT);
_timeout -= relmask & T->curtime;
timeout = MIN(_timeout, timeout);
}
relmask <<= WHEEL_BIT;
relmask |= WHEEL_MASK;
}
return timeout;
} /* timer_timeout() */
struct timeout *timer_get(struct timer *T) {
if (!CIRCLEQ_EMPTY(&T->expired)) { if (!CIRCLEQ_EMPTY(&T->expired)) {
return CIRCLEQ_FIRST(&T->expired); return CIRCLEQ_FIRST(&T->expired);
} else { } else {
return 0; return 0;
} }
} /* timer_expired() */ } /* timer_get() */
#if TIMER_MAIN - 0 #if TIMER_MAIN - 0
...@@ -420,6 +479,28 @@ struct timeout *timer_expired(struct timer *T) { ...@@ -420,6 +479,28 @@ struct timeout *timer_expired(struct timer *T) {
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
static timer_t timer_min(struct timer *T) {
struct timeout *to, *min = NULL;
unsigned i, j;
for (i = 0; i < countof(T->wheel); i++) {
for (j = 0; j < countof(T->wheel[i]); j++) {
CIRCLEQ_FOREACH(to, &T->wheel[i][j], cqe) {
if (!min || min->expires > to->expires)
min = to;
}
}
}
return (min)? min->expires : 0;
} /* timer_min() */
static inline timeout_t slow_timeout(struct timer *T) {
return timer_min(T) - T->curtime;
} /* slow_timeout() */
int main(int argc, char **argv) { int main(int argc, char **argv) {
extern int optind; extern int optind;
extern char *optarg; extern char *optarg;
...@@ -457,23 +538,22 @@ int main(int argc, char **argv) { ...@@ -457,23 +538,22 @@ int main(int argc, char **argv) {
argc -= optind; argc -= optind;
argv += optind; argv += optind;
timer_init(&T); timer_init(&T, TIMER_mHZ);
timer_step(&T, time); timer_step(&T, time);
timer_add(&T, timeout_init(&to[0]), time + 62); count++; timer_add(&T, timeout_init(&to[0], 0), time + 62); count++;
timer_add(&T, timeout_init(&to[1]), time + 63); count++; timer_add(&T, timeout_init(&to[1], 0), time + 63); count++;
timer_add(&T, timeout_init(&to[2]), time + 64); count++; timer_add(&T, timeout_init(&to[2], 0), time + 64); count++;
timer_add(&T, timeout_init(&to[3]), time + 65); count++; timer_add(&T, timeout_init(&to[3], 0), time + 65); count++;
// timer_add(&T, timeout_init(&to[4]), 100); count++; timer_add(&T, timeout_init(&to[5], 0), time + 192); count++;
timer_add(&T, timeout_init(&to[5]), time + 192); count++;
// timer_add(&T, timeout_init(&to[6]), 65536); count++;
// timer_add(&T, timeout_init(&to[7]), 65535 + 62); count++;
while (count > 0 && time <= stop - 1) { while (count > 0 && time <= stop - 1) {
time += step; time += step;
//printf("step: %llu\n", time); //printf("step: %llu\n", time);
SAY("timeout -> %" TIMEOUT_PRIu " (actual:%" TIMEOUT_PRIu " curtime:%" TIMER_PRIu ")", timer_timeout(&T), slow_timeout(&T), T.curtime);
timer_step(&T, time); timer_step(&T, time);
//SAY("timeout <- %" TIMEOUT_PRIu " (curtime:%" TIMER_PRIu ")", timer_timeout(&T), T.curtime);
while ((expired = timer_expired(&T))) { while ((expired = timer_get(&T))) {
timer_del(&T, expired); timer_del(&T, expired);
SAY("step %llu expired %llu @@@@@@@@@@@@@@@@@@@@", time, expired->expires); SAY("step %llu expired %llu @@@@@@@@@@@@@@@@@@@@", time, expired->expires);
count--; count--;
......
...@@ -26,7 +26,8 @@ ...@@ -26,7 +26,8 @@
#ifndef TIMER_H #ifndef TIMER_H
#define TIMER_H #define TIMER_H
#include <stdint.h> /* uint64_t */ #include <stdbool.h> /* bool */
#include <inttypes.h> /* PRIu64 PRIx64 PRIX64 uint64_t */
/* /*
...@@ -34,7 +35,51 @@ ...@@ -34,7 +35,51 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#define TIMER_mHZ TIMER_C(1000)
#define TIMER_uHZ TIMER_C(1000000)
#define TIMER_nHZ TIMER_C(1000000000)
#define TIMER_C(n) UINT64_C(n)
#define TIMER_PRIu PRIu64
#define TIMER_PRIx PRIx64
#define TIMER_PRIX PRIX64
#define TIMEOUT_C(n) TIMER_C(n)
#define TIMEOUT_PRIu TIMER_PRIu
#define TIMEOUT_PRIx TIMER_PRIx
#define TIMEOUT_PRIX TIMER_PRIX
typedef uint64_t timer_t; /* absolute times */
typedef timer_t timeout_t; /* relative times */
struct timer; struct timer;
struct timeout;
void timer_add(struct timer *, struct timeout *, timeout_t);
void timer_del(struct timer *, struct timeout *);
bool timer_pending(struct timer *);
timeout_t timer_timeout(struct timer *);
/*
* T I M E O U T C O N T E X T I N T E R F A C E S
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#define TIMEOUT_PERIODIC 0x01
struct timeout *timeout_init(struct timeout *, int);
bool timeout_pending(struct timeout *);
/* true if pending in a timing wheel or on expired queue, false otherwise */
bool timeout_expired(struct timeout *);
/* true if currently or previously on expired queue, false otherwise */
#endif /* TIMER_H */ #endif /* TIMER_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment