1238374Skib/*-
2238374Skib * Copyright (c) 2006, Stephan Uphoff <ups@freebsd.org>
3238374Skib * All rights reserved.
4238374Skib *
5238374Skib * Redistribution and use in source and binary forms, with or without
6238374Skib * modification, are permitted provided that the following conditions
7238374Skib * are met:
8238374Skib * 1. Redistributions of source code must retain the above copyright
9238374Skib *    notice unmodified, this list of conditions, and the following
10238374Skib *    disclaimer.
11238374Skib * 2. Redistributions in binary form must reproduce the above copyright
12238374Skib *    notice, this list of conditions and the following disclaimer in the
13238374Skib *    documentation and/or other materials provided with the distribution.
14238374Skib *
15238374Skib * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16238374Skib * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17238374Skib * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18238374Skib * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19238374Skib * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20238374Skib * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21238374Skib * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22238374Skib * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23238374Skib * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24238374Skib * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25238374Skib *
26238374Skib * $FreeBSD$
27238374Skib */
28238374Skib
29238374Skib
30238374Skib#include <sys/types.h>
31238374Skib#include <unistd.h>
32238374Skib#include <sys/stat.h>
33238374Skib#include <fcntl.h>
34238374Skib#include <stdio.h>
35238374Skib#include <sys/mman.h>
36238374Skib
37238374Skib
38238374Skibint prepareFile(char* filename,int* fdp);
39238374Skibint mapBuffer(char** bufferp,int fd1,int fd2);
40238374Skibint startIO(int fd,char *buffer);
41238374Skib
42238374Skibint pagesize;
43238374Skib
44238374Skib#define FILESIZE (32*1024)
45238374Skibchar wbuffer[FILESIZE];
46238374Skib
47238374Skib/* Create a FILESIZE sized file - then remove file data from the cache*/
48238374Skibint prepareFile(char* filename,int* fdp)
49238374Skib{
50238374Skib  int fd;
51238374Skib  int len;
52238374Skib  int status;
53238374Skib  void *addr;
54238374Skib
55238374Skib  fd = open(filename,O_CREAT | O_TRUNC | O_RDWR,S_IRWXU);
56238374Skib  if (fd == -1)
57238374Skib    {
58238374Skib      perror("Creating file");
59238374Skib      return fd;
60238374Skib    }
61238374Skib
62238374Skib  len = write(fd,wbuffer,FILESIZE);
63238374Skib  if (len < 0)
64238374Skib    {
65238374Skib      perror("Write failed");
66238374Skib      return 1;
67238374Skib    }
68238374Skib
69238374Skib  status = fsync(fd);
70238374Skib   if (status != 0)
71238374Skib    {
72238374Skib        perror("fsync failed");
73238374Skib	return 1;
74238374Skib    }
75238374Skib
76238374Skib  addr = mmap(NULL,FILESIZE, PROT_READ | PROT_WRITE , MAP_SHARED, fd, 0);
77238374Skib  if (addr == MAP_FAILED)
78238374Skib    {
79238374Skib      perror("Mmap failed");
80238374Skib      return 1;
81238374Skib    }
82238374Skib
83238374Skib  status = msync(addr,FILESIZE,MS_INVALIDATE | MS_SYNC);
84238374Skib  if (status != 0)
85238374Skib    {
86238374Skib        perror("Msync failed");
87238374Skib	return 1;
88238374Skib    }
89238374Skib
90238374Skib  munmap(addr,FILESIZE);
91238374Skib
92238374Skib  *fdp = fd;
93238374Skib  return 0;
94238374Skib}
95238374Skib
96238374Skib
97238374Skib/* mmap a 2 page buffer - first page is from fd1, second page from fd2 */
98238374Skibint mapBuffer(char** bufferp,int fd1,int fd2)
99238374Skib{
100238374Skib  void* addr;
101238374Skib  char *buffer;
102238374Skib
103238374Skib  addr = mmap(NULL,pagesize*2, PROT_READ | PROT_WRITE , MAP_SHARED, fd1, 0);
104238374Skib  if (addr == MAP_FAILED)
105238374Skib    {
106238374Skib      perror("Mmap failed");
107238374Skib      return 1;
108238374Skib    }
109238374Skib
110238374Skib  buffer = addr;
111238374Skib  addr = mmap(buffer + pagesize,pagesize, PROT_READ | PROT_WRITE , MAP_FIXED |
112238374SkibMAP_SHARED, fd2, 0);
113238374Skib
114238374Skib  if (addr == MAP_FAILED)
115238374Skib    {
116238374Skib      perror("Mmap2 failed");
117238374Skib      return 1;
118238374Skib    }
119238374Skib  *bufferp = buffer;
120238374Skib  return 0;
121238374Skib}
122238374Skib
123238374Skib
124238374Skibint startIO(int fd,char *buffer)
125238374Skib{
126238374Skib  ssize_t len;
127238374Skib  len = write(fd,buffer,2*pagesize);
128238374Skib  if (len == -1)
129238374Skib    {
130238374Skib      perror("write failed");
131238374Skib      return 1;
132238374Skib    }
133238374Skib  return 0;
134238374Skib}
135238374Skib
136238374Skib
137238374Skibint main(int argc,char *argv[],char *envp[])
138238374Skib{
139238374Skib
140238374Skib  int fdA,fdB,fdDelayA,fdDelayB;
141238374Skib  int status;
142238374Skib  char *bufferA,*bufferB;
143238374Skib  pid_t pid;
144238374Skib
145238374Skib  pagesize = getpagesize();
146238374Skib
147238374Skib  if ((prepareFile("A",&fdA))
148238374Skib      || (prepareFile("B",&fdB))
149238374Skib      || (prepareFile("DelayA",&fdDelayA))
150238374Skib      || (prepareFile("DelayB",&fdDelayB))
151238374Skib      || (mapBuffer(&bufferA,fdDelayA,fdB))
152238374Skib      || (mapBuffer(&bufferB,fdDelayB,fdA)))
153238374Skib    exit(1);
154238374Skib
155238374Skib  pid = fork();
156238374Skib
157238374Skib  if (pid == 0)
158238374Skib    {
159238374Skib      status = startIO(fdA,bufferA);
160238374Skib      exit(status);
161238374Skib    }
162238374Skib
163238374Skib  if (pid == -1)
164238374Skib    {
165238374Skib      exit(1);
166238374Skib    }
167238374Skib  status = startIO(fdB,bufferB);
168238374Skib  exit(status);
169238374Skib
170238374Skib}
171238374Skib
172238374Skib
173238374Skib
174238374Skib
175238374Skib
176