Xinqi Bao's Git

cpu_perc: Check for division by zero
[slstatus.git] / components / cpu.c
1 /* See LICENSE file for copyright and license details. */
2 #include <stdint.h>
3 #include <stdio.h>
4 #include <string.h>
5
6 #include "../util.h"
7
8 #if defined(__linux__)
9 const char *
10 cpu_freq(void)
11 {
12 uintmax_t freq;
13
14 /* in kHz */
15 if (pscanf("/sys/devices/system/cpu/cpu0/cpufreq/"
16 "scaling_cur_freq", "%ju", &freq) != 1) {
17 return NULL;
18 }
19
20 return fmt_human(freq * 1000, 1000);
21 }
22
23 const char *
24 cpu_perc(void)
25 {
26 static long double a[7];
27 long double b[7], sum;
28
29 memcpy(b, a, sizeof(b));
30 /* cpu user nice system idle iowait irq softirq */
31 if (pscanf("/proc/stat", "%*s %Lf %Lf %Lf %Lf %Lf %Lf %Lf",
32 &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6])
33 != 7) {
34 return NULL;
35 }
36 if (b[0] == 0) {
37 return NULL;
38 }
39
40 sum = (b[0] + b[1] + b[2] + b[3] + b[4] + b[5] + b[6]) -
41 (a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6]);
42
43 if (sum == 0) {
44 return NULL;
45 }
46
47 return bprintf("%d", (int)(100 *
48 ((b[0] + b[1] + b[2] + b[5] + b[6]) -
49 (a[0] + a[1] + a[2] + a[5] + a[6])) / sum));
50 }
51 #elif defined(__OpenBSD__)
52 #include <sys/param.h>
53 #include <sys/sched.h>
54 #include <sys/sysctl.h>
55
56 const char *
57 cpu_freq(void)
58 {
59 int freq, mib[2];
60 size_t size;
61
62 mib[0] = CTL_HW;
63 mib[1] = HW_CPUSPEED;
64
65 size = sizeof(freq);
66
67 /* in MHz */
68 if (sysctl(mib, 2, &freq, &size, NULL, 0) < 0) {
69 warn("sysctl 'HW_CPUSPEED':");
70 return NULL;
71 }
72
73 return fmt_human(freq * 1E6, 1000);
74 }
75
76 const char *
77 cpu_perc(void)
78 {
79 int mib[2];
80 static uintmax_t a[CPUSTATES];
81 uintmax_t b[CPUSTATES], sum;
82 size_t size;
83
84 mib[0] = CTL_KERN;
85 mib[1] = KERN_CPTIME;
86
87 size = sizeof(a);
88
89 memcpy(b, a, sizeof(b));
90 if (sysctl(mib, 2, &a, &size, NULL, 0) < 0) {
91 warn("sysctl 'KERN_CPTIME':");
92 return NULL;
93 }
94 if (b[0] == 0) {
95 return NULL;
96 }
97
98 sum = (a[CP_USER] + a[CP_NICE] + a[CP_SYS] + a[CP_INTR] + a[CP_IDLE]) -
99 (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + b[CP_INTR] + b[CP_IDLE]);
100
101 if (sum == 0) {
102 return NULL;
103 }
104
105 return bprintf("%d", 100 *
106 ((a[CP_USER] + a[CP_NICE] + a[CP_SYS] +
107 a[CP_INTR]) -
108 (b[CP_USER] + b[CP_NICE] + b[CP_SYS] +
109 b[CP_INTR])) / sum);
110 }
111 #elif defined(__FreeBSD__)
112 #include <sys/param.h>
113 #include <sys/sysctl.h>
114 #include <devstat.h>
115
116 const char *
117 cpu_freq(void)
118 {
119 int freq;
120 size_t size;
121
122 size = sizeof(freq);
123 /* in MHz */
124 if (sysctlbyname("hw.clockrate", &freq, &size, NULL, 0) == -1
125 || !size) {
126 warn("sysctlbyname 'hw.clockrate':");
127 return NULL;
128 }
129
130 return fmt_human(freq * 1E6, 1000);
131 }
132
133 const char *
134 cpu_perc(void)
135 {
136 size_t size;
137 static long a[CPUSTATES];
138 long b[CPUSTATES], sum;
139
140 size = sizeof(a);
141 memcpy(b, a, sizeof(b));
142 if (sysctlbyname("kern.cp_time", &a, &size, NULL, 0) == -1
143 || !size) {
144 warn("sysctlbyname 'kern.cp_time':");
145 return NULL;
146 }
147 if (b[0] == 0) {
148 return NULL;
149 }
150
151 sum = (a[CP_USER] + a[CP_NICE] + a[CP_SYS] + a[CP_INTR] + a[CP_IDLE]) -
152 (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + b[CP_INTR] + b[CP_IDLE]);
153
154 if (sum == 0) {
155 return NULL;
156 }
157
158 return bprintf("%d", 100 *
159 ((a[CP_USER] + a[CP_NICE] + a[CP_SYS] +
160 a[CP_INTR]) -
161 (b[CP_USER] + b[CP_NICE] + b[CP_SYS] +
162 b[CP_INTR])) / sum);
163 }
164 #endif