mirror of
https://github.com/libretro/RetroArch
synced 2025-04-16 17:43:02 +00:00
(retro_file) Implement RFILE_HINT_MMAP
This commit is contained in:
parent
80a89bbd36
commit
eb7b46c7c1
@ -68,6 +68,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <retro_file.h>
|
#include <retro_file.h>
|
||||||
|
#include <memmap.h>
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
#define HAVE_BUFFERED_IO 1
|
#define HAVE_BUFFERED_IO 1
|
||||||
@ -83,6 +84,11 @@ struct RFILE
|
|||||||
unsigned hints;
|
unsigned hints;
|
||||||
#if defined(HAVE_BUFFERED_IO)
|
#if defined(HAVE_BUFFERED_IO)
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
#endif
|
||||||
|
#if defined(HAVE_MMAP)
|
||||||
|
uint8_t *mapped;
|
||||||
|
uint64_t mappos;
|
||||||
|
uint64_t mapsize;
|
||||||
#endif
|
#endif
|
||||||
int fd;
|
int fd;
|
||||||
#endif
|
#endif
|
||||||
@ -119,6 +125,13 @@ RFILE *retro_fopen(const char *path, unsigned mode, ssize_t len)
|
|||||||
|
|
||||||
stream->hints = mode;
|
stream->hints = mode;
|
||||||
|
|
||||||
|
#ifdef HAVE_MMAP
|
||||||
|
if (stream->hints & RFILE_HINT_MMAP && (stream->hints & 0xff) == RFILE_MODE_READ)
|
||||||
|
stream->hints |= RFILE_HINT_UNBUFFERED;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
stream->hints &= ~RFILE_HINT_MMAP;
|
||||||
|
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case RFILE_MODE_READ:
|
case RFILE_MODE_READ:
|
||||||
@ -132,9 +145,9 @@ RFILE *retro_fopen(const char *path, unsigned mode, ssize_t len)
|
|||||||
#if defined(HAVE_BUFFERED_IO)
|
#if defined(HAVE_BUFFERED_IO)
|
||||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||||
mode_str = "rb";
|
mode_str = "rb";
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
flags = O_RDONLY;
|
/* No "else" here */
|
||||||
|
flags = O_RDONLY;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case RFILE_MODE_WRITE:
|
case RFILE_MODE_WRITE:
|
||||||
@ -148,8 +161,8 @@ RFILE *retro_fopen(const char *path, unsigned mode, ssize_t len)
|
|||||||
#if defined(HAVE_BUFFERED_IO)
|
#if defined(HAVE_BUFFERED_IO)
|
||||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||||
mode_str = "wb";
|
mode_str = "wb";
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
|
else
|
||||||
flags = O_WRONLY | O_CREAT | O_TRUNC | S_IRUSR | S_IWUSR;
|
flags = O_WRONLY | O_CREAT | O_TRUNC | S_IRUSR | S_IWUSR;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
@ -164,8 +177,8 @@ RFILE *retro_fopen(const char *path, unsigned mode, ssize_t len)
|
|||||||
#if defined(HAVE_BUFFERED_IO)
|
#if defined(HAVE_BUFFERED_IO)
|
||||||
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
|
||||||
mode_str = "w+";
|
mode_str = "w+";
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
|
else
|
||||||
{
|
{
|
||||||
flags = O_RDWR;
|
flags = O_RDWR;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -194,6 +207,33 @@ RFILE *retro_fopen(const char *path, unsigned mode, ssize_t len)
|
|||||||
stream->fd = open(path, flags);
|
stream->fd = open(path, flags);
|
||||||
if (stream->fd == -1)
|
if (stream->fd == -1)
|
||||||
goto error;
|
goto error;
|
||||||
|
#ifdef HAVE_MMAP
|
||||||
|
if (stream->hints & RFILE_HINT_MMAP)
|
||||||
|
{
|
||||||
|
stream->mappos = 0;
|
||||||
|
stream->mapped = NULL;
|
||||||
|
stream->mapsize = 0;
|
||||||
|
|
||||||
|
if (retro_fseek(stream, 0, SEEK_END) != 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
stream->mapsize = retro_ftell(stream);
|
||||||
|
if (stream->mapsize == (uint64_t)-1)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
retro_frewind(stream);
|
||||||
|
|
||||||
|
stream->mapped = mmap((void*)0, stream->mapsize, PROT_READ, MAP_SHARED, stream->fd, 0);
|
||||||
|
|
||||||
|
if (stream->mapped == MAP_FAILED)
|
||||||
|
{
|
||||||
|
#ifdef RARCH_INTERNAL
|
||||||
|
RARCH_WARN("mmap()ing %s failed: %s\n", path, strerror(errno));
|
||||||
|
#endif
|
||||||
|
stream->hints &= ~RFILE_HINT_MMAP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -233,10 +273,46 @@ ssize_t retro_fseek(RFILE *stream, ssize_t offset, int whence)
|
|||||||
return fseek(stream->fp, (long)offset, whence);
|
return fseek(stream->fp, (long)offset, whence);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
#ifdef HAVE_MMAP
|
||||||
ret = lseek(stream->fd, offset, whence);
|
/* Need to check stream->mapped because this function is called in retro_fopen() */
|
||||||
return ret == -1 ? -1 : 0;
|
if (stream->mapped && stream->hints & RFILE_HINT_MMAP)
|
||||||
}
|
{
|
||||||
|
switch (whence)
|
||||||
|
{
|
||||||
|
case SEEK_SET:
|
||||||
|
if (offset < 0)
|
||||||
|
offset = 0;
|
||||||
|
|
||||||
|
stream->mappos = offset;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SEEK_CUR:
|
||||||
|
if (offset < 0 && stream->mappos + offset > stream->mappos)
|
||||||
|
stream->mappos = 0;
|
||||||
|
else
|
||||||
|
stream->mappos += offset;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SEEK_END:
|
||||||
|
if (offset < 0)
|
||||||
|
offset = 0;
|
||||||
|
|
||||||
|
if (stream->mapsize - offset > stream->mapsize)
|
||||||
|
stream->mappos = 0;
|
||||||
|
else
|
||||||
|
stream->mappos = stream->mapsize - offset;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
ret = lseek(stream->fd, offset, whence);
|
||||||
|
return ret == -1 ? -1 : 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,7 +333,13 @@ ssize_t retro_ftell(RFILE *stream)
|
|||||||
return ftell(stream->fp);
|
return ftell(stream->fp);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
return lseek(stream->fd, 0, SEEK_CUR);
|
#ifdef HAVE_MMAP
|
||||||
|
/* Need to check stream->mapped because this function is called in retro_fopen() */
|
||||||
|
if (stream->mapped && stream->hints & RFILE_HINT_MMAP)
|
||||||
|
return stream->mappos;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
return lseek(stream->fd, 0, SEEK_CUR);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,7 +365,20 @@ ssize_t retro_fread(RFILE *stream, void *s, size_t len)
|
|||||||
return fread(s, 1, len, stream->fp);
|
return fread(s, 1, len, stream->fp);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
return read(stream->fd, s, len);
|
#ifdef HAVE_MMAP
|
||||||
|
if (stream->hints & RFILE_HINT_MMAP)
|
||||||
|
{
|
||||||
|
if (stream->mappos + len > stream->mapsize)
|
||||||
|
len = stream->mapsize - stream->mappos;
|
||||||
|
|
||||||
|
memcpy(s, &stream->mapped[stream->mappos], len);
|
||||||
|
stream->mappos += len;
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
return read(stream->fd, s, len);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,7 +399,12 @@ ssize_t retro_fwrite(RFILE *stream, const void *s, size_t len)
|
|||||||
return fwrite(s, 1, len, stream->fp);
|
return fwrite(s, 1, len, stream->fp);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
return write(stream->fd, s, len);
|
#ifdef HAVE_MMAP
|
||||||
|
if (stream->hints & RFILE_HINT_MMAP)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return write(stream->fd, s, len);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,6 +428,11 @@ int retro_fclose(RFILE *stream)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_MMAP
|
||||||
|
if (stream->hints & RFILE_HINT_MMAP)
|
||||||
|
munmap(stream->mapped, stream->mapsize);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (stream->fd > 0)
|
if (stream->fd > 0)
|
||||||
close(stream->fd);
|
close(stream->fd);
|
||||||
#endif
|
#endif
|
||||||
|
@ -44,7 +44,7 @@ enum
|
|||||||
|
|
||||||
/* There is no garantee these requests will be attended. */
|
/* There is no garantee these requests will be attended. */
|
||||||
RFILE_HINT_UNBUFFERED = 1<<8,
|
RFILE_HINT_UNBUFFERED = 1<<8,
|
||||||
RFILE_HINT_MMAP = 1<<7
|
RFILE_HINT_MMAP = 1<<9 /* requires RFILE_MODE_READ */
|
||||||
};
|
};
|
||||||
|
|
||||||
RFILE *retro_fopen(const char *path, unsigned mode, ssize_t len);
|
RFILE *retro_fopen(const char *path, unsigned mode, ssize_t len);
|
||||||
|
@ -401,7 +401,7 @@ void libretrodb_cursor_close(libretrodb_cursor_t *cursor)
|
|||||||
int libretrodb_cursor_open(libretrodb_t *db, libretrodb_cursor_t *cursor,
|
int libretrodb_cursor_open(libretrodb_t *db, libretrodb_cursor_t *cursor,
|
||||||
libretrodb_query_t *q)
|
libretrodb_query_t *q)
|
||||||
{
|
{
|
||||||
cursor->fd = retro_fopen(db->path, RFILE_MODE_READ | RFILE_HINT_UNBUFFERED, -1);
|
cursor->fd = retro_fopen(db->path, RFILE_MODE_READ | RFILE_HINT_MMAP, -1);
|
||||||
|
|
||||||
if (!cursor->fd)
|
if (!cursor->fd)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user