diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2011-10-10 14:12:20 -0400 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2011-10-10 14:12:20 -0400 |
commit | c9133cb774fa1f7390007c88fe807b681c8e08e2 (patch) | |
tree | b6b83c8b6c9d89fc26922ae04699aec8ebeb50e8 | |
parent | ba42974ea389f7f69800ddb39c7072f5252cbf98 (diff) |
Fixed potential race condition in event group timer
-rw-r--r-- | litmus/event_group.c | 29 |
1 files changed, 19 insertions, 10 deletions
diff --git a/litmus/event_group.c b/litmus/event_group.c index 365ec1ee3651..4a54881fb256 100644 --- a/litmus/event_group.c +++ b/litmus/event_group.c | |||
@@ -29,34 +29,43 @@ static unsigned int time2slot(lt_t time) | |||
29 | */ | 29 | */ |
30 | static enum hrtimer_restart on_timer(struct hrtimer *timer) | 30 | static enum hrtimer_restart on_timer(struct hrtimer *timer) |
31 | { | 31 | { |
32 | unsigned long flags; | ||
33 | unsigned long num = 0; | 32 | unsigned long num = 0; |
34 | struct event_list *el; | 33 | struct event_list *el; |
35 | struct rt_event *e; | 34 | struct rt_event *e; |
36 | struct list_head *pos, safe, events; | 35 | struct list_head *pos, events; |
37 | 36 | ||
38 | el = container_of(timer, struct event_list, timer); | 37 | el = container_of(timer, struct event_list, timer); |
39 | 38 | ||
40 | raw_spin_lock_irqsave(&el->group->queue_lock, flags); | 39 | raw_spin_lock(&el->group->queue_lock); |
40 | |||
41 | /* Remove event_list from hashtable so no more events | ||
42 | * are added to it. | ||
43 | */ | ||
41 | VTRACE("Removing event list 0x%p\n", el); | 44 | VTRACE("Removing event list 0x%p\n", el); |
42 | list_del_init(&el->queue_node); | 45 | list_del_init(&el->queue_node); |
43 | raw_spin_unlock_irqrestore(&el->group->queue_lock, flags); | ||
44 | 46 | ||
45 | /* Empty event list so this event can be requeued */ | 47 | /* Empty event list so that it can be re-used as soon |
48 | * as the lock is released. | ||
49 | */ | ||
46 | VTRACE("Emptying event list 0x%p\n", el); | 50 | VTRACE("Emptying event list 0x%p\n", el); |
47 | list_replace_init(&el->events, &events); | 51 | list_replace_init(&el->events, &events); |
48 | 52 | ||
49 | /* Fire events */ | 53 | /* Fire events */ |
50 | for (pos = events.next; prefetch(pos->next), pos != &events;) { | 54 | for (pos = events.next; prefetch(pos->next), events.next != &events; |
51 | num++; | 55 | pos = events.next, num++) { |
56 | |||
52 | e = list_entry(pos, struct rt_event, events_node); | 57 | e = list_entry(pos, struct rt_event, events_node); |
58 | list_del_init(pos); | ||
59 | raw_spin_unlock(&el->group->queue_lock); | ||
60 | |||
53 | VTRACE("Dequeueing event 0x%p with prio %d from 0x%p\n", | 61 | VTRACE("Dequeueing event 0x%p with prio %d from 0x%p\n", |
54 | e, e->prio, el); | 62 | e, e->prio, el); |
55 | list_replace(pos, &safe); | 63 | |
56 | list_del_init(pos); | ||
57 | e->function(e); | 64 | e->function(e); |
58 | pos = safe.next; | 65 | |
66 | raw_spin_lock(&el->group->queue_lock); | ||
59 | } | 67 | } |
68 | raw_spin_unlock(&el->group->queue_lock); | ||
60 | VTRACE("Exhausted %d events from list 0x%p\n", num, el); | 69 | VTRACE("Exhausted %d events from list 0x%p\n", num, el); |
61 | /* sched_trace_action(NULL, num); */ | 70 | /* sched_trace_action(NULL, num); */ |
62 | return HRTIMER_NORESTART; | 71 | return HRTIMER_NORESTART; |