xref: /original-bsd/sys/vm/vm_meter.c (revision e59fb703)
1 /*
2  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)vm_meter.c	7.12 (Berkeley) 09/03/91
8  */
9 
10 #include "param.h"
11 #include "proc.h"
12 #include "systm.h"
13 #include "kernel.h"
14 #include "vm.h"
15 
16 fixpt_t	averunnable[3];		/* load average, of runnable procs */
17 
18 int	maxslp = MAXSLP;
19 int	saferss = SAFERSS;
20 
21 
22 vmmeter()
23 {
24 	register unsigned *cp, *rp, *sp;
25 
26 	if (time.tv_sec % 5 == 0)
27 		loadav(averunnable);
28 	if (proc0.p_slptime > maxslp/2)
29 		wakeup((caddr_t)&proc0);
30 }
31 
32 /*
33  * Constants for averages over 1, 5, and 15 minutes
34  * when sampling at 5 second intervals.
35  */
36 fixpt_t	cexp[3] = {
37 	0.9200444146293232 * FSCALE,	/* exp(-1/12) */
38 	0.9834714538216174 * FSCALE,	/* exp(-1/60) */
39 	0.9944598480048967 * FSCALE,	/* exp(-1/180) */
40 };
41 
42 /*
43  * Compute a tenex style load average of a quantity on
44  * 1, 5 and 15 minute intervals.
45  */
46 loadav(avg)
47 	register fixpt_t *avg;
48 {
49 	register int i, nrun;
50 	register struct proc *p;
51 
52 	for (nrun = 0, p = allproc; p != NULL; p = p->p_nxt) {
53 		switch (p->p_stat) {
54 		case SSLEEP:
55 			if (p->p_pri > PZERO || p->p_slptime != 0)
56 				continue;
57 			/* fall through */
58 		case SRUN:
59 		case SIDL:
60 			nrun++;
61 		}
62 	}
63 	for (i = 0; i < 3; i++)
64 		avg[i] = (cexp[i] * avg[i] + nrun * FSCALE * (FSCALE - cexp[i]))
65 		         >> FSHIFT;
66 #if defined(COMPAT_43) && (defined(vax) || defined(tahoe))
67 	for (i = 0; i < 3; i++)
68 		avenrun[i] = (double) averunnable[i] / FSCALE;
69 #endif /* COMPAT_43 */
70 }
71 
72 /*
73  * Calculate and return vmtotals structure.
74  */
75 kinfo_meter(op, where, acopysize, arg, aneeded)
76 	int op;
77 	caddr_t where;
78 	int *acopysize, arg, *aneeded;
79 {
80 	struct vmtotal vmtotals;
81 	int error;
82 
83 	*aneeded = sizeof(struct vmtotal);
84 	if (where == NULL)
85 		return (0);
86 	if (*acopysize < sizeof(struct vmtotal))
87 		return (EINVAL);
88 	vmtotal(&vmtotals);
89 	if (error = copyout((caddr_t)&vmtotals, where, sizeof(struct vmtotal)))
90 		return (error);
91 	*acopysize = sizeof(struct vmtotal);
92 	return (0);
93 }
94 
95 /*
96  * Calculate the current state of the system.
97  * Done on demand from getkerninfo().
98  */
99 vmtotal(totalp)
100 	register struct vmtotal *totalp;
101 {
102 	register struct proc *p;
103 	register vm_map_entry_t	entry;
104 	register vm_object_t object;
105 	register vm_map_t map;
106 	int paging;
107 
108 	bzero(totalp, sizeof *totalp);
109 	/*
110 	 * Mark all objects as inactive.
111 	 */
112 	simple_unlock(&vm_object_list_lock);
113 	simple_lock(&vm_object_list_lock);
114 	object = (vm_object_t) queue_first(&vm_object_list);
115 	while (!queue_end(&vm_object_list, (queue_entry_t) object)) {
116 		object->flags &= ~OBJ_ACTIVE;
117 		object = (vm_object_t) queue_next(&object->object_list);
118 	}
119 	simple_unlock(&vm_object_list_lock);
120 	/*
121 	 * Calculate process statistics.
122 	 */
123 	for (p = allproc; p != NULL; p = p->p_nxt) {
124 		if (p->p_flag & SSYS)
125 			continue;
126 		switch (p->p_stat) {
127 		case 0:
128 			continue;
129 
130 		case SSLEEP:
131 		case SSTOP:
132 			if (p->p_flag & SLOAD) {
133 				if (p->p_pri <= PZERO)
134 					totalp->t_dw++;
135 				else if (p->p_slptime < maxslp)
136 					totalp->t_sl++;
137 			} else if (p->p_slptime < maxslp)
138 				totalp->t_sw++;
139 			if (p->p_slptime >= maxslp)
140 				continue;
141 			break;
142 
143 		case SRUN:
144 		case SIDL:
145 			if (p->p_flag & SLOAD)
146 				totalp->t_rq++;
147 			else
148 				totalp->t_sw++;
149 			if (p->p_stat == SIDL)
150 				continue;
151 			break;
152 		}
153 		/*
154 		 * Note active objects.
155 		 */
156 		paging = 0;
157 		for (map = &p->p_vmspace->vm_map, entry = map->header.next;
158 		     entry != &map->header; entry = entry->next) {
159 			if (entry->is_a_map || entry->is_sub_map)
160 				continue;
161 			entry->object.vm_object->flags |= OBJ_ACTIVE;
162 			paging |= entry->object.vm_object->paging_in_progress;
163 		}
164 		if (paging)
165 			totalp->t_pw++;
166 	}
167 	/*
168 	 * Calculate object memory usage statistics.
169 	 */
170 	simple_lock(&vm_object_list_lock);
171 	object = (vm_object_t) queue_first(&vm_object_list);
172 	while (!queue_end(&vm_object_list, (queue_entry_t) object)) {
173 		totalp->t_vm += num_pages(object->size);
174 		totalp->t_rm += object->resident_page_count;
175 		if (object->flags & OBJ_ACTIVE) {
176 			totalp->t_avm += num_pages(object->size);
177 			totalp->t_arm += object->resident_page_count;
178 		}
179 		if (object->ref_count > 1) {
180 			/* shared object */
181 			totalp->t_vmshr += num_pages(object->size);
182 			totalp->t_rmshr += object->resident_page_count;
183 			if (object->flags & OBJ_ACTIVE) {
184 				totalp->t_avmshr += num_pages(object->size);
185 				totalp->t_armshr += object->resident_page_count;
186 			}
187 		}
188 		object = (vm_object_t) queue_next(&object->object_list);
189 	}
190 	totalp->t_free = cnt.v_free_count;
191 }
192