1*25d39513SDavid van Moolenbroek /* MIB service - vm.c - implementation of the CTL_VM subtree */
2*25d39513SDavid van Moolenbroek
3*25d39513SDavid van Moolenbroek #include "mib.h"
4*25d39513SDavid van Moolenbroek
5*25d39513SDavid van Moolenbroek #include <sys/resource.h>
6*25d39513SDavid van Moolenbroek #include <uvm/uvm_extern.h>
7*25d39513SDavid van Moolenbroek
8*25d39513SDavid van Moolenbroek /*
9*25d39513SDavid van Moolenbroek * Implementation of CTL_VM VM_LOADAVG.
10*25d39513SDavid van Moolenbroek */
11*25d39513SDavid van Moolenbroek static ssize_t
mib_vm_loadavg(struct mib_call * call __unused,struct mib_node * node __unused,struct mib_oldp * oldp,struct mib_newp * newp __unused)12*25d39513SDavid van Moolenbroek mib_vm_loadavg(struct mib_call * call __unused,
13*25d39513SDavid van Moolenbroek struct mib_node * node __unused, struct mib_oldp * oldp,
14*25d39513SDavid van Moolenbroek struct mib_newp * newp __unused)
15*25d39513SDavid van Moolenbroek {
16*25d39513SDavid van Moolenbroek struct loadavg loadavg;
17*25d39513SDavid van Moolenbroek struct loadinfo loadinfo;
18*25d39513SDavid van Moolenbroek unsigned long proc_load;
19*25d39513SDavid van Moolenbroek u32_t ticks_per_slot, ticks;
20*25d39513SDavid van Moolenbroek unsigned int p;
21*25d39513SDavid van Moolenbroek int unfilled_ticks;
22*25d39513SDavid van Moolenbroek int h, slots, latest, slot;
23*25d39513SDavid van Moolenbroek int minutes[3] = { 1, 5, 15 };
24*25d39513SDavid van Moolenbroek
25*25d39513SDavid van Moolenbroek assert(__arraycount(loadavg.ldavg) == __arraycount(minutes));
26*25d39513SDavid van Moolenbroek
27*25d39513SDavid van Moolenbroek if (sys_getloadinfo(&loadinfo) != OK)
28*25d39513SDavid van Moolenbroek return EINVAL;
29*25d39513SDavid van Moolenbroek
30*25d39513SDavid van Moolenbroek memset(&loadavg, 0, sizeof(loadavg));
31*25d39513SDavid van Moolenbroek
32*25d39513SDavid van Moolenbroek /*
33*25d39513SDavid van Moolenbroek * The following code is inherited from the old MINIX libc.
34*25d39513SDavid van Moolenbroek */
35*25d39513SDavid van Moolenbroek
36*25d39513SDavid van Moolenbroek /* How many ticks are missing from the newest-filled slot? */
37*25d39513SDavid van Moolenbroek ticks_per_slot = _LOAD_UNIT_SECS * sys_hz();
38*25d39513SDavid van Moolenbroek unfilled_ticks =
39*25d39513SDavid van Moolenbroek ticks_per_slot - (loadinfo.last_clock % ticks_per_slot);
40*25d39513SDavid van Moolenbroek
41*25d39513SDavid van Moolenbroek for (p = 0; p < __arraycount(loadavg.ldavg); p++) {
42*25d39513SDavid van Moolenbroek latest = loadinfo.proc_last_slot;
43*25d39513SDavid van Moolenbroek slots = minutes[p] * 60 / _LOAD_UNIT_SECS;
44*25d39513SDavid van Moolenbroek proc_load = 0;
45*25d39513SDavid van Moolenbroek
46*25d39513SDavid van Moolenbroek /*
47*25d39513SDavid van Moolenbroek * Add up the total number of process ticks for this number
48*25d39513SDavid van Moolenbroek * of minutes (minutes[p]). Start with the newest slot, which
49*25d39513SDavid van Moolenbroek * is latest, and count back for the number of slots that
50*25d39513SDavid van Moolenbroek * correspond to the right number of minutes. Take wraparound
51*25d39513SDavid van Moolenbroek * into account by calculating the index modulo _LOAD_HISTORY,
52*25d39513SDavid van Moolenbroek * which is the number of slots of history kept.
53*25d39513SDavid van Moolenbroek */
54*25d39513SDavid van Moolenbroek for (h = 0; h < slots; h++) {
55*25d39513SDavid van Moolenbroek slot = (latest - h + _LOAD_HISTORY) % _LOAD_HISTORY;
56*25d39513SDavid van Moolenbroek proc_load += loadinfo.proc_load_history[slot];
57*25d39513SDavid van Moolenbroek }
58*25d39513SDavid van Moolenbroek
59*25d39513SDavid van Moolenbroek /*
60*25d39513SDavid van Moolenbroek * The load average over this number of minutes is the number
61*25d39513SDavid van Moolenbroek * of process-ticks divided by the number of ticks, not
62*25d39513SDavid van Moolenbroek * counting the number of ticks the last slot hasn't been
63*25d39513SDavid van Moolenbroek * around yet.
64*25d39513SDavid van Moolenbroek */
65*25d39513SDavid van Moolenbroek ticks = slots * ticks_per_slot - unfilled_ticks;
66*25d39513SDavid van Moolenbroek
67*25d39513SDavid van Moolenbroek loadavg.ldavg[p] = 100UL * proc_load / ticks;
68*25d39513SDavid van Moolenbroek }
69*25d39513SDavid van Moolenbroek
70*25d39513SDavid van Moolenbroek loadavg.fscale = 100L;
71*25d39513SDavid van Moolenbroek
72*25d39513SDavid van Moolenbroek return mib_copyout(oldp, 0, &loadavg, sizeof(loadavg));
73*25d39513SDavid van Moolenbroek }
74*25d39513SDavid van Moolenbroek
75*25d39513SDavid van Moolenbroek /*
76*25d39513SDavid van Moolenbroek * Implementation of CTL_VM VM_UVMEXP2.
77*25d39513SDavid van Moolenbroek */
78*25d39513SDavid van Moolenbroek static ssize_t
mib_vm_uvmexp2(struct mib_call * call __unused,struct mib_node * node __unused,struct mib_oldp * oldp,struct mib_newp * newp __unused)79*25d39513SDavid van Moolenbroek mib_vm_uvmexp2(struct mib_call * call __unused,
80*25d39513SDavid van Moolenbroek struct mib_node * node __unused, struct mib_oldp * oldp,
81*25d39513SDavid van Moolenbroek struct mib_newp * newp __unused)
82*25d39513SDavid van Moolenbroek {
83*25d39513SDavid van Moolenbroek struct vm_stats_info vsi;
84*25d39513SDavid van Moolenbroek struct uvmexp_sysctl ues;
85*25d39513SDavid van Moolenbroek unsigned int shift;
86*25d39513SDavid van Moolenbroek
87*25d39513SDavid van Moolenbroek if (vm_info_stats(&vsi) != OK)
88*25d39513SDavid van Moolenbroek return EINVAL;
89*25d39513SDavid van Moolenbroek
90*25d39513SDavid van Moolenbroek memset(&ues, 0, sizeof(ues));
91*25d39513SDavid van Moolenbroek
92*25d39513SDavid van Moolenbroek /*
93*25d39513SDavid van Moolenbroek * TODO: by far most of the structure is not filled correctly yet,
94*25d39513SDavid van Moolenbroek * since the MINIX3 system does not provide much of the information
95*25d39513SDavid van Moolenbroek * exposed by NetBSD. This will gradually have to be filled in.
96*25d39513SDavid van Moolenbroek * For now, we provide just some basic information used by top(1).
97*25d39513SDavid van Moolenbroek */
98*25d39513SDavid van Moolenbroek ues.pagesize = vsi.vsi_pagesize;
99*25d39513SDavid van Moolenbroek ues.pagemask = vsi.vsi_pagesize - 1;
100*25d39513SDavid van Moolenbroek for (shift = 0; shift < CHAR_BIT * sizeof(void *); shift++)
101*25d39513SDavid van Moolenbroek if ((1U << shift) == vsi.vsi_pagesize)
102*25d39513SDavid van Moolenbroek break;
103*25d39513SDavid van Moolenbroek if (shift < CHAR_BIT * sizeof(void *))
104*25d39513SDavid van Moolenbroek ues.pageshift = shift;
105*25d39513SDavid van Moolenbroek ues.npages = vsi.vsi_total;
106*25d39513SDavid van Moolenbroek ues.free = vsi.vsi_free;
107*25d39513SDavid van Moolenbroek ues.filepages = vsi.vsi_cached;
108*25d39513SDavid van Moolenbroek /*
109*25d39513SDavid van Moolenbroek * We use one of the structure's unused fields to expose information
110*25d39513SDavid van Moolenbroek * not exposed by NetBSD, namely the largest area of physically
111*25d39513SDavid van Moolenbroek * contiguous memory. If NetBSD repurposes this field, we have to find
112*25d39513SDavid van Moolenbroek * another home for it (or expose it through a separate node or so).
113*25d39513SDavid van Moolenbroek */
114*25d39513SDavid van Moolenbroek ues.unused1 = vsi.vsi_largest;
115*25d39513SDavid van Moolenbroek
116*25d39513SDavid van Moolenbroek return mib_copyout(oldp, 0, &ues, sizeof(ues));
117*25d39513SDavid van Moolenbroek }
118*25d39513SDavid van Moolenbroek
119*25d39513SDavid van Moolenbroek /* The CTL_VM nodes. */
120*25d39513SDavid van Moolenbroek static struct mib_node mib_vm_table[] = {
121*25d39513SDavid van Moolenbroek /* 1*/ /* VM_METER: not yet supported */
122*25d39513SDavid van Moolenbroek /* 2*/ [VM_LOADAVG] = MIB_FUNC(_P | _RO | CTLTYPE_STRUCT,
123*25d39513SDavid van Moolenbroek sizeof(struct loadavg), mib_vm_loadavg,
124*25d39513SDavid van Moolenbroek "loadavg", "System load average history"),
125*25d39513SDavid van Moolenbroek /* 3*/ /* VM_UVMEXP: not yet supported */
126*25d39513SDavid van Moolenbroek /* 4*/ /* VM_NKMEMPAGES: not yet supported */
127*25d39513SDavid van Moolenbroek /* 5*/ [VM_UVMEXP2] = MIB_FUNC(_P | _RO | CTLTYPE_STRUCT,
128*25d39513SDavid van Moolenbroek sizeof(struct uvmexp_sysctl),
129*25d39513SDavid van Moolenbroek mib_vm_uvmexp2, "uvmexp2",
130*25d39513SDavid van Moolenbroek "Detailed system-wide virtual memory "
131*25d39513SDavid van Moolenbroek "statistics (MI)"),
132*25d39513SDavid van Moolenbroek /* 6*/ /* VM_ANONMIN: not yet supported */
133*25d39513SDavid van Moolenbroek /* 7*/ /* VM_EXECMIN: not yet supported */
134*25d39513SDavid van Moolenbroek /* 8*/ /* VM_FILEMIN: not yet supported */
135*25d39513SDavid van Moolenbroek /* 9*/ [VM_MAXSLP] = MIB_INT(_P | _RO, MAXSLP, "maxslp",
136*25d39513SDavid van Moolenbroek "Maximum process sleep time before being "
137*25d39513SDavid van Moolenbroek "swapped"),
138*25d39513SDavid van Moolenbroek /*10*/ [VM_USPACE] = MIB_INT(_P | _RO, 0, "uspace", "Number of "
139*25d39513SDavid van Moolenbroek "bytes allocated for a kernel stack"),
140*25d39513SDavid van Moolenbroek /* MINIX3 processes don't have k-stacks */
141*25d39513SDavid van Moolenbroek /*11*/ /* VM_ANONMAX: not yet supported */
142*25d39513SDavid van Moolenbroek /*12*/ /* VM_EXECMAX: not yet supported */
143*25d39513SDavid van Moolenbroek /*13*/ /* VM_FILEMAX: not yet supported */
144*25d39513SDavid van Moolenbroek };
145*25d39513SDavid van Moolenbroek
146*25d39513SDavid van Moolenbroek /*
147*25d39513SDavid van Moolenbroek * Initialize the CTL_VM subtree.
148*25d39513SDavid van Moolenbroek */
149*25d39513SDavid van Moolenbroek void
mib_vm_init(struct mib_node * node)150*25d39513SDavid van Moolenbroek mib_vm_init(struct mib_node * node)
151*25d39513SDavid van Moolenbroek {
152*25d39513SDavid van Moolenbroek
153*25d39513SDavid van Moolenbroek MIB_INIT_ENODE(node, mib_vm_table);
154*25d39513SDavid van Moolenbroek }
155