had a look at mmap() due to gamedev post. cleaned it up; now bulletproof and armor-plated (I hope :)).

This was SVN commit r1064.
This commit is contained in:
janwas 2004-08-27 00:29:46 +00:00
parent 357874a48c
commit d607aad4db
2 changed files with 75 additions and 25 deletions

View File

@ -449,56 +449,103 @@ int pthread_mutex_timedlock(pthread_mutex_t* m, const struct timespec* abs_timeo
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
void* mmap(void* start, size_t len, int prot, int flags, int fd, off_t offset) void* mmap(void* const user_start, const size_t len, const int prot, const int flags, const int fd, const off_t offset)
{ {
{
WIN_SAVE_LAST_ERROR; WIN_SAVE_LAST_ERROR;
if(!(flags & MAP_FIXED)) // assume fd = -1 (requesting mapping backed by page file),
start = 0; // so that we notice invalid file handles below.
HANDLE hFile = INVALID_HANDLE_VALUE;
if(fd != -1)
{
hFile = mk_handle(_get_osfhandle(fd));
if(hFile == INVALID_HANDLE_VALUE)
{
debug_warn("mmap: invalid file handle");
goto fail;
}
}
/* interpret protection/mapping flags. */ // MapView.. will choose start address unless MAP_FIXED was specified.
SECURITY_ATTRIBUTES sec = { sizeof(SECURITY_ATTRIBUTES), 0, 0 }; void* start = 0;
DWORD flProtect = PAGE_READONLY; /* mapping object permission */ if(flags & MAP_FIXED)
DWORD dwAccess = FILE_MAP_READ; /* file map access permission */ {
start = user_start;
if(start == 0) // assert below would fire
goto fail;
}
// figure out access rights.
// note: reads are always allowed (Win32 limitation).
SECURITY_ATTRIBUTES sec = { sizeof(SECURITY_ATTRIBUTES), (void*)0, FALSE };
DWORD flProtect = PAGE_READONLY;
DWORD dwAccess = FILE_MAP_READ;
// .. no access: not possible on Win32.
if(prot == PROT_NONE)
goto fail;
// .. write or read/write (Win32 doesn't support write-only)
if(prot & PROT_WRITE) if(prot & PROT_WRITE)
{ {
flProtect = PAGE_READWRITE; flProtect = PAGE_READWRITE;
/* changes are shared & written to file */ const bool shared = (flags & MAP_SHARED ) != 0;
if(flags & MAP_SHARED) const bool priv = (flags & MAP_PRIVATE) != 0;
// .. both aren't allowed
if(shared && priv)
goto fail;
// .. changes are shared & written to file
else if(shared)
{ {
sec.bInheritHandle = 1; sec.bInheritHandle = TRUE;
dwAccess = FILE_MAP_ALL_ACCESS; dwAccess = FILE_MAP_ALL_ACCESS;
} }
/* private copy on write mapping */ // .. private copy-on-write mapping
else if(flags & MAP_PRIVATE) else if(priv)
{ {
flProtect = PAGE_WRITECOPY; flProtect = PAGE_WRITECOPY;
dwAccess = FILE_MAP_COPY; dwAccess = FILE_MAP_COPY;
} }
} }
DWORD len_hi = (DWORD)((u64)len >> 32), len_lo = (DWORD)len & 0xffffffff; // now actually map.
const DWORD len_hi = (DWORD)((u64)len >> 32);
HANDLE hFile = mk_handle(_get_osfhandle(fd)); // careful! language doesn't allow shifting 32-bit types by 32 bits.
HANDLE hMap = CreateFileMapping(hFile, &sec, flProtect, len_hi, len_lo, 0); const DWORD len_lo = (DWORD)len & 0xffffffff;
const HANDLE hMap = CreateFileMapping(hFile, &sec, flProtect, len_hi, len_lo, (LPCSTR)0);
if(hMap == INVALID_HANDLE_VALUE)
// bail now so that MapView.. doesn't overwrite the last error value.
goto fail;
void* ptr = MapViewOfFileEx(hMap, dwAccess, len_hi, offset, len_lo, start); void* ptr = MapViewOfFileEx(hMap, dwAccess, len_hi, offset, len_lo, start);
/* file mapping object will be freed when ptr is unmapped */ // free the mapping object now, so that we don't have to hold on to its
CloseHandle(hMap); // handle until munmap(). it's not actually released yet due to the
// reference held by MapViewOfFileEx (if it succeeded).
if(hMap != INVALID_HANDLE_VALUE) // avoid "invalid handle" error
CloseHandle(hMap);
if(!ptr || (flags & MAP_FIXED && ptr != start)) if(!ptr)
return MAP_FAILED; // bail now, before the last error value is restored,
// but after freeing the mapping object.
goto fail;
assert(!(flags & MAP_FIXED) || (ptr == start));
// fixed => ptr = start
WIN_RESTORE_LAST_ERROR; WIN_RESTORE_LAST_ERROR;
return ptr; return ptr;
}
fail:
return MAP_FAILED;
} }
int munmap(void* start, size_t /* len */) int munmap(void* const start, const size_t len)
{ {
UNUSED(len);
BOOL ok = UnmapViewOfFile(start); BOOL ok = UnmapViewOfFile(start);
return ok? 0 : -1; return ok? 0 : -1;
} }

View File

@ -217,11 +217,14 @@ extern int closedir(DIR*);
// <sys/mman.h> // <sys/mman.h>
// //
#define PROT_READ 0x01 // page can be read // mmap prot flags
#define PROT_WRITE 0x02 // page can be written #define PROT_NONE 0x00 // no access (not supported on Win32)
#define PROT_READ 0x01
#define PROT_WRITE 0x02
// mmap flags
#define MAP_SHARED 0x01 // share changes across processes #define MAP_SHARED 0x01 // share changes across processes
#define MAP_PRIVATE 0x02 // private copy on write mapping #define MAP_PRIVATE 0x02 // private copy-on-write mapping
#define MAP_FIXED 0x04 #define MAP_FIXED 0x04
#define MAP_FAILED 0 #define MAP_FAILED 0