summaryrefslogtreecommitdiff
path: root/minix/fs/procfs/util.c
blob: 51703e7dc0ae11f77dad69c100109cce312257d2 (plain)
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
/* ProcFS - util.c - utility functions */

#include "inc.h"

/*
 * Retrieve system load average information.
 */
int
procfs_getloadavg(struct load * loadavg, int nelem)
{
	struct loadinfo loadinfo;
	u32_t system_hz, ticks_per_slot;
	int p, unfilled_ticks;
	int h, slots, latest, slot;
	int minutes[3] = { 1, 5, 15 };
	ssize_t l;

	if (nelem < 1) {
		errno = ENOSPC;
		return -1;
	}

	system_hz = sys_hz();

	if ((l = sys_getloadinfo(&loadinfo)) != OK)
		return -1;
	if (nelem > 3)
		nelem = 3;

	/* How many ticks are missing from the newest-filled slot? */
	ticks_per_slot = _LOAD_UNIT_SECS * system_hz;
	unfilled_ticks =
	    ticks_per_slot - (loadinfo.last_clock % ticks_per_slot);

	for (p = 0; p < nelem; p++) {
		latest = loadinfo.proc_last_slot;
		slots = minutes[p] * 60 / _LOAD_UNIT_SECS;
		loadavg[p].proc_load = 0;

		/*
		 * Add up the total number of process ticks for this number
		 * of minutes (minutes[p]).  Start with the newest slot, which
		 * is latest, and count back for the number of slots that
		 * correspond to the right number of minutes.  Take wraparound
		 * into account by calculating the index modulo _LOAD_HISTORY,
		 * which is the number of slots of history kept.
		 */
		for (h = 0; h < slots; h++) {
			slot = (latest - h + _LOAD_HISTORY) % _LOAD_HISTORY;
			loadavg[p].proc_load +=
			    loadinfo.proc_load_history[slot];
			l += (ssize_t) loadinfo.proc_load_history[slot];
		}

		/*
		 * The load average over this number of minutes is the number
		 * of process-ticks divided by the number of ticks, not
		 * counting the number of ticks the last slot hasn't been
		 * around yet.
		 */
		loadavg[p].ticks = slots * ticks_per_slot - unfilled_ticks;
	}

	return nelem;
}