1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
/**
* @namespace biewlib
* @file biewlib/sysdep/generic/linux/mmfio.c
* @brief This file contains implementation of memory mapped file i/o routines for POSIX compatible OS.
* @version -
* @remark this source file is part of Binary vIEW project (BIEW).
* The Binary vIEW (BIEW) is copyright (C) 1995 Nick Kurshev.
* All rights reserved. This software is redistributable under the
* licence given in the file "Licence.en" ("Licence.ru" in russian
* translation) distributed in the BIEW archive.
* @note Requires POSIX compatible development system
*
* @author Nick Kurshev
* @since 2000
* @note Development, fixes and improvements
**/
#ifdef __DISABLE_MMF
#include "biewlib/sysdep/ia16/dos/mmfio.c"
#else
#include <sys/mman.h>
#include "biewlib/pmalloc.h"
#include "biewlib/biewlib.h"
#ifndef MREMAP_MAYMOVE
#define MREMAP_MAYMOVE 1
#endif
struct mmfRecord
{
void * addr;
long length;
int fhandle;
int mode;
};
static int __FASTCALL__ mk_prot(int mode)
{
int pflg;
pflg = PROT_READ;
if(mode & FO_WRITEONLY) pflg = PROT_WRITE;
else
if(mode & FO_READWRITE) pflg |= PROT_WRITE;
return pflg;
}
static int __FASTCALL__ mk_flags(int mode)
{
int pflg;
pflg = 0;
#ifdef MAP_SHARED
if((mode & SO_DENYREAD) ||
(mode & SO_DENYWRITE) ||
(mode & SO_DENYNONE)) pflg |= MAP_SHARED;
#endif
#ifdef MAP_PRIVATE
if(mode & SO_PRIVATE) pflg |= MAP_PRIVATE;
#endif
return pflg;
}
mmfHandle __FASTCALL__ __mmfOpen(const char *fname,int mode)
{
struct mmfRecord *mret;
int fhandle;
fhandle = __OsOpen(fname,mode);
if(fhandle != -1)
{
mret = PMalloc(sizeof(struct mmfRecord));
if(mret)
{
long length;
void *addr;
length = __FileLength(fhandle);
addr = mmap(NULL,length,mk_prot(mode),
mk_flags(mode),fhandle,0L);
if(addr != (void *)-1)
{
mret->fhandle = fhandle;
mret->addr = addr;
mret->length = length;
mret->mode = mode;
return mret;
}
PFree(mret);
}
__OsClose(fhandle);
}
return NULL;
}
tBool __FASTCALL__ __mmfFlush(mmfHandle mh)
{
struct mmfRecord *mrec = (struct mmfRecord *)mh;
return msync(mrec->addr,mrec->length,MS_SYNC) ? False : True;
}
mmfHandle __FASTCALL__ __mmfSync(mmfHandle mh)
{
struct mmfRecord *mrec = (struct mmfRecord *)mh;
long length;
length = __FileLength(mrec->fhandle);
msync(mrec->addr,min(length,mrec->length),MS_SYNC);
if((mrec->addr = mremap(mrec->addr,mrec->length,length,MREMAP_MAYMOVE)) != (void *)-1)
{
mrec->length = length;
return mrec;
}
__OsClose(mrec->fhandle);
PFree(mrec);
return NULL;
}
tBool __FASTCALL__ __mmfProtect(mmfHandle mh,int flags)
{
struct mmfRecord *mrec = (struct mmfRecord *)mh;
mrec->mode = flags;
return mprotect(mrec->addr,mrec->length,mk_prot(flags)) ? False : True;
}
tBool __FASTCALL__ __mmfResize(mmfHandle mh,long size)
{
struct mmfRecord *mrec = (struct mmfRecord *)mh;
void *new_addr;
tBool can_continue = False;
if(mrec->length > size) /* truncate */
{
if((new_addr = mremap(mrec->addr,mrec->length,size,MREMAP_MAYMOVE)) != (void *)-1) can_continue = True;
if(can_continue)
can_continue = __OsChSize(mrec->fhandle,size) != -1 ? True : False;
}
else /* expand */
{
if(__OsChSize(mrec->fhandle,size) != -1) can_continue = True;
if(can_continue)
can_continue = (new_addr = mremap(mrec->addr,mrec->length,size,MREMAP_MAYMOVE)) != (void *)-1 ? True : False;
}
if(can_continue)
{
mrec->addr = new_addr;
mrec->length = size;
return True;
}
else /* Attempt to unroll transaction back */
__OsChSize(mrec->fhandle,mrec->length);
return False;
}
void __FASTCALL__ __mmfClose(mmfHandle mh)
{
struct mmfRecord *mrec = (struct mmfRecord *)mh;
munmap(mrec->addr,mrec->length);
__OsClose(mrec->fhandle);
PFree(mrec);
}
void * __FASTCALL__ __mmfAddress(mmfHandle mh)
{
return ((struct mmfRecord *)mh)->addr;
}
long __FASTCALL__ __mmfSize(mmfHandle mh)
{
return ((struct mmfRecord *)mh)->length;
}
tBool __FASTCALL__ __mmfIsWorkable( void ) { return True; }
#endif
|