ANDROID: cpufreq: times: don't copy invalid freqs from freq table
Invalid frequency checks are a bottleneck in reading
/proc/uid_time_in_state, but there's no reason to include invalid
frequencies in our local copies of frequency tables. Revise
cpufreq_times_create_policy() to only copy valid frequencies, and
eliminate all the checks this change makes unnecessary.
Bug: 111216804
Test: cat /proc/uid_time_in_state & confirm values & format are sane
Test: /proc/uid_time_in_state read times reduced by ~40%
Change-Id: I506420a6ac5fe8a6c87d01b16ad267b192d43f1d
Signed-off-by: Connor O'Brien <connoro@google.com>
diff --git a/drivers/cpufreq/cpufreq_times.c b/drivers/cpufreq/cpufreq_times.c
index 2883d67..5b5248a 100644
--- a/drivers/cpufreq/cpufreq_times.c
+++ b/drivers/cpufreq/cpufreq_times.c
@@ -137,27 +137,10 @@
return uid_entry;
}
-static bool freq_index_invalid(unsigned int index)
-{
- unsigned int cpu;
- struct cpu_freqs *freqs;
-
- for_each_possible_cpu(cpu) {
- freqs = all_freqs[cpu];
- if (!freqs || index < freqs->offset ||
- freqs->offset + freqs->max_state <= index)
- continue;
- return freqs->freq_table[index - freqs->offset] ==
- CPUFREQ_ENTRY_INVALID;
- }
- return true;
-}
-
static int single_uid_time_in_state_show(struct seq_file *m, void *ptr)
{
struct uid_entry *uid_entry;
unsigned int i;
- u64 time;
uid_t uid = from_kuid_munged(current_user_ns(), *(kuid_t *)m->private);
if (uid == overflowuid)
@@ -172,9 +155,7 @@
}
for (i = 0; i < uid_entry->max_state; ++i) {
- if (freq_index_invalid(i))
- continue;
- time = nsec_to_clock_t(uid_entry->time_in_state[i]);
+ u64 time = nsec_to_clock_t(uid_entry->time_in_state[i]);
seq_write(m, &time, sizeof(time));
}
@@ -219,9 +200,6 @@
continue;
last_freqs = freqs;
for (i = 0; i < freqs->max_state; i++) {
- if (freqs->freq_table[i] ==
- CPUFREQ_ENTRY_INVALID)
- continue;
seq_put_decimal_ull(m, " ",
freqs->freq_table[i]);
}
@@ -237,10 +215,7 @@
seq_putc(m, ':');
}
for (i = 0; i < uid_entry->max_state; ++i) {
- u64 time;
- if (freq_index_invalid(i))
- continue;
- time = nsec_to_clock_t(uid_entry->time_in_state[i]);
+ u64 time = nsec_to_clock_t(uid_entry->time_in_state[i]);
seq_put_decimal_ull(m, " ", time);
}
if (uid_entry->max_state)
@@ -407,8 +382,6 @@
seq_printf(m, "cpu%u\n", cpu);
for (i = 0; i < freqs->max_state; i++) {
- if (freqs->freq_table[i] == CPUFREQ_ENTRY_INVALID)
- continue;
cputime = 0;
if (freqs->offset + i < p->max_state &&
p->time_in_state)
@@ -488,9 +461,19 @@
rcu_read_unlock();
}
+static int cpufreq_times_get_index(struct cpu_freqs *freqs, unsigned int freq)
+{
+ int index;
+ for (index = 0; index < freqs->max_state; ++index) {
+ if (freqs->freq_table[index] == freq)
+ return index;
+ }
+ return -1;
+}
+
void cpufreq_times_create_policy(struct cpufreq_policy *policy)
{
- int cpu, index;
+ int cpu, index = 0;
unsigned int count = 0;
struct cpufreq_frequency_table *pos, *table;
struct cpu_freqs *freqs;
@@ -503,7 +486,7 @@
if (!table)
return;
- cpufreq_for_each_entry(pos, table)
+ cpufreq_for_each_valid_entry(pos, table)
count++;
tmp = kzalloc(sizeof(*freqs) + sizeof(freqs->freq_table[0]) * count,
@@ -514,13 +497,13 @@
freqs = tmp;
freqs->max_state = count;
- index = cpufreq_frequency_table_get_index(policy, policy->cur);
+ cpufreq_for_each_valid_entry(pos, table)
+ freqs->freq_table[index++] = pos->frequency;
+
+ index = cpufreq_times_get_index(freqs, policy->cur);
if (index >= 0)
WRITE_ONCE(freqs->last_index, index);
- cpufreq_for_each_entry(pos, table)
- freqs->freq_table[pos - table] = pos->frequency;
-
freqs->offset = next_offset;
WRITE_ONCE(next_offset, freqs->offset + count);
for_each_cpu(cpu, policy->related_cpus)
@@ -564,7 +547,7 @@
if (!freqs)
return;
- index = cpufreq_frequency_table_get_index(policy, new_freq);
+ index = cpufreq_times_get_index(freqs, new_freq);
if (index >= 0)
WRITE_ONCE(freqs->last_index, index);
}