]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
Merge branch 'cpuidle-teo'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 23 Jan 2025 13:29:18 +0000 (14:29 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 23 Jan 2025 13:29:18 +0000 (14:29 +0100)
Two mistakes were made back at the time when the teo governor was
rearranged to avoid calling tick_nohz_get_sleep_length() every time it
was looking for a CPU idle state.  One of them was to make it always
skip calling tick_nohz_get_sleep_length() when idle state 0 was about
to be selected and the other one was to make skipping the invocation of
tick_nohz_get_sleep_length() in other cases conditional on whether or
not idle state 0 was a "polling" state (that is, a special sequence of
instructions continuously executed by the CPU in a loop).

One problem overlooked at that time was that, even though teo might not
need to call tick_nohz_get_sleep_length() in order to select an idle
state in some cases, it would still need to know its return value to be
able to tell whether or not the subsequent CPU wakeup would be caused by
a timer.  Without that information, it has to count the wakeup as a non-
timer one, so if there were many timer wakeups between idle state 0 and
the next enabled idle state, they would all be counted as non-timer
wakeups promoting the selection of idle state 0 in the future.  However,
in the absence of an imminent timer, it might have been better to select
the next enabled idle state instead of it.

There was an attempt to address this issue by making teo always call
tick_nohz_get_sleep_length() when idle state 0 was about to be selected
again, but that did not really play well with the systems where idle
state 1 was very shallow and it should have been preferred to idle state
0 (which was a "polling" state), which wanted to reduce the governor
latency as much as possible in the cases when idle state 0 was selected
and clearly calling tick_nohz_get_sleep_length() in those cases did not
align with that goal.

Another problem is that making the governor behavior conditional on any
particular propoerties of idle state 0 is confusing at best and it
should not have been done at all.  It was based on the assumtion that
idle state 0 would be a "polling" one only if idle state 1 would be very
close to it, so idle state 0 would only be selected in the cases when
idle duration tends to be extemely short, but that assumption turned out
to be invalid.  There are platforms in which idle state 0 is a "polling"
state and the target residency of the next enabled idle state is orders
of magnitude larger than the target residency of idle state 0.

To address the first problem described above, modify teo to count
wakeups occurring after a very small idle duration and use that metric
for avoiding tick_nohz_get_sleep_length() invocations.  Namely, if idle
duration is sufficiently small in the majority of cases taken into
account and the idle state about to be selected is shallow enough, it
should be safe to skip calling tick_nohz_get_sleep_length() and count
the subsequent wakeup as non-timer one.  This can also be done if the
idle state exit residency constraint value is small enough.  Otherwise,
it is necessary to call tick_nohz_get_sleep_length() to avoid
classifying timer wakeups inaccurately, which may adversely affect
future governor decisions.

Doing the above also helps to address the second problem because it can
be done regardless of the properties of idle state 0.

Some preliminary cleanups and preparatory changes are made in addition.

* cpuidle-teo:
  cpuidle: teo: Skip sleep length computation for low latency constraints
  cpuidle: teo: Replace time_span_ns with a flag
  cpuidle: teo: Simplify handling of total events count
  cpuidle: teo: Skip getting the sleep length if wakeups are very frequent
  cpuidle: teo: Simplify counting events used for tick management
  cpuidle: teo: Clarify two code comments
  cpuidle: teo: Drop local variable prev_intercept_idx
  cpuidle: teo: Combine candidate state index checks against 0
  cpuidle: teo: Reorder candidate state index checks
  cpuidle: teo: Rearrange idle state lookup code


Trivial merge