slstatus

Fork of suckless' slstatus with my personal patches
git clone https://git.instinctive.eu/slstatus.git
Log | Files | Refs | README | LICENSE

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