+/** add up per-cpu counters */
+void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
+ struct lprocfs_counter *cnt)
+{
+ unsigned int num_cpu;
+ struct lprocfs_counter t;
+ struct lprocfs_counter *percpu_cntr;
+ int centry, i;
+
+ memset(cnt, 0, sizeof(*cnt));
+
+ if (stats == NULL) {
+ /* set count to 1 to avoid divide-by-zero errs in callers */
+ cnt->lc_count = 1;
+ return;
+ }
+
+ cnt->lc_min = LC_MIN_INIT;
+
+ if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
+ num_cpu = 1;
+ else
+ num_cpu = cfs_num_possible_cpus();
+
+ for (i = 0; i < num_cpu; i++) {
+ percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
+
+ do {
+ centry = cfs_atomic_read(&percpu_cntr-> \
+ lc_cntl.la_entry);
+ t.lc_count = percpu_cntr->lc_count;
+ t.lc_sum = percpu_cntr->lc_sum;
+ t.lc_min = percpu_cntr->lc_min;
+ t.lc_max = percpu_cntr->lc_max;
+ t.lc_sumsquare = percpu_cntr->lc_sumsquare;
+ } while (centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
+ la_entry) &&
+ centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \
+ la_exit));
+ cnt->lc_count += t.lc_count;
+ cnt->lc_sum += t.lc_sum;
+ if (t.lc_min < cnt->lc_min)
+ cnt->lc_min = t.lc_min;
+ if (t.lc_max > cnt->lc_max)
+ cnt->lc_max = t.lc_max;
+ cnt->lc_sumsquare += t.lc_sumsquare;
+ }
+
+ cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
+}
+