File: info.c

package info (click to toggle)
s390-tools 2.35.0-3
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 12,248 kB
  • sloc: ansic: 184,236; sh: 12,152; cpp: 4,954; makefile: 2,763; perl: 2,519; asm: 1,085; python: 697; xml: 29
file content (157 lines) | stat: -rw-r--r-- 4,274 bytes parent folder | download | duplicates (5)
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;
}