summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Ahern <[email protected]>2016-02-26 22:21:51 -0800
committerWilliam Ahern <[email protected]>2016-02-26 22:21:51 -0800
commit948cacb51795fdbc6964916212d4a260d4f11e7a (patch)
tree0e4e141ad71a649913c4de9fb68947c1dc27c432
parenta8a62b4f356f6c67ead7bcbd1ecb8202c4f6af6f (diff)
parent43a854241b93a85929785b37f45e133bd880690c (diff)
Merge branch 'nmathewson-fixing_intervals'
-rw-r--r--test-timeout.c36
-rw-r--r--timeout.c19
2 files changed, 37 insertions, 18 deletions
diff --git a/test-timeout.c b/test-timeout.c
index 47582e0..4607958 100644
--- a/test-timeout.c
+++ b/test-timeout.c
@@ -226,6 +226,7 @@ struct intervals_cfg {
int n_timeouts;
timeout_t start_at;
timeout_t end_at;
+ timeout_t skip;
};
int
@@ -261,23 +262,35 @@ check_intervals(struct intervals_cfg *cfg)
while (now < cfg->end_at) {
timeout_t delay = timeouts_timeout(tos);
+ if (cfg->skip && delay < cfg->skip)
+ delay = cfg->skip;
timeouts_step(tos, delay);
-
now += delay;
while (NULL != (to = timeouts_get(tos))) {
i = to - &t[0];
assert(&t[i] == to);
fired[i]++;
+ if (0 != (to->expires - cfg->start_at) % cfg->timeouts[i])
+ FAIL();
+ if (to->expires <= now)
+ FAIL();
+ if (to->expires > now + cfg->timeouts[i])
+ FAIL();
}
if (!timeouts_check(tos, stderr))
FAIL();
}
- timeout_t duration = cfg->end_at - cfg->start_at;
+ timeout_t duration = now - cfg->start_at;
for (i = 0; i < cfg->n_timeouts; ++i) {
- if (fired[i] != duration / cfg->timeouts[i])
- FAIL();
+ if (cfg->skip) {
+ if (fired[i] > duration / cfg->timeouts[i])
+ FAIL();
+ } else {
+ if (fired[i] != duration / cfg->timeouts[i])
+ FAIL();
+ }
if (!timeout_pending(&t[i]))
FAIL();
}
@@ -420,25 +433,36 @@ main(int argc, char **argv)
.n_timeouts = sizeof(primes)/sizeof(timeout_t),
.start_at = 50,
.end_at = 5322,
+ .skip = 0,
};
DO(check_intervals(&icfg1));
struct intervals_cfg icfg2 = {
- .timeouts = primes,
+ .timeouts = factors_of_1337,
.n_timeouts = sizeof(factors_of_1337)/sizeof(timeout_t),
.start_at = 50,
.end_at = 50000,
+ .skip = 0,
};
DO(check_intervals(&icfg2));
struct intervals_cfg icfg3 = {
- .timeouts = primes,
+ .timeouts = multiples_of_five,
.n_timeouts = sizeof(multiples_of_five)/sizeof(timeout_t),
.start_at = 49,
.end_at = 5333,
+ .skip = 0,
};
DO(check_intervals(&icfg3));
+ struct intervals_cfg icfg4 = {
+ .timeouts = primes,
+ .n_timeouts = sizeof(primes)/sizeof(timeout_t),
+ .start_at = 50,
+ .end_at = 5322,
+ .skip = 16,
+ };
+ DO(check_intervals(&icfg4));
if (n_failed) {
puts("\nFAIL");
diff --git a/timeout.c b/timeout.c
index 596949c..e78f57d 100644
--- a/timeout.c
+++ b/timeout.c
@@ -358,18 +358,13 @@ static void timeouts_readd(struct timeouts *T, struct timeout *to) {
to->expires += to->interval;
if (to->expires <= T->curtime) {
- if (to->expires < T->curtime) {
- timeout_t n = T->curtime - to->expires;
- timeout_t q = n / to->interval;
- timeout_t r = n % to->interval;
-
- if (r)
- to->expires += (to->interval * q) + (to->interval - r);
- else
- to->expires += (to->interval * q);
- } else {
- to->expires += to->interval;
- }
+ /* If we've missed the next firing of this timeout, reschedule
+ * it to occur at the next multiple of its interval after
+ * the last time that it fired.
+ */
+ timeout_t n = T->curtime - to->expires;
+ timeout_t r = n % to->interval;
+ to->expires = T->curtime + (to->interval - r);
}
timeouts_sched(T, to, to->expires);