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