Commit e570dc2a authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'sched-fixes-for-linus' of...

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

* 'sched-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  sched, delay accounting: fix incorrect delay time when constantly waiting on runqueue
  sched: CPU hotplug events must not destroy scheduler domains created by the cpusets
  sched: rt-group: fix RR buglet
  sched: rt-group: heirarchy aware throttle
  sched: rt-group: fix hierarchy
  sched: NULL pointer dereference while setting sched_rt_period_us
  sched: fix defined-but-unused warning
parents b1ae8d3a d4abc238
...@@ -1890,6 +1890,12 @@ static void common_cpu_mem_hotplug_unplug(void) ...@@ -1890,6 +1890,12 @@ static void common_cpu_mem_hotplug_unplug(void)
top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY]; top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
scan_for_empty_cpusets(&top_cpuset); scan_for_empty_cpusets(&top_cpuset);
/*
* Scheduler destroys domains on hotplug events.
* Rebuild them based on the current settings.
*/
rebuild_sched_domains();
cgroup_unlock(); cgroup_unlock();
} }
......
...@@ -1127,6 +1127,7 @@ static enum hrtimer_restart hrtick(struct hrtimer *timer) ...@@ -1127,6 +1127,7 @@ static enum hrtimer_restart hrtick(struct hrtimer *timer)
return HRTIMER_NORESTART; return HRTIMER_NORESTART;
} }
#ifdef CONFIG_SMP
static void hotplug_hrtick_disable(int cpu) static void hotplug_hrtick_disable(int cpu)
{ {
struct rq *rq = cpu_rq(cpu); struct rq *rq = cpu_rq(cpu);
...@@ -1182,6 +1183,7 @@ static void init_hrtick(void) ...@@ -1182,6 +1183,7 @@ static void init_hrtick(void)
{ {
hotcpu_notifier(hotplug_hrtick, 0); hotcpu_notifier(hotplug_hrtick, 0);
} }
#endif /* CONFIG_SMP */
static void init_rq_hrtick(struct rq *rq) static void init_rq_hrtick(struct rq *rq)
{ {
...@@ -7235,6 +7237,18 @@ void __attribute__((weak)) arch_update_cpu_topology(void) ...@@ -7235,6 +7237,18 @@ void __attribute__((weak)) arch_update_cpu_topology(void)
{ {
} }
/*
* Free current domain masks.
* Called after all cpus are attached to NULL domain.
*/
static void free_sched_domains(void)
{
ndoms_cur = 0;
if (doms_cur != &fallback_doms)
kfree(doms_cur);
doms_cur = &fallback_doms;
}
/* /*
* Set up scheduler domains and groups. Callers must hold the hotplug lock. * Set up scheduler domains and groups. Callers must hold the hotplug lock.
* For now this just excludes isolated cpus, but could be used to * For now this just excludes isolated cpus, but could be used to
...@@ -7382,6 +7396,7 @@ int arch_reinit_sched_domains(void) ...@@ -7382,6 +7396,7 @@ int arch_reinit_sched_domains(void)
get_online_cpus(); get_online_cpus();
mutex_lock(&sched_domains_mutex); mutex_lock(&sched_domains_mutex);
detach_destroy_domains(&cpu_online_map); detach_destroy_domains(&cpu_online_map);
free_sched_domains();
err = arch_init_sched_domains(&cpu_online_map); err = arch_init_sched_domains(&cpu_online_map);
mutex_unlock(&sched_domains_mutex); mutex_unlock(&sched_domains_mutex);
put_online_cpus(); put_online_cpus();
...@@ -7467,6 +7482,7 @@ static int update_sched_domains(struct notifier_block *nfb, ...@@ -7467,6 +7482,7 @@ static int update_sched_domains(struct notifier_block *nfb,
case CPU_DOWN_PREPARE: case CPU_DOWN_PREPARE:
case CPU_DOWN_PREPARE_FROZEN: case CPU_DOWN_PREPARE_FROZEN:
detach_destroy_domains(&cpu_online_map); detach_destroy_domains(&cpu_online_map);
free_sched_domains();
return NOTIFY_OK; return NOTIFY_OK;
case CPU_UP_CANCELED: case CPU_UP_CANCELED:
...@@ -7485,8 +7501,16 @@ static int update_sched_domains(struct notifier_block *nfb, ...@@ -7485,8 +7501,16 @@ static int update_sched_domains(struct notifier_block *nfb,
return NOTIFY_DONE; return NOTIFY_DONE;
} }
#ifndef CONFIG_CPUSETS
/*
* Create default domain partitioning if cpusets are disabled.
* Otherwise we let cpusets rebuild the domains based on the
* current setup.
*/
/* The hotplug lock is already held by cpu_up/cpu_down */ /* The hotplug lock is already held by cpu_up/cpu_down */
arch_init_sched_domains(&cpu_online_map); arch_init_sched_domains(&cpu_online_map);
#endif
return NOTIFY_OK; return NOTIFY_OK;
} }
...@@ -7626,7 +7650,6 @@ static void init_tg_rt_entry(struct task_group *tg, struct rt_rq *rt_rq, ...@@ -7626,7 +7650,6 @@ static void init_tg_rt_entry(struct task_group *tg, struct rt_rq *rt_rq,
else else
rt_se->rt_rq = parent->my_q; rt_se->rt_rq = parent->my_q;
rt_se->rt_rq = &rq->rt;
rt_se->my_q = rt_rq; rt_se->my_q = rt_rq;
rt_se->parent = parent; rt_se->parent = parent;
INIT_LIST_HEAD(&rt_se->run_list); INIT_LIST_HEAD(&rt_se->run_list);
...@@ -8348,7 +8371,7 @@ static unsigned long to_ratio(u64 period, u64 runtime) ...@@ -8348,7 +8371,7 @@ static unsigned long to_ratio(u64 period, u64 runtime)
#ifdef CONFIG_CGROUP_SCHED #ifdef CONFIG_CGROUP_SCHED
static int __rt_schedulable(struct task_group *tg, u64 period, u64 runtime) static int __rt_schedulable(struct task_group *tg, u64 period, u64 runtime)
{ {
struct task_group *tgi, *parent = tg->parent; struct task_group *tgi, *parent = tg ? tg->parent : NULL;
unsigned long total = 0; unsigned long total = 0;
if (!parent) { if (!parent) {
......
...@@ -449,13 +449,19 @@ void dec_rt_tasks(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) ...@@ -449,13 +449,19 @@ void dec_rt_tasks(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq)
#endif #endif
} }
static void enqueue_rt_entity(struct sched_rt_entity *rt_se) static void __enqueue_rt_entity(struct sched_rt_entity *rt_se)
{ {
struct rt_rq *rt_rq = rt_rq_of_se(rt_se); struct rt_rq *rt_rq = rt_rq_of_se(rt_se);
struct rt_prio_array *array = &rt_rq->active; struct rt_prio_array *array = &rt_rq->active;
struct rt_rq *group_rq = group_rt_rq(rt_se); struct rt_rq *group_rq = group_rt_rq(rt_se);
if (group_rq && rt_rq_throttled(group_rq)) /*
* Don't enqueue the group if its throttled, or when empty.
* The latter is a consequence of the former when a child group
* get throttled and the current group doesn't have any other
* active members.
*/
if (group_rq && (rt_rq_throttled(group_rq) || !group_rq->rt_nr_running))
return; return;
list_add_tail(&rt_se->run_list, array->queue + rt_se_prio(rt_se)); list_add_tail(&rt_se->run_list, array->queue + rt_se_prio(rt_se));
...@@ -464,7 +470,7 @@ static void enqueue_rt_entity(struct sched_rt_entity *rt_se) ...@@ -464,7 +470,7 @@ static void enqueue_rt_entity(struct sched_rt_entity *rt_se)
inc_rt_tasks(rt_se, rt_rq); inc_rt_tasks(rt_se, rt_rq);
} }
static void dequeue_rt_entity(struct sched_rt_entity *rt_se) static void __dequeue_rt_entity(struct sched_rt_entity *rt_se)
{ {
struct rt_rq *rt_rq = rt_rq_of_se(rt_se); struct rt_rq *rt_rq = rt_rq_of_se(rt_se);
struct rt_prio_array *array = &rt_rq->active; struct rt_prio_array *array = &rt_rq->active;
...@@ -480,11 +486,10 @@ static void dequeue_rt_entity(struct sched_rt_entity *rt_se) ...@@ -480,11 +486,10 @@ static void dequeue_rt_entity(struct sched_rt_entity *rt_se)
* Because the prio of an upper entry depends on the lower * Because the prio of an upper entry depends on the lower
* entries, we must remove entries top - down. * entries, we must remove entries top - down.
*/ */
static void dequeue_rt_stack(struct task_struct *p) static void dequeue_rt_stack(struct sched_rt_entity *rt_se)
{ {
struct sched_rt_entity *rt_se, *back = NULL; struct sched_rt_entity *back = NULL;
rt_se = &p->rt;
for_each_sched_rt_entity(rt_se) { for_each_sched_rt_entity(rt_se) {
rt_se->back = back; rt_se->back = back;
back = rt_se; back = rt_se;
...@@ -492,7 +497,26 @@ static void dequeue_rt_stack(struct task_struct *p) ...@@ -492,7 +497,26 @@ static void dequeue_rt_stack(struct task_struct *p)
for (rt_se = back; rt_se; rt_se = rt_se->back) { for (rt_se = back; rt_se; rt_se = rt_se->back) {
if (on_rt_rq(rt_se)) if (on_rt_rq(rt_se))
dequeue_rt_entity(rt_se); __dequeue_rt_entity(rt_se);
}
}
static void enqueue_rt_entity(struct sched_rt_entity *rt_se)
{
dequeue_rt_stack(rt_se);
for_each_sched_rt_entity(rt_se)
__enqueue_rt_entity(rt_se);
}
static void dequeue_rt_entity(struct sched_rt_entity *rt_se)
{
dequeue_rt_stack(rt_se);
for_each_sched_rt_entity(rt_se) {
struct rt_rq *rt_rq = group_rt_rq(rt_se);
if (rt_rq && rt_rq->rt_nr_running)
__enqueue_rt_entity(rt_se);
} }
} }
...@@ -506,32 +530,15 @@ static void enqueue_task_rt(struct rq *rq, struct task_struct *p, int wakeup) ...@@ -506,32 +530,15 @@ static void enqueue_task_rt(struct rq *rq, struct task_struct *p, int wakeup)
if (wakeup) if (wakeup)
rt_se->timeout = 0; rt_se->timeout = 0;
dequeue_rt_stack(p);
/*
* enqueue everybody, bottom - up.
*/
for_each_sched_rt_entity(rt_se)
enqueue_rt_entity(rt_se); enqueue_rt_entity(rt_se);
} }
static void dequeue_task_rt(struct rq *rq, struct task_struct *p, int sleep) static void dequeue_task_rt(struct rq *rq, struct task_struct *p, int sleep)
{ {
struct sched_rt_entity *rt_se = &p->rt; struct sched_rt_entity *rt_se = &p->rt;
struct rt_rq *rt_rq;
update_curr_rt(rq); update_curr_rt(rq);
dequeue_rt_entity(rt_se);
dequeue_rt_stack(p);
/*
* re-enqueue all non-empty rt_rq entities.
*/
for_each_sched_rt_entity(rt_se) {
rt_rq = group_rt_rq(rt_se);
if (rt_rq && rt_rq->rt_nr_running)
enqueue_rt_entity(rt_se);
}
} }
/* /*
...@@ -542,8 +549,10 @@ static ...@@ -542,8 +549,10 @@ static
void requeue_rt_entity(struct rt_rq *rt_rq, struct sched_rt_entity *rt_se) void requeue_rt_entity(struct rt_rq *rt_rq, struct sched_rt_entity *rt_se)
{ {
struct rt_prio_array *array = &rt_rq->active; struct rt_prio_array *array = &rt_rq->active;
struct list_head *queue = array->queue + rt_se_prio(rt_se);
list_move_tail(&rt_se->run_list, array->queue + rt_se_prio(rt_se)); if (on_rt_rq(rt_se))
list_move_tail(&rt_se->run_list, queue);
} }
static void requeue_task_rt(struct rq *rq, struct task_struct *p) static void requeue_task_rt(struct rq *rq, struct task_struct *p)
......
...@@ -198,6 +198,9 @@ static inline void sched_info_queued(struct task_struct *t) ...@@ -198,6 +198,9 @@ static inline void sched_info_queued(struct task_struct *t)
/* /*
* Called when a process ceases being the active-running process, either * Called when a process ceases being the active-running process, either
* voluntarily or involuntarily. Now we can calculate how long we ran. * voluntarily or involuntarily. Now we can calculate how long we ran.
* Also, if the process is still in the TASK_RUNNING state, call
* sched_info_queued() to mark that it has now again started waiting on
* the runqueue.
*/ */
static inline void sched_info_depart(struct task_struct *t) static inline void sched_info_depart(struct task_struct *t)
{ {
...@@ -206,6 +209,9 @@ static inline void sched_info_depart(struct task_struct *t) ...@@ -206,6 +209,9 @@ static inline void sched_info_depart(struct task_struct *t)
t->sched_info.cpu_time += delta; t->sched_info.cpu_time += delta;
rq_sched_info_depart(task_rq(t), delta); rq_sched_info_depart(task_rq(t), delta);
if (t->state == TASK_RUNNING)
sched_info_queued(t);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment