1#!/bin/sh 2 3# 4# Copyright (c) 2015 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# Demonstrate resource starvation using msync(2). 30 31. ../default.cfg 32 33dir=/tmp 34odir=`pwd` 35cd $dir 36sed '1,/^EOF/d' < $odir/$0 > $dir/db.c 37mycc -o db -Wall -Wextra -O0 -g db.c -lpthread || exit 1 38rm -f db.c 39cd $odir 40 41dd if=/dev/zero of=$diskimage bs=1m count=10 status=none 42 43/tmp/db $diskimage & 44 45start=`date '+%s'` 46ls -l $diskimage > /dev/null # Will wait for more than 90 seconds 47[ `date '+%s'` -gt $((start + 90)) ] && fail="yes" 48wait 49e=$((`date +%s` - start)) 50[ $fail ] && 51 echo "Time for a ls is $((e / 60)) minutes $((e % 60)) seconds" 52rm -f /tmp/db $diskimage 53#[ $fail ] && exit 1 || exit 0 # Known issue 54exit 0 55 56EOF 57#include <sys/types.h> 58#include <sys/param.h> 59#include <sys/fcntl.h> 60#include <sys/mman.h> 61#include <sys/stat.h> 62 63#include <err.h> 64#include <errno.h> 65#include <pthread.h> 66#ifdef __FreeBSD__ 67#include <pthread_np.h> 68#define __NP__ 69#endif 70#include <stdio.h> 71#include <stdlib.h> 72#include <strings.h> 73#include <time.h> 74#include <unistd.h> 75 76pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 77size_t len; 78void *p; 79int wthreads; 80 81#define BZ 128 /* buffer size */ 82#define RUNTIME 180 /* runtime for test */ 83#define RTHREADS 64 /* reader threads */ 84#define WTHREADS 64 /* writer threads */ 85 86void * 87wt(void *arg __unused) 88{ 89 time_t start; 90 int64_t pos; 91 void *c; 92 int r; 93 char buf[BZ]; 94 95#ifdef __NP__ 96 pthread_set_name_np(pthread_self(), __func__); 97#endif 98 if ((r = pthread_mutex_lock(&mutex)) != 0) 99 errc(1, r, "pthread_mutex_lock"); 100 wthreads++; 101 if ((r = pthread_mutex_unlock(&mutex)) != 0) 102 errc(1, r, "pthread_mutex_unlock"); 103 104 start = time(NULL); 105 while (time(NULL) - start < RUNTIME) { 106 pos = arc4random() % (len / BZ); 107 pos = pos * BZ; 108 c = p + pos; 109 bcopy(buf, c, BZ); 110 c = (void *)trunc_page((unsigned long)c); 111 if (msync((void *)c, round_page(BZ), MS_SYNC) == -1) 112 err(1, "msync(%p)", c); 113 usleep(10000 + arc4random() % 1000); 114 } 115 116 if ((r = pthread_mutex_lock(&mutex)) != 0) 117 errc(1, r, "pthread_mutex_lock"); 118 wthreads--; 119 if ((r = pthread_mutex_unlock(&mutex)) != 0) 120 errc(1, r, "pthread_mutex_unlock"); 121 122 return (NULL); 123} 124 125void * 126rt(void *arg __unused) 127{ 128 int64_t pos; 129 char buf[BZ], *c; 130 131#ifdef __NP__ 132 pthread_set_name_np(pthread_self(), __func__); 133#endif 134 c = p; 135 do { 136 pos = arc4random() % (len / BZ); 137 pos = pos * BZ; 138 bcopy(&c[pos], buf, BZ); 139 usleep(10000 + arc4random() % 1000); 140 } while (wthreads != 0); 141 142 return (NULL); 143} 144 145int 146main(int argc, char *argv[]) 147{ 148 pthread_t cp[RTHREADS + WTHREADS]; 149 struct stat st; 150 int fd, i, j, rc; 151 152 if (argc != 2) 153 errx(1, "Usage: %s <file>", argv[0]); 154 if ((fd = open(argv[1], O_RDWR)) == -1) 155 err(1, "open %s", argv[1]); 156 if (fstat(fd, &st) == -1) 157 err(1, "stat"); 158 len = round_page(st.st_size); 159 p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 160 if ((void *)p == MAP_FAILED) 161 err(1, "mmap"); 162 163 i = 0; 164 for (j = 0; j < WTHREADS; j++) { 165 if ((rc = pthread_create(&cp[i++], NULL, wt, NULL)) != 0) 166 errc(1, rc, "pthread_create()"); 167 } 168 usleep(100); 169 for (j = 0; j < RTHREADS; j++) { 170 if ((rc = pthread_create(&cp[i++], NULL, rt, NULL)) != 0) 171 errc(1, rc, "pthread_create()"); 172 } 173 174 for (j = 0; j < RTHREADS + WTHREADS; j++) 175 pthread_join(cp[--i], NULL); 176 177 return (0); 178} 179