mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
This commit is based on the s390-tools-1.39.0 version. Changes on top of s390-tools-1.39.0: - Add MIT license to all source files - Add LICENSE file - Transform REAMDE to README.md (markdown) - Add AUTHORS.md file - Add CONTRIBUTING.md file - Move changelog from README to CHANGELOG.md file Reviewed-by: Stefan Haberland <sth@linux.vnet.ibm.com> Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
158 lines
4.2 KiB
C
158 lines
4.2 KiB
C
/*
|
|
* 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;
|
|
}
|