aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2011-10-10 14:12:20 -0400
committerJonathan Herman <hermanjl@cs.unc.edu>2011-10-10 14:12:20 -0400
commitc9133cb774fa1f7390007c88fe807b681c8e08e2 (patch)
treeb6b83c8b6c9d89fc26922ae04699aec8ebeb50e8
parentba42974ea389f7f69800ddb39c7072f5252cbf98 (diff)
Fixed potential race condition in event group timer
-rw-r--r--litmus/event_group.c29
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 */
30static enum hrtimer_restart on_timer(struct hrtimer *timer) 30static 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;