diff options
author | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2010-03-02 08:41:40 -0500 |
---|---|---|
committer | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2010-03-02 08:41:40 -0500 |
commit | 4475feaebe149153cda72d7e7cf17f4f03377dcb (patch) | |
tree | 50f261a758ee8e8e21f983b3e6ea69c015c852d5 | |
parent | da2cb92c9df507fe61053045caa0c9a08de4c73b (diff) |
Revert "Bugfix: PSN-EDF task_block flow-path may race with schedule()"
This reverts commit 851baec36d80e7ee279c69677b113428d20562c8.
-rw-r--r-- | litmus/sched_psn_edf.c | 51 |
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 | ||
64 | static void requeue(struct task_struct* t, rt_domain_t *edf) | 56 | static 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) | |||
288 | static void psnedf_task_block(struct task_struct *t) | 266 | static 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 | ||