aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2011-10-07 18:13:28 -0400
committerJonathan Herman <hermanjl@cs.unc.edu>2011-10-07 18:13:28 -0400
commit054b92b95cfc2249ff7c1b110fb9aee8fa43378c (patch)
tree825a392b4b3b0a536e8dfc1c770546ea073f5739
parentc0c51f136eae07e09bff56baa4954c4567d558fe (diff)
Fixed global task deadlock
-rw-r--r--litmus/sched_mc.c49
-rw-r--r--litmus/sched_mc_ce.c2
2 files changed, 33 insertions, 18 deletions
diff --git a/litmus/sched_mc.c b/litmus/sched_mc.c
index 8e261426171e..90a60c568183 100644
--- a/litmus/sched_mc.c
+++ b/litmus/sched_mc.c
@@ -176,15 +176,30 @@ static void update_ghost_time(struct task_struct *p)
176 } 176 }
177} 177}
178 178
179/*
180 * Update crit entry position in a global heap. Caller must hold
181 * @ce's domain lock.
182 */
183static inline void update_crit_position(struct crit_entry *ce)
184{
185 struct bheap *heap;
186 if (is_global(ce->domain)) {
187 heap = domain_data(ce->domain)->heap;
188 BUG_ON(!heap);
189 BUG_ON(!bheap_node_in_heap(ce->node));
190 bheap_delete(cpu_lower_prio, heap, ce->node);
191 bheap_insert(cpu_lower_prio, heap, ce->node);
192 }
193}
194
179/** 195/**
180 * link_task_to_crit() - Logically run a task at a criticality level. 196 * link_task_to_crit() - Logically run a task at a criticality level.
181 * Caller must hold @ce's domain's lock. 197 * Caller must hold @ce's CPU lock.
182 */ 198 */
183static void link_task_to_crit(struct crit_entry *ce, 199static void link_task_to_crit(struct crit_entry *ce,
184 struct task_struct *task) 200 struct task_struct *task)
185{ 201{
186 lt_t when_to_fire; 202 lt_t when_to_fire;
187 struct bheap *heap;
188 203
189 TRACE_CRIT_ENTRY(ce, "Linking " TS, TA(task)); 204 TRACE_CRIT_ENTRY(ce, "Linking " TS, TA(task));
190 BUG_ON(!ce->usable && task); 205 BUG_ON(!ce->usable && task);
@@ -221,15 +236,6 @@ static void link_task_to_crit(struct crit_entry *ce,
221 arm_ghost(ce, when_to_fire); 236 arm_ghost(ce, when_to_fire);
222 } 237 }
223 } 238 }
224
225 /* Update global heap node position */
226 if (is_global(ce->domain)) {
227 heap = domain_data(ce->domain)->heap;
228 BUG_ON(!heap);
229 BUG_ON(!bheap_node_in_heap(ce->node));
230 bheap_delete(cpu_lower_prio, heap, ce->node);
231 bheap_insert(cpu_lower_prio, heap, ce->node);
232 }
233} 239}
234 240
235static void check_for_preempt(struct domain*); 241static void check_for_preempt(struct domain*);
@@ -351,18 +357,18 @@ static void preempt(struct domain *dom, struct crit_entry *ce)
351{ 357{
352 struct task_struct *task = dom->take_ready(dom); 358 struct task_struct *task = dom->take_ready(dom);
353 struct cpu_entry *entry = crit_cpu(ce); 359 struct cpu_entry *entry = crit_cpu(ce);
354 struct task_struct *old; 360 struct task_struct *old = ce->linked;
355 361
356 BUG_ON(!task); 362 BUG_ON(!task);
357 TRACE_CRIT_ENTRY(ce, "Preempted by " TS, TA(task)); 363 TRACE_CRIT_ENTRY(ce, "Preempted by " TS, TA(task));
358 364
359 old = ce->linked;
360
361 /* Per-domain preemption */ 365 /* Per-domain preemption */
362 if (old && can_requeue(old)) { 366 if (old && can_requeue(old)) {
363 dom->requeue(dom, old); 367 dom->requeue(dom, old);
364 } 368 }
365 link_task_to_crit(ce, task); 369 link_task_to_crit(ce, task);
370 update_crit_position(ce);
371
366 /* Preempt actual execution if this is a running task */ 372 /* Preempt actual execution if this is a running task */
367 if (!is_ghost(task)) { 373 if (!is_ghost(task)) {
368 link_task_to_cpu(entry, task); 374 link_task_to_cpu(entry, task);
@@ -412,8 +418,18 @@ static void update_crit_levels(struct cpu_entry *entry)
412 /* Re-admit tasks to the system */ 418 /* Re-admit tasks to the system */
413 for (i = level + 1; i < NUM_CRIT_LEVELS; i++) { 419 for (i = level + 1; i < NUM_CRIT_LEVELS; i++) {
414 ce = &entry->crit_entries[i]; 420 ce = &entry->crit_entries[i];
415 if (readmit[i]) 421 if (readmit[i]) {
422 /* Position of the crit entry changed earlier.
423 * We couldn't update it while we held the entry
424 * lock. Update it here.
425 */
426 if (is_global(ce->domain)) {
427 raw_spin_lock(ce->domain->lock);
428 update_crit_position(ce);
429 raw_spin_unlock(ce->domain->lock);
430 }
416 low_prio_arrival(readmit[i]); 431 low_prio_arrival(readmit[i]);
432 }
417 } 433 }
418} 434}
419 435
@@ -479,6 +495,7 @@ static void remove_from_all(struct task_struct* task)
479 if (task->rt_param.linked_on != NO_CPU) { 495 if (task->rt_param.linked_on != NO_CPU) {
480 BUG_ON(ce->linked != task); 496 BUG_ON(ce->linked != task);
481 link_task_to_crit(ce, NULL); 497 link_task_to_crit(ce, NULL);
498 update_crit_position(ce);
482 if (!is_ghost(task) && entry->linked == task) { 499 if (!is_ghost(task) && entry->linked == task) {
483 update = 1; 500 update = 1;
484 link_task_to_cpu(entry, NULL); 501 link_task_to_cpu(entry, NULL);
@@ -577,7 +594,6 @@ static enum hrtimer_restart mc_ghost_exhausted(struct hrtimer *timer)
577 update_ghost_time(ce->linked); 594 update_ghost_time(ce->linked);
578 if (tsk_mc_data(ce->linked)->mc_job.ghost_budget == 0) { 595 if (tsk_mc_data(ce->linked)->mc_job.ghost_budget == 0) {
579 tmp = ce->linked; 596 tmp = ce->linked;
580 link_task_to_crit(ce, NULL);
581 } 597 }
582 } 598 }
583 raw_spin_unlock(&crit_cpu(ce)->lock); 599 raw_spin_unlock(&crit_cpu(ce)->lock);
@@ -886,6 +902,7 @@ static struct task_struct* mc_schedule(struct task_struct * prev)
886 if (!entry->linked && ce->usable && !ce->linked && dtask) { 902 if (!entry->linked && ce->usable && !ce->linked && dtask) {
887 dom->take_ready(dom); 903 dom->take_ready(dom);
888 link_task_to_crit(ce, dtask); 904 link_task_to_crit(ce, dtask);
905 update_crit_position(ce);
889 ready_task = (is_ghost(dtask)) ? NULL : dtask; 906 ready_task = (is_ghost(dtask)) ? NULL : dtask;
890 907
891 /* Task found! */ 908 /* Task found! */
diff --git a/litmus/sched_mc_ce.c b/litmus/sched_mc_ce.c
index ffcc25873581..5a19628b06df 100644
--- a/litmus/sched_mc_ce.c
+++ b/litmus/sched_mc_ce.c
@@ -421,10 +421,8 @@ void mc_ce_task_exit_common(struct task_struct *ts)
421 const int lvl_a_id = tsk_mc_data(ts)->mc_task.lvl_a_id; 421 const int lvl_a_id = tsk_mc_data(ts)->mc_task.lvl_a_id;
422 struct ce_pid_table *pid_table = get_pid_table(ce_data->cpu); 422 struct ce_pid_table *pid_table = get_pid_table(ce_data->cpu);
423 423
424 BUG_ON(task_cpu(ts) != get_partition(ts));
425 BUG_ON(CRIT_LEVEL_A != tsk_mc_crit(ts)); 424 BUG_ON(CRIT_LEVEL_A != tsk_mc_crit(ts));
426 BUG_ON(lvl_a_id >= pid_table->num_pid_entries); 425 BUG_ON(lvl_a_id >= pid_table->num_pid_entries);
427 BUG_ON(ce_data->cpu != task_cpu(ts));
428 426
429 raw_spin_lock_irqsave(dom->lock, flags); 427 raw_spin_lock_irqsave(dom->lock, flags);
430 pid = pid_table->entries[lvl_a_id].pid; 428 pid = pid_table->entries[lvl_a_id].pid;