|
41 | 41 | * idle state 2, the third bin spans from the target residency of idle state 2
|
42 | 42 | * up to, but not including, the target residency of idle state 3 and so on.
|
43 | 43 | * 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. |
49 | 45 | *
|
50 | 46 | * Two metrics called "hits" and "intercepts" are associated with each bin.
|
51 | 47 | * They are updated every time before selecting an idle state for the given CPU
|
|
60 | 56 | * into by the sleep length (these events are also referred to as "intercepts"
|
61 | 57 | * below).
|
62 | 58 | *
|
| 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 | + * |
63 | 63 | * In order to select an idle state for a CPU, the governor takes the following
|
64 | 64 | * steps (modulo the possible latency constraint that must be taken into account
|
65 | 65 | * too):
|
@@ -128,14 +128,14 @@ struct teo_bin {
|
128 | 128 | * @sleep_length_ns: Time till the closest timer event (at the selection time).
|
129 | 129 | * @state_bins: Idle state data bins for this CPU.
|
130 | 130 | * @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. |
132 | 132 | */
|
133 | 133 | struct teo_cpu {
|
134 | 134 | s64 time_span_ns;
|
135 | 135 | s64 sleep_length_ns;
|
136 | 136 | struct teo_bin state_bins[CPUIDLE_STATE_MAX];
|
137 | 137 | unsigned int total;
|
138 |
| - unsigned int tick_hits; |
| 138 | + unsigned int tick_intercepts; |
139 | 139 | };
|
140 | 140 |
|
141 | 141 | 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)
|
207 | 207 | }
|
208 | 208 | }
|
209 | 209 |
|
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; |
230 | 211 | /*
|
231 | 212 | * If the measured idle duration falls into the same bin as the sleep
|
232 | 213 | * length, this is a "hit", so update the "hits" metric for that bin.
|
233 | 214 | * Otherwise, update the "intercepts" metric for the bin fallen into by
|
234 | 215 | * the measured idle duration.
|
235 | 216 | */
|
236 |
| - if (idx_timer == idx_duration) |
| 217 | + if (idx_timer == idx_duration) { |
237 | 218 | cpu_data->state_bins[idx_timer].hits += PULSE;
|
238 |
| - else |
| 219 | + } else { |
239 | 220 | cpu_data->state_bins[idx_duration].intercepts += PULSE;
|
| 221 | + if (TICK_NSEC <= measured_ns) |
| 222 | + cpu_data->tick_intercepts += PULSE; |
| 223 | + } |
240 | 224 |
|
241 |
| -end: |
242 | 225 | cpu_data->total += PULSE;
|
243 | 226 | }
|
244 | 227 |
|
@@ -286,7 +269,6 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
|
286 | 269 | struct teo_cpu *cpu_data = per_cpu_ptr(&teo_cpus, dev->cpu);
|
287 | 270 | s64 latency_req = cpuidle_governor_latency_req(dev->cpu);
|
288 | 271 | ktime_t delta_tick = TICK_NSEC / 2;
|
289 |
| - unsigned int tick_intercept_sum = 0; |
290 | 272 | unsigned int idx_intercept_sum = 0;
|
291 | 273 | unsigned int intercept_sum = 0;
|
292 | 274 | unsigned int idx_hit_sum = 0;
|
@@ -365,9 +347,6 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
|
365 | 347 | goto end;
|
366 | 348 | }
|
367 | 349 |
|
368 |
| - tick_intercept_sum = intercept_sum + |
369 |
| - cpu_data->state_bins[drv->state_count-1].intercepts; |
370 |
| - |
371 | 350 | /*
|
372 | 351 | * If the sum of the intercepts metric for all of the idle states
|
373 | 352 | * 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,
|
477 | 456 | * total wakeup events, do not stop the tick.
|
478 | 457 | */
|
479 | 458 | 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) |
481 | 460 | duration_ns = TICK_NSEC / 2;
|
482 | 461 |
|
483 | 462 | end:
|
|
0 commit comments