Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 44 additions & 46 deletions timeout.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,21 +73,20 @@
#define MAX(a, b) (((a) > (b))? (a) : (b))
#endif

#if !defined TAILQ_CONCAT
#define TAILQ_CONCAT(head1, head2, field) do { \
if (!TAILQ_EMPTY(head2)) { \
*(head1)->tqh_last = (head2)->tqh_first; \
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
(head1)->tqh_last = (head2)->tqh_last; \
TAILQ_INIT((head2)); \
} \
#define LIST_MOVE(to, from, field) do { \
if (LIST_EMPTY(from)) { \
LIST_INIT((to)); \
} else { \
(to)->lh_first = (from)->lh_first; \
(to)->lh_first->field.le_prev = &(to)->lh_first; \
LIST_INIT((from)); \
} \
} while (0)
#endif

#if !defined TAILQ_FOREACH_SAFE
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = TAILQ_FIRST(head); \
(var) && ((tvar) = TAILQ_NEXT(var, field), 1); \
#if !defined LIST_FOREACH_SAFE
#define LIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = LIST_FIRST(head); \
(var) && ((tvar) = LIST_NEXT(var, field), 1); \
(var) = (tvar))
#endif

Expand Down Expand Up @@ -203,7 +202,7 @@ static inline wheel_t rotr(const wheel_t v, int c) {
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

TAILQ_HEAD(timeout_list, timeout);
LIST_HEAD(timeout_list, timeout);

struct timeouts {
struct timeout_list wheel[WHEEL_NUM][WHEEL_LEN], expired;
Expand All @@ -220,11 +219,11 @@ static struct timeouts *timeouts_init(struct timeouts *T, timeout_t hz) {

for (i = 0; i < countof(T->wheel); i++) {
for (j = 0; j < countof(T->wheel[i]); j++) {
TAILQ_INIT(&T->wheel[i][j]);
LIST_INIT(&T->wheel[i][j]);
}
}

TAILQ_INIT(&T->expired);
LIST_INIT(&T->expired);

for (i = 0; i < countof(T->pending); i++) {
T->pending[i] = 0;
Expand All @@ -250,21 +249,19 @@ TIMEOUT_PUBLIC struct timeouts *timeouts_open(timeout_t hz, int *error) {


static void timeouts_reset(struct timeouts *T) {
struct timeout_list reset;
struct timeout *to;
unsigned i, j;

TAILQ_INIT(&reset);

for (i = 0; i < countof(T->wheel); i++) {
for (j = 0; j < countof(T->wheel[i]); j++) {
TAILQ_CONCAT(&reset, &T->wheel[i][j], tqe);
LIST_FOREACH(to, &T->wheel[i][j], le) {
to->pending = NULL;
TO_SET_TIMEOUTS(to, NULL);
}
}
}

TAILQ_CONCAT(&reset, &T->expired, tqe);

TAILQ_FOREACH(to, &reset, tqe) {
LIST_FOREACH(to, &T->expired, le) {
to->pending = NULL;
TO_SET_TIMEOUTS(to, NULL);
}
Expand All @@ -289,9 +286,9 @@ TIMEOUT_PUBLIC timeout_t timeouts_hz(struct timeouts *T) {

TIMEOUT_PUBLIC void timeouts_del(struct timeouts *T, struct timeout *to) {
if (to->pending) {
TAILQ_REMOVE(to->pending, to, tqe);
LIST_REMOVE(to, le);

if (to->pending != &T->expired && TAILQ_EMPTY(to->pending)) {
if (to->pending != &T->expired && LIST_EMPTY(to->pending)) {
ptrdiff_t index = to->pending - &T->wheel[0][0];
int wheel = index / WHEEL_LEN;
int slot = index % WHEEL_LEN;
Expand Down Expand Up @@ -343,12 +340,12 @@ static void timeouts_sched(struct timeouts *T, struct timeout *to, timeout_t exp
slot = timeout_slot(wheel, to->expires);

to->pending = &T->wheel[wheel][slot];
TAILQ_INSERT_TAIL(to->pending, to, tqe);
LIST_INSERT_HEAD(to->pending, to, le);

T->pending[wheel] |= WHEEL_C(1) << slot;
} else {
to->pending = &T->expired;
TAILQ_INSERT_TAIL(to->pending, to, tqe);
LIST_INSERT_HEAD(to->pending, to, le);
}
} /* timeouts_sched() */

Expand Down Expand Up @@ -387,10 +384,8 @@ TIMEOUT_PUBLIC void timeouts_add(struct timeouts *T, struct timeout *to, timeout

TIMEOUT_PUBLIC void timeouts_update(struct timeouts *T, abstime_t curtime) {
timeout_t elapsed = curtime - T->curtime;
struct timeout_list todo;
int wheel;

TAILQ_INIT(&todo);
int wheel, i, n_todo = 0;
struct timeout_list todo[WHEEL_NUM*WHEEL_LEN];

/*
* There's no avoiding looping over every wheel. It's best to keep
Expand Down Expand Up @@ -435,7 +430,8 @@ TIMEOUT_PUBLIC void timeouts_update(struct timeouts *T, abstime_t curtime) {
while (pending & T->pending[wheel]) {
/* ctz input cannot be zero: loop condition. */
int slot = ctz(pending & T->pending[wheel]);
TAILQ_CONCAT(&todo, &T->wheel[wheel][slot], tqe);
struct timeout_list *target = &todo[n_todo++];
LIST_MOVE(target, &T->wheel[wheel][slot], le);
T->pending[wheel] &= ~(UINT64_C(1) << slot);
}

Expand All @@ -448,13 +444,15 @@ TIMEOUT_PUBLIC void timeouts_update(struct timeouts *T, abstime_t curtime) {

T->curtime = curtime;

while (!TAILQ_EMPTY(&todo)) {
struct timeout *to = TAILQ_FIRST(&todo);
for (i = 0; i < n_todo; ++i) {
while (!LIST_EMPTY(&todo[i])) {
struct timeout *to = LIST_FIRST(&todo[i]);

TAILQ_REMOVE(&todo, to, tqe);
to->pending = NULL;
LIST_REMOVE(to, le);
to->pending = NULL;

timeouts_sched(T, to, to->expires);
timeouts_sched(T, to, to->expires);
}
}

return;
Expand All @@ -479,7 +477,7 @@ TIMEOUT_PUBLIC bool timeouts_pending(struct timeouts *T) {


TIMEOUT_PUBLIC bool timeouts_expired(struct timeouts *T) {
return !TAILQ_EMPTY(&T->expired);
return !LIST_EMPTY(&T->expired);
} /* timeouts_expired() */


Expand Down Expand Up @@ -534,18 +532,18 @@ static timeout_t timeouts_int(struct timeouts *T) {
* events.
*/
TIMEOUT_PUBLIC timeout_t timeouts_timeout(struct timeouts *T) {
if (!TAILQ_EMPTY(&T->expired))
if (!LIST_EMPTY(&T->expired))
return 0;

return timeouts_int(T);
} /* timeouts_timeout() */


TIMEOUT_PUBLIC struct timeout *timeouts_get(struct timeouts *T) {
if (!TAILQ_EMPTY(&T->expired)) {
struct timeout *to = TAILQ_FIRST(&T->expired);
if (!LIST_EMPTY(&T->expired)) {
struct timeout *to = LIST_FIRST(&T->expired);

TAILQ_REMOVE(&T->expired, to, tqe);
LIST_REMOVE(to, le);
to->pending = NULL;
TO_SET_TIMEOUTS(to, NULL);

Expand All @@ -571,7 +569,7 @@ static struct timeout *timeouts_min(struct timeouts *T) {

for (i = 0; i < countof(T->wheel); i++) {
for (j = 0; j < countof(T->wheel[i]); j++) {
TAILQ_FOREACH(to, &T->wheel[i][j], tqe) {
LIST_FOREACH(to, &T->wheel[i][j], le) {
if (!min || to->expires < min->expires)
min = to;
}
Expand Down Expand Up @@ -613,7 +611,7 @@ TIMEOUT_PUBLIC bool timeouts_check(struct timeouts *T, FILE *fp) {
} else {
timeout = timeouts_timeout(T);

if (!TAILQ_EMPTY(&T->expired))
if (!LIST_EMPTY(&T->expired))
check(timeout == 0, "wrong soft timeout (soft:%" TIMEOUT_PRIu " != hard:%" TIMEOUT_PRIu ")\n", timeout, TIMEOUT_C(0));
else
check(timeout == ~TIMEOUT_C(0), "wrong soft timeout (soft:%" TIMEOUT_PRIu " != hard:%" TIMEOUT_PRIu ")\n", timeout, ~TIMEOUT_C(0));
Expand Down Expand Up @@ -655,7 +653,7 @@ TIMEOUT_PUBLIC struct timeout *timeouts_next(struct timeouts *T, struct timeouts
YIELD(to);
}
} else {
TAILQ_FOREACH_SAFE(to, &T->expired, tqe, it->to) {
LIST_FOREACH_SAFE(to, &T->expired, le, it->to) {
YIELD(to);
}
}
Expand All @@ -664,7 +662,7 @@ TIMEOUT_PUBLIC struct timeout *timeouts_next(struct timeouts *T, struct timeouts
if (it->flags & TIMEOUTS_PENDING) {
for (it->i = 0; it->i < countof(T->wheel); it->i++) {
for (it->j = 0; it->j < countof(T->wheel[it->i]); it->j++) {
TAILQ_FOREACH_SAFE(to, &T->wheel[it->i][it->j], tqe, it->to) {
LIST_FOREACH_SAFE(to, &T->wheel[it->i][it->j], le, it->to) {
YIELD(to);
}
}
Expand Down
2 changes: 1 addition & 1 deletion timeout.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ struct timeout {
struct timeout_list *pending;
/* timeout list if pending on wheel or expiry queue */

TAILQ_ENTRY(timeout) tqe;
LIST_ENTRY(timeout) le;
/* entry member for struct timeout_list lists */

#ifndef TIMEOUT_DISABLE_CALLBACKS
Expand Down