1#!/bin/sh 2 3# 4# Copyright (c) 2012 Peter Holm <pho@FreeBSD.org> 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[ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1 30 31. ../default.cfg 32 33# core dumps seen in watchdogd after mlockall() was added. 34# This scenario demonstrates the problem. Fixed in r242012. 35 36# "panic: freeing mapped page 0xfffff8181b38a5e8" seen: 37# https://people.freebsd.org/~pho/stress/log/mark030.txt 38 39mem=`sysctl -n hw.usermem` 40[ `sysctl -n vm.swap_total` -eq 0 ] && mem=$((mem / 100 * 60)) 41 42here=`pwd` 43cd /tmp 44sed '1,/^EOF/d' < $here/$0 > mlockall2.c 45mycc -o mlockall2 -Wall -Wextra -O2 -g mlockall2.c || exit 1 46rm -f mlockall2.c 47cd $here 48 49rm -f mlockall2.core 50/tmp/mlockall2 $mem & 51while kill -0 $! 2>/dev/null; do 52 [ -r mlockall2.core ] && kill $! && break 53 sleep 10 54done 55[ -r mlockall2.core ] && s=1 || s=0 56pkill mlockall2 57wait 58rm -f /tmp/mlockall2 mlockall2.core 59exit $s 60EOF 61#include <sys/types.h> 62#include <sys/mman.h> 63#include <sys/rtprio.h> 64#include <sys/wait.h> 65 66#include <err.h> 67#include <signal.h> 68#include <stdlib.h> 69#include <time.h> 70#include <unistd.h> 71 72#define LOAD 40 73#define N 90000 74#define PARALLEL 5 75#define RUNTIME 600 76 77static long size; 78 79static void 80swap(void) 81{ 82 long i; 83 int page; 84 volatile char *c; 85 86 setproctitle("swap"); 87 c = malloc(size); 88 while (c == NULL) { 89 size -= 1024 * 1024; 90 c = malloc(size); 91 } 92 page = getpagesize(); 93 for (;;) { 94 i = 0; 95 while (i < size) { 96 c[i] = 0; 97 i += page; 98 } 99 } 100} 101 102static void 103test(void) 104{ 105 pid_t p; 106 int i, status; 107 108 setproctitle("test"); 109 for (i = 0; i < N; i++) { 110 if ((p = fork()) == 0) { 111 _exit(0); 112 } 113 if (p > 0) 114 waitpid(p, &status, 0); 115 if (status != 0) 116 break; 117 } 118 _exit(0); 119} 120 121int 122main(int argc __unused, char **argv) 123{ 124 time_t start; 125 struct rtprio rtp; 126 pid_t pids[LOAD], pids2[PARALLEL]; 127 int i; 128 129 size = atol(argv[1]) / LOAD * 1.5; 130 for (i = 0; i < LOAD; i++) 131 if ((pids[i] = fork()) == 0) 132 swap(); 133 sleep(10); 134 135 rtp.type = RTP_PRIO_REALTIME; 136 rtp.prio = 0; 137 if (rtprio(RTP_SET, 0, &rtp) == -1) 138 err(1, "rtprio"); 139 140 if (madvise(0, 0, MADV_PROTECT) != 0) 141 err(1, "madvise failed"); 142 if (mlockall(MCL_CURRENT | MCL_FUTURE) != 0) 143 err(1, "mlockall failed"); 144 145 start = time(NULL); 146 while (time(NULL) - start < RUNTIME) { 147 for (i = 0; i < PARALLEL; i++) { 148 if ((pids2[i] = fork()) == 0) 149 test(); 150 } 151 152 for (i = 0; i < PARALLEL; i++) 153 if (waitpid(pids2[i], NULL, 0) != pids2[i]) 154 err(1, "waitpid(%d) (2)", pids2[i]); 155 if (access("mlockall2.core", R_OK) == 0) 156 break; 157 } 158 for (i = 0; i < LOAD; i++) 159 kill(pids[i], SIGKILL); 160 for (i = 0; i < LOAD; i++) 161 if (waitpid(pids[i], NULL, 0) != pids[i]) 162 err(1, "waitpid(%d)", pids[i]); 163 164 return (0); 165} 166