xref: /dragonfly/test/debug/vmpqinactive.c (revision b9a6fe08)
1*2dac8a3eSMatthew Dillon /*
2*2dac8a3eSMatthew Dillon  * VMPQINACTIVE.C
3*2dac8a3eSMatthew Dillon  *
4*2dac8a3eSMatthew Dillon  * cc -I/usr/src/sys vmpqinactive.c -o ~/bin/vmpqinactive -lkvm
5*2dac8a3eSMatthew Dillon  *
6*2dac8a3eSMatthew Dillon  * vmpqinactive
7*2dac8a3eSMatthew Dillon  *
8*2dac8a3eSMatthew Dillon  * Calculate how many inactive pages are dirty
9*2dac8a3eSMatthew Dillon  *
10*2dac8a3eSMatthew Dillon  * Copyright (c) 2004-2020 The DragonFly Project.  All rights reserved.
11*2dac8a3eSMatthew Dillon  *
12*2dac8a3eSMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
13*2dac8a3eSMatthew Dillon  * by Matthew Dillon <dillon@backplane.com>
14*2dac8a3eSMatthew Dillon  *
15*2dac8a3eSMatthew Dillon  * Redistribution and use in source and binary forms, with or without
16*2dac8a3eSMatthew Dillon  * modification, are permitted provided that the following conditions
17*2dac8a3eSMatthew Dillon  * are met:
18*2dac8a3eSMatthew Dillon  *
19*2dac8a3eSMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
20*2dac8a3eSMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
21*2dac8a3eSMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
22*2dac8a3eSMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
23*2dac8a3eSMatthew Dillon  *    the documentation and/or other materials provided with the
24*2dac8a3eSMatthew Dillon  *    distribution.
25*2dac8a3eSMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
26*2dac8a3eSMatthew Dillon  *    contributors may be used to endorse or promote products derived
27*2dac8a3eSMatthew Dillon  *    from this software without specific, prior written permission.
28*2dac8a3eSMatthew Dillon  *
29*2dac8a3eSMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30*2dac8a3eSMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31*2dac8a3eSMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
32*2dac8a3eSMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
33*2dac8a3eSMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
34*2dac8a3eSMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
35*2dac8a3eSMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36*2dac8a3eSMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
37*2dac8a3eSMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
38*2dac8a3eSMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
39*2dac8a3eSMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40*2dac8a3eSMatthew Dillon  * SUCH DAMAGE.
41*2dac8a3eSMatthew Dillon  */
42*2dac8a3eSMatthew Dillon 
43*2dac8a3eSMatthew Dillon #define _KERNEL_STRUCTURES_
44*2dac8a3eSMatthew Dillon #include <sys/param.h>
45*2dac8a3eSMatthew Dillon #include <sys/user.h>
46*2dac8a3eSMatthew Dillon #include <sys/malloc.h>
47*2dac8a3eSMatthew Dillon #include <sys/signalvar.h>
48*2dac8a3eSMatthew Dillon #include <sys/vnode.h>
49*2dac8a3eSMatthew Dillon #include <sys/buf.h>
50*2dac8a3eSMatthew Dillon #include <sys/namecache.h>
51*2dac8a3eSMatthew Dillon #include <sys/slaballoc.h>
52*2dac8a3eSMatthew Dillon 
53*2dac8a3eSMatthew Dillon #include <vm/vm.h>
54*2dac8a3eSMatthew Dillon #include <vm/vm_page.h>
55*2dac8a3eSMatthew Dillon #include <vm/vm_kern.h>
56*2dac8a3eSMatthew Dillon #include <vm/vm_object.h>
57*2dac8a3eSMatthew Dillon #include <vm/swap_pager.h>
58*2dac8a3eSMatthew Dillon #include <vm/vnode_pager.h>
59*2dac8a3eSMatthew Dillon 
60*2dac8a3eSMatthew Dillon #include <stdio.h>
61*2dac8a3eSMatthew Dillon #include <stdlib.h>
62*2dac8a3eSMatthew Dillon #include <string.h>
63*2dac8a3eSMatthew Dillon #include <fcntl.h>
64*2dac8a3eSMatthew Dillon #include <kvm.h>
65*2dac8a3eSMatthew Dillon #include <nlist.h>
66*2dac8a3eSMatthew Dillon #include <getopt.h>
67*2dac8a3eSMatthew Dillon 
68*2dac8a3eSMatthew Dillon struct nlist Nl[] = {
69*2dac8a3eSMatthew Dillon     { "_vm_page_array" },
70*2dac8a3eSMatthew Dillon     { "_vm_page_array_size" },
71*2dac8a3eSMatthew Dillon     { "_kernel_object" },
72*2dac8a3eSMatthew Dillon     { "_nbuf" },
73*2dac8a3eSMatthew Dillon     { "_nswbuf_mem" },
74*2dac8a3eSMatthew Dillon     { "_nswbuf_kva" },
75*2dac8a3eSMatthew Dillon     { "_nswbuf_raw" },
76*2dac8a3eSMatthew Dillon     { "_kernbase" },
77*2dac8a3eSMatthew Dillon     { "__end" },
78*2dac8a3eSMatthew Dillon     { NULL }
79*2dac8a3eSMatthew Dillon };
80*2dac8a3eSMatthew Dillon 
81*2dac8a3eSMatthew Dillon int debugopt;
82*2dac8a3eSMatthew Dillon int verboseopt;
83*2dac8a3eSMatthew Dillon #if 0
84*2dac8a3eSMatthew Dillon struct vm_page **vm_page_buckets;
85*2dac8a3eSMatthew Dillon int vm_page_hash_mask;
86*2dac8a3eSMatthew Dillon #endif
87*2dac8a3eSMatthew Dillon struct vm_page *vm_page_array;
88*2dac8a3eSMatthew Dillon struct vm_object *kernel_object_ptr;
89*2dac8a3eSMatthew Dillon int vm_page_array_size;
90*2dac8a3eSMatthew Dillon long nbuf;
91*2dac8a3eSMatthew Dillon long nswbuf_mem;
92*2dac8a3eSMatthew Dillon long nswbuf_kva;
93*2dac8a3eSMatthew Dillon long nswbuf_raw;
94*2dac8a3eSMatthew Dillon long kern_size;
95*2dac8a3eSMatthew Dillon 
96*2dac8a3eSMatthew Dillon void checkpage(kvm_t *kd, vm_page_t mptr, vm_page_t m, struct vm_object *obj);
97*2dac8a3eSMatthew Dillon static void kkread_vmpage(kvm_t *kd, u_long addr, vm_page_t m);
98*2dac8a3eSMatthew Dillon static void kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes);
99*2dac8a3eSMatthew Dillon static int kkread_err(kvm_t *kd, u_long addr, void *buf, size_t nbytes);
100*2dac8a3eSMatthew Dillon 
101*2dac8a3eSMatthew Dillon #if 0
102*2dac8a3eSMatthew Dillon static void addsltrack(vm_page_t m);
103*2dac8a3eSMatthew Dillon static void dumpsltrack(kvm_t *kd);
104*2dac8a3eSMatthew Dillon #endif
105*2dac8a3eSMatthew Dillon static int unique_object(void *ptr);
106*2dac8a3eSMatthew Dillon 
107*2dac8a3eSMatthew Dillon long count_free;
108*2dac8a3eSMatthew Dillon long count_wired;		/* total */
109*2dac8a3eSMatthew Dillon long count_wired_vnode;
110*2dac8a3eSMatthew Dillon long count_wired_anon;
111*2dac8a3eSMatthew Dillon long count_wired_in_pmap;
112*2dac8a3eSMatthew Dillon long count_wired_pgtable;
113*2dac8a3eSMatthew Dillon long count_wired_other;
114*2dac8a3eSMatthew Dillon long count_wired_kernel;
115*2dac8a3eSMatthew Dillon long count_wired_obj_other;
116*2dac8a3eSMatthew Dillon 
117*2dac8a3eSMatthew Dillon long count_anon;
118*2dac8a3eSMatthew Dillon long count_anon_in_pmap;
119*2dac8a3eSMatthew Dillon long count_vnode;
120*2dac8a3eSMatthew Dillon long count_device;
121*2dac8a3eSMatthew Dillon long count_phys;
122*2dac8a3eSMatthew Dillon long count_kernel;
123*2dac8a3eSMatthew Dillon long count_unknown;
124*2dac8a3eSMatthew Dillon long count_noobj_offqueue;
125*2dac8a3eSMatthew Dillon long count_noobj_onqueue;
126*2dac8a3eSMatthew Dillon 
127*2dac8a3eSMatthew Dillon int
main(int ac,char ** av)128*2dac8a3eSMatthew Dillon main(int ac, char **av)
129*2dac8a3eSMatthew Dillon {
130*2dac8a3eSMatthew Dillon     const char *corefile = NULL;
131*2dac8a3eSMatthew Dillon     const char *sysfile = NULL;
132*2dac8a3eSMatthew Dillon     struct vm_page m;
133*2dac8a3eSMatthew Dillon     struct vm_object obj;
134*2dac8a3eSMatthew Dillon     kvm_t *kd;
135*2dac8a3eSMatthew Dillon     int ch;
136*2dac8a3eSMatthew Dillon #if 0
137*2dac8a3eSMatthew Dillon     vm_page_t mptr;
138*2dac8a3eSMatthew Dillon     int hv;
139*2dac8a3eSMatthew Dillon #endif
140*2dac8a3eSMatthew Dillon     int i;
141*2dac8a3eSMatthew Dillon     const char *qstr;
142*2dac8a3eSMatthew Dillon     const char *ostr;
143*2dac8a3eSMatthew Dillon     long pqinactive_clean;
144*2dac8a3eSMatthew Dillon     long pqinactive_dirty1;
145*2dac8a3eSMatthew Dillon     long pqinactive_dirty2;
146*2dac8a3eSMatthew Dillon     long pqinactive_refd;
147*2dac8a3eSMatthew Dillon     long pqinactive_ready;
148*2dac8a3eSMatthew Dillon 
149*2dac8a3eSMatthew Dillon     pqinactive_clean = 0;
150*2dac8a3eSMatthew Dillon     pqinactive_dirty1 = 0;
151*2dac8a3eSMatthew Dillon     pqinactive_dirty2 = 0;
152*2dac8a3eSMatthew Dillon     pqinactive_refd = 0;
153*2dac8a3eSMatthew Dillon     pqinactive_ready = 0;
154*2dac8a3eSMatthew Dillon 
155*2dac8a3eSMatthew Dillon     while ((ch = getopt(ac, av, "M:N:dv")) != -1) {
156*2dac8a3eSMatthew Dillon 	switch(ch) {
157*2dac8a3eSMatthew Dillon 	case 'd':
158*2dac8a3eSMatthew Dillon 	    ++debugopt;
159*2dac8a3eSMatthew Dillon 	    break;
160*2dac8a3eSMatthew Dillon 	case 'v':
161*2dac8a3eSMatthew Dillon 	    ++verboseopt;
162*2dac8a3eSMatthew Dillon 	    break;
163*2dac8a3eSMatthew Dillon 	case 'M':
164*2dac8a3eSMatthew Dillon 	    corefile = optarg;
165*2dac8a3eSMatthew Dillon 	    break;
166*2dac8a3eSMatthew Dillon 	case 'N':
167*2dac8a3eSMatthew Dillon 	    sysfile = optarg;
168*2dac8a3eSMatthew Dillon 	    break;
169*2dac8a3eSMatthew Dillon 	default:
170*2dac8a3eSMatthew Dillon 	    fprintf(stderr, "%s [-M core] [-N system]\n", av[0]);
171*2dac8a3eSMatthew Dillon 	    exit(1);
172*2dac8a3eSMatthew Dillon 	}
173*2dac8a3eSMatthew Dillon     }
174*2dac8a3eSMatthew Dillon     ac -= optind;
175*2dac8a3eSMatthew Dillon     av += optind;
176*2dac8a3eSMatthew Dillon 
177*2dac8a3eSMatthew Dillon     if ((kd = kvm_open(sysfile, corefile, NULL, O_RDONLY, "kvm:")) == NULL) {
178*2dac8a3eSMatthew Dillon 	perror("kvm_open");
179*2dac8a3eSMatthew Dillon 	exit(1);
180*2dac8a3eSMatthew Dillon     }
181*2dac8a3eSMatthew Dillon     if (kvm_nlist(kd, Nl) != 0) {
182*2dac8a3eSMatthew Dillon 	perror("kvm_nlist");
183*2dac8a3eSMatthew Dillon 	exit(1);
184*2dac8a3eSMatthew Dillon     }
185*2dac8a3eSMatthew Dillon 
186*2dac8a3eSMatthew Dillon     kkread(kd, Nl[0].n_value, &vm_page_array, sizeof(vm_page_array));
187*2dac8a3eSMatthew Dillon     kkread(kd, Nl[1].n_value, &vm_page_array_size, sizeof(vm_page_array_size));
188*2dac8a3eSMatthew Dillon     kernel_object_ptr = (void *)Nl[2].n_value;
189*2dac8a3eSMatthew Dillon     kkread(kd, Nl[3].n_value, &nbuf, sizeof(nbuf));
190*2dac8a3eSMatthew Dillon     kkread(kd, Nl[4].n_value, &nswbuf_mem, sizeof(nswbuf_mem));
191*2dac8a3eSMatthew Dillon     kkread(kd, Nl[5].n_value, &nswbuf_kva, sizeof(nswbuf_kva));
192*2dac8a3eSMatthew Dillon     kkread(kd, Nl[6].n_value, &nswbuf_raw, sizeof(nswbuf_raw));
193*2dac8a3eSMatthew Dillon     kern_size = Nl[8].n_value - Nl[7].n_value;
194*2dac8a3eSMatthew Dillon 
195*2dac8a3eSMatthew Dillon     /*
196*2dac8a3eSMatthew Dillon      * Scan the vm_page_array validating all pages with associated objects
197*2dac8a3eSMatthew Dillon      */
198*2dac8a3eSMatthew Dillon     for (i = 0; i < vm_page_array_size; ++i) {
199*2dac8a3eSMatthew Dillon 	if (debugopt && (i & 1023) == 0) {
200*2dac8a3eSMatthew Dillon 	    printf("page %d/%d\r", i, vm_page_array_size);
201*2dac8a3eSMatthew Dillon 	    fflush(stdout);
202*2dac8a3eSMatthew Dillon 	}
203*2dac8a3eSMatthew Dillon 	kkread_vmpage(kd, (u_long)&vm_page_array[i], &m);
204*2dac8a3eSMatthew Dillon 	if (m.object) {
205*2dac8a3eSMatthew Dillon 	    kkread(kd, (u_long)m.object, &obj, sizeof(obj));
206*2dac8a3eSMatthew Dillon 	    checkpage(kd, &vm_page_array[i], &m, &obj);
207*2dac8a3eSMatthew Dillon 	}
208*2dac8a3eSMatthew Dillon 	if (m.queue >= PQ_HOLD) {
209*2dac8a3eSMatthew Dillon 	    qstr = "HOLD";
210*2dac8a3eSMatthew Dillon 	} else if (m.queue >= PQ_CACHE) {
211*2dac8a3eSMatthew Dillon 	    qstr = "CACHE";
212*2dac8a3eSMatthew Dillon 	} else if (m.queue >= PQ_ACTIVE) {
213*2dac8a3eSMatthew Dillon 	    qstr = "ACTIVE";
214*2dac8a3eSMatthew Dillon 	} else if (m.queue >= PQ_INACTIVE) {
215*2dac8a3eSMatthew Dillon 	    qstr = "INACTIVE";
216*2dac8a3eSMatthew Dillon 	    if (m.dirty || m.wire_count || m.busy_count || m.hold_count ||
217*2dac8a3eSMatthew Dillon 		(m.flags & PG_NEED_COMMIT)) {
218*2dac8a3eSMatthew Dillon 		    if (m.flags & PG_WINATCFLS)
219*2dac8a3eSMatthew Dillon 			    ++pqinactive_dirty2;
220*2dac8a3eSMatthew Dillon 		    else
221*2dac8a3eSMatthew Dillon 			    ++pqinactive_dirty1;
222*2dac8a3eSMatthew Dillon 	    } else {
223*2dac8a3eSMatthew Dillon 		    ++pqinactive_clean;
224*2dac8a3eSMatthew Dillon 		    if (m.flags & PG_REFERENCED)
225*2dac8a3eSMatthew Dillon 			    ++pqinactive_refd;
226*2dac8a3eSMatthew Dillon 		    else
227*2dac8a3eSMatthew Dillon 			    ++pqinactive_ready;
228*2dac8a3eSMatthew Dillon 	    }
229*2dac8a3eSMatthew Dillon 	} else if (m.queue >= PQ_FREE) {
230*2dac8a3eSMatthew Dillon 	    qstr = "FREE";
231*2dac8a3eSMatthew Dillon 	    ++count_free;
232*2dac8a3eSMatthew Dillon 	} else {
233*2dac8a3eSMatthew Dillon 	    qstr = "NONE";
234*2dac8a3eSMatthew Dillon 	}
235*2dac8a3eSMatthew Dillon 	if (m.wire_count) {
236*2dac8a3eSMatthew Dillon 		++count_wired;
237*2dac8a3eSMatthew Dillon 		if (m.object == NULL) {
238*2dac8a3eSMatthew Dillon 			if ((m.flags & PG_MAPPED) &&
239*2dac8a3eSMatthew Dillon 			    (m.flags & PG_WRITEABLE) &&
240*2dac8a3eSMatthew Dillon 			    (m.flags & PG_UNQUEUED)) {
241*2dac8a3eSMatthew Dillon 				++count_wired_pgtable;
242*2dac8a3eSMatthew Dillon 			} else {
243*2dac8a3eSMatthew Dillon 				++count_wired_other;
244*2dac8a3eSMatthew Dillon 			}
245*2dac8a3eSMatthew Dillon 		} else if (m.object == kernel_object_ptr) {
246*2dac8a3eSMatthew Dillon 			++count_wired_kernel;
247*2dac8a3eSMatthew Dillon 		} else {
248*2dac8a3eSMatthew Dillon 			switch(obj.type) {
249*2dac8a3eSMatthew Dillon 			case OBJT_VNODE:
250*2dac8a3eSMatthew Dillon 				++count_wired_vnode;
251*2dac8a3eSMatthew Dillon 				break;
252*2dac8a3eSMatthew Dillon 			case OBJT_DEFAULT:
253*2dac8a3eSMatthew Dillon 			case OBJT_SWAP:
254*2dac8a3eSMatthew Dillon 				if (m.flags & PG_MAPPED)
255*2dac8a3eSMatthew Dillon 					++count_wired_in_pmap;
256*2dac8a3eSMatthew Dillon 				else
257*2dac8a3eSMatthew Dillon 					++count_wired_anon;
258*2dac8a3eSMatthew Dillon 				break;
259*2dac8a3eSMatthew Dillon 			default:
260*2dac8a3eSMatthew Dillon 				++count_wired_obj_other;
261*2dac8a3eSMatthew Dillon 				break;
262*2dac8a3eSMatthew Dillon 			}
263*2dac8a3eSMatthew Dillon 		}
264*2dac8a3eSMatthew Dillon 	} else
265*2dac8a3eSMatthew Dillon 	if (m.flags & PG_MAPPED) {
266*2dac8a3eSMatthew Dillon 		if (m.object && m.object != kernel_object_ptr) {
267*2dac8a3eSMatthew Dillon 			switch(obj.type) {
268*2dac8a3eSMatthew Dillon 			case OBJT_DEFAULT:
269*2dac8a3eSMatthew Dillon 			case OBJT_SWAP:
270*2dac8a3eSMatthew Dillon 				++count_anon_in_pmap;
271*2dac8a3eSMatthew Dillon 				break;
272*2dac8a3eSMatthew Dillon 			default:
273*2dac8a3eSMatthew Dillon 				break;
274*2dac8a3eSMatthew Dillon 			}
275*2dac8a3eSMatthew Dillon 		}
276*2dac8a3eSMatthew Dillon 	}
277*2dac8a3eSMatthew Dillon 
278*2dac8a3eSMatthew Dillon 	if (verboseopt) {
279*2dac8a3eSMatthew Dillon 	    printf("page %p obj %p/%-8ju(%016jx) val=%02x dty=%02x hold=%d "
280*2dac8a3eSMatthew Dillon 		   "wire=%-2d act=%-3d busy=%d w/pmapcnt=%d/%d %8s",
281*2dac8a3eSMatthew Dillon 		&vm_page_array[i],
282*2dac8a3eSMatthew Dillon 		m.object,
283*2dac8a3eSMatthew Dillon 		(intmax_t)m.pindex,
284*2dac8a3eSMatthew Dillon 		(intmax_t)m.pindex * PAGE_SIZE,
285*2dac8a3eSMatthew Dillon 		m.valid,
286*2dac8a3eSMatthew Dillon 		m.dirty,
287*2dac8a3eSMatthew Dillon 		m.hold_count,
288*2dac8a3eSMatthew Dillon 		m.wire_count,
289*2dac8a3eSMatthew Dillon 		m.act_count,
290*2dac8a3eSMatthew Dillon 		m.busy_count,
291*2dac8a3eSMatthew Dillon 		((m.flags & PG_WRITEABLE) != 0),
292*2dac8a3eSMatthew Dillon 		((m.flags & PG_MAPPED) != 0),
293*2dac8a3eSMatthew Dillon 		qstr
294*2dac8a3eSMatthew Dillon 	    );
295*2dac8a3eSMatthew Dillon 	}
296*2dac8a3eSMatthew Dillon 
297*2dac8a3eSMatthew Dillon 	if (m.object == kernel_object_ptr) {
298*2dac8a3eSMatthew Dillon 		ostr = "kernel";
299*2dac8a3eSMatthew Dillon 		if (unique_object(m.object))
300*2dac8a3eSMatthew Dillon 			count_kernel += obj.resident_page_count;
301*2dac8a3eSMatthew Dillon 	} else if (m.object) {
302*2dac8a3eSMatthew Dillon 	    switch(obj.type) {
303*2dac8a3eSMatthew Dillon 	    case OBJT_DEFAULT:
304*2dac8a3eSMatthew Dillon 		ostr = "default";
305*2dac8a3eSMatthew Dillon 		if (unique_object(m.object))
306*2dac8a3eSMatthew Dillon 			count_anon += obj.resident_page_count;
307*2dac8a3eSMatthew Dillon 		break;
308*2dac8a3eSMatthew Dillon 	    case OBJT_SWAP:
309*2dac8a3eSMatthew Dillon 		ostr = "swap";
310*2dac8a3eSMatthew Dillon 		if (unique_object(m.object))
311*2dac8a3eSMatthew Dillon 			count_anon += obj.resident_page_count;
312*2dac8a3eSMatthew Dillon 		break;
313*2dac8a3eSMatthew Dillon 	    case OBJT_VNODE:
314*2dac8a3eSMatthew Dillon 		ostr = "vnode";
315*2dac8a3eSMatthew Dillon 		if (unique_object(m.object))
316*2dac8a3eSMatthew Dillon 			count_vnode += obj.resident_page_count;
317*2dac8a3eSMatthew Dillon 		break;
318*2dac8a3eSMatthew Dillon 	    case OBJT_DEVICE:
319*2dac8a3eSMatthew Dillon 		ostr = "device";
320*2dac8a3eSMatthew Dillon 		if (unique_object(m.object))
321*2dac8a3eSMatthew Dillon 			count_device += obj.resident_page_count;
322*2dac8a3eSMatthew Dillon 		break;
323*2dac8a3eSMatthew Dillon 	    case OBJT_PHYS:
324*2dac8a3eSMatthew Dillon 		ostr = "phys";
325*2dac8a3eSMatthew Dillon 		if (unique_object(m.object))
326*2dac8a3eSMatthew Dillon 			count_phys += obj.resident_page_count;
327*2dac8a3eSMatthew Dillon 		break;
328*2dac8a3eSMatthew Dillon 	    case OBJT_DEAD:
329*2dac8a3eSMatthew Dillon 		ostr = "dead";
330*2dac8a3eSMatthew Dillon 		if (unique_object(m.object))
331*2dac8a3eSMatthew Dillon 			count_unknown += obj.resident_page_count;
332*2dac8a3eSMatthew Dillon 		break;
333*2dac8a3eSMatthew Dillon 	    default:
334*2dac8a3eSMatthew Dillon 		if (unique_object(m.object))
335*2dac8a3eSMatthew Dillon 			count_unknown += obj.resident_page_count;
336*2dac8a3eSMatthew Dillon 		ostr = "unknown";
337*2dac8a3eSMatthew Dillon 		break;
338*2dac8a3eSMatthew Dillon 	    }
339*2dac8a3eSMatthew Dillon 	} else {
340*2dac8a3eSMatthew Dillon 	    ostr = "-";
341*2dac8a3eSMatthew Dillon 	    if (m.queue == PQ_NONE)
342*2dac8a3eSMatthew Dillon 		    ++count_noobj_offqueue;
343*2dac8a3eSMatthew Dillon 	    else if (m.queue - m.pc != PQ_FREE)
344*2dac8a3eSMatthew Dillon 		    ++count_noobj_onqueue;
345*2dac8a3eSMatthew Dillon 	}
346*2dac8a3eSMatthew Dillon 
347*2dac8a3eSMatthew Dillon 	if (verboseopt) {
348*2dac8a3eSMatthew Dillon 	    printf(" %-7s", ostr);
349*2dac8a3eSMatthew Dillon 	    if (m.busy_count & PBUSY_LOCKED)
350*2dac8a3eSMatthew Dillon 		printf(" BUSY");
351*2dac8a3eSMatthew Dillon 	    if (m.busy_count & PBUSY_WANTED)
352*2dac8a3eSMatthew Dillon 		printf(" WANTED");
353*2dac8a3eSMatthew Dillon 	    if (m.flags & PG_WINATCFLS)
354*2dac8a3eSMatthew Dillon 		printf(" WINATCFLS");
355*2dac8a3eSMatthew Dillon 	    if (m.flags & PG_FICTITIOUS)
356*2dac8a3eSMatthew Dillon 		printf(" FICTITIOUS");
357*2dac8a3eSMatthew Dillon 	    if (m.flags & PG_WRITEABLE)
358*2dac8a3eSMatthew Dillon 		printf(" WRITEABLE");
359*2dac8a3eSMatthew Dillon 	    if (m.flags & PG_MAPPED)
360*2dac8a3eSMatthew Dillon 		printf(" MAPPED");
361*2dac8a3eSMatthew Dillon 	    if (m.flags & PG_NEED_COMMIT)
362*2dac8a3eSMatthew Dillon 		printf(" NEED_COMMIT");
363*2dac8a3eSMatthew Dillon 	    if (m.flags & PG_REFERENCED)
364*2dac8a3eSMatthew Dillon 		printf(" REFERENCED");
365*2dac8a3eSMatthew Dillon 	    if (m.flags & PG_CLEANCHK)
366*2dac8a3eSMatthew Dillon 		printf(" CLEANCHK");
367*2dac8a3eSMatthew Dillon 	    if (m.busy_count & PBUSY_SWAPINPROG)
368*2dac8a3eSMatthew Dillon 		printf(" SWAPINPROG");
369*2dac8a3eSMatthew Dillon 	    if (m.flags & PG_NOSYNC)
370*2dac8a3eSMatthew Dillon 		printf(" NOSYNC");
371*2dac8a3eSMatthew Dillon 	    if (m.flags & PG_UNQUEUED)
372*2dac8a3eSMatthew Dillon 		printf(" UNQUEUED");
373*2dac8a3eSMatthew Dillon 	    if (m.flags & PG_MARKER)
374*2dac8a3eSMatthew Dillon 		printf(" MARKER");
375*2dac8a3eSMatthew Dillon 	    if (m.flags & PG_RAM)
376*2dac8a3eSMatthew Dillon 		printf(" RAM");
377*2dac8a3eSMatthew Dillon 	    if (m.flags & PG_SWAPPED)
378*2dac8a3eSMatthew Dillon 		printf(" SWAPPED");
379*2dac8a3eSMatthew Dillon #if 0
380*2dac8a3eSMatthew Dillon 	    if (m.flags & PG_SLAB)
381*2dac8a3eSMatthew Dillon 		printf(" SLAB");
382*2dac8a3eSMatthew Dillon #endif
383*2dac8a3eSMatthew Dillon 	    printf("\n");
384*2dac8a3eSMatthew Dillon #if 0
385*2dac8a3eSMatthew Dillon 	    if (m.flags & PG_SLAB)
386*2dac8a3eSMatthew Dillon 		addsltrack(&m);
387*2dac8a3eSMatthew Dillon #endif
388*2dac8a3eSMatthew Dillon 	}
389*2dac8a3eSMatthew Dillon     }
390*2dac8a3eSMatthew Dillon     if (debugopt || verboseopt)
391*2dac8a3eSMatthew Dillon 	printf("\n");
392*2dac8a3eSMatthew Dillon     printf("%8.2fM free\n",
393*2dac8a3eSMatthew Dillon 	count_free * 4096.0 / 1048576.0);
394*2dac8a3eSMatthew Dillon     printf("%8.2fM inactive-clean\n",
395*2dac8a3eSMatthew Dillon 	pqinactive_clean * 4096.0 / 1048576.0);
396*2dac8a3eSMatthew Dillon     printf("%8.2fM inactive-clean-and-referenced\n",
397*2dac8a3eSMatthew Dillon 	pqinactive_refd * 4096.0 / 1048576.0);
398*2dac8a3eSMatthew Dillon     printf("%8.2fM inactive-clean-and-ready\n",
399*2dac8a3eSMatthew Dillon 	pqinactive_ready * 4096.0 / 1048576.0);
400*2dac8a3eSMatthew Dillon     printf("%8.2fM inactive-dirty/first-LRU\n",
401*2dac8a3eSMatthew Dillon 	pqinactive_dirty1 * 4096.0 / 1048576.0);
402*2dac8a3eSMatthew Dillon     printf("%8.2fM inactive-dirty/second-LRU\n",
403*2dac8a3eSMatthew Dillon 	pqinactive_dirty2 * 4096.0 / 1048576.0);
404*2dac8a3eSMatthew Dillon 
405*2dac8a3eSMatthew Dillon     printf("%8.2fM wired vnode (in buffer cache)\n",
406*2dac8a3eSMatthew Dillon 	count_wired_vnode * 4096.0 / 1048576.0);
407*2dac8a3eSMatthew Dillon     printf("%8.2fM wired in-pmap (probably vnode pages also in buffer cache)\n",
408*2dac8a3eSMatthew Dillon 	count_wired_in_pmap * 4096.0 / 1048576.0);
409*2dac8a3eSMatthew Dillon     printf("%8.2fM wired pgtable\n",
410*2dac8a3eSMatthew Dillon 	count_wired_pgtable * 4096.0 / 1048576.0);
411*2dac8a3eSMatthew Dillon     printf("%8.2fM wired anon\n",
412*2dac8a3eSMatthew Dillon 	count_wired_anon * 4096.0 / 1048576.0);
413*2dac8a3eSMatthew Dillon     printf("%8.2fM wired kernel_object\n",
414*2dac8a3eSMatthew Dillon 	count_wired_kernel * 4096.0 / 1048576.0);
415*2dac8a3eSMatthew Dillon 
416*2dac8a3eSMatthew Dillon 	printf("\t%8.2fM vm_page_array\n",
417*2dac8a3eSMatthew Dillon 	    vm_page_array_size * sizeof(struct vm_page) / 1048576.0);
418*2dac8a3eSMatthew Dillon 	printf("\t%8.2fM buf, swbuf_mem, swbuf_kva, swbuf_raw\n",
419*2dac8a3eSMatthew Dillon 	    (nbuf + nswbuf_mem + nswbuf_kva + nswbuf_raw) *
420*2dac8a3eSMatthew Dillon 	    sizeof(struct buf) / 1048576.0);
421*2dac8a3eSMatthew Dillon 	printf("\t%8.2fM kernel binary\n", kern_size / 1048576.0);
422*2dac8a3eSMatthew Dillon 	printf("\t(also add in KMALLOC id kmapinfo, or loosely, vmstat -m)\n");
423*2dac8a3eSMatthew Dillon 
424*2dac8a3eSMatthew Dillon     printf("%8.2fM wired other (unknown object)\n",
425*2dac8a3eSMatthew Dillon 	count_wired_obj_other * 4096.0 / 1048576.0);
426*2dac8a3eSMatthew Dillon     printf("%8.2fM wired other (no object, probably kernel)\n",
427*2dac8a3eSMatthew Dillon 	count_wired_other * 4096.0 / 1048576.0);
428*2dac8a3eSMatthew Dillon 
429*2dac8a3eSMatthew Dillon     printf("%8.2fM WIRED TOTAL\n",
430*2dac8a3eSMatthew Dillon 	count_wired * 4096.0 / 1048576.0);
431*2dac8a3eSMatthew Dillon 
432*2dac8a3eSMatthew Dillon     printf("\n");
433*2dac8a3eSMatthew Dillon     printf("%8.2fM anonymous (total, includes in-pmap)\n",
434*2dac8a3eSMatthew Dillon 	count_anon * 4096.0 / 1048576.0);
435*2dac8a3eSMatthew Dillon     printf("%8.2fM anonymous memory in-pmap\n",
436*2dac8a3eSMatthew Dillon 	count_anon_in_pmap * 4096.0 / 1048576.0);
437*2dac8a3eSMatthew Dillon     printf("%8.2fM vnode (includes wired)\n",
438*2dac8a3eSMatthew Dillon 	count_vnode * 4096.0 / 1048576.0);
439*2dac8a3eSMatthew Dillon     printf("%8.2fM device\n", count_device * 4096.0 / 1048576.0);
440*2dac8a3eSMatthew Dillon     printf("%8.2fM phys\n", count_phys * 4096.0 / 1048576.0);
441*2dac8a3eSMatthew Dillon     printf("%8.2fM kernel (includes wired)\n",
442*2dac8a3eSMatthew Dillon 	count_kernel * 4096.0 / 1048576.0);
443*2dac8a3eSMatthew Dillon     printf("%8.2fM unknown\n", count_unknown * 4096.0 / 1048576.0);
444*2dac8a3eSMatthew Dillon     printf("%8.2fM no_object, off queue (includes wired w/o object)\n",
445*2dac8a3eSMatthew Dillon 	count_noobj_offqueue * 4096.0 / 1048576.0);
446*2dac8a3eSMatthew Dillon     printf("%8.2fM no_object, on non-free queue (includes wired w/o object)\n",
447*2dac8a3eSMatthew Dillon 	count_noobj_onqueue * 4096.0 / 1048576.0);
448*2dac8a3eSMatthew Dillon 
449*2dac8a3eSMatthew Dillon #if 0
450*2dac8a3eSMatthew Dillon     /*
451*2dac8a3eSMatthew Dillon      * Scan the vm_page_buckets array validating all pages found
452*2dac8a3eSMatthew Dillon      */
453*2dac8a3eSMatthew Dillon     for (i = 0; i <= vm_page_hash_mask; ++i) {
454*2dac8a3eSMatthew Dillon 	if (debugopt) {
455*2dac8a3eSMatthew Dillon 	    printf("index %d\r", i);
456*2dac8a3eSMatthew Dillon 	    fflush(stdout);
457*2dac8a3eSMatthew Dillon 	}
458*2dac8a3eSMatthew Dillon 	kkread(kd, (u_long)&vm_page_buckets[i], &mptr, sizeof(mptr));
459*2dac8a3eSMatthew Dillon 	while (mptr) {
460*2dac8a3eSMatthew Dillon 	    kkread(kd, (u_long)mptr, &m, sizeof(m));
461*2dac8a3eSMatthew Dillon 	    if (m.object) {
462*2dac8a3eSMatthew Dillon 		kkread(kd, (u_long)m.object, &obj, sizeof(obj));
463*2dac8a3eSMatthew Dillon 		hv = ((uintptr_t)m.object + m.pindex) ^ obj.hash_rand;
464*2dac8a3eSMatthew Dillon 		hv &= vm_page_hash_mask;
465*2dac8a3eSMatthew Dillon 		if (i != hv)
466*2dac8a3eSMatthew Dillon 		    printf("vm_page_buckets[%d] ((struct vm_page *)%p)"
467*2dac8a3eSMatthew Dillon 			" should be in bucket %d\n", i, mptr, hv);
468*2dac8a3eSMatthew Dillon 		checkpage(kd, mptr, &m, &obj);
469*2dac8a3eSMatthew Dillon 	    } else {
470*2dac8a3eSMatthew Dillon 		printf("vm_page_buckets[%d] ((struct vm_page *)%p)"
471*2dac8a3eSMatthew Dillon 			" has no object\n", i, mptr);
472*2dac8a3eSMatthew Dillon 	    }
473*2dac8a3eSMatthew Dillon 	    mptr = m.hnext;
474*2dac8a3eSMatthew Dillon 	}
475*2dac8a3eSMatthew Dillon     }
476*2dac8a3eSMatthew Dillon #endif
477*2dac8a3eSMatthew Dillon     if (debugopt)
478*2dac8a3eSMatthew Dillon 	printf("\n");
479*2dac8a3eSMatthew Dillon #if 0
480*2dac8a3eSMatthew Dillon     dumpsltrack(kd);
481*2dac8a3eSMatthew Dillon #endif
482*2dac8a3eSMatthew Dillon     return(0);
483*2dac8a3eSMatthew Dillon }
484*2dac8a3eSMatthew Dillon 
485*2dac8a3eSMatthew Dillon /*
486*2dac8a3eSMatthew Dillon  * A page with an object.
487*2dac8a3eSMatthew Dillon  */
488*2dac8a3eSMatthew Dillon void
checkpage(kvm_t * kd,vm_page_t mptr,vm_page_t m,struct vm_object * obj)489*2dac8a3eSMatthew Dillon checkpage(kvm_t *kd, vm_page_t mptr, vm_page_t m, struct vm_object *obj)
490*2dac8a3eSMatthew Dillon {
491*2dac8a3eSMatthew Dillon #if 0
492*2dac8a3eSMatthew Dillon     struct vm_page scan;
493*2dac8a3eSMatthew Dillon     vm_page_t scanptr;
494*2dac8a3eSMatthew Dillon     int hv;
495*2dac8a3eSMatthew Dillon 
496*2dac8a3eSMatthew Dillon     hv = ((uintptr_t)m->object + m->pindex) ^ obj->hash_rand;
497*2dac8a3eSMatthew Dillon     hv &= vm_page_hash_mask;
498*2dac8a3eSMatthew Dillon     kkread(kd, (u_long)&vm_page_buckets[hv], &scanptr, sizeof(scanptr));
499*2dac8a3eSMatthew Dillon     while (scanptr) {
500*2dac8a3eSMatthew Dillon 	if (scanptr == mptr)
501*2dac8a3eSMatthew Dillon 	    break;
502*2dac8a3eSMatthew Dillon 	kkread(kd, (u_long)scanptr, &scan, sizeof(scan));
503*2dac8a3eSMatthew Dillon 	scanptr = scan.hnext;
504*2dac8a3eSMatthew Dillon     }
505*2dac8a3eSMatthew Dillon     if (scanptr) {
506*2dac8a3eSMatthew Dillon 	if (debugopt > 1)
507*2dac8a3eSMatthew Dillon 	    printf("good checkpage %p bucket %d\n", mptr, hv);
508*2dac8a3eSMatthew Dillon     } else {
509*2dac8a3eSMatthew Dillon 	printf("vm_page_buckets[%d] ((struct vm_page *)%p)"
510*2dac8a3eSMatthew Dillon 		" page not found in bucket list\n", hv, mptr);
511*2dac8a3eSMatthew Dillon     }
512*2dac8a3eSMatthew Dillon #endif
513*2dac8a3eSMatthew Dillon }
514*2dac8a3eSMatthew Dillon 
515*2dac8a3eSMatthew Dillon /*
516*2dac8a3eSMatthew Dillon  * Acclerate the reading of VM pages
517*2dac8a3eSMatthew Dillon  */
518*2dac8a3eSMatthew Dillon #define VPCACHE_SIZE	65536
519*2dac8a3eSMatthew Dillon 
520*2dac8a3eSMatthew Dillon static void
kkread_vmpage(kvm_t * kd,u_long addr,vm_page_t m)521*2dac8a3eSMatthew Dillon kkread_vmpage(kvm_t *kd, u_long addr, vm_page_t m)
522*2dac8a3eSMatthew Dillon {
523*2dac8a3eSMatthew Dillon     static struct vm_page vpcache[VPCACHE_SIZE];
524*2dac8a3eSMatthew Dillon     static u_long vpbeg;
525*2dac8a3eSMatthew Dillon     static u_long vpend;
526*2dac8a3eSMatthew Dillon 
527*2dac8a3eSMatthew Dillon     if (addr < vpbeg || addr >= vpend) {
528*2dac8a3eSMatthew Dillon 	vpbeg = addr;
529*2dac8a3eSMatthew Dillon 	vpend = addr + VPCACHE_SIZE * sizeof(*m);
530*2dac8a3eSMatthew Dillon 	if (vpend > (u_long)(uintptr_t)vm_page_array +
531*2dac8a3eSMatthew Dillon 		    vm_page_array_size * sizeof(*m)) {
532*2dac8a3eSMatthew Dillon 	    vpend = (u_long)(uintptr_t)vm_page_array +
533*2dac8a3eSMatthew Dillon 		    vm_page_array_size * sizeof(*m);
534*2dac8a3eSMatthew Dillon 	}
535*2dac8a3eSMatthew Dillon 	kkread(kd, vpbeg, vpcache, vpend - vpbeg);
536*2dac8a3eSMatthew Dillon     }
537*2dac8a3eSMatthew Dillon     *m = vpcache[(addr - vpbeg) / sizeof(*m)];
538*2dac8a3eSMatthew Dillon }
539*2dac8a3eSMatthew Dillon 
540*2dac8a3eSMatthew Dillon static void
kkread(kvm_t * kd,u_long addr,void * buf,size_t nbytes)541*2dac8a3eSMatthew Dillon kkread(kvm_t *kd, u_long addr, void *buf, size_t nbytes)
542*2dac8a3eSMatthew Dillon {
543*2dac8a3eSMatthew Dillon     if (kvm_read(kd, addr, buf, nbytes) != nbytes) {
544*2dac8a3eSMatthew Dillon         perror("kvm_read");
545*2dac8a3eSMatthew Dillon         exit(1);
546*2dac8a3eSMatthew Dillon     }
547*2dac8a3eSMatthew Dillon }
548*2dac8a3eSMatthew Dillon 
549*2dac8a3eSMatthew Dillon static int
kkread_err(kvm_t * kd,u_long addr,void * buf,size_t nbytes)550*2dac8a3eSMatthew Dillon kkread_err(kvm_t *kd, u_long addr, void *buf, size_t nbytes)
551*2dac8a3eSMatthew Dillon {
552*2dac8a3eSMatthew Dillon     if (kvm_read(kd, addr, buf, nbytes) != nbytes) {
553*2dac8a3eSMatthew Dillon 	return 1;
554*2dac8a3eSMatthew Dillon     }
555*2dac8a3eSMatthew Dillon     return 0;
556*2dac8a3eSMatthew Dillon }
557*2dac8a3eSMatthew Dillon 
558*2dac8a3eSMatthew Dillon struct SLTrack {
559*2dac8a3eSMatthew Dillon         struct SLTrack *next;
560*2dac8a3eSMatthew Dillon         u_long addr;
561*2dac8a3eSMatthew Dillon };
562*2dac8a3eSMatthew Dillon 
563*2dac8a3eSMatthew Dillon #define SLHSIZE 1024
564*2dac8a3eSMatthew Dillon #define SLHMASK (SLHSIZE - 1)
565*2dac8a3eSMatthew Dillon 
566*2dac8a3eSMatthew Dillon struct SLTrack *SLHash[SLHSIZE];
567*2dac8a3eSMatthew Dillon 
568*2dac8a3eSMatthew Dillon #if 0
569*2dac8a3eSMatthew Dillon static
570*2dac8a3eSMatthew Dillon void
571*2dac8a3eSMatthew Dillon addsltrack(vm_page_t m)
572*2dac8a3eSMatthew Dillon {
573*2dac8a3eSMatthew Dillon 	struct SLTrack *slt;
574*2dac8a3eSMatthew Dillon 	u_long addr = (m->pindex * PAGE_SIZE) & ~131071L;
575*2dac8a3eSMatthew Dillon 	int i;
576*2dac8a3eSMatthew Dillon 
577*2dac8a3eSMatthew Dillon 	if (m->wire_count == 0 || (m->flags & PG_MAPPED) == 0 ||
578*2dac8a3eSMatthew Dillon 	    m->object == NULL)
579*2dac8a3eSMatthew Dillon 		return;
580*2dac8a3eSMatthew Dillon 
581*2dac8a3eSMatthew Dillon 	i = (addr / 131072) & SLHMASK;
582*2dac8a3eSMatthew Dillon 	for (slt = SLHash[i]; slt; slt = slt->next) {
583*2dac8a3eSMatthew Dillon 		if (slt->addr == addr)
584*2dac8a3eSMatthew Dillon 			break;
585*2dac8a3eSMatthew Dillon 	}
586*2dac8a3eSMatthew Dillon 	if (slt == NULL) {
587*2dac8a3eSMatthew Dillon 		slt = malloc(sizeof(*slt));
588*2dac8a3eSMatthew Dillon 		slt->addr = addr;
589*2dac8a3eSMatthew Dillon 		slt->next = SLHash[i];
590*2dac8a3eSMatthew Dillon 		SLHash[i] = slt;
591*2dac8a3eSMatthew Dillon 	}
592*2dac8a3eSMatthew Dillon }
593*2dac8a3eSMatthew Dillon #endif
594*2dac8a3eSMatthew Dillon 
595*2dac8a3eSMatthew Dillon static
596*2dac8a3eSMatthew Dillon void
dumpsltrack(kvm_t * kd)597*2dac8a3eSMatthew Dillon dumpsltrack(kvm_t *kd)
598*2dac8a3eSMatthew Dillon {
599*2dac8a3eSMatthew Dillon 	struct SLTrack *slt;
600*2dac8a3eSMatthew Dillon 	int i;
601*2dac8a3eSMatthew Dillon 	long total_zones = 0;
602*2dac8a3eSMatthew Dillon 	long full_zones = 0;
603*2dac8a3eSMatthew Dillon 
604*2dac8a3eSMatthew Dillon 	for (i = 0; i < SLHSIZE; ++i) {
605*2dac8a3eSMatthew Dillon 		for (slt = SLHash[i]; slt; slt = slt->next) {
606*2dac8a3eSMatthew Dillon 			SLZone z;
607*2dac8a3eSMatthew Dillon 
608*2dac8a3eSMatthew Dillon 			if (kkread_err(kd, slt->addr, &z, sizeof(z))) {
609*2dac8a3eSMatthew Dillon 				printf("SLZone 0x%016lx not mapped\n",
610*2dac8a3eSMatthew Dillon 					slt->addr);
611*2dac8a3eSMatthew Dillon 				continue;
612*2dac8a3eSMatthew Dillon 			}
613*2dac8a3eSMatthew Dillon 			printf("SLZone 0x%016lx { mag=%08x cpu=%-2d NFree=%-3d "
614*2dac8a3eSMatthew Dillon 			       "chunksz=%-5d }\n",
615*2dac8a3eSMatthew Dillon 			       slt->addr,
616*2dac8a3eSMatthew Dillon 			       z.z_Magic,
617*2dac8a3eSMatthew Dillon 			       z.z_Cpu,
618*2dac8a3eSMatthew Dillon 			       z.z_NFree,
619*2dac8a3eSMatthew Dillon 			       z.z_ChunkSize
620*2dac8a3eSMatthew Dillon 			);
621*2dac8a3eSMatthew Dillon 			++total_zones;
622*2dac8a3eSMatthew Dillon 			if (z.z_NFree == 0)
623*2dac8a3eSMatthew Dillon 				++full_zones;
624*2dac8a3eSMatthew Dillon 		}
625*2dac8a3eSMatthew Dillon 	}
626*2dac8a3eSMatthew Dillon 	printf("FullZones/TotalZones: %ld/%ld\n", full_zones, total_zones);
627*2dac8a3eSMatthew Dillon }
628*2dac8a3eSMatthew Dillon 
629*2dac8a3eSMatthew Dillon #define HASH_SIZE	(1024*1024)
630*2dac8a3eSMatthew Dillon #define HASH_MASK	(HASH_SIZE - 1)
631*2dac8a3eSMatthew Dillon 
632*2dac8a3eSMatthew Dillon struct dup_entry {
633*2dac8a3eSMatthew Dillon 	struct dup_entry *next;
634*2dac8a3eSMatthew Dillon 	void	*ptr;
635*2dac8a3eSMatthew Dillon };
636*2dac8a3eSMatthew Dillon 
637*2dac8a3eSMatthew Dillon struct dup_entry *dup_hash[HASH_SIZE];
638*2dac8a3eSMatthew Dillon 
639*2dac8a3eSMatthew Dillon static int
unique_object(void * ptr)640*2dac8a3eSMatthew Dillon unique_object(void *ptr)
641*2dac8a3eSMatthew Dillon {
642*2dac8a3eSMatthew Dillon 	struct dup_entry *hen;
643*2dac8a3eSMatthew Dillon 	int hv;
644*2dac8a3eSMatthew Dillon 
645*2dac8a3eSMatthew Dillon 	hv = (intptr_t)ptr ^ ((intptr_t)ptr >> 20);
646*2dac8a3eSMatthew Dillon 	hv &= HASH_MASK;
647*2dac8a3eSMatthew Dillon 	for (hen = dup_hash[hv]; hen; hen = hen->next) {
648*2dac8a3eSMatthew Dillon 		if (hen->ptr == ptr)
649*2dac8a3eSMatthew Dillon 			return 0;
650*2dac8a3eSMatthew Dillon 	}
651*2dac8a3eSMatthew Dillon 	hen = malloc(sizeof(*hen));
652*2dac8a3eSMatthew Dillon 	hen->next = dup_hash[hv];
653*2dac8a3eSMatthew Dillon 	hen->ptr = ptr;
654*2dac8a3eSMatthew Dillon 	dup_hash[hv] = hen;
655*2dac8a3eSMatthew Dillon 
656*2dac8a3eSMatthew Dillon 	return 1;
657*2dac8a3eSMatthew Dillon }
658