1#!/bin/sh 2 3# 4# Copyright (c) 2014 EMC Corp. 5# All rights reserved. 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27# 28 29# "panic: vm_page_dirty: page is invalid!" seen. 30# http://people.freebsd.org/~pho/stress/log/mmap10.txt 31# No problems seen after r271681. 32 33. ../default.cfg 34 35[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 36 37here=`pwd` 38cd /tmp 39sed '1,/^EOF/d' < $here/$0 > mmap10.c 40mycc -o mmap10 -Wall -Wextra -O2 -g mmap10.c -lpthread || exit 1 41rm -f mmap10.c 42 43daemon sh -c "(cd $here/../testcases/swap; ./swap -t 2m -i 20 -k)" 44sleep `jot -r 1 0 9` 45for i in `jot 2`; do 46 /tmp/mmap10 & 47done 48sleep 300 49while pgrep -q mmap10; do 50 pkill -9 mmap10 51 sleep 2 52done 53wait 54killall -q swap 55 56rm -f /tmp/mmap10 /tmp/mmap10.core 57exit 0 58EOF 59#include <sys/types.h> 60#include <sys/mman.h> 61#include <sys/stat.h> 62#include <sys/wait.h> 63 64#include <err.h> 65#include <errno.h> 66#include <fcntl.h> 67#include <pthread.h> 68#include <pthread_np.h> 69#include <stdio.h> 70#include <stdlib.h> 71#include <string.h> 72#include <unistd.h> 73 74#define LOOPS 2 75#define MMSIZE (192 * 1024 * 1024) 76#define N (128 * 1024 / (int)sizeof(u_int32_t)) 77#define PARALLEL 50 78 79void *p; 80u_int32_t r[N]; 81 82unsigned long 83makearg(void) 84{ 85 unsigned long val; 86 unsigned int i; 87 88 val = arc4random(); 89 i = arc4random() % 100; 90 if (i < 20) 91 val = val & 0xff; 92 if (i >= 20 && i < 40) 93 val = val & 0xffff; 94 if (i >= 40 && i < 60) 95 val = (unsigned long)(r) | (val & 0xffff); 96#if defined(__LP64__) 97 if (i >= 60) { 98 val = (val << 32) | arc4random(); 99 if (i > 80) 100 val = val & 0x00007fffffffffffUL; 101 } 102#endif 103 104 return(val); 105} 106 107void * 108makeptr(void) 109{ 110 unsigned long val; 111 112 if (p != MAP_FAILED && p != NULL) 113 val = (unsigned long)p + arc4random(); 114 else 115 val = makearg(); 116 val = trunc_page(val); 117 118 return ((void *)val); 119} 120 121void * 122tmmap(void *arg __unused) 123{ 124 size_t len; 125 int i, j, fd; 126 127 pthread_set_name_np(pthread_self(), __func__); 128 len = MMSIZE; 129 130 for (i = 0, j = 0; i < 100; i++) { 131 if ((fd = open("/dev/zero", O_RDWR)) == -1) 132 err(1,"open()"); 133 134 if ((p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, 135 fd, 0)) != MAP_FAILED) { 136 usleep(100); 137 munmap(p, len); 138 j++; 139 } 140 141 if ((p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_ANON, 142 -1, 0)) != MAP_FAILED) { 143 usleep(100); 144 munmap(p, len); 145 j++; 146 } 147 close(fd); 148 } 149 if (j == 0) 150 fprintf(stderr, "FAIL: all mmap(2) calls failed.\n"); 151 152 return (NULL); 153} 154 155void * 156tmlock(void *arg __unused) 157{ 158 size_t len; 159 int i, n; 160 161 pthread_set_name_np(pthread_self(), __func__); 162 n = 0; 163 for (i = 0; i < 200; i++) { 164 len = trunc_page(makearg()); 165 if (mlock(makeptr(), len) == 0) 166 n++; 167 len = trunc_page(makearg()); 168 if (arc4random() % 100 < 50) 169 if (munlock(makeptr(), len) == 0) 170 n++; 171 } 172 if (n < 10) 173 fprintf(stderr, "Note: tmlock() only succeeded %d times.\n", 174 n); 175 176 return (NULL); 177} 178 179void * 180tmprotect(void *arg __unused) 181{ 182 size_t len; 183 void *addr; 184 int i, n, prot; 185 186 pthread_set_name_np(pthread_self(), __func__); 187 n = 0; 188 for (i = 0; i < 200; i++) { 189 addr = makeptr(); 190 len = trunc_page(makearg()); 191 prot = makearg(); 192 if (mprotect(addr, len, prot) == 0) 193 n++; 194 usleep(1000); 195 } 196 if (n < 10) 197 fprintf(stderr, "Note: tmprotect() only succeeded %d times.\n", 198 n); 199 200 return (NULL); 201} 202 203void * 204tmlockall(void *arg __unused) 205{ 206 int flags, i, n; 207 208 pthread_set_name_np(pthread_self(), __func__); 209 n = 0; 210 for (i = 0; i < 200; i++) { 211 flags = makearg(); 212 if (mlockall(flags) == 0) 213 n++; 214 usleep(100); 215 munlockall(); 216 usleep(1000); 217 } 218 if (n < 10) 219 fprintf(stderr, "Note: tmlockall() only succeeded %d times.\n", 220 n); 221 222 return (NULL); 223} 224 225void 226test(void) 227{ 228 pthread_t tid[4]; 229 int i, rc; 230 231 if ((rc = pthread_create(&tid[0], NULL, tmmap, NULL)) != 0) 232 errc(1, rc, "tmmap()"); 233 if ((rc = pthread_create(&tid[1], NULL, tmlock, NULL)) != 0) 234 errc(1, rc, "tmlock()"); 235 if ((rc = pthread_create(&tid[2], NULL, tmprotect, NULL)) != 0) 236 errc(1, rc, "tmprotect()"); 237 if ((rc = pthread_create(&tid[3], NULL, tmlockall, NULL)) != 0) 238 errc(1, rc, "tmlockall()"); 239 240 for (i = 0; i < 100; i++) { 241 if (fork() == 0) { 242 usleep(10000); 243 _exit(0); 244 } 245 wait(NULL); 246 } 247 248 for (i = 0; i < 4; i++) 249 if ((rc = pthread_join(tid[i], NULL)) != 0) 250 errc(1, rc, "pthread_join(%d)", i); 251 _exit(0); 252} 253 254int 255main(void) 256{ 257 int i, j; 258 259 for (i = 0; i < N; i++) 260 r[i] = arc4random(); 261 262 for (i = 0; i < LOOPS; i++) { 263 for (j = 0; j < PARALLEL; j++) { 264 if (fork() == 0) 265 test(); 266 } 267 268 for (j = 0; j < PARALLEL; j++) 269 wait(NULL); 270 } 271 272 return (0); 273} 274