1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
/*
* cpuplugd - Linux for System z Hotplug Daemon
*
* /proc info functions
*
* Copyright IBM Corp. 2007, 2017
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <sys/stat.h>
#include <sys/types.h>
#include "cpuplugd.h"
/*
* Return current load average and runnable processes based on /proc/loadavg
*
* Example: 0.20 0.18 0.12 1/80 11206
*
* The first three columns measure CPU utilization of the last 1, 5,
* and 15 minute periods.
* The fourth column shows the number of currently running processes
* and the total number of processes.
* The last column displays the last process ID used.
*/
void get_loadavg_runnable(double *loadavg, double *runnable)
{
FILE *filp;
double dummy;
int rc;
filp = fopen("/proc/loadavg", "r");
if (!filp)
cpuplugd_exit("cannot open kernel loadaverage "
"statistics: %s\n", strerror(errno));
rc = fscanf(filp, "%lf %lf %lf %lf/", loadavg, &dummy, &dummy,
runnable);
if (rc != 4)
cpuplugd_exit("cannot parse kernel loadaverage "
"statistics: %s\n", strerror(errno));
fclose(filp);
return;
}
void proc_cpu_read(char *procinfo)
{
FILE *filp;
unsigned int rc, onumcpus;
unsigned long user, nice, system, idle, iowait, irq, softirq, steal,
guest, guest_nice, total_ticks;
double loadavg, runnable;
guest = guest_nice = 0; /* set to 0 if not present in kernel */
filp = fopen("/proc/stat", "r");
if (!filp)
cpuplugd_exit("/proc/stat open failed: %s\n", strerror(errno));
rc = fscanf(filp, "cpu %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld", &user,
&nice, &system, &idle, &iowait, &irq, &softirq, &steal,
&guest, &guest_nice);
get_loadavg_runnable(&loadavg, &runnable);
onumcpus = get_num_online_cpus();
total_ticks = user + nice + system + idle + iowait + irq + softirq +
steal + guest + guest_nice;
rc = snprintf(procinfo, cpustat_size, "onumcpus %d\nloadavg %f\n"
"runnable_proc %f\nuser %ld\nnice %ld\nsystem %ld\n"
"idle %ld\niowait %ld\nirq %ld\nsoftirq %ld\nsteal %ld\n"
"guest %ld\nguest_nice %ld\ntotal_ticks %ld\n",
onumcpus, loadavg, runnable, user, nice, system, idle,
iowait, irq, softirq, steal, guest, guest_nice,
total_ticks);
if (rc >= cpustat_size)
cpuplugd_exit("cpustat buffer too small: need %d, have %ld "
"(bytes)\n", rc, cpustat_size);
fclose(filp);
return;
}
void proc_read(char *procinfo, char *path, unsigned long size)
{
size_t bytes_read;
FILE *filp;
filp = fopen(path, "r");
if (!filp)
cpuplugd_exit("%s open failed: %s\n", path, strerror(errno));
bytes_read = fread(procinfo, 1, size, filp);
if (bytes_read == 0)
cpuplugd_exit("%s read failed\n", path);
if (bytes_read == size)
cpuplugd_exit("procinfo buffer too small for %s\n", path);
procinfo[bytes_read] = '\0';
fclose(filp);
return;
}
unsigned long proc_read_size(char *path)
{
FILE *filp;
char buf[PROCINFO_LINE];
char *linep, *linep_offset;
unsigned long size;
filp = fopen(path, "r");
if (!filp)
cpuplugd_exit("%s open failed: %s\n", path, strerror(errno));
size = 0;
while ((linep = fgets(buf, sizeof(buf), filp))) {
if (!(linep_offset = strchr(linep, '\n')))
cpuplugd_exit("buf too small for line\n");
size = size + linep_offset - linep + 1;
}
fclose(filp);
return size;
}
double get_proc_value(char *procinfo, char *name, char separator)
{
char buf[PROCINFO_LINE];
char *proc_offset;
unsigned long proc_length, name_length;
double value;
int found;
value = -1;
found = 0;
name_length = strlen(name);
while ((proc_offset = strchr(procinfo, separator))) {
proc_length = proc_offset - procinfo;
/*
* proc_read_size() made sure that proc_length < PROCINFO_LINE
*/
memcpy(buf, procinfo, proc_length);
buf[proc_length] = '\0';
procinfo = proc_offset + 1;
if (strncmp(buf, name, MAX(proc_length, name_length)) == 0) {
errno = 0;
value = strtod(procinfo, NULL);
if (errno)
cpuplugd_exit("strtod failed\n");
found = 1;
break;
}
proc_offset = strchr(procinfo, '\n');
procinfo = proc_offset + 1;
}
if (!found)
cpuplugd_exit("Symbol %s not found, check your config file\n",
name);
return value;
}
|