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# Variation of mmap18.sh. 30# "panic: vm_page_unwire: page 0xfffff81038d721f0's wire count is zero" seen: 31# https://people.freebsd.org/~pho/stress/log/mlockall7.txt 32# Fixed by r328880 33 34[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 35 36. ../default.cfg 37 38here=`pwd` 39cd /tmp 40sed '1,/^EOF/d' < $here/$0 > mlockall7.c 41mycc -o mlockall7 -Wall -Wextra -O2 mlockall7.c -lpthread || exit 1 42rm -f mlockall7.c 43 44/tmp/mlockall7 `[ $# -eq 0 ] && echo 1 || echo $1` || s=1 45 46sleep 2 47rm -f /tmp/mlockall7 /tmp/mlockall7.core 48exit $s 49EOF 50#include <sys/types.h> 51#include <sys/mman.h> 52#include <sys/resource.h> 53#include <sys/stat.h> 54#include <sys/sysctl.h> 55#include <sys/time.h> 56#include <sys/wait.h> 57 58#include <err.h> 59#include <fcntl.h> 60#include <pwd.h> 61#include <pthread.h> 62#include <pthread_np.h> 63#include <sched.h> 64#include <signal.h> 65#include <stdio.h> 66#include <stdlib.h> 67#include <string.h> 68#include <time.h> 69#include <unistd.h> 70 71#define N 4096 72#define PARALLEL 50 73#define RUNTIME 180 74 75static u_int32_t r[N]; 76static void *p; 77 78static unsigned long 79makearg(void) 80{ 81 unsigned long val; 82 unsigned int i; 83 84 val = arc4random(); 85 i = arc4random() % 100; 86 if (i < 20) 87 val = val & 0xff; 88 if (i >= 20 && i < 40) 89 val = val & 0xffff; 90 if (i >= 40 && i < 60) 91 val = (unsigned long)(r) | (val & 0xffff); 92#if defined(__LP64__) 93 if (i >= 60) { 94 val = (val << 32) | arc4random(); 95 if (i > 80) 96 val = val & 0x00007fffffffffffUL; 97 } 98#endif 99 100 return (val); 101} 102 103static void * 104tmmap(void *arg __unused) 105{ 106 size_t len; 107 time_t start; 108 109 pthread_set_name_np(pthread_self(), __func__); 110 len = 128LL * 1024 * 1024; 111 112 start = time(NULL); 113 while (time(NULL) - start < 60) { 114 if ((p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_ANON, 115 -1, 0)) != MAP_FAILED) { 116 usleep(100); 117 munmap(p, len); 118 } 119 } 120 121 return (NULL); 122} 123 124static void * 125tmlockall(void *arg __unused) 126{ 127 time_t start; 128 int flags; 129 130 pthread_set_name_np(pthread_self(), __func__); 131 start = time(NULL); 132 while (time(NULL) - start < 60) { 133 flags = makearg() & 0xff; 134 mlockall(flags); 135 usleep(100); 136 munlockall(); 137 usleep(1000); 138 } 139 140 return (NULL); 141} 142 143static void 144test(void) 145{ 146 pthread_t tid[2]; 147 time_t start; 148 int i, rc; 149 150 if ((rc = pthread_create(&tid[0], NULL, tmmap, NULL)) != 0) 151 errc(1, rc, "tmmap()"); 152 if ((rc = pthread_create(&tid[1], NULL, tmlockall, NULL)) != 0) 153 errc(1, rc, "tmlock()"); 154 155 start = time(NULL); 156 while (time(NULL) - start < 60) { 157 if (fork() == 0) { 158 usleep(10000); 159 _exit(0); 160 } 161 wait(NULL); 162 } 163 164 for (i = 0; i < 2; i++) 165 if ((rc = pthread_join(tid[i], NULL)) != 0) 166 errc(1, rc, "pthread_join"); 167 _exit(0); 168} 169 170int 171testing(unsigned long maxl) 172{ 173 struct passwd *pw; 174 struct rlimit rl; 175 rlim_t maxlock; 176 time_t start; 177 int i; 178 179 maxlock = maxl; 180 if ((pw = getpwnam("nobody")) == NULL) 181 err(1, "failed to resolve nobody"); 182 if (setgroups(1, &pw->pw_gid) || 183 setegid(pw->pw_gid) || setgid(pw->pw_gid) || 184 seteuid(pw->pw_uid) || setuid(pw->pw_uid)) 185 err(1, "Can't drop privileges to \"nobody\""); 186 endpwent(); 187 188 rl.rlim_max = rl.rlim_cur = 0; 189 if (setrlimit(RLIMIT_CORE, &rl) == -1) 190 warn("setrlimit"); 191 192 if (getrlimit(RLIMIT_MEMLOCK, &rl) == -1) 193 warn("getrlimit"); 194 if (maxlock <= 0) 195 errx(1, "Argument is %jd", maxlock); 196 maxlock = (maxlock / 10 * 8) / PARALLEL * PAGE_SIZE; 197 if (maxlock < rl.rlim_cur) { 198 rl.rlim_max = rl.rlim_cur = maxlock; 199 if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1) 200 warn("setrlimit"); 201 } 202 203 for (i = 0; i < N; i++) 204 r[i] = arc4random(); 205 206 start = time(NULL); 207 while (time(NULL) - start < RUNTIME) { 208 for (i = 0; i < PARALLEL; i++) { 209 if (fork() == 0) 210 test(); 211 } 212 213 for (i = 0; i < PARALLEL; i++) 214 wait(NULL); 215 } 216 217 _exit(0); 218} 219 220int 221main(int argc, char *argv[]) 222{ 223 pid_t pid; 224 size_t len; 225 int i, loops, s, status; 226 unsigned long max_wired; 227 unsigned int wire_count, wire_count_old; 228 229 s = 0; 230 if (argc != 2) 231 errx(1, "Usage: %s <loops>", argv[0]); 232 loops = atoi(argv[1]); 233 234 len = sizeof(max_wired); 235 if (sysctlbyname("vm.max_user_wired", &max_wired, &len, NULL, 0) != 0) 236 err(1, "vm.max_user_wired"); 237 238 len = sizeof(wire_count); 239 if (sysctlbyname("vm.stats.vm.v_user_wire_count", &wire_count, &len, 240 NULL, 0) != 0) 241 err(1, "vm.stats.vm.v_user_wire_count"); 242 243 for (i = 0; i < loops; i++) { 244 wire_count_old = wire_count; 245 246 if ((pid = fork()) == 0) 247 testing(max_wired); 248 if (waitpid(pid, &status, 0) != pid) 249 err(1, "waitpid(%d)", pid); 250 if (status != 0) 251 errx(1, "Exit status %d from pid %d\n", status, pid); 252 253 len = sizeof(wire_count); 254 if (sysctlbyname("vm.stats.vm.v_user_wire_count", &wire_count, &len, 255 NULL, 0) != 0) 256 err(1, "vm.stats.vm.v_user_wire_count"); 257 fprintf(stderr, "vm.stats.vm.v_user_wire_count was %d, is %d. %d\n", 258 wire_count_old, wire_count, wire_count - wire_count_old); 259 } 260 261 return (s); 262} 263