summaryrefslogtreecommitdiffstats
path: root/kernel/sched/psi.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab+samsung@kernel.org>2019-02-18 10:12:12 -0500
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>2019-02-18 10:12:12 -0500
commit5f09bc8cc4010a3ea17c5881a62fc45192ebe7b0 (patch)
treec8e30ba4eaf357699ef97a786bf56661f4591be8 /kernel/sched/psi.c
parent6fd369dd1cb65a032f1ab9227033ecb7b759656d (diff)
parenta3b22b9f11d9fbc48b0291ea92259a5a810e9438 (diff)
downloadlinux-5f09bc8cc4010a3ea17c5881a62fc45192ebe7b0.tar.bz2
Merge tag 'v5.0-rc7' into patchwork
Linux 5.0-rc7 * tag 'v5.0-rc7': (1667 commits) Linux 5.0-rc7 Input: elan_i2c - add ACPI ID for touchpad in Lenovo V330-15ISK Input: st-keyscan - fix potential zalloc NULL dereference Input: apanel - switch to using brightness_set_blocking() powerpc/64s: Fix possible corruption on big endian due to pgd/pud_present() efi/arm: Revert "Defer persistent reservations until after paging_init()" arm64, mm, efi: Account for GICv3 LPI tables in static memblock reserve table sunrpc: fix 4 more call sites that were using stack memory with a scatterlist include/linux/module.h: copy __init/__exit attrs to init/cleanup_module Compiler Attributes: add support for __copy (gcc >= 9) lib/crc32.c: mark crc32_le_base/__crc32c_le_base aliases as __pure auxdisplay: ht16k33: fix potential user-after-free on module unload x86/platform/UV: Use efi_runtime_lock to serialise BIOS calls i2c: bcm2835: Clear current buffer pointers and counts after a transfer i2c: cadence: Fix the hold bit setting drm: Use array_size() when creating lease dm thin: fix bug where bio that overwrites thin block ignores FUA Revert "exec: load_script: don't blindly truncate shebang string" Revert "gfs2: read journal in large chunks to locate the head" net: ethernet: freescale: set FEC ethtool regs version ... Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Diffstat (limited to 'kernel/sched/psi.c')
-rw-r--r--kernel/sched/psi.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/kernel/sched/psi.c b/kernel/sched/psi.c
index fe24de3fbc93..c3484785b179 100644
--- a/kernel/sched/psi.c
+++ b/kernel/sched/psi.c
@@ -124,6 +124,7 @@
* sampling of the aggregate task states would be.
*/
+#include "../workqueue_internal.h"
#include <linux/sched/loadavg.h>
#include <linux/seq_file.h>
#include <linux/proc_fs.h>
@@ -480,9 +481,6 @@ static void psi_group_change(struct psi_group *group, int cpu,
groupc->tasks[t]++;
write_seqcount_end(&groupc->seq);
-
- if (!delayed_work_pending(&group->clock_work))
- schedule_delayed_work(&group->clock_work, PSI_FREQ);
}
static struct psi_group *iterate_groups(struct task_struct *task, void **iter)
@@ -513,6 +511,7 @@ void psi_task_change(struct task_struct *task, int clear, int set)
{
int cpu = task_cpu(task);
struct psi_group *group;
+ bool wake_clock = true;
void *iter = NULL;
if (!task->pid)
@@ -530,8 +529,22 @@ void psi_task_change(struct task_struct *task, int clear, int set)
task->psi_flags &= ~clear;
task->psi_flags |= set;
- while ((group = iterate_groups(task, &iter)))
+ /*
+ * Periodic aggregation shuts off if there is a period of no
+ * task changes, so we wake it back up if necessary. However,
+ * don't do this if the task change is the aggregation worker
+ * itself going to sleep, or we'll ping-pong forever.
+ */
+ if (unlikely((clear & TSK_RUNNING) &&
+ (task->flags & PF_WQ_WORKER) &&
+ wq_worker_last_func(task) == psi_update_work))
+ 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);
+ }
}
void psi_memstall_tick(struct task_struct *task, int cpu)