aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjoern B. Brandenburg <bbb@cs.unc.edu>2011-11-24 13:59:33 -0500
committerBjoern B. Brandenburg <bbb@cs.unc.edu>2011-11-24 13:59:33 -0500
commit2fec12d43b366b7257c602af784b172466d8d4c5 (patch)
tree704b5b4c7bf2f70bd4f19185932a18355b81dfa9
parentd1d6e4c300d858c47b834be145f30973bc2921bf (diff)
Pfair: improve robustness of suspensions
This patch fixes two crash or hang bugs related to suspensions in Pfair. 1) When a job was not present at the end of its last subtask, then its linked_on field was not cleared. This confused the scheduler when it later resumed. Fix: clear the field. 2) Just testing for linked_on == NO_CPU is insufficient in the wake_up path to determine whether a task should be added to the ready queue. If the task remained linked and then was "preempted" at a later quantum boundary, then it already is in the ready queue and nothing is required. Fix: encode need to requeue in task_rt(t)->flags.
-rw-r--r--litmus/sched_pfair.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/litmus/sched_pfair.c b/litmus/sched_pfair.c
index c95bde87b5d7..16f1065bbdca 100644
--- a/litmus/sched_pfair.c
+++ b/litmus/sched_pfair.c
@@ -98,6 +98,8 @@ struct pfair_cluster {
98 raw_spinlock_t release_lock; 98 raw_spinlock_t release_lock;
99}; 99};
100 100
101#define RT_F_REQUEUE 0x2
102
101static inline struct pfair_cluster* cpu_cluster(struct pfair_state* state) 103static inline struct pfair_cluster* cpu_cluster(struct pfair_state* state)
102{ 104{
103 return container_of(state->topology.cluster, struct pfair_cluster, topology); 105 return container_of(state->topology.cluster, struct pfair_cluster, topology);
@@ -288,6 +290,8 @@ static void drop_all_references(struct task_struct *t)
288 if (s->scheduled == t) 290 if (s->scheduled == t)
289 s->scheduled = NULL; 291 s->scheduled = NULL;
290 } 292 }
293 /* make sure we don't have a stale linked_on field */
294 tsk_rt(t)->linked_on = NO_CPU;
291} 295}
292 296
293static void pfair_prepare_next_period(struct task_struct* t) 297static void pfair_prepare_next_period(struct task_struct* t)
@@ -312,6 +316,7 @@ static int advance_subtask(quanta_t time, struct task_struct* t, int cpu)
312 } else { 316 } else {
313 /* remove task from system until it wakes */ 317 /* remove task from system until it wakes */
314 drop_all_references(t); 318 drop_all_references(t);
319 tsk_rt(t)->flags = RT_F_REQUEUE;
315 TRACE_TASK(t, "on %d advanced to subtask %lu (not present)\n", 320 TRACE_TASK(t, "on %d advanced to subtask %lu (not present)\n",
316 cpu, p->cur); 321 cpu, p->cur);
317 return 0; 322 return 0;
@@ -688,6 +693,7 @@ static void pfair_task_wake_up(struct task_struct *t)
688{ 693{
689 unsigned long flags; 694 unsigned long flags;
690 lt_t now; 695 lt_t now;
696 int requeue = 0;
691 struct pfair_cluster* cluster; 697 struct pfair_cluster* cluster;
692 698
693 cluster = tsk_pfair(t)->cluster; 699 cluster = tsk_pfair(t)->cluster;
@@ -702,16 +708,21 @@ static void pfair_task_wake_up(struct task_struct *t)
702 * (as if it never blocked at all). Otherwise, we have a 708 * (as if it never blocked at all). Otherwise, we have a
703 * new sporadic job release. 709 * new sporadic job release.
704 */ 710 */
711 requeue = tsk_rt(t)->flags == RT_F_REQUEUE;
705 now = litmus_clock(); 712 now = litmus_clock();
706 if (lt_before(get_deadline(t), now)) { 713 if (lt_before(get_deadline(t), now)) {
714 TRACE_TASK(t, "sporadic release!\n");
707 release_at(t, now); 715 release_at(t, now);
708 prepare_release(t, time2quanta(now, CEIL)); 716 prepare_release(t, time2quanta(now, CEIL));
709 sched_trace_task_release(t); 717 sched_trace_task_release(t);
710 } 718 }
711 719
712 /* only add to ready queue if the task isn't still linked somewhere */ 720 /* only add to ready queue if the task isn't still linked somewhere */
713 if (tsk_rt(t)->linked_on == NO_CPU) 721 if (requeue) {
722 TRACE_TASK(t, "requeueing required\n");
723 tsk_rt(t)->flags = RT_F_RUNNING;
714 __add_ready(&cluster->pfair, t); 724 __add_ready(&cluster->pfair, t);
725 }
715 726
716 check_preempt(t); 727 check_preempt(t);
717 728