1 /* $NetBSD: mmap.c,v 1.17 2005/02/06 06:05:20 perry Exp $ */
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
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
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>
49 #include <string.h> /* for memset declaration (?) */
51 int main(int, char *[]);
54 int check_residency(void *, int);
59 #define MAPPED_FILE "mapped_file"
60 #define TEST_PATTERN 0xa5
68 void *addr
, *addr2
, *addr3
;
69 int i
, ch
, ecode
, fd
, npgs
, shmid
;
73 while ((ch
= getopt(argc
, argv
, "v")) != -1) {
93 pgsize
= sysconf(_SC_PAGESIZE
);
96 * TEST MLOCKING A FILE.
99 printf(">>> MAPPING FILE <<<\n");
101 fd
= open(filename
, O_RDONLY
, 0666);
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
,
110 if (addr
== MAP_FAILED
)
111 err(1, "mmap %s", filename
);
115 npgs
= (st
.st_size
/ pgsize
);
116 if (st
.st_size
% pgsize
!= 0)
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");
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.
148 printf(">>> MAPPING %d PAGE ANONYMOUS REGION WITH MAP_WIRED <<<\n",
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");
163 (void) munmap(addr
, npgs
* pgsize
);
166 * TEST MLOCKALL'ING AN ANONYMOUS MEMORY RANGE.
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");
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");
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");
210 printf(">>> MAPPING THIRD %d PAGE ANONYMOUS REGION, PROT_NONE <<<\n",
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");
224 printf(" PROT_READ'ING MAPPING\n");
226 if (mprotect(addr3
, npgs
* pgsize
, PROT_READ
) == -1)
229 printf(" CHECKING RESIDENCY\n");
231 if (check_residency(addr3
, npgs
) != npgs
) {
232 printf(" RESIDENCY CHECK FAILED!\n");
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");
248 printf(">>> MADV_FREE'ING SECOND ANONYMOUS REGION <<<\n");
250 if (madvise(addr2
, npgs
* pgsize
, MADV_FREE
) == -1)
253 printf(" CHECKING RESIDENCY\n");
255 if (check_residency(addr2
, npgs
) != 0) {
256 printf(" RESIDENCY CHECK FAILED!\n");
260 printf(">>> MADV_FREE'ING FIRST ANONYMOUS REGION <<<\n");
262 if (madvise(addr
, npgs
* pgsize
, MADV_FREE
) == -1)
265 printf(" CHECKING RESIDENCY\n");
267 if (check_residency(addr
, npgs
) != 0) {
268 printf(" RESIDENCY CHECK FAILED!\n");
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");
283 printf(">>> MADV_FREE'ING FIRST ANONYMOUS REGION AGAIN <<<\n");
285 if (madvise(addr
, npgs
* pgsize
, MADV_FREE
) == -1)
288 printf(" CHECKING RESIDENCY\n");
290 if (check_residency(addr
, npgs
) != 0) {
291 printf(" RESIDENCY CHECK FAILED!\n");
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
);
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
);
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
],
359 printf(">>> CREATING SYSV SHM SEGMENT <<<\n");
361 if ((shmid
= shmget(IPC_PRIVATE
, npgs
* pgsize
,
362 IPC_CREAT
|S_IRUSR
|S_IWUSR
)) == -1)
365 if ((addr
= shmat(shmid
, NULL
, 0)) == (void *) -1)
368 printf(" CHECKING RESIDENCY\n");
370 if (check_residency(addr
, npgs
) != 0) {
371 printf(" RESIDENCY CHECK FAILED!\n");
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");
386 printf(" MADV_FREE'ING SEGMENT\n");
387 if (madvise(addr
, npgs
* pgsize
, MADV_FREE
) == -1)
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)
411 if (shmctl(shmid
, IPC_RMID
, NULL
) == -1)
418 check_residency(addr
, npgs
)
427 err(1, "malloc mincore vec");
429 if (mincore(addr
, npgs
* pgsize
, vec
) == -1)
432 for (i
= 0, resident
= 0; i
< npgs
; i
++) {
436 printf("page 0x%lx is %sresident\n",
437 addr
+ (i
* pgsize
), vec
[i
] ? "" : "not ");
449 fprintf(stderr
, "usage: %s [-v] filename\n", getprogname());