Skip to content

Commit

Permalink
cpuidle: menu: Better idle duration measurement without using CPUIDLE…
Browse files Browse the repository at this point in the history
…_FLAG_TIME_INVALID

When menu sees CPUIDLE_FLAG_TIME_INVALID, it ignores its timestamps,
and assumes that idle lasted as long as the time till next predicted
timer expiration.

But if an interrupt was seen and serviced before that duration,
it would actually be more accurate to use the measured time
rather than rounding up to the next predicted timer expiration.

And if an interrupt is seen and serviced such that the mesured time
exceeds the time till next predicted timer expiration, then
truncating to that expiration is the right thing to do --
since we can never stay idle past that timer expiration.

So the code can do a better job without
checking for CPUIDLE_FLAG_TIME_INVALID.

Signed-off-by: Len Brown <len.brown@intel.com>
Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Reviewed-by: Tuukka Tikkanen <tuukka.tikkanen@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  • Loading branch information
Len Brown authored and Rafael J. Wysocki committed Dec 17, 2014
1 parent 0c570c1 commit 4108b3d
Showing 1 changed file with 10 additions and 15 deletions.
25 changes: 10 additions & 15 deletions drivers/cpuidle/governors/menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -396,31 +396,26 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
* power state and occurrence of the wakeup event.
*
* If the entered idle state didn't support residency measurements,
* we are basically lost in the dark how much time passed.
* As a compromise, assume we slept for the whole expected time.
* we use them anyway if they are short, and if long,
* truncate to the whole expected time.
*
* Any measured amount of time will include the exit latency.
* Since we are interested in when the wakeup begun, not when it
* was completed, we must subtract the exit latency. However, if
* the measured amount of time is less than the exit latency,
* assume the state was never reached and the exit latency is 0.
*/
if (unlikely(target->flags & CPUIDLE_FLAG_TIME_INVALID)) {
/* Use timer value as is */
measured_us = data->next_timer_us;

} else {
/* Use measured value */
measured_us = cpuidle_get_last_residency(dev);
/* measured value */
measured_us = cpuidle_get_last_residency(dev);

/* Deduct exit latency */
if (measured_us > target->exit_latency)
measured_us -= target->exit_latency;
/* Deduct exit latency */
if (measured_us > target->exit_latency)
measured_us -= target->exit_latency;

/* Make sure our coefficients do not exceed unity */
if (measured_us > data->next_timer_us)
measured_us = data->next_timer_us;
}
/* Make sure our coefficients do not exceed unity */
if (measured_us > data->next_timer_us)
measured_us = data->next_timer_us;

/* Update our correction ratio */
new_factor = data->correction_factor[data->bucket];
Expand Down

0 comments on commit 4108b3d

Please sign in to comment.