+struct runnables_avg_sample {
+ u64 previous_integral;
+ unsigned int avg;
+ bool integral_sampled;
+ u64 prev_timestamp;
+};
+
+static DEFINE_PER_CPU(struct runnables_avg_sample, avg_nr_sample);
+
+/* EXP = alpha in the exponential moving average.
+ * Alpha = e ^ (-sample_rate / window_size) * FIXED_1
+ * Calculated for sample_rate of 10ms, window size of 63.82ms
+ */
+#define EXP 1751
+
+static unsigned int get_avg_nr_runnables(void)
+{
+ unsigned int i, sum = 0;
+ static unsigned int avg;
+ struct runnables_avg_sample *sample;
+ u64 integral, old_integral, delta_integral, delta_time, cur_time;
+
+ for_each_online_cpu(i) {
+ sample = &per_cpu(avg_nr_sample, i);
+ integral = nr_running_integral(i);
+ old_integral = sample->previous_integral;
+ sample->previous_integral = integral;
+ cur_time = ktime_to_ns(ktime_get());
+ delta_time = cur_time - sample->prev_timestamp;
+ sample->prev_timestamp = cur_time;
+
+ if (!sample->integral_sampled) {
+ sample->integral_sampled = true;
+ /* First sample to initialize prev_integral, skip
+ * avg calculation
+ */
+ continue;
+ }
+
+ if (integral < old_integral) {
+ /* Overflow */
+ delta_integral = (ULLONG_MAX - old_integral) + integral;
+ } else {
+ delta_integral = integral - old_integral;
+ }
+
+ /* Calculate average for the previous sample window */
+ do_div(delta_integral, delta_time);
+ sample->avg = delta_integral;
+ sum += sample->avg;
+ }
+
+ /* Exponential moving average
+ * Avgn = Avgn-1 * alpha + new_avg * (1 - alpha)
+ */
+ avg *= EXP;
+ avg += sum * (FIXED_1 - EXP);
+ avg >>= FSHIFT;
+
+ return avg;
+}
+
+static void update_runnables_state(unsigned int nr_run)