Skip to content
This repository has been archived by the owner on Aug 19, 2021. It is now read-only.

Commit

Permalink
Fixed drift in periodic events
Browse files Browse the repository at this point in the history
Before this patch, calculation for periodic events occured after the
event was dispatched, but didn't account for the overhead of the
callback itself.

Now calculation of the new target is based only on the previous target,
ignoring drift introduced by the callback. This may lead never sleeping
if the callback takes longer than its period, but the fairness of the
scheduler should avoid problems this may cause.

Additionally, equeue_enqueue was restructured to avoid calling
equeue_tick redundantly (a system call in some implementations).
  • Loading branch information
geky committed Aug 20, 2016
1 parent 847b2f9 commit 84d006b
Showing 1 changed file with 9 additions and 6 deletions.
15 changes: 9 additions & 6 deletions equeue.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,10 @@ void equeue_dealloc(equeue_t *q, void *p) {


// equeue scheduling functions
static int equeue_enqueue(equeue_t *q, struct equeue_event *e, unsigned ms) {
static int equeue_enqueue(equeue_t *q, struct equeue_event *e, unsigned tick) {
// setup event and hash local id with buffer offset for unique id
int id = (e->id << q->npw2) | ((unsigned char *)e - q->buffer);
e->target = equeue_tick() + ms;
e->target = tick + equeue_clampdiff(e->target, tick);
e->generation = q->generation;

equeue_mutex_lock(&q->queuelock);
Expand Down Expand Up @@ -235,7 +235,8 @@ static int equeue_enqueue(equeue_t *q, struct equeue_event *e, unsigned ms) {
// notify background timer
if ((q->background.update && q->background.active) &&
(q->queue == e && !e->sibling)) {
q->background.update(q->background.timer, ms);
q->background.update(q->background.timer,
equeue_clampdiff(e->target, tick));
}

equeue_mutex_unlock(&q->queuelock);
Expand Down Expand Up @@ -332,10 +333,11 @@ static struct equeue_event *equeue_dequeue(equeue_t *q, unsigned target) {

int equeue_post(equeue_t *q, void (*cb)(void*), void *p) {
struct equeue_event *e = (struct equeue_event*)p - 1;
unsigned tick = equeue_tick();
e->cb = cb;
e->target = equeue_clampdiff(e->target, 0);
e->target = tick + e->target;

int id = equeue_enqueue(q, e, e->target);
int id = equeue_enqueue(q, e, tick);
equeue_sema_signal(&q->eventsema);
return id;
}
Expand Down Expand Up @@ -380,7 +382,8 @@ void equeue_dispatch(equeue_t *q, int ms) {

// reenqueue periodic events or deallocate
if (e->period >= 0) {
equeue_enqueue(q, e, e->period);
e->target += e->period;
equeue_enqueue(q, e, equeue_tick());
} else {
equeue_incid(q, e);
equeue_dealloc(q, e+1);
Expand Down

0 comments on commit 84d006b

Please sign in to comment.