kernel: Fix massive cpufreq stats memory leaks
authorSultan Alsawaf <sultanxda@gmail.com>
Sun, 3 Jun 2018 17:47:51 +0000 (10:47 -0700)
committerDanny Wood <danwood76@gmail.com>
Mon, 8 Apr 2019 09:21:25 +0000 (10:21 +0100)
commit3c5147122eb016112670e168153237a1fb43c018
tree636aed3b8541d648fdf8e048159c84836aab91b9
parent19d0e7ea41f1683872ad9adc2cfc5328007541f2
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 <sultanxda@gmail.com>
kernel/sched/core.c