1/*-
2 * Copyright (c) 2006, Stephan Uphoff <ups@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice unmodified, this list of conditions, and the following
10 *    disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * $FreeBSD$
27 */
28
29
30#include <sys/types.h>
31#include <unistd.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <stdio.h>
35#include <sys/mman.h>
36
37
38int prepareFile(char* filename,int* fdp);
39int mapBuffer(char** bufferp,int fd1,int fd2);
40int startIO(int fd,char *buffer);
41
42int pagesize;
43
44#define FILESIZE (32*1024)
45char wbuffer[FILESIZE];
46
47/* Create a FILESIZE sized file - then remove file data from the cache*/
48int prepareFile(char* filename,int* fdp)
49{
50  int fd;
51  int len;
52  int status;
53  void *addr;
54
55  fd = open(filename,O_CREAT | O_TRUNC | O_RDWR,S_IRWXU);
56  if (fd == -1)
57    {
58      perror("Creating file");
59      return fd;
60    }
61
62  len = write(fd,wbuffer,FILESIZE);
63  if (len < 0)
64    {
65      perror("Write failed");
66      return 1;
67    }
68
69  status = fsync(fd);
70   if (status != 0)
71    {
72        perror("fsync failed");
73	return 1;
74    }
75
76  addr = mmap(NULL,FILESIZE, PROT_READ | PROT_WRITE , MAP_SHARED, fd, 0);
77  if (addr == MAP_FAILED)
78    {
79      perror("Mmap failed");
80      return 1;
81    }
82
83  status = msync(addr,FILESIZE,MS_INVALIDATE | MS_SYNC);
84  if (status != 0)
85    {
86        perror("Msync failed");
87	return 1;
88    }
89
90  munmap(addr,FILESIZE);
91
92  *fdp = fd;
93  return 0;
94}
95
96
97/* mmap a 2 page buffer - first page is from fd1, second page from fd2 */
98int mapBuffer(char** bufferp,int fd1,int fd2)
99{
100  void* addr;
101  char *buffer;
102
103  addr = mmap(NULL,pagesize*2, PROT_READ | PROT_WRITE , MAP_SHARED, fd1, 0);
104  if (addr == MAP_FAILED)
105    {
106      perror("Mmap failed");
107      return 1;
108    }
109
110  buffer = addr;
111  addr = mmap(buffer + pagesize,pagesize, PROT_READ | PROT_WRITE , MAP_FIXED |
112MAP_SHARED, fd2, 0);
113
114  if (addr == MAP_FAILED)
115    {
116      perror("Mmap2 failed");
117      return 1;
118    }
119  *bufferp = buffer;
120  return 0;
121}
122
123
124int startIO(int fd,char *buffer)
125{
126  ssize_t len;
127  len = write(fd,buffer,2*pagesize);
128  if (len == -1)
129    {
130      perror("write failed");
131      return 1;
132    }
133  return 0;
134}
135
136
137int main(int argc,char *argv[],char *envp[])
138{
139
140  int fdA,fdB,fdDelayA,fdDelayB;
141  int status;
142  char *bufferA,*bufferB;
143  pid_t pid;
144
145  pagesize = getpagesize();
146
147  if ((prepareFile("A",&fdA))
148      || (prepareFile("B",&fdB))
149      || (prepareFile("DelayA",&fdDelayA))
150      || (prepareFile("DelayB",&fdDelayB))
151      || (mapBuffer(&bufferA,fdDelayA,fdB))
152      || (mapBuffer(&bufferB,fdDelayB,fdA)))
153    exit(1);
154
155  pid = fork();
156
157  if (pid == 0)
158    {
159      status = startIO(fdA,bufferA);
160      exit(status);
161    }
162
163  if (pid == -1)
164    {
165      exit(1);
166    }
167  status = startIO(fdB,bufferB);
168  exit(status);
169
170}
171
172
173
174
175
176