cpu.c (5964B)
1 /* See LICENSE file for copyright and license details. */ 2 #include <stdint.h> 3 #include <stdio.h> 4 #include <string.h> 5 6 #include "../slstatus.h" 7 #include "../util.h" 8 9 #define MAX_CPU 16 10 11 #if defined(__linux__) 12 #include <stdlib.h> 13 #define CPU_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq" 14 15 const char * 16 cpu_freq(const char *unused) 17 { 18 uintmax_t freq; 19 20 /* in kHz */ 21 if (pscanf(CPU_FREQ, "%ju", &freq) != 1) 22 return NULL; 23 24 return fmt_human(freq * 1000, 1000); 25 } 26 27 const char * 28 cpu_perc(const char *unused) 29 { 30 static long double a[7]; 31 long double b[7], sum; 32 33 memcpy(b, a, sizeof(b)); 34 /* cpu user nice system idle iowait irq softirq */ 35 if (pscanf("/proc/stat", "%*s %Lf %Lf %Lf %Lf %Lf %Lf %Lf", 36 &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6]) 37 != 7) 38 return NULL; 39 40 if (b[0] == 0) 41 return NULL; 42 43 sum = (b[0] + b[1] + b[2] + b[3] + b[4] + b[5] + b[6]) - 44 (a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6]); 45 46 if (sum == 0) 47 return NULL; 48 49 return bprintf("%d", (int)(100 * 50 ((b[0] + b[1] + b[2] + b[5] + b[6]) - 51 (a[0] + a[1] + a[2] + a[5] + a[6])) / sum)); 52 } 53 54 const char * 55 cpu_perc_sum(const char *unused) 56 { 57 static long long a[MAX_CPU][2]; 58 long long b[MAX_CPU][2]; 59 long long c[7]; 60 long long numerator, denominator, result = 0; 61 int i; 62 unsigned j; 63 FILE *fp; 64 static char *buf; 65 static size_t bufsize; 66 char *begin, *end; 67 68 memcpy(b, a, sizeof(b)); 69 70 if (!(fp = fopen("/proc/stat", "r"))) { 71 warn("fopen '/proc/stat':"); 72 return NULL; 73 } 74 75 i = 0; 76 for (;;) { 77 if (getline(&buf, &bufsize, fp) < 0) { 78 warn("getline in /proc/stat:"); 79 break; 80 } 81 82 if (i >= MAX_CPU || 83 buf[0] != 'c' || buf[1] != 'p' || buf[2] != 'u') 84 break; 85 86 if (buf[3] == ' ') 87 continue; 88 89 for (begin = buf + 4; *begin >= '0' && *begin <= '9'; begin++); 90 91 for (j = 0; j < LEN(c); j++) { 92 if (*begin != ' ') break; 93 c[j] = strtoll(begin, &end, 10); 94 begin = end; 95 } 96 97 if (j < LEN(c)) { 98 warn("Incorrect /proc/stat line %d: \"%s\"", 99 i + 1, buf); 100 break; 101 } 102 103 a[i][0] = c[0] + c[1] + c[2] + c[5] + c[6]; 104 a[i][1] = a[i][0] + c[3] + c[4]; 105 106 denominator = a[i][1] - b[i][1]; 107 numerator = a[i][0] - b[i][0]; 108 if (denominator > 0) 109 result += (100 * numerator + denominator / 2) / 110 denominator; 111 112 i++; 113 } 114 115 fclose(fp); 116 117 if (i == 0 || b[0][0] == 0) 118 return NULL; 119 120 return bprintf("%Ld", result); 121 } 122 #elif defined(__OpenBSD__) 123 #include <sys/param.h> 124 #include <sys/sched.h> 125 #include <sys/sysctl.h> 126 127 const char * 128 cpu_freq(const char *unused) 129 { 130 int freq, mib[2]; 131 size_t size; 132 133 mib[0] = CTL_HW; 134 mib[1] = HW_CPUSPEED; 135 136 size = sizeof(freq); 137 138 /* in MHz */ 139 if (sysctl(mib, 2, &freq, &size, NULL, 0) < 0) { 140 warn("sysctl 'HW_CPUSPEED':"); 141 return NULL; 142 } 143 144 return fmt_human(freq * 1E6, 1000); 145 } 146 147 const char * 148 cpu_perc(const char *unused) 149 { 150 int mib[2]; 151 static uintmax_t a[CPUSTATES]; 152 uintmax_t b[CPUSTATES], sum; 153 size_t size; 154 155 mib[0] = CTL_KERN; 156 mib[1] = KERN_CPTIME; 157 158 size = sizeof(a); 159 160 memcpy(b, a, sizeof(b)); 161 if (sysctl(mib, 2, &a, &size, NULL, 0) < 0) { 162 warn("sysctl 'KERN_CPTIME':"); 163 return NULL; 164 } 165 if (b[0] == 0) 166 return NULL; 167 168 sum = (a[CP_USER] + a[CP_NICE] + a[CP_SYS] + a[CP_INTR] + a[CP_IDLE]) - 169 (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + b[CP_INTR] + b[CP_IDLE]); 170 171 if (sum == 0) 172 return NULL; 173 174 return bprintf("%d", 100 * 175 ((a[CP_USER] + a[CP_NICE] + a[CP_SYS] + 176 a[CP_INTR]) - 177 (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + 178 b[CP_INTR])) / sum); 179 } 180 #elif defined(__FreeBSD__) 181 #include <devstat.h> 182 #include <sys/param.h> 183 #include <sys/sysctl.h> 184 185 const char * 186 cpu_freq(const char *unused) 187 { 188 int freq; 189 size_t size; 190 191 size = sizeof(freq); 192 /* in MHz */ 193 if (sysctlbyname("hw.clockrate", &freq, &size, NULL, 0) < 0 || !size) { 194 warn("sysctlbyname 'hw.clockrate':"); 195 return NULL; 196 } 197 198 return fmt_human(freq * 1E6, 1000); 199 } 200 201 const char * 202 cpu_perc(const char *unused) 203 { 204 size_t size; 205 static long a[CPUSTATES]; 206 long b[CPUSTATES], sum; 207 208 size = sizeof(a); 209 memcpy(b, a, sizeof(b)); 210 if (sysctlbyname("kern.cp_time", &a, &size, NULL, 0) < 0 || !size) { 211 warn("sysctlbyname 'kern.cp_time':"); 212 return NULL; 213 } 214 if (b[0] == 0) 215 return NULL; 216 217 sum = (a[CP_USER] + a[CP_NICE] + a[CP_SYS] + a[CP_INTR] + a[CP_IDLE]) - 218 (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + b[CP_INTR] + b[CP_IDLE]); 219 220 if (sum == 0) 221 return NULL; 222 223 return bprintf("%d", 100 * 224 ((a[CP_USER] + a[CP_NICE] + a[CP_SYS] + 225 a[CP_INTR]) - 226 (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + 227 b[CP_INTR])) / sum); 228 } 229 230 const char * 231 cpu_perc_sum(const char *unused) 232 { 233 size_t size, cpus; 234 static long a[MAX_CPU][2]; 235 long b[MAX_CPU][2]; 236 long c[MAX_CPU][CPUSTATES]; 237 long numerator, denominator, result = 0; 238 static int mib[4]; 239 static size_t mib_len = LEN(mib); 240 int i; 241 242 if (!mib[0] && 243 sysctlnametomib("kern.cp_times", mib, &mib_len) < 0) { 244 warn("sysctlnametomib 'kern.cp_times':"); 245 return NULL; 246 } 247 248 size = sizeof(c); 249 memcpy(b, a, sizeof(b)); 250 if (sysctl(mib, mib_len, &c, &size, NULL, 0) < 0 || !size) { 251 warn("sysctl 'kern.cp_times':"); 252 return NULL; 253 } 254 255 cpus = size / (CPUSTATES * sizeof(long)); 256 if (cpus == 0 || cpus * CPUSTATES * sizeof(long) != size) { 257 warn("cpu_perc_sum: Inconsistent size %zu for %zu cpus", size, cpus); 258 return NULL; 259 } 260 261 for (i = 0; i < (int)cpus; i++) { 262 a[i][0] = c[i][CP_USER] + c[i][CP_NICE] + 263 c[i][CP_SYS] + c[i][CP_INTR]; 264 a[i][1] = a[i][0] + c[i][CP_IDLE]; 265 266 denominator = a[i][1] - b[i][1]; 267 numerator = a[i][0] - b[i][0]; 268 if (denominator > 0) 269 result += (100 * numerator + denominator / 2) / 270 denominator; 271 } 272 273 if (b[0][0] == 0) 274 return NULL; 275 276 return bprintf("%ld", result); 277 } 278 #endif