Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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. But that's not all! Task structs can be freed outside of release_task(), which creates another memory leak because a task struct can be freed without having its cpufreq stats allocation freed. To fix this, free the cpufreq stats allocation at the same time that task struct allocations are freed. Signed-off-by: Sultan Alsawaf <sultanxda@gmail.com>
- Loading branch information