1#!/bin/sh 2 3# 4# Copyright (c) 2009 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# $FreeBSD$ 29# 30 31# Stress mmap by having at most 100 threads mapping random areas within 32# a 100 Mb range. 33 34# Test scenario by kib@ 35 36odir=`pwd` 37cd /tmp 38sed '1,/^EOF/d' < $odir/$0 > mmap2.c 39cc -o mmap2 -Wall mmap2.c -lpthread 40rm -f mmap2.c 41 42for i in `jot 10`; do 43 ./mmap2 44done 45rm -f ./mmap2 46exit 47 48EOF 49#include <sys/types.h> 50#include <err.h> 51#include <stdio.h> 52#include <stdlib.h> 53#include <unistd.h> 54#include <fcntl.h> 55#include <pthread.h> 56#include <sys/mman.h> 57#include <sys/param.h> 58#include <string.h> 59#include <unistd.h> 60#include <errno.h> 61 62#define THREADS 100 63#define STARTADDR 0x50000000U 64#define ADRSPACE 0x06400000U /* 100 Mb */ 65 66static void 67work(int nr) 68{ 69 int fd, m; 70 void *p; 71 size_t left, len; 72 char path[128]; 73 74 p = (void *)STARTADDR + trunc_page(arc4random() % ADRSPACE); 75 left = ADRSPACE - (size_t)p + STARTADDR; 76 len = trunc_page(arc4random() % left) + PAGE_SIZE; 77 fd = -1; 78 79 if (arc4random() % 100 < 90) 80 sprintf(path, "/tmp/mmap.%06d.%04d", getpid(), nr); 81 else 82 sprintf(path, "/dev/zero"); 83 if (arc4random() % 2 == 0) { 84 if ((fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0622)) == -1) 85 err(1,"open()"); 86 if (ftruncate(fd, len) == -1) 87 err(1, "ftruncate"); 88 if (arc4random() % 2 == 0) { 89 if ((p = mmap(p, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == 90 MAP_FAILED) { 91 if (errno == ENOMEM) 92 return; 93 err(1, "mmap()"); 94 } 95 } else { 96 if ((p = mmap(p, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0)) == 97 MAP_FAILED) { 98 if (errno == ENOMEM) 99 return; 100 err(1, "mmap()"); 101 } 102 } 103 if (fd > 0 && strcmp(path, "/dev/zero")) 104 if (unlink(path) == -1) 105 err(1, "unlink(%s)", path); 106 } else { 107 if ((p = mmap(p, len, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0)) == MAP_FAILED) { 108 if (errno == ENOMEM) 109 return; 110 err(1, "mmap()"); 111 } 112 strcpy(path, "anon"); 113 } 114#if 0 115 printf("nr = %d, %-14s, start = %p, end = %p, len = 0x%08x, (%5d pages)\n", 116 nr, path, p, p + len, len, len>>PAGE_SHIFT); 117#endif 118 119 *(int *)p = 1; 120 121 if (arc4random() % 2 == 0) { 122 m = arc4random() % 10; 123 if (madvise(p, len, m) == -1) 124 warn("madvise(%p, %d, %d)", p, len, m); 125 } 126 if (arc4random() %2 == 0) 127 if (mprotect(p, trunc_page(arc4random() % len), PROT_READ) == -1 ) 128 err(1, "mprotect failed with error:"); 129 if (arc4random() % 2 == 0) { 130 if (arc4random() %2 == 0) { 131 if (msync(p, 0, MS_SYNC) == -1) 132 err(1, "msync(%p)", p); 133 } else { 134 if (msync(p, 0, MS_INVALIDATE) == -1) 135 err(1, "msync(%p)", p); 136 } 137 } 138 if (munmap(p, len) == -1) 139 err(1, "munmap(%p)", p); 140 close(fd); 141} 142 143void * 144thr(void *arg) 145{ 146 int i; 147 148 for (i = 0; i < 512; i++) { 149 work(*(int *)arg); 150 } 151 return (0); 152} 153 154int 155main(int argc, char **argv) 156{ 157 pthread_t threads[THREADS]; 158 int nr[THREADS]; 159 int i, n, r; 160 161// printf("Address start 0x%x, address end 0x%x, pages %d\n", 162// STARTADDR, STARTADDR + ADRSPACE, ADRSPACE>>PAGE_SHIFT); 163 n = arc4random() % THREADS + 1; 164 for (i = 0; i < n; i++) { 165 nr[i] = i; 166 if ((r = pthread_create(&threads[i], NULL, thr, (void *)&nr[i])) != 0) 167 err(1, "pthread_create(): %s\n", strerror(r)); 168 } 169 170 for (i = 0; i < n; i++) { 171 if (pthread_join(threads[i], NULL) != 0) 172 err(1, "pthread_join(%d)", i); 173 } 174 175 return (0); 176} 177