|
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