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