mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Zhongqiu Han <zhongqiu.han@oss.qualcomm.com>
To: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: viresh.kumar@linaro.org, venkatesh.pallipadi@intel.com,
	davej@redhat.com, trenn@suse.de, linux-pm@vger.kernel.org,
	linux-kernel@vger.kernel.org, zhongqiu.han@oss.qualcomm.com
Subject: Re: [PATCH v3 0/2] governor: Fix races and stale baseline on prev_cpu_nice
Date: Sun, 24 May 2026 13:57:09 +0800	[thread overview]
Message-ID: <0b1ff222-ecda-4b21-9604-7d4e8fc86279@oss.qualcomm.com> (raw)
In-Reply-To: <CAJZ5v0i_KhPRkh-p2pCKgV+UKO5bnTJF0TVbQNsjpY4iBO3w+g@mail.gmail.com>

On 5/22/2026 11:14 PM, Rafael J. Wysocki wrote:
> On Sun, Apr 19, 2026 at 3:27 PM Zhongqiu Han
> <zhongqiu.han@oss.qualcomm.com> wrote:
>>
>> Patch 1 fixes two baseline-consistency issues in the DBS governor
>> framework.
>>
>> gov_update_cpu_data() writes prev_cpu_idle and prev_cpu_nice while
>> holding only attr_set->update_lock, whereas dbs_update() reads and
>> writes the same fields while holding only policy_dbs->update_mutex.
>> Because these are independent locks, the two paths are not mutually
>> exclusive.  The fix acquires policy_dbs->update_mutex inside
>> gov_update_cpu_data() for each policy.
>>
>> Additionally, cpufreq_dbs_governor_start() reads io_is_busy before
>> acquiring policy_dbs->update_mutex.  A concurrent io_is_busy_store()
>> can update io_is_busy and call gov_update_cpu_data(), which writes
>> prev_cpu_idle with the new value under the mutex.
>> cpufreq_dbs_governor_start() then overwrites prev_cpu_idle with the
>> stale value.  The fix reads io_is_busy inside the mutex.
>>
>> Patch 2 fixes a stale-baseline race on prev_cpu_nice when
>> ignore_nice_load is enabled via sysfs.  There is a race window
>> between setting ignore_nice_load and gov_update_cpu_data() acquiring
>> update_mutex: a concurrent dbs_update() can see the new ignore_nice_load
>> value but read a stale prev_cpu_nice, producing an inflated idle_time
>> for that sample.
>>
>> The fix unconditionally advances prev_cpu_nice on every dbs_update()
>> call.  With prev_cpu_nice always reflecting the most recent sample,
>> enabling ignore_nice_load can never produce a stale-baseline spike.
>> To keep prev_cpu_nice handling consistent, gov_update_cpu_data()
>> resets prev_cpu_nice unconditionally alongside prev_cpu_idle, and
>> cpufreq_dbs_governor_start() initializes prev_cpu_nice unconditionally.
>>
>> v3:
>> - Update linux-next base
>> - Fix two additional issues found during sashiko.dev review:
>>      - Patch 1: move io_busy read inside policy_dbs->update_mutex in
>>        cpufreq_dbs_governor_start() to close a TOCTOU window against
>>        concurrent io_is_busy_store().
>>      - Patch 2: restore unconditional prev_cpu_nice reset in
>>        gov_update_cpu_data() to keep both baselines consistent when
>>        io_is_busy changes with ignore_nice_load enabled; update comment.
>>      - Patch 2: keep gov_update_cpu_data() in ignore_nice_load_store() to
>>        prevent a stale-baseline spike in the governor-start window (when
>>        ignore_nice_load is set before the first dbs_update() call); only
>>        cpufreq_governor.c is modified.  Update commit message and add one
>>        more fixes tag '326c86deaed54a ("[CPUFREQ] Remove unneeded locks").'
>>      - Update the commit messages.
>> - Link to v2: https://lore.kernel.org/all/20260409111407.9775-1-zhongqiu.han@oss.qualcomm.com/
>> - Sashiko v2 comments: https://sashiko.dev/#/patchset/20260409111407.9775-1-zhongqiu.han%40oss.qualcomm.com
> 
> So sashiko.dev still has some comments on the first patch in v3:
> 
> https://sashiko.dev/#/patchset/20260419132655.3800673-1-zhongqiu.han%40oss.qualcomm.com
> 
> Can you please have a look at that and let me know what you think?
> 


Hi Rafael,
Thanks for pointing this out. I've looked at both comments:

Comment 1 (io_is_busy transition window):

The race is real but pre-existing. After Patch 1 the only remaining
window is the gap between the io_is_busy write and gov_update_cpu_data()
acquiring the lock:

CPU0 (io_is_busy_store):    CPU1 (dbs_update):
io_is_busy = 1              mutex_lock()
/* waiting for mutex */     io_busy = 1  /* sees new value */
                             cur_idle = get_cpu_idle_time(io_busy=1)
                             /* prev_cpu_idle still set with io_busy=0 */
                             /* idle_time may be clamped to 0 */
                             /* load inflated for this sample */
                             mutex_unlock()
mutex_lock()
prev_cpu_idle = ../* reset */
mutex_unlock()

The mismatch between the two metrics causes a one-sample anomaly in
either direction: 0→1 tends to inflate the load estimate (frequency
pushed upward), while 1→0 tends to deflate it. The AI's "drives to
minimum" conclusion is wrong for the 0→1 case.

This window is inherent to the design. One possible fix is to add a per
policy io_is_busy copy inside policy_dbs_info and update it under
update_mutex in gov_update_cpu_data(), so dbs_update() always reads a
value consistent with the current prev_cpu_idle baseline. The impact
should be a single-sample frequency spike that self-corrects.


Comment 2 (sampling_rate_store vs. gov_set_update_util):

Also pre-existing. The race:

   cpufreq_dbs_governor_start():     sampling_rate_store():
     mutex_unlock()                    mutex_lock()
     gov->start()                      sample_delay_ns = 0
     gov_set_update_util()             mutex_unlock()
       sample_delay_ns = rate  <--->

If needed, e possible approach would be to move both gov->start() and
gov_set_update_util() inside the mutex would work.


Perhaps both can be evaluated and handled either in this patch or as a
separate follow-up.


>> v2:
>> - Update linux-next base
>> - Based on v1 review, patch 1 is updated to add the missing
>>    protection around cpufreq_dbs_governor_start(), and patch 2/2 is added.
>> - Link to v1: https://lore.kernel.org/all/20260406110113.3475920-1-zhongqiu.han@oss.qualcomm.com/
>>
>> Zhongqiu Han (2):
>>    cpufreq: governor: Fix data races on per-CPU idle/nice baselines
>>    cpufreq: governor: Fix stale prev_cpu_nice spike when enabling
>>      ignore_nice_load
>>
>>   drivers/cpufreq/cpufreq_governor.c | 42 ++++++++++++++++++++----------
>>   1 file changed, 28 insertions(+), 14 deletions(-)
>>
>>
>> base-commit: c7275b05bc428c7373d97aa2da02d3a7fa6b9f66
>> --
>> 2.43.0
>>
>>


-- 
Thx and BRs,
Zhongqiu Han

  reply	other threads:[~2026-05-24  5:57 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-19 13:26 Zhongqiu Han
2026-04-19 13:26 ` [PATCH v3 1/2] cpufreq: governor: Fix data races on per-CPU idle/nice baselines Zhongqiu Han
2026-04-19 13:26 ` [PATCH v3 2/2] cpufreq: governor: Fix stale prev_cpu_nice spike when enabling ignore_nice_load Zhongqiu Han
2026-05-22 15:14 ` [PATCH v3 0/2] governor: Fix races and stale baseline on prev_cpu_nice Rafael J. Wysocki
2026-05-24  5:57   ` Zhongqiu Han [this message]
2026-05-26 17:09     ` Rafael J. Wysocki
2026-05-27 14:26       ` Zhongqiu Han

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=0b1ff222-ecda-4b21-9604-7d4e8fc86279@oss.qualcomm.com \
    --to=zhongqiu.han@oss.qualcomm.com \
    --cc=davej@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=rafael@kernel.org \
    --cc=trenn@suse.de \
    --cc=venkatesh.pallipadi@intel.com \
    --cc=viresh.kumar@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®