Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / regress / sys / uvm / mmap / mmap.c
blob0f39dc361d33a14094358555a87b887a8f4cbe60
1 /* $NetBSD: mmap.c,v 1.17 2005/02/06 06:05:20 perry Exp $ */
3 /*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
34 * Test various memory mapping facilities.
37 #include <sys/param.h>
38 #include <sys/mman.h>
39 #include <sys/stat.h>
40 #include <sys/ipc.h>
41 #include <sys/shm.h>
43 #include <err.h>
44 #include <errno.h>
45 #include <fcntl.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <unistd.h>
49 #include <string.h> /* for memset declaration (?) */
51 int main(int, char *[]);
52 void usage(void);
54 int check_residency(void *, int);
56 int pgsize;
57 int verbose;
59 #define MAPPED_FILE "mapped_file"
60 #define TEST_PATTERN 0xa5
62 int
63 main(argc, argv)
64 int argc;
65 char *argv[];
67 struct stat st;
68 void *addr, *addr2, *addr3;
69 int i, ch, ecode, fd, npgs, shmid;
70 const char *filename;
71 u_int8_t *cp;
73 while ((ch = getopt(argc, argv, "v")) != -1) {
74 switch (ch) {
75 case 'v':
76 verbose = 1;
77 break;
79 default:
80 usage();
83 argv += optind;
84 argc -= optind;
86 if (argc != 1)
87 usage();
89 filename = argv[0];
91 ecode = 0;
93 pgsize = sysconf(_SC_PAGESIZE);
96 * TEST MLOCKING A FILE.
99 printf(">>> MAPPING FILE <<<\n");
101 fd = open(filename, O_RDONLY, 0666);
102 if (fd == -1)
103 err(1, "open %s", filename);
105 if (fstat(fd, &st) == -1)
106 err(1, "fstat %s", filename);
108 addr = mmap(NULL, (size_t) st.st_size, PROT_READ, MAP_FILE|MAP_SHARED,
109 fd, (off_t) 0);
110 if (addr == MAP_FAILED)
111 err(1, "mmap %s", filename);
113 (void) close(fd);
115 npgs = (st.st_size / pgsize);
116 if (st.st_size % pgsize != 0)
117 npgs++;
119 printf(" CHECKING RESIDENCY\n");
121 (void) check_residency(addr, npgs);
123 printf(" LOCKING RANGE\n");
125 if (mlock(addr, npgs * pgsize) == -1)
126 err(1, "mlock %s", filename);
128 printf(" CHECKING RESIDENCY\n");
130 if (check_residency(addr, npgs) != npgs) {
131 printf(" RESIDENCY CHECK FAILED!\n");
132 ecode = 1;
135 printf(" UNLOCKING RANGE\n");
137 if (munlock(addr, pgsize) == -1)
138 err(1, "munlock %s", filename);
140 (void) munmap(addr, st.st_size);
143 * TEST THE MAP_WIRED FLAG TO MMAP.
146 npgs = 128;
148 printf(">>> MAPPING %d PAGE ANONYMOUS REGION WITH MAP_WIRED <<<\n",
149 npgs);
151 addr = mmap(NULL, npgs * pgsize, PROT_READ|PROT_WRITE,
152 MAP_ANON|MAP_PRIVATE|MAP_WIRED, -1, (off_t) 0);
153 if (addr == MAP_FAILED)
154 err(1, "mmap anon MAP_WIRED");
156 printf(" CHECKING RESIDENCY\n");
158 if (check_residency(addr, npgs) != npgs) {
159 printf(" RESIDENCY CHECK FAILED!\n");
160 ecode = 1;
163 (void) munmap(addr, npgs * pgsize);
166 * TEST MLOCKALL'ING AN ANONYMOUS MEMORY RANGE.
169 npgs = 128;
171 printf(">>> MAPPING %d PAGE ANONYMOUS REGION <<<\n", npgs);
173 addr = mmap(NULL, npgs * pgsize, PROT_READ|PROT_WRITE,
174 MAP_ANON|MAP_PRIVATE, -1, (off_t) 0);
175 if (addr == MAP_FAILED)
176 err(1, "mmap anon #1");
178 printf(" CHECKING RESIDENCY\n");
180 if (check_residency(addr, npgs) != 0) {
181 printf(" RESIDENCY CHECK FAILED!\n");
182 ecode = 1;
185 printf(" LOCKING ALL - CURRENT and FUTURE\n");
187 if (mlockall(MCL_CURRENT|MCL_FUTURE) == -1)
188 err(1, "mlockall current/future");
190 printf(" CHECKING RESIDENCY\n");
192 if (check_residency(addr, npgs) != npgs) {
193 printf(" RESIDENCY CHECK FAILED!\n");
194 ecode = 1;
197 printf(">>> MAPPING ANOTHER %d PAGE ANONYMOUS REGION <<<\n", npgs);
199 addr2 = mmap(NULL, npgs * pgsize, PROT_READ, MAP_ANON, -1, (off_t) 0);
200 if (addr2 == MAP_FAILED)
201 err(1, "mmap anon #2");
203 printf(" CHECKING RESIDENCY\n");
205 if (check_residency(addr2, npgs) != npgs) {
206 printf(" RESIDENCY CHECK FAILED!\n");
207 ecode = 1;
210 printf(">>> MAPPING THIRD %d PAGE ANONYMOUS REGION, PROT_NONE <<<\n",
211 npgs);
213 addr3 = mmap(NULL, npgs * pgsize, PROT_NONE, MAP_ANON, -1, (off_t) 0);
214 if (addr3 == MAP_FAILED)
215 err(1, "mmap anon #3");
217 printf(" CHECKING RESIDENCY\n");
219 if (check_residency(addr3, npgs) != 0) {
220 printf(" RESIDENCY CHECK FAILED!\n");
221 ecode = 1;
224 printf(" PROT_READ'ING MAPPING\n");
226 if (mprotect(addr3, npgs * pgsize, PROT_READ) == -1)
227 err(1, "mprotect");
229 printf(" CHECKING RESIDENCY\n");
231 if (check_residency(addr3, npgs) != npgs) {
232 printf(" RESIDENCY CHECK FAILED!\n");
233 ecode = 1;
236 printf(" UNLOCKING ALL\n");
238 printf(" CHECKING RESIDENCY\n");
240 if (check_residency(addr, npgs) != npgs ||
241 check_residency(addr2, npgs) != npgs) {
242 printf(" RESIDENCY CHECK FAILED!\n");
243 ecode = 1;
246 (void) munlockall();
248 printf(">>> MADV_FREE'ING SECOND ANONYMOUS REGION <<<\n");
250 if (madvise(addr2, npgs * pgsize, MADV_FREE) == -1)
251 err(1, "madvise");
253 printf(" CHECKING RESIDENCY\n");
255 if (check_residency(addr2, npgs) != 0) {
256 printf(" RESIDENCY CHECK FAILED!\n");
257 ecode = 1;
260 printf(">>> MADV_FREE'ING FIRST ANONYMOUS REGION <<<\n");
262 if (madvise(addr, npgs * pgsize, MADV_FREE) == -1)
263 err(1, "madvise");
265 printf(" CHECKING RESIDENCY\n");
267 if (check_residency(addr, npgs) != 0) {
268 printf(" RESIDENCY CHECK FAILED!\n");
269 ecode = 1;
272 printf(">>> ZEROING FIRST ANONYMOUS REGION <<<\n");
274 memset(addr, 0, npgs * pgsize);
276 printf(" CHECKING RESIDENCY\n");
278 if (check_residency(addr, npgs) != npgs) {
279 printf(" RESIDENCY CHECK FAILED!\n");
280 ecode = 1;
283 printf(">>> MADV_FREE'ING FIRST ANONYMOUS REGION AGAIN <<<\n");
285 if (madvise(addr, npgs * pgsize, MADV_FREE) == -1)
286 err(1, "madvise");
288 printf(" CHECKING RESIDENCY\n");
290 if (check_residency(addr, npgs) != 0) {
291 printf(" RESIDENCY CHECK FAILED!\n");
292 ecode = 1;
295 printf(">>> UNMAPPING ANONYMOUS REGIONS <<<\n");
297 (void) munmap(addr, npgs * pgsize);
298 (void) munmap(addr2, npgs * pgsize);
299 (void) munmap(addr3, npgs * pgsize);
301 printf(">>> CREATING MAPPED FILE <<<\n");
303 (void) unlink(MAPPED_FILE);
305 if ((fd = open(MAPPED_FILE, O_RDWR|O_CREAT|O_TRUNC, 0666)) == -1)
306 err(1, "open %s", MAPPED_FILE);
308 if ((cp = malloc(npgs * pgsize)) == NULL)
309 err(1, "malloc %d bytes", npgs * pgsize);
311 memset(cp, 0x01, npgs * pgsize);
313 if (write(fd, cp, npgs * pgsize) != npgs * pgsize)
314 err(1, "write %s", MAPPED_FILE);
316 addr = mmap(NULL, npgs * pgsize, PROT_READ|PROT_WRITE,
317 MAP_FILE|MAP_SHARED, fd, (off_t) 0);
318 if (addr == MAP_FAILED)
319 err(1, "mmap %s", MAPPED_FILE);
321 (void) close(fd);
323 printf(" WRITING TEST PATTERN\n");
325 for (i = 0; i < npgs * pgsize; i++)
326 ((u_int8_t *)addr)[i] = TEST_PATTERN;
328 printf(" SYNCING FILE\n");
330 if (msync(addr, npgs * pgsize, MS_SYNC|MS_INVALIDATE) == -1)
331 err(1, "msync %s", MAPPED_FILE);
333 printf(" UNMAPPING FILE\n");
335 (void) munmap(addr, npgs * pgsize);
337 printf(" READING FILE\n");
339 if ((fd = open(MAPPED_FILE, O_RDONLY, 0666)) == -1)
340 err(1, "open %s", MAPPED_FILE);
342 if (read(fd, cp, npgs * pgsize) != npgs * pgsize)
343 err(1, "read %s", MAPPED_FILE);
345 (void) close(fd);
347 printf(" CHECKING TEST PATTERN\n");
349 for (i = 0; i < npgs * pgsize; i++) {
350 if (cp[i] != TEST_PATTERN) {
351 printf(" INCORRECT BYTE AT OFFSET %d: "
352 "0x%02x should be 0x%02x\n", i, cp[i],
353 TEST_PATTERN);
354 ecode = 1;
355 break;
359 printf(">>> CREATING SYSV SHM SEGMENT <<<\n");
361 if ((shmid = shmget(IPC_PRIVATE, npgs * pgsize,
362 IPC_CREAT|S_IRUSR|S_IWUSR)) == -1)
363 err(1, "shmget");
365 if ((addr = shmat(shmid, NULL, 0)) == (void *) -1)
366 err(1, "shmat");
368 printf(" CHECKING RESIDENCY\n");
370 if (check_residency(addr, npgs) != 0) {
371 printf(" RESIDENCY CHECK FAILED!\n");
372 ecode = 1;
375 printf(" ZEROING SEGMENT\n");
377 memset(addr, 0xff, npgs * pgsize);
379 printf(" CHECKING RESIDENCY\n");
381 if (check_residency(addr, npgs) != npgs) {
382 printf(" RESIDENCY CHECK FAILED!\n");
383 ecode = 1;
386 printf(" MADV_FREE'ING SEGMENT\n");
387 if (madvise(addr, npgs * pgsize, MADV_FREE) == -1)
388 err(1, "madvise");
390 printf(" CHECKING RESIDENCY\n");
393 * NOTE! Even though we have MADV_FREE'd the range,
394 * there is another reference (the kernel's) to the
395 * object which owns the pages. In this case, the
396 * kernel does not simply free the pages, as haphazardly
397 * freeing pages when there are still references to
398 * an object can cause data corruption (say, the other
399 * referencer doesn't expect the pages to be freed,
400 * and is surprised by the subsequent ZFOD).
402 * Because of this, we simply report the number of
403 * pages still resident, for information only.
406 npgs = check_residency(addr, npgs);
407 printf(" RESIDENCY CHECK: %d pages still resident\n", npgs);
409 if (shmdt(addr) == -1)
410 warn("shmdt");
411 if (shmctl(shmid, IPC_RMID, NULL) == -1)
412 err(1, "shmctl");
414 exit(ecode);
418 check_residency(addr, npgs)
419 void *addr;
420 int npgs;
422 char *vec;
423 int i, resident;
425 vec = malloc(npgs);
426 if (vec == NULL)
427 err(1, "malloc mincore vec");
429 if (mincore(addr, npgs * pgsize, vec) == -1)
430 err(1, "mincore");
432 for (i = 0, resident = 0; i < npgs; i++) {
433 if (vec[i] != 0)
434 resident++;
435 if (verbose)
436 printf("page 0x%lx is %sresident\n",
437 addr + (i * pgsize), vec[i] ? "" : "not ");
440 free(vec);
442 return (resident);
445 void
446 usage()
449 fprintf(stderr, "usage: %s [-v] filename\n", getprogname());
450 exit(1);