- static char statpath[512];
- strcpy(statpath, "/proc/stat");
- if (!slurp(statpath, buf, sizeof(buf)) ||
- sscanf(buf, "cpu %d %d %d %d", &curr_user, &curr_nice, &curr_system, &curr_idle) != 4)
- goto error;
-
- curr_total = curr_user + curr_nice + curr_system + curr_idle;
- diff_idle = curr_idle - prev_idle;
- diff_total = curr_total - prev_total;
- diff_usage = (1000 * (diff_total - diff_idle)/diff_total + 5)/10;
- prev_total = curr_total;
- prev_idle = curr_idle;
-#elif defined(__FreeBSD__)
- size_t size;
- long cp_time[CPUSTATES];
- size = sizeof cp_time;
- if (sysctlbyname("kern.cp_time", &cp_time, &size, NULL, 0) < 0)
- goto error;
-
- curr_user = cp_time[CP_USER];
- curr_nice = cp_time[CP_NICE];
- curr_system = cp_time[CP_SYS];
- curr_idle = cp_time[CP_IDLE];
- curr_total = curr_user + curr_nice + curr_system + curr_idle;
- diff_idle = curr_idle - prev_idle;
- diff_total = curr_total - prev_total;
- diff_usage = (1000 * (diff_total - diff_idle)/diff_total + 5)/10;
- prev_total = curr_total;
- prev_idle = curr_idle;
+
+ // Detecting if CPU count has changed
+ int curr_cpu_count = sysconf(_SC_NPROCESSORS_ONLN);
+ if (curr_cpu_count != cpu_count) {
+ cpu_count = curr_cpu_count;
+ free(prev_cpus);
+ prev_cpus = (struct cpu_usage *)calloc(cpu_count, sizeof(struct cpu_usage));
+ free(curr_cpus);
+ curr_cpus = (struct cpu_usage *)calloc(cpu_count, sizeof(struct cpu_usage));
+ }
+
+ char buf[4096];
+ if (!slurp(path, buf, sizeof(buf)))
+ goto error;
+ // Parsing all cpu values using strtok
+ if (strtok(buf, "\n") == NULL)
+ goto error;
+ char *buf_itr = NULL;
+ for (int cpu_idx = 0; cpu_idx < cpu_count; cpu_idx++) {
+ buf_itr = strtok(NULL, "\n");
+ int curr_cpu_idx = -1;
+ if (!buf_itr || sscanf(buf_itr, "cpu%d %d %d %d %d", &curr_cpu_idx, &curr_cpus[cpu_idx].user, &curr_cpus[cpu_idx].nice, &curr_cpus[cpu_idx].system, &curr_cpus[cpu_idx].idle) != 5 || curr_cpu_idx != cpu_idx)
+ goto error;
+ curr_cpus[cpu_idx].total = curr_cpus[cpu_idx].user + curr_cpus[cpu_idx].nice + curr_cpus[cpu_idx].system + curr_cpus[cpu_idx].idle;
+ curr_all.user += curr_cpus[cpu_idx].user;
+ curr_all.nice += curr_cpus[cpu_idx].nice;
+ curr_all.system += curr_cpus[cpu_idx].system;
+ curr_all.idle += curr_cpus[cpu_idx].idle;
+ curr_all.total += curr_cpus[cpu_idx].total;
+ }
+
+ diff_idle = curr_all.idle - prev_all.idle;
+ diff_total = curr_all.total - prev_all.total;
+ diff_usage = (diff_total ? (1000 * (diff_total - diff_idle) / diff_total + 5) / 10 : 0);
+ prev_all = curr_all;
+#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
+
+#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__)
+ size_t size;
+ long cp_time[CPUSTATES];
+ size = sizeof cp_time;
+ if (sysctlbyname("kern.cp_time", &cp_time, &size, NULL, 0) < 0)
+ goto error;