From c2dc4297f139019e5fb8416a51618f94e5f3eb9f Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 12 Feb 2019 15:03:03 +0100 Subject: [PATCH 149/298] psi: replace delayed work with timer + work psi_task_change() is invoked with disabled interrupts and this does not allow to use schedule_delayed_work(). Replace schedule_delayed_work() with a timer which schedules the work immediately. Signed-off-by: Sebastian Andrzej Siewior --- include/linux/psi_types.h | 3 ++- kernel/sched/psi.c | 39 ++++++++++++++++++++++++++++++--------- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/include/linux/psi_types.h b/include/linux/psi_types.h index 2cf422db5d18..89a89f697c33 100644 --- a/include/linux/psi_types.h +++ b/include/linux/psi_types.h @@ -76,7 +76,8 @@ struct psi_group { u64 total_prev[NR_PSI_STATES - 1]; u64 last_update; u64 next_update; - struct delayed_work clock_work; + struct work_struct clock_work; + struct timer_list clock_work_timer; /* Total stall times and sampled pressure averages */ u64 total[NR_PSI_STATES - 1]; diff --git a/kernel/sched/psi.c b/kernel/sched/psi.c index 0e97ca9306ef..b59c557cca0a 100644 --- a/kernel/sched/psi.c +++ b/kernel/sched/psi.c @@ -124,6 +124,7 @@ * sampling of the aggregate task states would be. */ +#include #include "../workqueue_internal.h" #include #include @@ -131,7 +132,6 @@ #include #include #include -#include #include #include "sched.h" @@ -166,6 +166,7 @@ static struct psi_group psi_system = { }; static void psi_update_work(struct work_struct *work); +static void psi_sched_update_work(struct timer_list *t); static void group_init(struct psi_group *group) { @@ -174,7 +175,8 @@ static void group_init(struct psi_group *group) for_each_possible_cpu(cpu) seqcount_init(&per_cpu_ptr(group->pcpu, cpu)->seq); group->next_update = sched_clock() + psi_period; - INIT_DELAYED_WORK(&group->clock_work, psi_update_work); + INIT_WORK(&group->clock_work, psi_update_work); + timer_setup(&group->clock_work_timer, psi_sched_update_work, 0); mutex_init(&group->stat_lock); } @@ -367,14 +369,14 @@ static bool update_stats(struct psi_group *group) return nonidle_total; } +static void psi_sched_delayed_work(struct psi_group *group, unsigned long delay); + static void psi_update_work(struct work_struct *work) { - struct delayed_work *dwork; struct psi_group *group; bool nonidle; - dwork = to_delayed_work(work); - group = container_of(dwork, struct psi_group, clock_work); + group = container_of(work, struct psi_group, clock_work); /* * If there is task activity, periodically fold the per-cpu @@ -393,7 +395,7 @@ static void psi_update_work(struct work_struct *work) now = sched_clock(); if (group->next_update > now) delay = nsecs_to_jiffies(group->next_update - now) + 1; - schedule_delayed_work(dwork, delay); + psi_sched_delayed_work(group, delay); } } @@ -507,6 +509,20 @@ static struct psi_group *iterate_groups(struct task_struct *task, void **iter) return &psi_system; } +static void psi_sched_update_work(struct timer_list *t) +{ + struct psi_group *group = from_timer(group, t, clock_work_timer); + + schedule_work(&group->clock_work); +} + +static void psi_sched_delayed_work(struct psi_group *group, unsigned long delay) +{ + if (!timer_pending(&group->clock_work_timer) && + !work_pending(&group->clock_work)) + mod_timer(&group->clock_work_timer, delay); +} + void psi_task_change(struct task_struct *task, int clear, int set) { int cpu = task_cpu(task); @@ -540,10 +556,14 @@ void psi_task_change(struct task_struct *task, int clear, int set) wq_worker_last_func(task) == psi_update_work)) wake_clock = false; + if (wake_clock) { + if (task_is_ktimer_softirqd(task)) + wake_clock = false; + } while ((group = iterate_groups(task, &iter))) { psi_group_change(group, cpu, clear, set); - if (wake_clock && !delayed_work_pending(&group->clock_work)) - schedule_delayed_work(&group->clock_work, PSI_FREQ); + if (wake_clock) + psi_sched_delayed_work(group, PSI_FREQ); } } @@ -640,7 +660,8 @@ void psi_cgroup_free(struct cgroup *cgroup) if (static_branch_likely(&psi_disabled)) return; - cancel_delayed_work_sync(&cgroup->psi.clock_work); + del_timer_sync(&cgroup->psi.clock_work_timer); + cancel_work_sync(&cgroup->psi.clock_work); free_percpu(cgroup->psi.pcpu); } -- 2.19.1