Merge branch 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull scheduler fixes from Ingo Molnar:
 "The biggest commit is an irqtime accounting loop latency fix, the rest
  are misc fixes all over the place: deadline scheduling, docs, numa,
  balancer and a bad to-idle latency fix"

* 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  sched/numa: Initialize newidle balance stats in sd_numa_init()
  sched: Fix updating rq->max_idle_balance_cost and rq->next_balance in idle_balance()
  sched: Skip double execution of pick_next_task_fair()
  sched: Use CPUPRI_NR_PRIORITIES instead of MAX_RT_PRIO in cpupri check
  sched/deadline: Fix memory leak
  sched/deadline: Fix sched_yield() behavior
  sched: Sanitize irq accounting madness
  sched/docbook: Fix 'make htmldocs' warnings caused by missing description
This commit is contained in:
Linus Torvalds 2014-05-23 10:04:04 -07:00
commit f02f79dbcb
7 changed files with 47 additions and 35 deletions

View File

@ -1153,9 +1153,12 @@ struct sched_dl_entity {
* *
* @dl_boosted tells if we are boosted due to DI. If so we are * @dl_boosted tells if we are boosted due to DI. If so we are
* outside bandwidth enforcement mechanism (but only until we * outside bandwidth enforcement mechanism (but only until we
* exit the critical section). * exit the critical section);
*
* @dl_yielded tells if task gave up the cpu before consuming
* all its available runtime during the last job.
*/ */
int dl_throttled, dl_new, dl_boosted; int dl_throttled, dl_new, dl_boosted, dl_yielded;
/* /*
* Bandwidth enforcement timer. Each -deadline task has its * Bandwidth enforcement timer. Each -deadline task has its

View File

@ -2592,8 +2592,14 @@ pick_next_task(struct rq *rq, struct task_struct *prev)
if (likely(prev->sched_class == class && if (likely(prev->sched_class == class &&
rq->nr_running == rq->cfs.h_nr_running)) { rq->nr_running == rq->cfs.h_nr_running)) {
p = fair_sched_class.pick_next_task(rq, prev); p = fair_sched_class.pick_next_task(rq, prev);
if (likely(p && p != RETRY_TASK)) if (unlikely(p == RETRY_TASK))
return p; goto again;
/* assumes fair_sched_class->next == idle_sched_class */
if (unlikely(!p))
p = idle_sched_class.pick_next_task(rq, prev);
return p;
} }
again: again:
@ -3124,6 +3130,7 @@ __setparam_dl(struct task_struct *p, const struct sched_attr *attr)
dl_se->dl_bw = to_ratio(dl_se->dl_period, dl_se->dl_runtime); dl_se->dl_bw = to_ratio(dl_se->dl_period, dl_se->dl_runtime);
dl_se->dl_throttled = 0; dl_se->dl_throttled = 0;
dl_se->dl_new = 1; dl_se->dl_new = 1;
dl_se->dl_yielded = 0;
} }
static void __setscheduler_params(struct task_struct *p, static void __setscheduler_params(struct task_struct *p,
@ -3639,6 +3646,7 @@ SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param)
* sys_sched_setattr - same as above, but with extended sched_attr * sys_sched_setattr - same as above, but with extended sched_attr
* @pid: the pid in question. * @pid: the pid in question.
* @uattr: structure containing the extended parameters. * @uattr: structure containing the extended parameters.
* @flags: for future extension.
*/ */
SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr, SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr,
unsigned int, flags) unsigned int, flags)
@ -3783,6 +3791,7 @@ err_size:
* @pid: the pid in question. * @pid: the pid in question.
* @uattr: structure containing the extended parameters. * @uattr: structure containing the extended parameters.
* @size: sizeof(attr) for fwd/bwd comp. * @size: sizeof(attr) for fwd/bwd comp.
* @flags: for future extension.
*/ */
SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr, SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr,
unsigned int, size, unsigned int, flags) unsigned int, size, unsigned int, flags)
@ -6017,6 +6026,8 @@ sd_numa_init(struct sched_domain_topology_level *tl, int cpu)
, ,
.last_balance = jiffies, .last_balance = jiffies,
.balance_interval = sd_weight, .balance_interval = sd_weight,
.max_newidle_lb_cost = 0,
.next_decay_max_lb_cost = jiffies,
}; };
SD_INIT_NAME(sd, NUMA); SD_INIT_NAME(sd, NUMA);
sd->private = &tl->data; sd->private = &tl->data;

View File

@ -210,7 +210,5 @@ int cpudl_init(struct cpudl *cp)
*/ */
void cpudl_cleanup(struct cpudl *cp) void cpudl_cleanup(struct cpudl *cp)
{ {
/* free_cpumask_var(cp->free_cpus);
* nothing to do for the moment
*/
} }

View File

@ -70,8 +70,7 @@ int cpupri_find(struct cpupri *cp, struct task_struct *p,
int idx = 0; int idx = 0;
int task_pri = convert_prio(p->prio); int task_pri = convert_prio(p->prio);
if (task_pri >= MAX_RT_PRIO) BUG_ON(task_pri >= CPUPRI_NR_PRIORITIES);
return 0;
for (idx = 0; idx < task_pri; idx++) { for (idx = 0; idx < task_pri; idx++) {
struct cpupri_vec *vec = &cp->pri_to_cpu[idx]; struct cpupri_vec *vec = &cp->pri_to_cpu[idx];

View File

@ -332,50 +332,50 @@ out:
* softirq as those do not count in task exec_runtime any more. * softirq as those do not count in task exec_runtime any more.
*/ */
static void irqtime_account_process_tick(struct task_struct *p, int user_tick, static void irqtime_account_process_tick(struct task_struct *p, int user_tick,
struct rq *rq) struct rq *rq, int ticks)
{ {
cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy); cputime_t scaled = cputime_to_scaled(cputime_one_jiffy);
u64 cputime = (__force u64) cputime_one_jiffy;
u64 *cpustat = kcpustat_this_cpu->cpustat; u64 *cpustat = kcpustat_this_cpu->cpustat;
if (steal_account_process_tick()) if (steal_account_process_tick())
return; return;
cputime *= ticks;
scaled *= ticks;
if (irqtime_account_hi_update()) { if (irqtime_account_hi_update()) {
cpustat[CPUTIME_IRQ] += (__force u64) cputime_one_jiffy; cpustat[CPUTIME_IRQ] += cputime;
} else if (irqtime_account_si_update()) { } else if (irqtime_account_si_update()) {
cpustat[CPUTIME_SOFTIRQ] += (__force u64) cputime_one_jiffy; cpustat[CPUTIME_SOFTIRQ] += cputime;
} else if (this_cpu_ksoftirqd() == p) { } else if (this_cpu_ksoftirqd() == p) {
/* /*
* ksoftirqd time do not get accounted in cpu_softirq_time. * ksoftirqd time do not get accounted in cpu_softirq_time.
* So, we have to handle it separately here. * So, we have to handle it separately here.
* Also, p->stime needs to be updated for ksoftirqd. * Also, p->stime needs to be updated for ksoftirqd.
*/ */
__account_system_time(p, cputime_one_jiffy, one_jiffy_scaled, __account_system_time(p, cputime, scaled, CPUTIME_SOFTIRQ);
CPUTIME_SOFTIRQ);
} else if (user_tick) { } else if (user_tick) {
account_user_time(p, cputime_one_jiffy, one_jiffy_scaled); account_user_time(p, cputime, scaled);
} else if (p == rq->idle) { } else if (p == rq->idle) {
account_idle_time(cputime_one_jiffy); account_idle_time(cputime);
} else if (p->flags & PF_VCPU) { /* System time or guest time */ } else if (p->flags & PF_VCPU) { /* System time or guest time */
account_guest_time(p, cputime_one_jiffy, one_jiffy_scaled); account_guest_time(p, cputime, scaled);
} else { } else {
__account_system_time(p, cputime_one_jiffy, one_jiffy_scaled, __account_system_time(p, cputime, scaled, CPUTIME_SYSTEM);
CPUTIME_SYSTEM);
} }
} }
static void irqtime_account_idle_ticks(int ticks) static void irqtime_account_idle_ticks(int ticks)
{ {
int i;
struct rq *rq = this_rq(); struct rq *rq = this_rq();
for (i = 0; i < ticks; i++) irqtime_account_process_tick(current, 0, rq, ticks);
irqtime_account_process_tick(current, 0, rq);
} }
#else /* CONFIG_IRQ_TIME_ACCOUNTING */ #else /* CONFIG_IRQ_TIME_ACCOUNTING */
static inline void irqtime_account_idle_ticks(int ticks) {} static inline void irqtime_account_idle_ticks(int ticks) {}
static inline void irqtime_account_process_tick(struct task_struct *p, int user_tick, static inline void irqtime_account_process_tick(struct task_struct *p, int user_tick,
struct rq *rq) {} struct rq *rq, int nr_ticks) {}
#endif /* CONFIG_IRQ_TIME_ACCOUNTING */ #endif /* CONFIG_IRQ_TIME_ACCOUNTING */
/* /*
@ -464,7 +464,7 @@ void account_process_tick(struct task_struct *p, int user_tick)
return; return;
if (sched_clock_irqtime) { if (sched_clock_irqtime) {
irqtime_account_process_tick(p, user_tick, rq); irqtime_account_process_tick(p, user_tick, rq, 1);
return; return;
} }

View File

@ -528,6 +528,7 @@ static enum hrtimer_restart dl_task_timer(struct hrtimer *timer)
sched_clock_tick(); sched_clock_tick();
update_rq_clock(rq); update_rq_clock(rq);
dl_se->dl_throttled = 0; dl_se->dl_throttled = 0;
dl_se->dl_yielded = 0;
if (p->on_rq) { if (p->on_rq) {
enqueue_task_dl(rq, p, ENQUEUE_REPLENISH); enqueue_task_dl(rq, p, ENQUEUE_REPLENISH);
if (task_has_dl_policy(rq->curr)) if (task_has_dl_policy(rq->curr))
@ -893,10 +894,10 @@ static void yield_task_dl(struct rq *rq)
* We make the task go to sleep until its current deadline by * We make the task go to sleep until its current deadline by
* forcing its runtime to zero. This way, update_curr_dl() stops * forcing its runtime to zero. This way, update_curr_dl() stops
* it and the bandwidth timer will wake it up and will give it * it and the bandwidth timer will wake it up and will give it
* new scheduling parameters (thanks to dl_new=1). * new scheduling parameters (thanks to dl_yielded=1).
*/ */
if (p->dl.runtime > 0) { if (p->dl.runtime > 0) {
rq->curr->dl.dl_new = 1; rq->curr->dl.dl_yielded = 1;
p->dl.runtime = 0; p->dl.runtime = 0;
} }
update_curr_dl(rq); update_curr_dl(rq);

View File

@ -6653,6 +6653,7 @@ static int idle_balance(struct rq *this_rq)
int this_cpu = this_rq->cpu; int this_cpu = this_rq->cpu;
idle_enter_fair(this_rq); idle_enter_fair(this_rq);
/* /*
* We must set idle_stamp _before_ calling idle_balance(), such that we * We must set idle_stamp _before_ calling idle_balance(), such that we
* measure the duration of idle_balance() as idle time. * measure the duration of idle_balance() as idle time.
@ -6705,14 +6706,16 @@ static int idle_balance(struct rq *this_rq)
raw_spin_lock(&this_rq->lock); raw_spin_lock(&this_rq->lock);
if (curr_cost > this_rq->max_idle_balance_cost)
this_rq->max_idle_balance_cost = curr_cost;
/* /*
* While browsing the domains, we released the rq lock. * While browsing the domains, we released the rq lock, a task could
* A task could have be enqueued in the meantime * have been enqueued in the meantime. Since we're not going idle,
* pretend we pulled a task.
*/ */
if (this_rq->cfs.h_nr_running && !pulled_task) { if (this_rq->cfs.h_nr_running && !pulled_task)
pulled_task = 1; pulled_task = 1;
goto out;
}
if (pulled_task || time_after(jiffies, this_rq->next_balance)) { if (pulled_task || time_after(jiffies, this_rq->next_balance)) {
/* /*
@ -6722,9 +6725,6 @@ static int idle_balance(struct rq *this_rq)
this_rq->next_balance = next_balance; this_rq->next_balance = next_balance;
} }
if (curr_cost > this_rq->max_idle_balance_cost)
this_rq->max_idle_balance_cost = curr_cost;
out: out:
/* Is there a task of a high priority class? */ /* Is there a task of a high priority class? */
if (this_rq->nr_running != this_rq->cfs.h_nr_running && if (this_rq->nr_running != this_rq->cfs.h_nr_running &&