From 2fec12d43b366b7257c602af784b172466d8d4c5 Mon Sep 17 00:00:00 2001 From: "Bjoern B. Brandenburg" Date: Thu, 24 Nov 2011 13:59:33 -0500 Subject: 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. --- litmus/sched_pfair.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) 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 { raw_spinlock_t release_lock; }; +#define RT_F_REQUEUE 0x2 + static inline struct pfair_cluster* cpu_cluster(struct pfair_state* state) { return container_of(state->topology.cluster, struct pfair_cluster, topology); @@ -288,6 +290,8 @@ static void drop_all_references(struct task_struct *t) if (s->scheduled == t) s->scheduled = NULL; } + /* make sure we don't have a stale linked_on field */ + tsk_rt(t)->linked_on = NO_CPU; } static 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) } else { /* remove task from system until it wakes */ drop_all_references(t); + tsk_rt(t)->flags = RT_F_REQUEUE; TRACE_TASK(t, "on %d advanced to subtask %lu (not present)\n", cpu, p->cur); return 0; @@ -688,6 +693,7 @@ static void pfair_task_wake_up(struct task_struct *t) { unsigned long flags; lt_t now; + int requeue = 0; struct pfair_cluster* cluster; cluster = tsk_pfair(t)->cluster; @@ -702,16 +708,21 @@ static void pfair_task_wake_up(struct task_struct *t) * (as if it never blocked at all). Otherwise, we have a * new sporadic job release. */ + requeue = tsk_rt(t)->flags == RT_F_REQUEUE; now = litmus_clock(); if (lt_before(get_deadline(t), now)) { + TRACE_TASK(t, "sporadic release!\n"); release_at(t, now); prepare_release(t, time2quanta(now, CEIL)); sched_trace_task_release(t); } /* only add to ready queue if the task isn't still linked somewhere */ - if (tsk_rt(t)->linked_on == NO_CPU) + if (requeue) { + TRACE_TASK(t, "requeueing required\n"); + tsk_rt(t)->flags = RT_F_RUNNING; __add_ready(&cluster->pfair, t); + } check_preempt(t); -- cgit v1.2.2