Revert "ANDROID: cpu/hotplug: add migration to paused_cpus"
This reverts commit e19b8ce907.
CPU Pause causes major merge conflicts with the 5.11 scheduler changes
(migrate-disable specifically), so lets revert Pause temporarily as it
is not needed urgently in android-mainline.
Signed-off-by: Quentin Perret <qperret@google.com>
Change-Id: Ibc5e502844d5e2e72cc48eede1032c89b16f5ccf
This commit is contained in:
@@ -711,10 +711,6 @@ struct task_struct {
|
||||
struct uclamp_se uclamp[UCLAMP_CNT];
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
struct list_head percpu_kthread_node;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PREEMPT_NOTIFIERS
|
||||
/* List of struct preempt_notifier: */
|
||||
struct hlist_head preempt_notifiers;
|
||||
|
||||
@@ -11,8 +11,6 @@ extern int sched_cpu_activate(unsigned int cpu);
|
||||
extern int sched_cpus_activate(struct cpumask *cpus);
|
||||
extern int sched_cpu_deactivate(unsigned int cpu);
|
||||
extern int sched_cpus_deactivate_nosync(struct cpumask *cpus);
|
||||
extern int sched_cpu_drain_rq(unsigned int cpu);
|
||||
extern void sched_cpu_drain_rq_wait(unsigned int cpu);
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
extern int sched_cpu_dying(unsigned int cpu);
|
||||
|
||||
@@ -1099,34 +1099,6 @@ EXPORT_SYMBOL_GPL(remove_cpu);
|
||||
|
||||
extern bool dl_cpu_busy(unsigned int cpu);
|
||||
|
||||
int __pause_drain_rq(struct cpumask *cpus)
|
||||
{
|
||||
unsigned int cpu;
|
||||
int err = 0;
|
||||
|
||||
/*
|
||||
* Disabling preemption avoids that one of the stopper, started from
|
||||
* sched_cpu_drain_rq(), blocks firing draining for the whole cpumask.
|
||||
*/
|
||||
preempt_disable();
|
||||
for_each_cpu(cpu, cpus) {
|
||||
err = sched_cpu_drain_rq(cpu);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
preempt_enable();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void __wait_drain_rq(struct cpumask *cpus)
|
||||
{
|
||||
unsigned int cpu;
|
||||
|
||||
for_each_cpu(cpu, cpus)
|
||||
sched_cpu_drain_rq_wait(cpu);
|
||||
}
|
||||
|
||||
int pause_cpus(struct cpumask *cpus)
|
||||
{
|
||||
int err = 0;
|
||||
@@ -1157,45 +1129,8 @@ int pause_cpus(struct cpumask *cpus)
|
||||
if (cpumask_empty(cpus))
|
||||
goto err_cpu_maps_update;
|
||||
|
||||
/*
|
||||
* Lazy migration:
|
||||
*
|
||||
* We do care about how fast a CPU can go idle and stay this in this
|
||||
* state. If we try to take the cpus_write_lock() here, we would have
|
||||
* to wait for a few dozens of ms, as this function might schedule.
|
||||
* However, we can, as a first step, flip the active mask and migrate
|
||||
* anything currently on the run-queue, to give a chance to the paused
|
||||
* CPUs to reach quickly an idle state. There's a risk meanwhile for
|
||||
* another CPU to observe an out-of-date active_mask or to incompletely
|
||||
* update a cpuset. Both problems would be resolved later in the slow
|
||||
* path, which ensures active_mask synchronization, triggers a cpuset
|
||||
* rebuild and migrate any task that would have escaped the lazy
|
||||
* migration.
|
||||
*/
|
||||
for_each_cpu(cpu, cpus)
|
||||
set_cpu_active(cpu, false);
|
||||
err = __pause_drain_rq(cpus);
|
||||
if (err) {
|
||||
__wait_drain_rq(cpus);
|
||||
for_each_cpu(cpu, cpus)
|
||||
set_cpu_active(cpu, true);
|
||||
goto err_cpu_maps_update;
|
||||
}
|
||||
|
||||
/*
|
||||
* Slow path deactivation:
|
||||
*
|
||||
* Now that paused CPUs are most likely idle, we can go through a
|
||||
* complete scheduler deactivation.
|
||||
*
|
||||
* The cpu_active_mask being already set and cpus_write_lock calling
|
||||
* synchronize_rcu(), we know that all preempt-disabled and RCU users
|
||||
* will observe the updated value.
|
||||
*/
|
||||
cpus_write_lock();
|
||||
|
||||
__wait_drain_rq(cpus);
|
||||
|
||||
cpuhp_tasks_frozen = 0;
|
||||
|
||||
if (sched_cpus_deactivate_nosync(cpus)) {
|
||||
@@ -1203,14 +1138,6 @@ int pause_cpus(struct cpumask *cpus)
|
||||
goto err_cpus_write_unlock;
|
||||
}
|
||||
|
||||
err = __pause_drain_rq(cpus);
|
||||
__wait_drain_rq(cpus);
|
||||
if (err) {
|
||||
for_each_cpu(cpu, cpus)
|
||||
sched_cpu_activate(cpu);
|
||||
goto err_cpus_write_unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* Even if living on the side of the regular HP path, pause is using
|
||||
* one of the HP step (CPUHP_AP_ACTIVE). This should be reflected on the
|
||||
|
||||
+4
-66
@@ -6786,14 +6786,11 @@ static struct task_struct *__pick_migrate_task(struct rq *rq)
|
||||
* Called with rq->lock held even though we'er in stop_machine() and
|
||||
* there's no concurrency possible, we hold the required locks anyway
|
||||
* because of lock validation efforts.
|
||||
*
|
||||
* force: if false, the function will skip CPU pinned kthreads.
|
||||
*/
|
||||
static void migrate_tasks(struct rq *dead_rq, struct rq_flags *rf, bool force)
|
||||
static void migrate_tasks(struct rq *dead_rq, struct rq_flags *rf)
|
||||
{
|
||||
struct rq *rq = dead_rq;
|
||||
struct task_struct *next, *tmp, *stop = rq->stop;
|
||||
LIST_HEAD(percpu_kthreads);
|
||||
struct task_struct *next, *stop = rq->stop;
|
||||
struct rq_flags orf = *rf;
|
||||
int dest_cpu;
|
||||
|
||||
@@ -6825,18 +6822,6 @@ static void migrate_tasks(struct rq *dead_rq, struct rq_flags *rf, bool force)
|
||||
|
||||
next = __pick_migrate_task(rq);
|
||||
|
||||
/*
|
||||
* Argh ... no iterator for tasks, we need to remove the
|
||||
* kthread from the run-queue to continue.
|
||||
*/
|
||||
if (!force && is_per_cpu_kthread(next)) {
|
||||
INIT_LIST_HEAD(&next->percpu_kthread_node);
|
||||
list_add(&next->percpu_kthread_node, &percpu_kthreads);
|
||||
deactivate_task(rq, next,
|
||||
DEQUEUE_NOCLOCK | DEQUEUE_SAVE);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rules for changing task_struct::cpus_mask are holding
|
||||
* both pi_lock and rq->lock, such that holding either
|
||||
@@ -6855,14 +6840,7 @@ static void migrate_tasks(struct rq *dead_rq, struct rq_flags *rf, bool force)
|
||||
* changed the task, WARN if weird stuff happened, because in
|
||||
* that case the above rq->lock drop is a fail too.
|
||||
*/
|
||||
if (task_rq(next) != rq || !task_on_rq_queued(next)) {
|
||||
/*
|
||||
* In the !force case, there is a hole between
|
||||
* rq_unlock() and rq_relock(), where another CPU might
|
||||
* not observe an up to date cpu_active_mask and try to
|
||||
* move tasks around.
|
||||
*/
|
||||
WARN_ON(force);
|
||||
if (WARN_ON(task_rq(next) != rq || !task_on_rq_queued(next))) {
|
||||
raw_spin_unlock(&next->pi_lock);
|
||||
continue;
|
||||
}
|
||||
@@ -6879,12 +6857,6 @@ static void migrate_tasks(struct rq *dead_rq, struct rq_flags *rf, bool force)
|
||||
raw_spin_unlock(&next->pi_lock);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(next, tmp, &percpu_kthreads,
|
||||
percpu_kthread_node) {
|
||||
activate_task(rq, next, ENQUEUE_NOCLOCK | ENQUEUE_RESTORE);
|
||||
list_del(&next->percpu_kthread_node);
|
||||
}
|
||||
|
||||
rq->stop = stop;
|
||||
}
|
||||
#endif /* CONFIG_HOTPLUG_CPU */
|
||||
@@ -6967,40 +6939,6 @@ static int cpuset_cpu_inactive(unsigned int cpu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drain_rq_cpu_stop(void *data)
|
||||
{
|
||||
struct rq *rq = this_rq();
|
||||
struct rq_flags rf;
|
||||
|
||||
rq_lock_irqsave(rq, &rf);
|
||||
migrate_tasks(rq, &rf, false);
|
||||
rq_unlock_irqrestore(rq, &rf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sched_cpu_drain_rq(unsigned int cpu)
|
||||
{
|
||||
struct cpu_stop_work *rq_drain = &(cpu_rq(cpu)->drain);
|
||||
struct cpu_stop_done *rq_drain_done = &(cpu_rq(cpu)->drain_done);
|
||||
|
||||
if (idle_cpu(cpu)) {
|
||||
rq_drain->done = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return stop_one_cpu_async(cpu, drain_rq_cpu_stop, NULL, rq_drain,
|
||||
rq_drain_done);
|
||||
}
|
||||
|
||||
void sched_cpu_drain_rq_wait(unsigned int cpu)
|
||||
{
|
||||
struct cpu_stop_work *rq_drain = &(cpu_rq(cpu)->drain);
|
||||
|
||||
if (rq_drain->done)
|
||||
cpu_stop_work_wait(rq_drain);
|
||||
}
|
||||
|
||||
int sched_cpu_activate(unsigned int cpu)
|
||||
{
|
||||
struct rq *rq = cpu_rq(cpu);
|
||||
@@ -7152,7 +7090,7 @@ int sched_cpu_dying(unsigned int cpu)
|
||||
BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span));
|
||||
set_rq_offline(rq);
|
||||
}
|
||||
migrate_tasks(rq, &rf, true);
|
||||
migrate_tasks(rq, &rf);
|
||||
BUG_ON(rq->nr_running != 1);
|
||||
rq_unlock_irqrestore(rq, &rf);
|
||||
|
||||
|
||||
@@ -1051,11 +1051,6 @@ struct rq {
|
||||
unsigned int ttwu_local;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
struct cpu_stop_work drain;
|
||||
struct cpu_stop_done drain_done;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CPU_IDLE
|
||||
/* Must be inspected within a rcu lock section */
|
||||
struct cpuidle_state *idle_state;
|
||||
|
||||
Reference in New Issue
Block a user