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_times_init() is,
and cpufreq_task_times_init() allocates memory for the task struct's
time_in_state array.
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_times_init() allocates this array again and overwrites
the existing allocation that the idle thread already had.
This causes memory to be leaked every time a CPU is onlined. In order
to fix this, move allocation of time_in_state into _do_fork to avoid
allocating it at all for idle threads. The cpufreq times 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 times allocation freed. To fix this, free the cpufreq
times allocation at the same time that task struct allocations are
freed, in free_task().
Since free_task() can also be called in error paths of copy_process()
after dup_task_struct(), set time_in_state to NULL immediately after
calling dup_task_struct() to avoid possible double free.
Bug description and fix adapted from patch submitted by
Sultan Alsawaf <sultanxda@gmail.com> at
https://android-review.googlesource.com/c/kernel/msm/+/700134
Bug: 110044919
Test: Hikey960 builds, boots & reports /proc/<pid>/time_in_state
correctly
Change-Id: I12fe7611fc88eb7f6c39f8f7629ad27b6ec4722c
Signed-off-by: Connor O'Brien <connoro@google.com>
The header of /proc/uid_time_in_state should match the logic used for
the rest of the file by skipping invalid frequency table entries.
Test: Read /proc/uid_time_in_state and check for invalid frequencies
in header.
Signed-off-by: Connor O'Brien <connoro@google.com>
Change-Id: I96888e7b71f4928383ff7080c98c988d5fe1a95c
since the variable called uid_entry is a pointer, need to use
sizeof(*uid_entry) to allocate enough space for a full uid_entry
struct.
Bug: 74338318
Change-Id: I488a7cab849398ef7b1f4712b7746f8cf645209d
Signed-off-by: Connor O'Brien <connoro@google.com>
Read times from p->time_in_state. Remove the "times" pointer, which is
never initialized.
Bug: 75238970
Test: /proc/<pid>/time_in_state now shows some nonzero values
Change-Id: I2f375b64ec39de034da3e24e5e5fb58b04958b76
Signed-off-by: Connor O'Brien <connoro@google.com>
__krealloc may return the same pointer that's passed in if the
original allocation provided enough memory to accommodate the new
request. In this case the "old" uid_entry should not be freed or
replaced in uid_hash_table, so add a check to avoid doing so.
Bug: 74338318
Test: Hikey960 boots & shows reasonable UID numbers
Change-Id: Id1a094f60a8ffcc827358d0f40c9f3ff70719cce
Signed-off-by: Connor O'Brien <connoro@google.com>
Add per-uid files that report the data in binary format rather than
text, to allow faster reading & parsing by userspace.
Signed-off-by: Connor O'Brien <connoro@google.com>
Bug: 72339335
Test: compare values to those reported in /proc/uid_time_in_state
Change-Id: I463039ea7f17b842be4c70024fe772539fe2ce02
Add time in state data to task structs, and create
/proc/<pid>/time_in_state files to show how long each individual task
has run at each frequency.
Create a CONFIG_CPU_FREQ_TIMES option to enable/disable this tracking.
Signed-off-by: Connor O'Brien <connoro@google.com>
Bug: 72339335
Test: Read /proc/<pid>/time_in_state
Change-Id: Ia6456754f4cb1e83b2bc35efa8fbe9f8696febc8