X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Faccess%2Fmmap.c;h=2c7dfbfc3544cb931e1eb32af33893f85cfb2c25;hb=295b0e07523b7e9daf6c7ed76eec02d2dcfd80f0;hp=188106825d819100227cdc7f2d218be9d667cb77;hpb=d801998f14fff1f11dc0405d32016c3826a01dcd;p=vlc diff --git a/modules/access/mmap.c b/modules/access/mmap.c index 188106825d..2c7dfbfc35 100644 --- a/modules/access/mmap.c +++ b/modules/access/mmap.c @@ -23,15 +23,15 @@ # include #endif -#include +#include +#include #include #include -#include -#include +#include +#include #include -#include #include #include #include @@ -42,24 +42,32 @@ #define FILE_MMAP_LONGTEXT N_( \ "Try to use memory mapping to read files and block devices." ) +#ifndef NDEBUG +/*# define MMAP_DEBUG 1*/ +#endif + static int Open (vlc_object_t *); static void Close (vlc_object_t *); -vlc_module_begin(); - set_shortname (_("MMap")); - set_description (_("Memory-mapped file input")); - set_category (CAT_INPUT); - set_subcategory (SUBCAT_INPUT_ACCESS); - set_capability ("access2", 52); - add_shortcut ("file"); - set_callbacks (Open, Close); - - add_bool ("file-mmap", VLC_TRUE, NULL, - FILE_MMAP_TEXT, FILE_MMAP_LONGTEXT, VLC_TRUE); -vlc_module_end(); +vlc_module_begin () + set_shortname (N_("MMap")) + set_description (N_("Memory-mapped file input")) + set_category (CAT_INPUT) + set_subcategory (SUBCAT_INPUT_ACCESS) + set_capability ("access", 52) + add_shortcut ("file") + set_callbacks (Open, Close) +#ifdef __APPLE__ + add_bool ("file-mmap", true, NULL, + FILE_MMAP_TEXT, FILE_MMAP_LONGTEXT, true) +#else + add_bool ("file-mmap", false, NULL, + FILE_MMAP_TEXT, FILE_MMAP_LONGTEXT, true) +#endif +vlc_module_end () static block_t *Block (access_t *); -static int Seek (access_t *, int64_t); +static int Seek (access_t *, uint64_t); static int Control (access_t *, int, va_list); struct access_sys_t @@ -75,21 +83,18 @@ static int Open (vlc_object_t *p_this) { access_t *p_access = (access_t *)p_this; access_sys_t *p_sys; - const char *path = p_access->psz_path; + const char *path = p_access->psz_filepath; int fd; - if (!var_CreateGetBool (p_this, "file-mmap")) + assert ((INT64_C(1) << 63) == ((off_t)(INT64_C(1) << 63))); + + if (!var_InheritBool (p_this, "file-mmap")) return VLC_EGENERIC; /* disabled */ STANDARD_BLOCK_ACCESS_INIT; - if (!strcmp (p_access->psz_path, "-")) - fd = dup (0); - else - { - msg_Dbg (p_access, "opening file %s", path); - fd = utf8_open (path, O_RDONLY | O_NOCTTY, 0666); - } + msg_Dbg (p_access, "opening file %s", path); + fd = vlc_open (path, O_RDONLY | O_NOCTTY); if (fd == -1) { @@ -110,10 +115,21 @@ static int Open (vlc_object_t *p_this) if (!S_ISREG (st.st_mode) && !S_ISBLK (st.st_mode)) { - msg_Dbg (p_access, "skipping non regular file %s", path); + msg_Dbg (p_access, "skipping non-regular file %s", path); goto error; } +#if defined(HAVE_FCNTL_H) + /* We'd rather use any available memory for reading ahead + * than for caching what we've already mmap'ed */ +# if defined(F_RDAHEAD) + fcntl (fd, F_RDAHEAD, 1); +# endif +# if defined(F_NOCACHE) + fcntl (fd, F_NOCACHE, 1); +# endif +#endif + /* Autodetect mmap() support */ if (st.st_size > 0) { @@ -131,7 +147,9 @@ static int Open (vlc_object_t *p_this) p_sys->fd = fd; p_access->info.i_size = st.st_size; +#ifdef HAVE_POSIX_FADVISE posix_fadvise (fd, 0, 0, POSIX_FADV_SEQUENTIAL); +#endif return VLC_SUCCESS; @@ -155,37 +173,35 @@ static void Close (vlc_object_t * p_this) static block_t *Block (access_t *p_access) { access_sys_t *p_sys = p_access->p_sys; -#ifndef NDEBUG - int64_t dbgpos = lseek (p_sys->fd, 0, SEEK_CUR); - if (dbgpos != p_access->info.i_pos) - msg_Err (p_access, "position: 0x%08llx instead of 0x%08llx", - p_access->info.i_pos, dbgpos); -#endif - if ((uint64_t)p_access->info.i_pos >= (uint64_t)p_access->info.i_size) - { - /* End of file - check if file size changed... */ - struct stat st; + /* Check if file size changed... */ + struct stat st; - if ((fstat (p_sys->fd, &st) == 0) - && (st.st_size != p_access->info.i_size)) - { - p_access->info.i_size = st.st_size; - p_access->info.i_update |= INPUT_UPDATE_SIZE; - } + if ((fstat (p_sys->fd, &st) == 0) + && (st.st_size != p_access->info.i_size)) + { + p_access->info.i_size = st.st_size; + p_access->info.i_update |= INPUT_UPDATE_SIZE; + } - /* Really at end of file then */ - if ((uint64_t)p_access->info.i_pos >= (uint64_t)p_access->info.i_size) - { - p_access->info.b_eof = VLC_TRUE; - msg_Dbg (p_access, "at end of memory mapped file"); - return NULL; - } + if (p_access->info.i_pos >= p_access->info.i_size) + { + /* We are at end of file */ + p_access->info.b_eof = true; + msg_Dbg (p_access, "at end of memory mapped file"); + return NULL; } +#ifdef MMAP_DEBUG + uint64_t dbgpos = lseek (p_sys->fd, 0, SEEK_CUR); + if (dbgpos != p_access->info.i_pos) + msg_Err (p_access, "position: 0x%016"PRIx64" instead of 0x%016"PRIx64, + p_access->info.i_pos, dbgpos); +#endif + const uintptr_t page_mask = p_sys->page_size - 1; /* Start the mapping on a page boundary: */ - off_t outer_offset = p_access->info.i_pos & ~page_mask; + off_t outer_offset = p_access->info.i_pos & ~(off_t)page_mask; /* Skip useless bytes at the beginning of the first page: */ size_t inner_offset = p_access->info.i_pos & page_mask; /* Map no more bytes than remain: */ @@ -201,36 +217,40 @@ static block_t *Block (access_t *p_access) /* NOTE: We use PROT_WRITE and MAP_PRIVATE so that the block can be * modified down the chain, without messing up with the underlying * original file. This does NOT need open write permission. */ - void *addr = mmap (NULL, length, PROT_READ|PROT_WRITE, MAP_PRIVATE, - p_sys->fd, outer_offset); + void *addr = mmap (NULL, length, PROT_READ|PROT_WRITE, MAP_PRIVATE +#ifdef MAP_NO_CACHE + | MAP_NOCACHE +#endif + , p_sys->fd, outer_offset); if (addr == MAP_FAILED) { msg_Err (p_access, "memory mapping failed (%m)"); - intf_UserFatal (p_access, VLC_FALSE, _("File reading failed"), + dialog_Fatal (p_access, _("File reading failed"), "%s", _("VLC could not read the file.")); - msleep (INPUT_ERROR_SLEEP); - return NULL; + goto fatal; } +#ifdef HAVE_POSIX_MADVISE posix_madvise (addr, length, POSIX_MADV_SEQUENTIAL); +#endif block_t *block = block_mmap_Alloc (addr, length); if (block == NULL) - return NULL; + goto fatal; block->p_buffer += inner_offset; block->i_buffer -= inner_offset; -#ifndef NDEBUG - msg_Dbg (p_access, "mapped 0x%lx bytes at %p from offset 0x%lx", - (unsigned long)length, addr, (unsigned long)outer_offset); +#ifdef MMAP_DEBUG + msg_Dbg (p_access, "mapped 0x%zx bytes at %p from offset 0x%"PRIx64, + length, addr, (uint64_t)outer_offset); /* Compare normal I/O with memory mapping */ char *buf = malloc (block->i_buffer); ssize_t i_read = read (p_sys->fd, buf, block->i_buffer); if (i_read != (ssize_t)block->i_buffer) - msg_Err (p_access, "read %u instead of %u bytes", (unsigned)i_read, - (unsigned)block->i_buffer); + msg_Err (p_access, "read %zd instead of %zu bytes", i_read, + block->i_buffer); if (memcmp (buf, block->p_buffer, block->i_buffer)) msg_Err (p_access, "inconsistent data buffer"); free (buf); @@ -238,37 +258,42 @@ static block_t *Block (access_t *p_access) p_access->info.i_pos = outer_offset + length; return block; + +fatal: + p_access->info.b_eof = true; + return NULL; } -static int Seek (access_t *p_access, int64_t i_pos) +static int Seek (access_t *p_access, uint64_t i_pos) { +#ifdef MMAP_DEBUG + lseek (p_access->p_sys->fd, i_pos, SEEK_SET); +#endif + p_access->info.i_pos = i_pos; - p_access->info.b_eof = VLC_FALSE; + p_access->info.b_eof = false; return VLC_SUCCESS; } static int Control (access_t *p_access, int query, va_list args) { - access_sys_t *p_sys = p_access->p_sys; - switch (query) { case ACCESS_CAN_SEEK: case ACCESS_CAN_FASTSEEK: case ACCESS_CAN_PAUSE: case ACCESS_CAN_CONTROL_PACE: - *((vlc_bool_t *)va_arg (args, vlc_bool_t *)) = VLC_TRUE; - return VLC_SUCCESS; - - case ACCESS_GET_MTU: - *((int *)va_arg (args, int *)) = p_sys->mtu; + *va_arg(args, bool *) = true; return VLC_SUCCESS; case ACCESS_GET_PTS_DELAY: - *((int64_t *)va_arg (args, int64_t *)) = DEFAULT_PTS_DELAY; + { + int64_t delay_ms = var_CreateGetInteger (p_access, "file-caching"); + *va_arg(args, int64_t *) = delay_ms * INT64_C (1000); return VLC_SUCCESS; + } case ACCESS_GET_TITLE_INFO: case ACCESS_GET_META: