Re: [RFC PATCH 1/2] CPUfreq ondemand: update sampling rate without waiting for next sampling

From: Rafael J. Wysocki
Date: Sat Feb 25 2012 - 18:55:20 EST


On Wednesday, February 22, 2012, MyungJoo Ham wrote:
> When a new sampling rate is shorter than the current one, (e.g., 1 sec
> --> 10 ms) regardless how short the new one is, the current ondemand
> mechanism wait for the previously set timer to be expired.
>
> For example, if the user has just expressed that the sampling rate
> should be 10 ms from now and the previous was 1000 ms, the new rate may
> become effective 999 ms later, which could be not acceptable for the
> user if the user has intended to speed up sampling because the system is
> expected to react to CPU load fluctuation quickly from __now__.
>
> In order to address this issue, we need to cancel the previously set
> timer (schedule_delayed_work) and reset the timer if resetting timer is
> expected to trigger the delayed_work ealier.
>
> Signed-off-by: MyungJoo Ham <myungjoo.ham@xxxxxxxxxxx>
> Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx>
> ---
> drivers/cpufreq/cpufreq_ondemand.c | 58 +++++++++++++++++++++++++++++++++++-
> 1 files changed, 57 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
> index c3e0652..2d66649 100644
> --- a/drivers/cpufreq/cpufreq_ondemand.c
> +++ b/drivers/cpufreq/cpufreq_ondemand.c
> @@ -257,6 +257,62 @@ show_one(sampling_down_factor, sampling_down_factor);
> show_one(ignore_nice_load, ignore_nice);
> show_one(powersave_bias, powersave_bias);
>
> +/**
> + * update_sampling_rate - update sampling rate effective immediately if needed.
> + * @new_rate: new sampling rate
> + *
> + * If new rate is smaller than the old, simply updaing
> + * dbs_tuners_int.sampling_rate might not be appropriate. For example,
> + * if the original sampling_rate was 1 second and the requested new sampling
> + * rate is 10 ms because the user needs immediate reaction from ondemand
> + * governor, but not sure if higher frequency will be required or not,
> + * then, the governor may change the sampling rate too late; up to 1 second
> + * later. Thus, if we are reducing the sampling rate, we need to make the
> + * new value effective immediately.
> + */
> +static void update_sampling_rate(unsigned int new_rate)
> +{
> + int cpu;
> +
> + dbs_tuners_ins.sampling_rate = new_rate
> + = max(new_rate, min_sampling_rate);
> +
> + for_each_online_cpu(cpu) {
> + struct cpufreq_policy *policy;
> + struct cpu_dbs_info_s *dbs_info;
> + struct timer_list *timer;
> + unsigned long appointed_at;
> +
> + policy = cpufreq_cpu_get(cpu);
> + if (!policy)
> + continue;
> + dbs_info = &per_cpu(od_cpu_dbs_info, policy->cpu);
> + cpufreq_cpu_put(policy);
> +
> + mutex_lock(&dbs_info->timer_mutex);
> +
> + if (!delayed_work_pending(&dbs_info->work))
> + goto next;
> +

What about doing

mutex_unlock(&dbs_info->timer_mutex);
continue;

here instead of the jump?


> + timer = &dbs_info->work.timer;
> + appointed_at = timer->expires;
> +

I would do

next_sampling = jiffies + usecs_to_jiffies(new_rate);

and compare that with timer->expires. Then, the if () below would look better.
Or perhaps use new_rate_jiffies = usecs_to_jiffies(new_rate) and use that here
and below?

> + if (time_before(jiffies + usecs_to_jiffies(new_rate),
> + appointed_at)) {
> +
> + mutex_unlock(&dbs_info->timer_mutex);

I'm not sure if this isn't going to be racy. Have you verified that?

> + cancel_delayed_work_sync(&dbs_info->work);
> + mutex_lock(&dbs_info->timer_mutex);
> +
> + schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work,
> + usecs_to_jiffies(new_rate));
> +
> + }
> +next:
> + mutex_unlock(&dbs_info->timer_mutex);
> + }
> +}
> +
> static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
> const char *buf, size_t count)
> {
> @@ -265,7 +321,7 @@ static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
> ret = sscanf(buf, "%u", &input);
> if (ret != 1)
> return -EINVAL;
> - dbs_tuners_ins.sampling_rate = max(input, min_sampling_rate);
> + update_sampling_rate(input);
> return count;
> }

Thanks,
Rafael
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/