Re: [RFCv7 PATCH 03/10] sched: scheduler-driven cpu frequency selection
From: Peter Zijlstra <peterz@infradead.org>
Date: 2016-02-25 09:28:43
Also in:
lkml
On Thu, Feb 25, 2016 at 04:55:57AM +0100, Rafael J. Wysocki wrote:
quoted
+static void dummy(void *info) {} + +static int cpufreq_sched_stop(struct cpufreq_policy *policy) +{ + struct gov_data *gd = policy->governor_data; + int cpu; + + /* + * The schedfreq static key is managed here so the global schedfreq + * lock must be taken - a per-policy lock such as policy->rwsem is + * not sufficient. + */ + mutex_lock(&gov_enable_lock); + + /* + * The governor stop path may or may not hold policy->rwsem. There + * must be synchronization with the slow path however. + */ + mutex_lock(&gd->slowpath_lock); + + /* + * Stop new entries into the hot path for all CPUs. This will + * potentially affect other policies which are still running but + * this is an infrequent operation. + */ + static_key_slow_dec(&__sched_freq); + enabled_policies--; + + /* + * Ensure that all CPUs currently part of this policy are out + * of the hot path so that if this policy exits we can free gd. + */ + preempt_disable(); + smp_call_function_many(policy->cpus, dummy, NULL, true); + preempt_enable();I'm not sure how this works, can you please tell me?
I think it relies on the fact that rq->lock disables IRQs, so if we've managed to IPI all relevant CPUs, it means they cannot be inside a rq->lock section. Its vile though; one should not spray IPIs if one can avoid it. Such things are much better done with RCU. Sure sync_sched() takes a little longer, but this isn't a fast path by any measure.
quoted
+ + /* + * Other CPUs in other policies may still have the schedfreq + * static key enabled. The percpu gd is used to signal which + * CPUs are enabled in the sched gov during the hot path. + */ + for_each_cpu(cpu, policy->cpus) + per_cpu(cpu_gov_data, cpu) = NULL; + + /* Pause the slow path for this policy. */ + gd->enabled = 0; + + if (enabled_policies) + static_key_slow_inc(&__sched_freq); + mutex_unlock(&gd->slowpath_lock); + mutex_unlock(&gov_enable_lock); + + return 0; +}