diff options
author | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2009-05-03 13:38:38 -0400 |
---|---|---|
committer | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2009-05-03 13:38:38 -0400 |
commit | 68c699e1046646a9f03fea09049e9edc690995d0 (patch) | |
tree | 510e9cfffe24a1707fed87d4db2ada66e1151507 | |
parent | 8c2ed856588664c82faf9f3df244eace68f565f3 (diff) |
rt domain: make sure release heap is not in use before re-init
This fixes a bug observed under G-EDF:
A task with extremely low wcet budget could get scheduled
and re-added to its own release heap while the heap was still
in use in the same timer callback that released the task.
Havoc, predictably, ensued.
-rw-r--r-- | litmus/rt_domain.c | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/litmus/rt_domain.c b/litmus/rt_domain.c index 0357df5f93..8065a2c0bd 100644 --- a/litmus/rt_domain.c +++ b/litmus/rt_domain.c | |||
@@ -47,6 +47,8 @@ static enum hrtimer_restart on_release_timer(struct hrtimer *timer) | |||
47 | long flags; | 47 | long flags; |
48 | struct release_heap* rh; | 48 | struct release_heap* rh; |
49 | 49 | ||
50 | TRACE("on_release_timer(0x%p) starts.\n", timer); | ||
51 | |||
50 | TS_RELEASE_START; | 52 | TS_RELEASE_START; |
51 | 53 | ||
52 | rh = container_of(timer, struct release_heap, timer); | 54 | rh = container_of(timer, struct release_heap, timer); |
@@ -62,6 +64,8 @@ static enum hrtimer_restart on_release_timer(struct hrtimer *timer) | |||
62 | 64 | ||
63 | TS_RELEASE_END; | 65 | TS_RELEASE_END; |
64 | 66 | ||
67 | TRACE("on_release_timer(0x%p) ends.\n", timer); | ||
68 | |||
65 | return HRTIMER_NORESTART; | 69 | return HRTIMER_NORESTART; |
66 | } | 70 | } |
67 | 71 | ||
@@ -124,6 +128,14 @@ static struct release_heap* get_release_heap(rt_domain_t *rt, struct task_struct | |||
124 | /* use pre-allocated release heap */ | 128 | /* use pre-allocated release heap */ |
125 | rh = tsk_rt(t)->rel_heap; | 129 | rh = tsk_rt(t)->rel_heap; |
126 | 130 | ||
131 | /* Make sure it is safe to use. The timer callback could still | ||
132 | * be executing on another CPU; hrtimer_cancel() will wait | ||
133 | * until the timer callback has completed. However, under no | ||
134 | * circumstances should the timer be active (= yet to be | ||
135 | * triggered). | ||
136 | */ | ||
137 | BUG_ON(hrtimer_cancel(&rh->timer)); | ||
138 | |||
127 | /* initialize */ | 139 | /* initialize */ |
128 | rh->release_time = release_time; | 140 | rh->release_time = release_time; |
129 | rh->dom = rt; | 141 | rh->dom = rt; |