diff --git a/kernel/sched/MuQSS.c b/kernel/sched/MuQSS.c index f261e030eefa..01a50fd91f5f 100644 --- a/kernel/sched/MuQSS.c +++ b/kernel/sched/MuQSS.c @@ -7562,16 +7562,19 @@ static void __init select_leaders(void) /* FIXME freeing locked spinlock */ static void __init share_and_free_rq(struct rq *leader, struct rq *rq) { + raw_spinlock_t *orig_lock = rq->lock; WARN_ON(rq->nr_running > 0); kfree(rq->node); kfree(rq->sl); - kfree(rq->lock); rq->node = leader->node; rq->sl = leader->sl; rq->lock = leader->lock; rq->is_leader = false; - barrier(); + raw_spin_unlock(orig_lock); + cpu_relax(); + raw_spin_lock(orig_lock); + kfree(orig_lock); /* To make up for not unlocking the freed runlock */ preempt_enable(); } @@ -7584,14 +7587,14 @@ static void __init share_rqs(void) for_each_online_cpu(cpu) { rq = cpu_rq(cpu); leader = rq->smp_leader; + if (!leader || rq == leader) + continue; - rq_lock(rq); - if (leader && rq != leader) { - printk(KERN_INFO "MuQSS sharing SMP runqueue from CPU %d to CPU %d\n", - leader->cpu, rq->cpu); - share_and_free_rq(leader, rq); - } else - rq_unlock(rq); + __double_rq_lock(leader, rq); + printk(KERN_INFO "MuQSS sharing SMP runqueue from CPU %d to CPU %d\n", + leader->cpu, rq->cpu); + share_and_free_rq(leader, rq); + rq_unlock(leader); } #ifdef CONFIG_SCHED_MC