summaryrefslogtreecommitdiff
path: root/src/ipcpd/timerwheel.c
diff options
context:
space:
mode:
authordimitri staessens <dimitri.staessens@intec.ugent.be>2016-11-25 18:39:26 +0100
committerdimitri staessens <dimitri.staessens@intec.ugent.be>2016-11-25 18:39:26 +0100
commitbf596a9abd6dc05b0d15e8401d267696632350a4 (patch)
tree4ad06a26bea1e80ba292f516da3afb34478d5af6 /src/ipcpd/timerwheel.c
parentaee22e3b33e3e051cbc0f99ca033faf5fac22990 (diff)
downloadouroboros-bf596a9abd6dc05b0d15e8401d267696632350a4.tar.gz
ouroboros-bf596a9abd6dc05b0d15e8401d267696632350a4.zip
ipcpd, lib: Fix timerwheel issues / time_utils
Timerwheel would skip some additions due to a missed wakeup signal. Addition of timespecs and timevals in the time utilities would overflow tv_nsec/tv_usec if the sum is an integer number of seconds.
Diffstat (limited to 'src/ipcpd/timerwheel.c')
-rw-r--r--src/ipcpd/timerwheel.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/src/ipcpd/timerwheel.c b/src/ipcpd/timerwheel.c
index f6785611..042f9cb3 100644
--- a/src/ipcpd/timerwheel.c
+++ b/src/ipcpd/timerwheel.c
@@ -136,10 +136,8 @@ static void * worker(void * o)
while (tw_get_state(tw) == TW_RUNNING) {
if (pthread_cond_timedwait(&tw->work, &tw->lock, &dl)
- == ETIMEDOUT) {
+ == ETIMEDOUT)
ts_add(&dl, &tw->intv, &dl);
- continue;
- }
list_for_each_safe(p, h, &tw->wq) {
struct tw_f * f = list_entry(p, struct tw_f, next);
@@ -149,6 +147,7 @@ static void * worker(void * o)
if (f->arg != NULL)
free(f->arg);
free(f);
+
pthread_mutex_lock(&tw->lock);
}
}
@@ -162,7 +161,7 @@ static void * movement(void * o)
{
struct timerwheel * tw = (struct timerwheel *) o;
struct timespec now = {0, 0};
- long ms = (tw->resolution * tw->elements);
+ long ms = tw->resolution * tw->elements;
struct timespec total = {ms / 1000,
(ms % 1000) * MILLION};
struct list_head * p;
@@ -170,18 +169,19 @@ static void * movement(void * o)
while (tw_get_state(tw) == TW_RUNNING) {
clock_gettime(CLOCK_MONOTONIC, &now);
+
+ pthread_mutex_lock(&tw->lock);
+
if (ts_diff_us(&tw->wheel[tw->pos].expiry, &now) < 0) {
+ pthread_mutex_unlock(&tw->lock);
nanosleep(&tw->intv, NULL);
continue;
}
- pthread_mutex_lock(&tw->lock);
-
list_for_each_safe(p, h, &tw->wheel[tw->pos].funcs) {
struct tw_f * f = list_entry(p, struct tw_f, next);
list_del(&f->next);
list_add(&f->next, &tw->wq);
- pthread_cond_signal(&tw->work);
}
ts_add(&tw->wheel[tw->pos].expiry,
@@ -190,6 +190,8 @@ static void * movement(void * o)
tw->pos = (tw->pos + 1) & (tw->elements - 1);
+ pthread_cond_signal(&tw->work);
+
pthread_mutex_unlock(&tw->lock);
}
@@ -228,8 +230,8 @@ struct timerwheel * timerwheel_create(unsigned int resolution,
tw->resolution = resolution;
- tw->intv.tv_sec = tw->resolution / (1000 * FRAC);
- tw->intv.tv_nsec = (tw->resolution % 1000) * (MILLION / FRAC);
+ tw->intv.tv_sec = (tw->resolution / FRAC) / 1000;
+ tw->intv.tv_nsec = ((tw->resolution / FRAC) % 1000) * MILLION;
INIT_LIST_HEAD(&tw->wq);
@@ -335,7 +337,7 @@ int timerwheel_add(struct timerwheel * tw,
size_t arg_len,
unsigned int delay)
{
- int pos = (tw->pos + delay / tw->resolution) & (tw->elements - 1);
+ int pos;
struct tw_f * f = malloc(sizeof(*f));
if (f == NULL)
return -ENOMEM;
@@ -353,6 +355,7 @@ int timerwheel_add(struct timerwheel * tw,
pthread_mutex_lock(&tw->lock);
+ pos = (tw->pos + delay / tw->resolution) & (tw->elements - 1);
list_add(&f->next, &tw->wheel[pos].funcs);
pthread_mutex_unlock(&tw->lock);