From 3c5147122eb016112670e168153237a1fb43c018 Mon Sep 17 00:00:00 2001 From: Sultan Alsawaf Date: Sun, 3 Jun 2018 10:47:51 -0700 Subject: [PATCH] kernel: Fix massive cpufreq stats memory leaks Every time _cpu_up() is called for a CPU, idle_thread_get() is called which then re-initializes a CPU's idle thread that was already previously created and cached in a global variable in smpboot.c. idle_thread_get() calls init_idle() which then calls __sched_fork(). __sched_fork() is where cpufreq_task_stats_init() is, and cpufreq_task_stats_init() allocates 512 bytes of memory to a pointer in the task struct. Since idle_thread_get() reuses a task struct instance that was already previously created, this means that every time it calls init_idle(), cpufreq_task_stats_init() allocates 512 bytes again and overwrites the existing 512-byte allocation that the idle thread already had. This causes 512 bytes to be leaked every time a CPU is onlined. This is significant when non-boot CPUs are enabled during resume from suspend; this means that (NR_CPUS - 1) * 512 bytes are leaked every time the device exits suspend (this turned out to be ~500 kiB leaked in 20 minutes with the device left on a desk with the screen off). In order to fix this, don't initialize cpufreq stats at all for the idle threads. The cpufreq stats interface is intended to be used for tracking userspace tasks, so we can safely remove it from the kernel's idle threads without killing any functionality. Change-Id: I12fe7611fc88eb7f6c39f8f7629ad27b6ec4722c Signed-off-by: Sultan Alsawaf --- kernel/sched/core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 517bdbf02d1..7bf72e0c3c1 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1738,10 +1738,6 @@ static void __sched_fork(struct task_struct *p) memset(&p->se.statistics, 0, sizeof(p->se.statistics)); #endif -#ifdef CONFIG_CPU_FREQ_STAT - cpufreq_task_stats_init(p); -#endif - INIT_LIST_HEAD(&p->rt.run_list); #ifdef CONFIG_PREEMPT_NOTIFIERS @@ -1790,6 +1786,10 @@ void sched_fork(struct task_struct *p) unsigned long flags; int cpu = get_cpu(); +#ifdef CONFIG_CPU_FREQ_STAT + cpufreq_task_stats_init(p); +#endif + __sched_fork(p); /* * We mark the process as running here. This guarantees that -- 2.20.1