Skip to content

Commit d619b5c

Browse files
committed
cpuidle: teo: Simplify counting events used for tick management
Replace the tick_hits metric with a new tick_intercepts one that can be used directly when deciding whether or not to stop the scheduler tick and update the governor functional description accordingly. No intentional functional impact. Signed-off-by: Rafael J. Wysocki <[email protected]> Reviewed-by: Christian Loehle <[email protected]> Tested-by: Aboorva Devarajan <[email protected]> Tested-by: Christian Loehle <[email protected]> Link: https://patch.msgid.link/[email protected]
1 parent e24f8a5 commit d619b5c

File tree

1 file changed

+14
-35
lines changed
  • drivers/cpuidle/governors

1 file changed

+14
-35
lines changed

drivers/cpuidle/governors/teo.c

Lines changed: 14 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,7 @@
4141
* idle state 2, the third bin spans from the target residency of idle state 2
4242
* up to, but not including, the target residency of idle state 3 and so on.
4343
* The last bin spans from the target residency of the deepest idle state
44-
* supplied by the driver to the scheduler tick period length or to infinity if
45-
* the tick period length is less than the target residency of that state. In
46-
* the latter case, the governor also counts events with the measured idle
47-
* duration between the tick period length and the target residency of the
48-
* deepest idle state.
44+
* supplied by the driver to infinity.
4945
*
5046
* Two metrics called "hits" and "intercepts" are associated with each bin.
5147
* They are updated every time before selecting an idle state for the given CPU
@@ -60,6 +56,10 @@
6056
* into by the sleep length (these events are also referred to as "intercepts"
6157
* below).
6258
*
59+
* The governor also counts "intercepts" with the measured idle duration below
60+
* the tick period length and uses this information when deciding whether or not
61+
* to stop the scheduler tick.
62+
*
6363
* In order to select an idle state for a CPU, the governor takes the following
6464
* steps (modulo the possible latency constraint that must be taken into account
6565
* too):
@@ -128,14 +128,14 @@ struct teo_bin {
128128
* @sleep_length_ns: Time till the closest timer event (at the selection time).
129129
* @state_bins: Idle state data bins for this CPU.
130130
* @total: Grand total of the "intercepts" and "hits" metrics for all bins.
131-
* @tick_hits: Number of "hits" after TICK_NSEC.
131+
* @tick_intercepts: "Intercepts" before TICK_NSEC.
132132
*/
133133
struct teo_cpu {
134134
s64 time_span_ns;
135135
s64 sleep_length_ns;
136136
struct teo_bin state_bins[CPUIDLE_STATE_MAX];
137137
unsigned int total;
138-
unsigned int tick_hits;
138+
unsigned int tick_intercepts;
139139
};
140140

141141
static DEFINE_PER_CPU(struct teo_cpu, teo_cpus);
@@ -207,38 +207,21 @@ static void teo_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
207207
}
208208
}
209209

210-
/*
211-
* If the deepest state's target residency is below the tick length,
212-
* make a record of it to help teo_select() decide whether or not
213-
* to stop the tick. This effectively adds an extra hits-only bin
214-
* beyond the last state-related one.
215-
*/
216-
if (target_residency_ns < TICK_NSEC) {
217-
cpu_data->tick_hits -= cpu_data->tick_hits >> DECAY_SHIFT;
218-
219-
cpu_data->total += cpu_data->tick_hits;
220-
221-
if (TICK_NSEC <= cpu_data->sleep_length_ns) {
222-
idx_timer = drv->state_count;
223-
if (TICK_NSEC <= measured_ns) {
224-
cpu_data->tick_hits += PULSE;
225-
goto end;
226-
}
227-
}
228-
}
229-
210+
cpu_data->tick_intercepts -= cpu_data->tick_intercepts >> DECAY_SHIFT;
230211
/*
231212
* If the measured idle duration falls into the same bin as the sleep
232213
* length, this is a "hit", so update the "hits" metric for that bin.
233214
* Otherwise, update the "intercepts" metric for the bin fallen into by
234215
* the measured idle duration.
235216
*/
236-
if (idx_timer == idx_duration)
217+
if (idx_timer == idx_duration) {
237218
cpu_data->state_bins[idx_timer].hits += PULSE;
238-
else
219+
} else {
239220
cpu_data->state_bins[idx_duration].intercepts += PULSE;
221+
if (TICK_NSEC <= measured_ns)
222+
cpu_data->tick_intercepts += PULSE;
223+
}
240224

241-
end:
242225
cpu_data->total += PULSE;
243226
}
244227

@@ -286,7 +269,6 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
286269
struct teo_cpu *cpu_data = per_cpu_ptr(&teo_cpus, dev->cpu);
287270
s64 latency_req = cpuidle_governor_latency_req(dev->cpu);
288271
ktime_t delta_tick = TICK_NSEC / 2;
289-
unsigned int tick_intercept_sum = 0;
290272
unsigned int idx_intercept_sum = 0;
291273
unsigned int intercept_sum = 0;
292274
unsigned int idx_hit_sum = 0;
@@ -365,9 +347,6 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
365347
goto end;
366348
}
367349

368-
tick_intercept_sum = intercept_sum +
369-
cpu_data->state_bins[drv->state_count-1].intercepts;
370-
371350
/*
372351
* If the sum of the intercepts metric for all of the idle states
373352
* shallower than the current candidate one (idx) is greater than the
@@ -477,7 +456,7 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
477456
* total wakeup events, do not stop the tick.
478457
*/
479458
if (drv->states[idx].target_residency_ns < TICK_NSEC &&
480-
tick_intercept_sum > cpu_data->total / 2 + cpu_data->total / 8)
459+
cpu_data->tick_intercepts > cpu_data->total / 2 + cpu_data->total / 8)
481460
duration_ns = TICK_NSEC / 2;
482461

483462
end:

0 commit comments

Comments
 (0)