From bc92369ba24f72b916384ed80d4381549c6537a7 Mon Sep 17 00:00:00 2001 From: Jonathan Herman Date: Sun, 9 Oct 2011 18:42:07 -0400 Subject: Fixed bug where finish switch could strand level-C tasks in neverland --- litmus/rt_domain.c | 4 +++- litmus/sched_mc.c | 17 ++++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/litmus/rt_domain.c b/litmus/rt_domain.c index 93f2a35fb29d..f242f33e990e 100644 --- a/litmus/rt_domain.c +++ b/litmus/rt_domain.c @@ -20,7 +20,7 @@ #include /* Uncomment when debugging timer races... */ -#if 1 +#if 0 #define VTRACE_TASK TRACE_TASK #define VTRACE TRACE #else @@ -404,7 +404,9 @@ void __add_release(rt_domain_t* rt, struct task_struct *task) static void pd_requeue(domain_t *dom, struct task_struct *task) { rt_domain_t *domain = (rt_domain_t*)dom->data; + BUG_ON(!task || !is_realtime(task)); + TRACE_TASK(task, "Requeueing"); BUG_ON(is_queued(task)); BUG_ON(get_task_domain(task) != dom); diff --git a/litmus/sched_mc.c b/litmus/sched_mc.c index 277762709d3d..61eb961eda23 100644 --- a/litmus/sched_mc.c +++ b/litmus/sched_mc.c @@ -63,8 +63,10 @@ static int interrupt_cpu; #define is_global_task(t) (is_global(get_task_domain(t))) #define can_use(ce) \ ((ce)->state == CS_ACTIVE || (ce->state == CS_ACTIVATE)) -#define can_requeue(t) \ - (!is_global_task(t) || (t)->rt_param.scheduled_on == NO_CPU) +#define can_requeue(t) \ + ((t)->rt_param.linked_on == NO_CPU && /* Not linked anywhere */ \ + !is_queued(t) && /* Not gonna be linked */ \ + (!is_global_task(t) || (t)->rt_param.scheduled_on == NO_CPU)) #define entry_level(e) \ (((e)->linked) ? tsk_mc_crit((e)->linked) : NUM_CRIT_LEVELS - 1) #define crit_cpu(ce) \ @@ -288,11 +290,11 @@ static void job_arrival(struct task_struct *task) TRACE_MC_TASK(task, "Job arriving\n"); BUG_ON(!task); + raw_spin_lock(dom->lock); if (can_requeue(task)) { - raw_spin_lock(dom->lock); + BUG_ON(task->rt_param.linked_on != NO_CPU); dom->requeue(dom, task); check_for_preempt(dom); - raw_spin_unlock(dom->lock); } else { /* If a global task is scheduled on one cpu, it CANNOT * be requeued into a global domain. Another cpu might @@ -302,6 +304,7 @@ static void job_arrival(struct task_struct *task) */ TRACE_MC_TASK(task, "Delayed arrival of scheduled task\n"); } + raw_spin_unlock(dom->lock); } /** @@ -547,11 +550,15 @@ static void remove_from_all(struct task_struct* task) update = 1; link_task_to_cpu(entry, NULL); } + } else { + TRACE_MC_TASK(task, "Unlinked before we got lock!"); } if (update) update_crit_levels(entry); else raw_spin_unlock(&entry->lock); + } else { + TRACE_MC_TASK(task, "Not linked to anything\n"); } /* Ensure the task isn't returned by its domain */ @@ -874,7 +881,7 @@ static struct task_struct* mc_schedule(struct task_struct* prev) local_irq_save(flags); raw_spin_lock(&entry->lock); - if (entry->scheduled) { + if (entry->scheduled && entry->scheduled != prev) { TRACE_TASK(entry->scheduled, " and prev is %d\n", prev->pid); } -- cgit v1.2.2