lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Wed, 26 Jun 2024 15:09:57 +0200
From: Dietmar Eggemann <dietmar.eggemann@....com>
To: Christian Loehle <christian.loehle@....com>, linux-pm@...r.kernel.org,
 linux-kernel@...r.kernel.org, rafael@...nel.org
Cc: vincent.guittot@...aro.org, qyousef@...alina.io, peterz@...radead.org,
 daniel.lezcano@...aro.org, ulf.hansson@...aro.org, anna-maria@...utronix.de,
 kajetan.puchalski@....com, lukasz.luba@....com
Subject: Re: [PATCHv2 3/3] cpuidle: teo: Don't count non-existent intercepts

On 11/06/2024 13:24, Christian Loehle wrote:
> When bailing out early, teo will not query the sleep length anymore
> since commit 6da8f9ba5a87 ("cpuidle: teo:
> Skip tick_nohz_get_sleep_length() call in some cases") with an
> expected sleep_length_ns value of KTIME_MAX.
> This lead to state0 accumulating lots of 'intercepts' because
> the actually measured sleep length was < KTIME_MAX, so count KTIME_MAX
> as a hit (we have to count them as something otherwise we are stuck)
> and therefore teo taking too long to recover from intercept-heavy
> scenarios.
> 
> Fundamentally we can only do one of the two:
> 1. Skip sleep_length_ns query when we think intercept is likely

Isn't this what we do right now? Skip tick_nohz_get_sleep_length() for
state0 and set cpu_data->sleep_length_ns to KTIME_MAX in teo_select()
and then count this as an 'intercept' in teo_update().

> 2. Have accurate data if sleep_length_ns is actually intercepted when
> we believe it is currently intercepted.
> 
> This patch chooses the latter as I've found the additional time it
> takes to query the sleep length to be negligible and the variants of
> option 1 (count all unknowns as misses or count all unknown as hits)
> had significant regressions (as misses had lots of too shallow idle
> state selections and as hits had terrible performance in
> intercept-heavy workloads).

IMHO, you do 2 things here:

(1) Set 'cpu_data->sleep_length_ns != KTIME_MAX' for '!idx &&
    prev_intercept_idx' in teo_select().

(2) Force an update with 'cpu_data->sleep_length_ns == KTIME_MAX' to be
    counted as a 'hit' rather an 'intercept' in teo_update().

Can't really see how this matches the explanatory text exactly.


> 
> Fixes: 6da8f9ba5a87 ("cpuidle: teo: Skip tick_nohz_get_sleep_length() call in some cases")
> Signed-off-by: Christian Loehle <christian.loehle@....com>
> ---
>  drivers/cpuidle/governors/teo.c | 18 ++++++++++++++++--
>  1 file changed, 16 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/cpuidle/governors/teo.c b/drivers/cpuidle/governors/teo.c
> index cc7df59f488d..1e4b40474f49 100644
> --- a/drivers/cpuidle/governors/teo.c
> +++ b/drivers/cpuidle/governors/teo.c
> @@ -231,8 +231,13 @@ static void teo_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
>  	 * length, this is a "hit", so update the "hits" metric for that bin.
>  	 * Otherwise, update the "intercepts" metric for the bin fallen into by
>  	 * the measured idle duration.
> +	 * If teo_select() bailed out early, we have to count this as a hit as
> +	 * we don't know what the true sleep length would've been. Otherwise
> +	 * we accumulate lots of intercepts at the shallower state (especially
> +	 * state0) even though there weren't any intercepts due to us
> +	 * anticipating one.
>  	 */
> -	if (idx_timer == idx_duration)
> +	if (idx_timer == idx_duration || cpu_data->sleep_length_ns == KTIME_MAX)
>  		cpu_data->state_bins[idx_timer].hits += PULSE;
>  	else
>  		cpu_data->state_bins[idx_duration].intercepts += PULSE;
> @@ -292,7 +297,7 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
>  	unsigned int hit_sum = 0;
>  	int constraint_idx = 0;
>  	int idx0 = 0, idx = -1;
> -	bool alt_intercepts, alt_recent;
> +	int prev_intercept_idx;
>  	s64 duration_ns;
>  	int i;
>  
> @@ -370,6 +375,7 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
>  	 * all of the deeper states a shallower idle state is likely to be a
>  	 * better choice.
>  	 */
> +	prev_intercept_idx = idx;
>  	if (2 * idx_intercept_sum > cpu_data->total - idx_hit_sum) {
>  		int first_suitable_idx = idx;
>  
> @@ -421,6 +427,14 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
>  			first_suitable_idx = i;
>  		}
>  	}
> +	if (!idx && prev_intercept_idx) {
> +		/*
> +		 * We have to query the sleep length here otherwise we don't
> +		 * know after wakeup if our guess was correct.
> +		 */
> +		duration_ns = tick_nohz_get_sleep_length(&delta_tick);
> +		cpu_data->sleep_length_ns = duration_ns;
> +	}
>  
>  	/*
>  	 * If there is a latency constraint, it may be necessary to select an


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ