aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern B. Brandenburg <bbb@cs.unc.edu>2010-03-02 08:41:40 -0500
committerBjoern B. Brandenburg <bbb@cs.unc.edu>2010-03-02 08:41:40 -0500
commit4475feaebe149153cda72d7e7cf17f4f03377dcb (patch)
tree50f261a758ee8e8e21f983b3e6ea69c015c852d5
parentda2cb92c9df507fe61053045caa0c9a08de4c73b (diff)
Revert "Bugfix: PSN-EDF task_block flow-path may race with schedule()"
This reverts commit 851baec36d80e7ee279c69677b113428d20562c8.
-rw-r--r--litmus/sched_psn_edf.c51
1 files changed, 11 insertions, 40 deletions
diff --git a/litmus/sched_psn_edf.c b/litmus/sched_psn_edf.c
index 7b0740b1c58a..3a93124e24f6 100644
--- a/litmus/sched_psn_edf.c
+++ b/litmus/sched_psn_edf.c
@@ -26,13 +26,6 @@ typedef struct {
26 int cpu; 26 int cpu;
27 struct task_struct* scheduled; /* only RT tasks */ 27 struct task_struct* scheduled; /* only RT tasks */
28/* 28/*
29 * A block event (mainly during synchronous release) may race
30 * with other releases or with triggering of the schedule() function.
31 * We need to trace a previous blocking event in the first execution of
32 * schedule()
33 */
34 int block;
35/*
36 * scheduling lock slock 29 * scheduling lock slock
37 * protects the domain and serializes scheduling decisions 30 * protects the domain and serializes scheduling decisions
38 */ 31 */
@@ -58,7 +51,6 @@ static void psnedf_domain_init(psnedf_domain_t* pedf,
58 edf_domain_init(&pedf->domain, check, release); 51 edf_domain_init(&pedf->domain, check, release);
59 pedf->cpu = cpu; 52 pedf->cpu = cpu;
60 pedf->scheduled = NULL; 53 pedf->scheduled = NULL;
61 pedf->block = 0;
62} 54}
63 55
64static void requeue(struct task_struct* t, rt_domain_t *edf) 56static void requeue(struct task_struct* t, rt_domain_t *edf)
@@ -148,36 +140,22 @@ static struct task_struct* psnedf_schedule(struct task_struct * prev)
148 140
149 /* (0) Determine state */ 141 /* (0) Determine state */
150 exists = pedf->scheduled != NULL; 142 exists = pedf->scheduled != NULL;
151 /* a task may block if 1) the task exists but is no more running 143 blocks = exists && !is_running(pedf->scheduled);
152 * 2) the task blocked and this schedule is racing with it while
153 * it is going to sleep. In this case pedf->schedule != prev (and we
154 * already reset pedf->schedule to NULL), but nonetheless we want to
155 * pick a real-time task as next (if such a task exists in the ready
156 * queue).
157 */
158 blocks = pedf->block || (exists && !is_running(pedf->scheduled));
159 out_of_time = exists && budget_exhausted(pedf->scheduled); 144 out_of_time = exists && budget_exhausted(pedf->scheduled);
160 np = exists && is_np(pedf->scheduled); 145 np = exists && is_np(pedf->scheduled);
161 sleep = exists && get_rt_flags(pedf->scheduled) == RT_F_SLEEP; 146 sleep = exists && get_rt_flags(pedf->scheduled) == RT_F_SLEEP;
162 preempt = edf_preemption_needed(edf, prev); 147 preempt = edf_preemption_needed(edf, prev);
163 148
149 /* If we need to preempt do so.
150 * The following checks set resched to 1 in case of special
151 * circumstances.
152 */
153 resched = preempt;
164 154
165 /* If a task blocks we have no choice but to reschedule. 155 /* If a task blocks we have no choice but to reschedule.
166 */ 156 */
167 if (blocks) { 157 if (blocks)
168
169 resched = 1; 158 resched = 1;
170 /* reset the block flag, we are about to reschedule */
171 pedf->block = 0;
172 } else {
173
174 /* If we need to preempt do so.
175 * The following checks set resched to 1 in case of special
176 * circumstances.
177 */
178 resched = preempt;
179 }
180
181 159
182 /* Request a sys_exit_np() call if we would like to preempt but cannot. 160 /* Request a sys_exit_np() call if we would like to preempt but cannot.
183 * Multiple calls to request_exit_np() don't hurt. 161 * Multiple calls to request_exit_np() don't hurt.
@@ -288,7 +266,6 @@ static void psnedf_task_wake_up(struct task_struct *task)
288static void psnedf_task_block(struct task_struct *t) 266static void psnedf_task_block(struct task_struct *t)
289{ 267{
290 psnedf_domain_t *pedf = task_pedf(t); 268 psnedf_domain_t *pedf = task_pedf(t);
291 unsigned long flags;
292 269
293 /* only running tasks can block, thus t is in no queue */ 270 /* only running tasks can block, thus t is in no queue */
294 TRACE_TASK(t, "block at %llu, state=%d\n", litmus_clock(), t->state); 271 TRACE_TASK(t, "block at %llu, state=%d\n", litmus_clock(), t->state);
@@ -296,18 +273,12 @@ static void psnedf_task_block(struct task_struct *t)
296 BUG_ON(!is_realtime(t)); 273 BUG_ON(!is_realtime(t));
297 BUG_ON(is_queued(t)); 274 BUG_ON(is_queued(t));
298 275
299 /* if this task is no more runnable, then we need to reset pedf->schedule 276 /* if this task is dead, then we need to reset pedf->schedule now
300 * and set the block flag as another schedule() may race wotj is while 277 * as we might get rescheduled before task_exit executes
301 * we are going to sleep
302 */ 278 */
303 if(likely(t->state != TASK_RUNNING)) { 279 if(unlikely(t->state == TASK_DEAD)) {
304 280 TRACE_TASK(t, "Dead, setting scheduled = NULL\n");
305 TRACE_TASK(t, "psnedf_task_block, setting block flag\n");
306
307 spin_lock_irqsave(&pedf->slock, flags);
308 pedf->block = 1;
309 pedf->scheduled = NULL; 281 pedf->scheduled = NULL;
310 spin_unlock_irqrestore(&pedf->slock, flags);
311 } 282 }
312} 283}
313 284