+#else /* !ENABLE_FEATURE_POWERTOP_PROCIRQ */
+# define process_irq_counts() ((void)0)
+#endif
+
+static NOINLINE int process_timer_stats(void)
+{
+ char buf[128];
+ char line[15 + 3 + 128];
+ int n;
+ FILE *fp;
+
+ buf[0] = '\0';
+
+ n = 0;
+ fp = NULL;
+ if (!G.cant_enable_timer_stats)
+ fp = fopen_for_read("/proc/timer_stats");
+ if (fp) {
+// Example file contents:
+// Timer Stats Version: v0.2
+// Sample period: 1.329 s
+// 76, 0 swapper hrtimer_start_range_ns (tick_sched_timer)
+// 88, 0 swapper hrtimer_start_range_ns (tick_sched_timer)
+// 24, 3787 firefox hrtimer_start_range_ns (hrtimer_wakeup)
+// 46D, 1136 kondemand/1 do_dbs_timer (delayed_work_timer_fn)
+// ...
+// 1, 1656 Xorg hrtimer_start_range_ns (hrtimer_wakeup)
+// 1, 2159 udisks-daemon hrtimer_start_range_ns (hrtimer_wakeup)
+// 331 total events, 249.059 events/sec
+ while (fgets(buf, sizeof(buf), fp)) {
+ const char *count, *process, *func;
+ char *p;
+ int idx;
+ unsigned cnt;
+
+ count = skip_whitespace(buf);
+ p = strchr(count, ',');
+ if (!p)
+ continue;
+ *p++ = '\0';
+ cnt = bb_strtou(count, NULL, 10);
+ if (strcmp(skip_non_whitespace(count), " total events") == 0) {
+#if ENABLE_FEATURE_POWERTOP_PROCIRQ
+ n = cnt / G.total_cpus;
+ if (n > 0 && n < G.interrupt_0) {
+ sprintf(line, " <interrupt> : %s", "extra timer interrupt");
+ save_line(line, G.interrupt_0 - n);
+ }
+#endif
+ break;
+ }
+ if (strchr(count, 'D'))
+ continue; /* deferred */
+ p = skip_whitespace(p); /* points to pid now */
+ process = NULL;
+ get_func_name:
+ p = strchr(p, ' ');
+ if (!p)
+ continue;
+ *p++ = '\0';
+ p = skip_whitespace(p);
+ if (process == NULL) {
+ process = p;
+ goto get_func_name;
+ }
+ func = p;
+
+ //if (strcmp(process, "swapper") == 0
+ // && strcmp(func, "hrtimer_start_range_ns (tick_sched_timer)\n") == 0
+ //) {
+ // process = "[kernel scheduler]";
+ // func = "Load balancing tick";
+ //}
+
+ if (is_prefixed_with(func, "tick_nohz_"))
+ continue;
+ if (is_prefixed_with(func, "tick_setup_sched_timer"))
+ continue;
+ //if (strcmp(process, "powertop") == 0)
+ // continue;
+
+ idx = index_in_strings("insmod\0modprobe\0swapper\0", process);
+ if (idx != -1) {
+ process = idx < 2 ? "[kernel module]" : "<kernel core>";
+ }
+
+ chomp(p);
+
+ // 46D\01136\0kondemand/1\0do_dbs_timer (delayed_work_timer_fn)
+ // ^ ^ ^
+ // count process func
+
+ //if (strchr(process, '['))
+ sprintf(line, "%15.15s : %s", process, func);
+ //else
+ // sprintf(line, "%s", process);
+ save_line(line, cnt);
+ }
+ fclose(fp);
+ }
+
+ return n;
+}