Initial import of binutils 2.22 on the new vendor branch
[dragonfly.git] / test / stress / stress2 / misc / datamove3.sh
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 # Threaded variation of datamove.sh
32
33 # Based on a test scenario by ups and suggestions by kib
34
35 [ `id -u ` -ne 0 ] && echo "Must be root!" && exit 1
36
37 here=`pwd`
38 cd /tmp
39 sed '1,/^EOF/d' < $here/$0 > dl.c
40 cc -o dl -Wall dl.c -lpthread
41 rm -f dl.c
42
43 n=5
44 old=`sysctl vm.old_msync | awk '{print $NF}'`
45 sysctl vm.old_msync=1
46 for i in `jot $n`; do
47         mkdir -p /tmp/dl.dir.$i
48         cd /tmp/dl.dir.$i
49         /tmp/dl &
50 done
51 cd /tmp
52 for i in `jot $n`; do
53         wait
54 done
55 for i in `jot $n`; do
56         rm -rf /tmp/dl.dir.$i
57 done
58 sysctl vm.old_msync=$old
59
60 rm -rf /tmp/dl
61 exit 0
62 EOF
63 #include <err.h>
64 #include <fcntl.h>
65 #include <pthread.h>
66 #include <stdio.h>
67 #include <stdio.h>
68 #include <stdlib.h>
69 #include <string.h>
70 #include <sys/mman.h>
71 #include <sys/stat.h>
72 #include <sys/types.h>
73 #include <unistd.h>
74
75 struct args {
76         char *bp;
77         int fd1;
78         int fd2;
79 } a[2];
80
81 int prepareFile(char *, int *);
82 void * mapBuffer(void *);
83 int startIO(int, char *);
84
85 int pagesize;
86
87 #define FILESIZE (32*1024)
88 char wbuffer   [FILESIZE];
89
90 /* Create a FILESIZE sized file - then remove file data from the cache */
91 int
92 prepareFile(char *filename, int *fdp)
93 {
94         int fd;
95         int len;
96         int status;
97         void *addr;
98
99         fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU);
100         if (fd == -1) {
101                 perror("Creating file");
102                 return fd;
103         }
104         len = write(fd, wbuffer, FILESIZE);
105         if (len < 0) {
106                 perror("Write failed");
107                 return 1;
108         }
109         status = fsync(fd);
110         if (status != 0) {
111                 perror("fsync failed");
112                 return 1;
113         }
114         addr = mmap(NULL, FILESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
115         if (addr == MAP_FAILED) {
116                 perror("Mmap failed");
117                 return 1;
118         }
119         status = msync(addr, FILESIZE, MS_INVALIDATE | MS_SYNC);
120         if (status != 0) {
121                 perror("Msync failed");
122                 return 1;
123         }
124         munmap(addr, FILESIZE);
125
126         *fdp = fd;
127         return 0;
128 }
129
130
131 /* mmap a 2 page buffer - first page is from fd1, second page from fd2 */
132 void *
133 mapBuffer(void *ar)
134 {
135         void *addr;
136         char *buffer;
137         int i;
138
139         i = (int )ar;
140         addr = mmap(NULL, pagesize * 2, PROT_READ | PROT_WRITE, MAP_SHARED, a[i].fd1, 0);
141         if (addr == MAP_FAILED) {
142                 err(1, "Mmap failed");
143         }
144         buffer = addr;
145         addr = mmap(buffer + pagesize, pagesize, PROT_READ | PROT_WRITE, MAP_FIXED |
146                     MAP_SHARED, a[i].fd2, 0);
147
148         if (addr == MAP_FAILED) {
149                 err(1, "Mmap2 failed");
150         }
151         a[i].bp = buffer;
152         sleep(1);
153         return (NULL);
154 }
155
156
157 int
158 startIO(int fd, char *buffer)
159 {
160         ssize_t len;
161
162         len = write(fd, buffer, 2 * pagesize);
163         if (len == -1) {
164                 warn("startIO(%d, %p): write failed", fd, buffer);
165                 return 1;
166         }
167         return 0;
168 }
169
170
171
172 int
173 main(int argc, char *argv[], char *envp[])
174 {
175
176         int fdA, fdB, fdDelayA, fdDelayB;
177         int r, status;
178         char *bufferA, *bufferB;
179         pid_t pid;
180         pthread_t threads[2];
181
182         pagesize = getpagesize();
183
184         if ((prepareFile("A", &fdA))
185             || (prepareFile("B", &fdB))
186             || (prepareFile("DelayA", &fdDelayA))
187             || (prepareFile("DelayB", &fdDelayB)))
188                 exit(1);
189
190         a[0].fd1 = fdDelayA;
191         a[0].fd2 = fdB;
192
193         a[1].fd1 = fdDelayB;
194         a[1].fd2 = fdA;
195
196         if ((r = pthread_create(&threads[0], NULL, mapBuffer, (void *)0)) != 0)
197                 err(1, "pthread_create(): %s\n", strerror(r));
198         if ((r = pthread_create(&threads[1], NULL, mapBuffer, (void *)1)) != 0)
199                 err(1, "pthread_create(): %s\n", strerror(r));
200
201         while (a[0].bp == NULL || a[1].bp == NULL)
202                 pthread_yield();
203
204         bufferA = a[0].bp;
205         bufferB = a[1].bp;
206
207         pid = fork();
208
209         if (pid == 0) {
210                 status = startIO(fdA, bufferA);
211                 exit(status);
212         }
213         if (pid == -1) {
214                 exit(1);
215         }
216         status = startIO(fdB, bufferB);
217         exit(status);
218
219 }