--- kernel/sched/bfs.c | 67 ++++++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 33 deletions(-) Index: linux-3.3-ck1/kernel/sched/bfs.c =================================================================== --- linux-3.3-ck1.orig/kernel/sched/bfs.c 2012-03-26 23:30:16.000000000 +1100 +++ linux-3.3-ck1/kernel/sched/bfs.c 2012-03-26 23:46:49.270688481 +1100 @@ -1758,8 +1758,9 @@ static bool try_to_wake_up(struct task_s if (!((unsigned int)p->state & state)) goto out_unlock; - grq_upgrade_rwlock(); rwupgrade = true; + grq_upgrade_rwlock(); + if (task_queued(p) || task_running(p)) goto out_running; @@ -2696,29 +2697,22 @@ ts_account: * * Called with task_grq_lock() held. */ -static u64 do_task_delta_exec(struct task_struct *p, struct rq *rq) +unsigned long long task_delta_exec(struct task_struct *p) { + unsigned long flags; + struct rq *rq; u64 ns = 0; + rq = task_grq_ulock(p, &flags); if (p == rq->curr) { + grq_upgrade_rwlock(); update_clocks(rq); ns = rq->clock_task - rq->rq_last_ran; if (unlikely((s64)ns < 0)) ns = 0; - } - - return ns; -} - -unsigned long long task_delta_exec(struct task_struct *p) -{ - unsigned long flags; - struct rq *rq; - u64 ns; - - rq = task_grq_wlock(p, &flags); - ns = do_task_delta_exec(p, rq); - task_grq_wunlock(&flags); + task_grq_wunlock(&flags); + } else + task_grq_uunlock(&flags); return ns; } @@ -2731,14 +2725,23 @@ unsigned long long task_delta_exec(struc unsigned long long task_sched_runtime(struct task_struct *p) { unsigned long flags; + u64 ps, ns = 0; struct rq *rq; - u64 ns; - rq = task_grq_wlock(p, &flags); - ns = p->sched_time + do_task_delta_exec(p, rq); - task_grq_wunlock(&flags); + rq = task_grq_ulock(p, &flags); + ps = p->sched_time; + if (p == rq->curr) { + grq_upgrade_rwlock(); + update_clocks(rq); + ns = rq->clock_task - rq->rq_last_ran; + if (unlikely((s64)ns < 0)) + ns = 0; + task_grq_wunlock(&flags); + } else + task_grq_uunlock(&flags); + ps += ns; - return ns; + return ps; } /* Compatibility crap for removal */ @@ -4394,7 +4397,6 @@ recheck: */ if (unlikely(policy == p->policy && (!is_rt_policy(policy) || param->sched_priority == p->rt_priority))) { - __task_grq_uunlock(); raw_spin_unlock_irqrestore(&p->pi_lock, flags); return 0; @@ -4860,7 +4862,7 @@ EXPORT_SYMBOL(yield); */ bool __sched yield_to(struct task_struct *p, bool preempt) { - bool yielded = 0, rwupgrade = false; + bool yielded = false; unsigned long flags; struct rq *rq; @@ -4868,8 +4870,8 @@ bool __sched yield_to(struct task_struct grq_ulock_irqsave(&flags); if (task_running(p) || p->state) goto out_unlock; - yielded = 1; - rwupgrade = true; + + yielded = true; grq_upgrade_rwlock(); if (p->deadline > rq->rq_deadline) p->deadline = rq->rq_deadline; @@ -4879,13 +4881,12 @@ bool __sched yield_to(struct task_struct p->time_slice = timeslice(); set_tsk_need_resched(rq->curr); out_unlock: - if (rwupgrade) + if (yielded) { grq_wunlock_irqrestore(&flags); - else + schedule(); + } else grq_uunlock_irqrestore(&flags); - if (yielded) - schedule(); return yielded; } EXPORT_SYMBOL_GPL(yield_to); @@ -5010,9 +5011,9 @@ SYSCALL_DEFINE2(sched_rr_get_interval, p if (retval) goto out_unlock; - grq_wlock_irqsave(&flags); + grq_rlock_irqsave(&flags); time_slice = p->policy == SCHED_FIFO ? 0 : MS_TO_NS(task_timeslice(p)); - grq_wunlock_irqrestore(&flags); + grq_runlock_irqrestore(&flags); rcu_read_unlock(); t = ns_to_timespec(time_slice); @@ -5290,11 +5291,11 @@ int set_cpus_allowed_ptr(struct task_str goto out; } + queued = task_queued(p); + rwupgrade = true; grq_upgrade_rwlock(); - queued = task_queued(p); - do_set_cpus_allowed(p, new_mask); /* Can the task run on the task's current CPU? If so, we're done */