From f21e1d0ef90c2e88ae6a563afc31ea601ed968c7 Mon Sep 17 00:00:00 2001 From: Jonathan Herman Date: Tue, 27 Sep 2011 14:47:26 -0400 Subject: Timer merging --- litmus/event_group.c | 108 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 72 insertions(+), 36 deletions(-) (limited to 'litmus/event_group.c') diff --git a/litmus/event_group.c b/litmus/event_group.c index 22c74a19d1d6..b4521ab370d1 100644 --- a/litmus/event_group.c +++ b/litmus/event_group.c @@ -5,6 +5,12 @@ #include #include +#if 1 +#define VTRACE TRACE +#else +#define VTRACE(fmt, args...) +#endif + /* * Return event_queue slot for the given time. */ @@ -20,6 +26,7 @@ static unsigned int time2slot(lt_t time) static enum hrtimer_restart on_timer(struct hrtimer *timer) { unsigned long flags; + int num = 0; struct event_list *el; struct rt_event *e; struct list_head *pos, *safe, list; @@ -27,19 +34,24 @@ static enum hrtimer_restart on_timer(struct hrtimer *timer) el = container_of(timer, struct event_list, timer); raw_spin_lock_irqsave(&el->group->queue_lock, flags); + VTRACE("Removing event list 0x%p\n", el); list_del_init(&el->list); raw_spin_unlock_irqrestore(&el->group->queue_lock, flags); /* Empty event list so this event can be requeued */ + VTRACE("Emptying event list 0x%p\n", el); list_replace_init(&el->events, &list); /* Fire events */ list_for_each_safe(pos, safe, &list) { + num++; e = list_entry(pos, struct rt_event, list); - TRACE("Dequeueing event with prio %d\n", e->prio); + TRACE("Dequeueing event with prio %d from 0x%p\n", + e->prio, el); list_del_init(pos); - e->fire(e->data); + e->function(e); } + VTRACE("Exhausted %d events from list 0x%p\n", num, el); return HRTIMER_NORESTART; } @@ -48,16 +60,22 @@ static enum hrtimer_restart on_timer(struct hrtimer *timer) */ void insert_event(struct event_list *el, struct rt_event *e) { - struct list_head *pos; + struct list_head *pos, *last = NULL; struct rt_event *queued; - list_for_each_prev(pos, &el->events) { + list_for_each(pos, &el->events) { queued = list_entry(pos, struct rt_event, list); + last = pos; if (e->prio < queued->prio) { - __list_add(&e->list, pos, pos->next); + VTRACE("Inserting priority %d 0x%p before %d 0x%p " + "in 0x%p, pos 0x%p\n", e->prio, &e->list, + queued->prio, &queued->list, el, pos); + list_add_tail(&e->list, pos); return; } } - list_add(&e->list, &el->events); + VTRACE("Inserting priority %d 0x%p at end of 0x%p, last 0x%p\n", + e->prio, &el->list, el, last); + list_add(&e->list, (last) ? last : pos); } /* @@ -65,52 +83,60 @@ void insert_event(struct event_list *el, struct rt_event *e) * is being used yet and use_event_heap is 1, will create the list * and return it. Otherwise it will return NULL. */ -static struct event_list *get_event_list(struct event_group *group, - struct rt_event *e, - lt_t fire, - int use_event_heap) +static struct event_list* get_event_list(struct event_group *group, + struct rt_event *e, + lt_t fire, + int use_event_list) { struct list_head* pos; struct event_list *el = NULL, *tmp; unsigned int slot = time2slot(fire); - /* initialize pos for the case that the list is empty */ + VTRACE("Getting list for %llu\n", fire); + + /* Initialize pos for the case that the list is empty */ pos = group->event_queue[slot].next; list_for_each(pos, &group->event_queue[slot]) { tmp = list_entry(pos, struct event_list, list); if (lt_after_eq(fire, tmp->fire_time) && - lt_before(tmp->fire_time, fire)) { - /* perfect match -- this happens on hyperperiod - * boundaries - */ + lt_before(fire, tmp->fire_time + group->res)) { + VTRACE("Found match at time %llu\n", tmp->fire_time); el = tmp; break; } else if (lt_before(fire, tmp->fire_time)) { - /* we need to insert a new node since rh is + /* We need to insert a new node since el is * already in the future */ + VTRACE("Time %llu was before %llu\n", + fire, tmp->fire_time); break; + } else { + VTRACE("Time %llu was after %llu\n", + fire, tmp->fire_time + group->res); } } - if (!el && use_event_heap) { - /* use pre-allocated release heap */ + if (!el && use_event_list) { + /* Use pre-allocated list */ tmp = e->event_list; tmp->fire_time = fire; tmp->group = group; - /* add to queue */ + /* Add to queue */ list_add(&tmp->list, pos->prev); el = tmp; + VTRACE("Using list for priority %d and time %llu\n", + e->prio, fire); } return el; } /* - * Prepare a release heap for a new set of events. + * Prepare a release list for a new set of events. */ static void reinit_event_list(struct rt_event *e) { struct event_list *el = e->event_list; BUG_ON(hrtimer_cancel(&el->timer)); + VTRACE("Reinitting 0x%p\n", el); INIT_LIST_HEAD(&el->events); atomic_set(&el->info.state, HRTIMER_START_ON_INACTIVE); } @@ -122,7 +148,8 @@ void add_event(struct event_group *group, struct rt_event *e, lt_t fire) { struct event_list *el; - TRACE("Adding event with prio %d @ %llu\n", event->prio, fire); + VTRACE("Adding event with priority %d for time %llu\n", + e->prio, fire); raw_spin_lock(&group->queue_lock); el = get_event_list(group, e, fire, 0); @@ -140,7 +167,7 @@ void add_event(struct event_group *group, struct rt_event *e, lt_t fire) /* Arm timer if we are the owner */ if (el == e->event_list) { - TRACE("Arming timer for %llu\n", fire); + VTRACE("Arming timer for %llu\n", fire); if (group->cpu == smp_processor_id()) { __hrtimer_start_range_ns(&el->timer, ns_to_ktime(el->fire_time), @@ -151,18 +178,23 @@ void add_event(struct event_group *group, struct rt_event *e, lt_t fire) HRTIMER_MODE_ABS_PINNED); } } else { - TRACE("Not my timer @%llu", fire); + VTRACE("Not my timer @%llu\n", fire); } } /** * cancel_event() - Remove event from the group. */ -void cancel_event(struct event_group *group, struct rt_event *e) +void cancel_event(struct rt_event *e) { - raw_spin_lock(&group->queue_lock); - list_del_init(&e->list); - raw_spin_unlock(&group->queue_lock); + struct event_group *group; + if (e->list.next != &e->list) { + group = e->event_list->group; + raw_spin_lock(&group->queue_lock); + VTRACE("Canceling event with priority %d\n", e->prio); + list_del_init(&e->list); + raw_spin_unlock(&group->queue_lock); + } } /** @@ -171,30 +203,34 @@ void cancel_event(struct event_group *group, struct rt_event *e) void init_event_group(struct event_group *group, lt_t res, int cpu) { int i; + VTRACE("Creating group with res %llu on CPU %d", res, cpu); group->res = res; group->cpu = cpu; - - for (i = 0; i < EVENT_QUEUE_SLOTS; i++) { + for (i = 0; i < EVENT_QUEUE_SLOTS; i++) INIT_LIST_HEAD(&group->event_queue[i]); - } - raw_spin_lock_init(&group->queue_lock); } -struct kmem_cache *event_list_cache; -struct event_list * event_list_alloc(int gfp_flags) +struct kmem_cache *event_list_cache, *event_cache; + +struct event_list* event_list_alloc(int gfp_flags) { struct event_list *el = kmem_cache_alloc(event_list_cache, gfp_flags); if (el) { hrtimer_init(&el->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); INIT_LIST_HEAD(&el->list); el->timer.function = on_timer; + } else { + VTRACE("Failed to allocate event list!"); } return el; } -void event_list_free(struct event_list *el) +void init_event(struct rt_event *e, int prio, fire_event_t function, + struct event_list *el) { - hrtimer_cancel(&el->timer); - kmem_cache_free(event_list_cache, el); + e->prio = prio; + e->function = function; + e->event_list = el; + INIT_LIST_HEAD(&e->list); } -- cgit v1.2.2