diff --git a/intern/guardedalloc/CMakeLists.txt b/intern/guardedalloc/CMakeLists.txt index 0d46e81cd87..b47565b8ef9 100644 --- a/intern/guardedalloc/CMakeLists.txt +++ b/intern/guardedalloc/CMakeLists.txt @@ -49,12 +49,6 @@ set(LIB ) if(WIN32 AND NOT UNIX) - list(APPEND SRC - intern/mmap_win.c - - mmap_win.h - ) - list(APPEND INC_SYS ${PTHREADS_INC} ) diff --git a/intern/guardedalloc/intern/mmap_win.c b/intern/guardedalloc/intern/mmap_win.c deleted file mode 100644 index a02a0f88fa9..00000000000 --- a/intern/guardedalloc/intern/mmap_win.c +++ /dev/null @@ -1,294 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2008 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup MEM - */ - -#ifdef WIN32 - -# include -# include -# include -# include -# include - -# include "mmap_win.h" - -# ifndef FILE_MAP_EXECUTE -// not defined in earlier versions of the Platform SDK (before February 2003) -# define FILE_MAP_EXECUTE 0x0020 -# endif - -/* copied from BLI_utildefines.h, ugh */ -# ifdef __GNUC__ -# define UNUSED(x) UNUSED_##x __attribute__((__unused__)) -# else -# define UNUSED(x) x -# endif - -/* --------------------------------------------------------------------- */ -/* local storage definitions */ -/* --------------------------------------------------------------------- */ -/* all memory mapped chunks are put in linked lists */ -typedef struct mmapLink { - struct mmapLink *next, *prev; -} mmapLink; - -typedef struct mmapListBase { - void *first, *last; -} mmapListBase; - -typedef struct MemMap { - struct MemMap *next, *prev; - void *mmap; - HANDLE fhandle; - HANDLE maphandle; -} MemMap; - -/* --------------------------------------------------------------------- */ -/* local functions */ -/* --------------------------------------------------------------------- */ - -static void mmap_addtail(volatile mmapListBase *listbase, void *vlink); -static void mmap_remlink(volatile mmapListBase *listbase, void *vlink); -static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr); - -static int mmap_get_prot_flags(int flags); -static int mmap_get_access_flags(int flags); - -/* --------------------------------------------------------------------- */ -/* vars */ -/* --------------------------------------------------------------------- */ -volatile static struct mmapListBase _mmapbase; -volatile static struct mmapListBase *mmapbase = &_mmapbase; - -/* --------------------------------------------------------------------- */ -/* implementation */ -/* --------------------------------------------------------------------- */ - -/* mmap for windows */ -void *mmap(void *UNUSED(start), size_t len, int prot, int flags, int fd, off_t offset) -{ - HANDLE fhandle = INVALID_HANDLE_VALUE; - HANDLE maphandle; - int prot_flags = mmap_get_prot_flags(prot); - int access_flags = mmap_get_access_flags(prot); - MemMap *mm = NULL; - void *ptr = NULL; - - if (flags & MAP_FIXED) { - return MAP_FAILED; - } - -# if 0 - if (fd == -1) { - _set_errno(EBADF); - return MAP_FAILED; - } -# endif - - if (fd != -1) { - fhandle = (HANDLE)_get_osfhandle(fd); - } - if (fhandle == INVALID_HANDLE_VALUE) { - if (!(flags & MAP_ANONYMOUS)) { - errno = EBADF; - return MAP_FAILED; - } - } - else { - if (!DuplicateHandle(GetCurrentProcess(), - fhandle, - GetCurrentProcess(), - &fhandle, - 0, - FALSE, - DUPLICATE_SAME_ACCESS)) { - return MAP_FAILED; - } - } - - /* Split 64 bit size into low and high bits. */ - DWORD len_bits_high = len >> 32; - DWORD len_bits_low = len & 0xFFFFFFFF; - - maphandle = CreateFileMapping(fhandle, NULL, prot_flags, len_bits_high, len_bits_low, NULL); - if (maphandle == 0) { - errno = EBADF; - return MAP_FAILED; - } - - ptr = MapViewOfFile(maphandle, access_flags, 0, offset, 0); - if (ptr == NULL) { - DWORD dwLastErr = GetLastError(); - if (dwLastErr == ERROR_MAPPED_ALIGNMENT) { - errno = EINVAL; - } - else { - errno = EACCES; - } - CloseHandle(maphandle); - return MAP_FAILED; - } - - mm = (MemMap *)malloc(sizeof(MemMap)); - if (!mm) { - errno = ENOMEM; - } - mm->fhandle = fhandle; - mm->maphandle = maphandle; - mm->mmap = ptr; - mmap_addtail(mmapbase, mm); - - return ptr; -} - -/* munmap for windows */ -intptr_t munmap(void *ptr, size_t UNUSED(size)) -{ - MemMap *mm = mmap_findlink(mmapbase, ptr); - if (!mm) { - errno = EINVAL; - return -1; - } - UnmapViewOfFile(mm->mmap); - CloseHandle(mm->maphandle); - CloseHandle(mm->fhandle); - mmap_remlink(mmapbase, mm); - free(mm); - return 0; -} - -/* --------------------------------------------------------------------- */ -/* local functions */ -/* --------------------------------------------------------------------- */ - -static void mmap_addtail(volatile mmapListBase *listbase, void *vlink) -{ - struct mmapLink *link = vlink; - - if (link == NULL) { - return; - } - if (listbase == NULL) { - return; - } - - link->next = 0; - link->prev = listbase->last; - - if (listbase->last) { - ((struct mmapLink *)listbase->last)->next = link; - } - if (listbase->first == NULL) { - listbase->first = link; - } - listbase->last = link; -} - -static void mmap_remlink(volatile mmapListBase *listbase, void *vlink) -{ - struct mmapLink *link = vlink; - - if (link == NULL) { - return; - } - if (listbase == NULL) { - return; - } - if (link->next) { - link->next->prev = link->prev; - } - if (link->prev) { - link->prev->next = link->next; - } - - if (listbase->last == link) { - listbase->last = link->prev; - } - if (listbase->first == link) { - listbase->first = link->next; - } -} - -static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr) -{ - MemMap *mm; - - if (ptr == NULL) { - return NULL; - } - if (listbase == NULL) { - return NULL; - } - - mm = (MemMap *)listbase->first; - while (mm) { - if (mm->mmap == ptr) { - return mm; - } - mm = mm->next; - } - return NULL; -} - -static int mmap_get_prot_flags(int flags) -{ - int prot = PAGE_NOACCESS; - - if ((flags & PROT_READ) == PROT_READ) { - if ((flags & PROT_WRITE) == PROT_WRITE) { - prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; - } - else { - prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READ : PAGE_READONLY; - } - } - else if ((flags & PROT_WRITE) == PROT_WRITE) { - prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READ : PAGE_WRITECOPY; - } - else if ((flags & PROT_EXEC) == PROT_EXEC) { - prot = PAGE_EXECUTE_READ; - } - return prot; -} - -static int mmap_get_access_flags(int flags) -{ - int access = 0; - - if ((flags & PROT_READ) == PROT_READ) { - if ((flags & PROT_WRITE) == PROT_WRITE) { - access = FILE_MAP_WRITE; - } - else { - access = (flags & PROT_EXEC) ? FILE_MAP_EXECUTE : FILE_MAP_READ; - } - } - else if ((flags & PROT_WRITE) == PROT_WRITE) { - access = FILE_MAP_COPY; - } - else if ((flags & PROT_EXEC) == PROT_EXEC) { - access = FILE_MAP_EXECUTE; - } - return access; -} - -#endif // WIN32 diff --git a/intern/guardedalloc/mmap_win.h b/intern/guardedalloc/mmap_win.h deleted file mode 100644 index c0cbaa0e512..00000000000 --- a/intern/guardedalloc/mmap_win.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2008 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup MEM - */ - -#ifndef __MMAP_WIN_H__ -#define __MMAP_WIN_H__ - -#define PROT_NONE 0 -#define PROT_READ 1 -#define PROT_WRITE 2 -#define PROT_EXEC 4 - -#define MAP_FILE 0 -#define MAP_SHARED 1 -#define MAP_PRIVATE 2 -#define MAP_TYPE 0xF -#define MAP_FIXED 0x10 -#define MAP_ANONYMOUS 0x20 -#define MAP_ANON MAP_ANONYMOUS - -#define MAP_FAILED ((void *)-1) - -/* needed for uintptr_t, exception, dont use BLI anywhere else in MEM_* */ -#include "../../source/blender/blenlib/BLI_sys_types.h" - -#include - -void *mmap(void *start, size_t len, int prot, int flags, int fd, off_t offset); -intptr_t munmap(void *ptr, size_t size); - -#endif diff --git a/source/blender/blenlib/BLI_mmap.h b/source/blender/blenlib/BLI_mmap.h new file mode 100644 index 00000000000..385c56bd10a --- /dev/null +++ b/source/blender/blenlib/BLI_mmap.h @@ -0,0 +1,59 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2020 Blender Foundation. + * All rights reserved. + */ + +#ifndef __BLI_MMAP_H__ +#define __BLI_MMAP_H__ + +/** \file + * \ingroup bli + */ + +#include "BLI_compiler_attrs.h" +#include "BLI_utildefines.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Memory-mapped file IO that implements all the OS-specific details and error handling. */ + +struct BLI_mmap_file; + +typedef struct BLI_mmap_file BLI_mmap_file; + +/* Prepares an opened file for memory-mapped IO. + * May return NULL if the operation fails. + * Note that this seeks to the end of the file to determine its length. */ +BLI_mmap_file *BLI_mmap_open(int fd) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; + +/* Reads length bytes from file at the given offset into dest. + * Returns whether the operation was successful (may fail when reading beyond the file + * end or when IO errors occur). */ +bool BLI_mmap_read(BLI_mmap_file *file, void *dest, size_t offset, size_t length) + ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); + +void *BLI_mmap_get_pointer(BLI_mmap_file *file) ATTR_WARN_UNUSED_RESULT; + +void BLI_mmap_free(BLI_mmap_file *file) ATTR_NONNULL(1); + +#ifdef __cplusplus +} +#endif + +#endif /* __BLI_MEMPOOL_H__ */ diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index aa4c4efe7d4..b7a13596dd0 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -54,6 +54,7 @@ set(SRC intern/BLI_memblock.c intern/BLI_memiter.c intern/BLI_mempool.c + intern/BLI_mmap.c intern/BLI_timer.c intern/DLRB_tree.c intern/array_store.c @@ -243,6 +244,7 @@ set(SRC BLI_mempool.h BLI_mesh_boolean.hh BLI_mesh_intersect.hh + BLI_mmap.h BLI_mpq2.hh BLI_mpq3.hh BLI_multi_value_map.hh diff --git a/source/blender/blenlib/intern/BLI_mmap.c b/source/blender/blenlib/intern/BLI_mmap.c new file mode 100644 index 00000000000..f0b13183c68 --- /dev/null +++ b/source/blender/blenlib/intern/BLI_mmap.c @@ -0,0 +1,233 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup bli + */ + +#include "BLI_mmap.h" +#include "BLI_fileops.h" +#include "BLI_listbase.h" +#include "MEM_guardedalloc.h" + +#include + +#ifndef WIN32 +# include +# include +# include // for mmap +# include // for read close +#else +# include "BLI_winstuff.h" +# include // for open close read +#endif + +struct BLI_mmap_file { + /* The address to which the file was mapped. */ + char *memory; + + /* The length of the file (and therefore the mapped region). */ + size_t length; + + /* Platform-specific handle for the mapping. */ + void *handle; + + /* Flag to indicate IO errors. Needs to be volatile since it's being set from + * within the signal handler, which is not part of the normal execution flow. */ + volatile bool io_error; +}; + +#ifndef WIN32 +/* When using memory-mapped files, any IO errors will result in a SIGBUS signal. + * Therefore, we need to catch that signal and stop reading the file in question. + * To do so, we keep a list of all current FileDatas that use memory-mapped files, + * and if a SIGBUS is caught, we check if the failed address is inside one of the + * mapped regions. + * If it is, we set a flag to indicate a failed read and remap the memory in + * question to a zero-backed region in order to avoid additional signals. + * The code that actually reads the memory area has to check whether the flag was + * set after it's done reading. + * If the error occurred outside of a memory-mapped region, we call the previous + * handler if one was configured and abort the process otherwise. + */ + +struct error_handler_data { + ListBase open_mmaps; + char configured; + void (*next_handler)(int, siginfo_t *, void *); +} error_handler = {0}; + +static void sigbus_handler(int sig, siginfo_t *siginfo, void *ptr) +{ + /* We only handle SIGBUS here for now. */ + BLI_assert(sig == SIGBUS); + + char *error_addr = (char *)siginfo->si_addr; + /* Find the file that this error belongs to. */ + LISTBASE_FOREACH (LinkData *, link, &error_handler.open_mmaps) { + BLI_mmap_file *file = link->data; + + /* Is the address where the error occurred in this file's mapped range? */ + if (error_addr >= file->memory && error_addr < file->memory + file->length) { + file->io_error = true; + + /* Replace the mapped memory with zeroes. */ + mmap(file->memory, file->length, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); + + return; + } + } + + /* Fall back to other handler if there was one. */ + if (error_handler.next_handler) { + error_handler.next_handler(sig, siginfo, ptr); + } + else { + fprintf(stderr, "Unhandled SIGBUS caught\n"); + abort(); + } +} + +/* Ensures that the error handler is set up and ready. */ +static bool sigbus_handler_setup(void) +{ + if (!error_handler.configured) { + struct sigaction newact = {0}, oldact = {0}; + + newact.sa_sigaction = sigbus_handler; + newact.sa_flags = SA_SIGINFO; + + if (sigaction(SIGBUS, &newact, &oldact)) { + return false; + } + + /* Remember the previously configured handler to fall back to it if the error + * does not belong to any of the mapped files. */ + error_handler.next_handler = oldact.sa_sigaction; + error_handler.configured = 1; + } + + return true; +} + +/* Adds a file to the list that the error handler checks. */ +static void sigbus_handler_add(BLI_mmap_file *file) +{ + BLI_addtail(&error_handler.open_mmaps, BLI_genericNodeN(file)); +} + +/* Removes a file from the list that the error handler checks. */ +static void sigbus_handler_remove(BLI_mmap_file *file) +{ + LinkData *link = BLI_findptr(&error_handler.open_mmaps, file, offsetof(LinkData, data)); + BLI_freelinkN(&error_handler.open_mmaps, link); +} +#endif + +BLI_mmap_file *BLI_mmap_open(int fd) +{ + void *memory, *handle = NULL; + size_t length = BLI_lseek(fd, 0, SEEK_END); + +#ifndef WIN32 + /* Ensure that the SIGBUS handler is configured. */ + if (!sigbus_handler_setup()) { + return NULL; + } + + /* Map the given file to memory. */ + memory = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0); + if (memory == MAP_FAILED) { + return NULL; + } +#else + /* Convert the POSIX-style file descriptor to a Windows handle. */ + void *file_handle = (void *)_get_osfhandle(fd); + /* Memory mapping on Windows is a two-step process - first we create a mapping, + * then we create a view into that mapping. + * In our case, one view that spans the entire file is enough. */ + handle = CreateFileMapping(file_handle, NULL, PAGE_READONLY, 0, 0, NULL); + if (handle == NULL) { + return NULL; + } + memory = MapViewOfFile(handle, FILE_MAP_READ, 0, 0, 0); + if (memory == NULL) { + CloseHandle(handle); + return NULL; + } +#endif + + /* Now that the mapping was successful, allocate memory and set up the BLI_mmap_file. */ + BLI_mmap_file *file = MEM_callocN(sizeof(BLI_mmap_file), __func__); + file->memory = memory; + file->handle = handle; + file->length = length; + +#ifndef WIN32 + /* Register the file with the error handler. */ + sigbus_handler_add(file); +#endif + + return file; +} + +bool BLI_mmap_read(BLI_mmap_file *file, void *dest, size_t offset, size_t length) +{ + /* If a previous read has already failed or we try to read past the end, + * don't even attempt to read any further. */ + if (file->io_error || (offset + length > file->length)) { + return false; + } + +#ifndef WIN32 + /* If an error occurs in this call, sigbus_handler will be called and will set + * file->io_error to true. */ + memcpy(dest, file->memory + offset, length); +#else + /* On Windows, we use exception handling to be notified of errors. */ + __try { + memcpy(dest, file->memory + offset, length); + } + __except (GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR ? EXCEPTION_EXECUTE_HANDLER : + EXCEPTION_CONTINUE_SEARCH) { + file->io_error = true; + return false; + } +#endif + + return !file->io_error; +} + +void *BLI_mmap_get_pointer(BLI_mmap_file *file) +{ + return file->memory; +} + +void BLI_mmap_free(BLI_mmap_file *file) +{ +#ifndef WIN32 + munmap((void *)file->memory, file->length); + sigbus_handler_remove(file); +#else + UnmapViewOfFile(file->memory); + CloseHandle(file->handle); +#endif + + MEM_freeN(file); +} diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index b61abd4ed06..2192e9a378f 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -68,6 +68,7 @@ #include "BLI_math.h" #include "BLI_memarena.h" #include "BLI_mempool.h" +#include "BLI_mmap.h" #include "BLI_threads.h" #include "BLT_translation.h" @@ -1179,6 +1180,53 @@ static ssize_t fd_read_from_memory(FileData *filedata, return readsize; } +/* Memory-mapped file reading. + * By using mmap(), we can map a file so that it can be treated like normal memory, + * meaning that we can just read from it with memcpy() etc. + * This avoids system call overhead and can significantly speed up file loading. + */ + +static ssize_t fd_read_from_mmap(FileData *filedata, + void *buffer, + size_t size, + bool *UNUSED(r_is_memchunck_identical)) +{ + /* don't read more bytes than there are available in the buffer */ + size_t readsize = MIN2(size, (size_t)(filedata->buffersize - filedata->file_offset)); + + if (!BLI_mmap_read(filedata->mmap_file, buffer, filedata->file_offset, readsize)) { + return 0; + } + + filedata->file_offset += readsize; + + return readsize; +} + +static off64_t fd_seek_from_mmap(FileData *filedata, off64_t offset, int whence) +{ + off64_t new_pos; + if (whence == SEEK_CUR) { + new_pos = filedata->file_offset + offset; + } + else if (whence == SEEK_SET) { + new_pos = offset; + } + else if (whence == SEEK_END) { + new_pos = filedata->buffersize + offset; + } + else { + return -1; + } + + if (new_pos < 0 || new_pos > filedata->buffersize) { + return -1; + } + + filedata->file_offset = new_pos; + return filedata->file_offset; +} + /* MemFile reading. */ static ssize_t fd_read_from_memfile(FileData *filedata, @@ -1306,6 +1354,8 @@ static FileData *blo_filedata_from_file_descriptor(const char *filepath, { FileDataReadFn *read_fn = NULL; FileDataSeekFn *seek_fn = NULL; /* Optional. */ + size_t buffersize = 0; + BLI_mmap_file *mmap_file = NULL; gzFile gzfile = (gzFile)Z_NULL; @@ -1322,14 +1372,21 @@ static FileData *blo_filedata_from_file_descriptor(const char *filepath, return NULL; } - BLI_lseek(file, 0, SEEK_SET); - /* Regular file. */ if (memcmp(header, "BLENDER", sizeof(header)) == 0) { read_fn = fd_read_data_from_file; seek_fn = fd_seek_data_from_file; + + mmap_file = BLI_mmap_open(file); + if (mmap_file != NULL) { + read_fn = fd_read_from_mmap; + seek_fn = fd_seek_from_mmap; + buffersize = BLI_lseek(file, 0, SEEK_END); + } } + BLI_lseek(file, 0, SEEK_SET); + /* Gzip file. */ errno = 0; if ((read_fn == NULL) && @@ -1363,6 +1420,8 @@ static FileData *blo_filedata_from_file_descriptor(const char *filepath, fd->read = read_fn; fd->seek = seek_fn; + fd->mmap_file = mmap_file; + fd->buffersize = buffersize; return fd; } @@ -1531,6 +1590,11 @@ void blo_filedata_free(FileData *fd) fd->buffer = NULL; } + if (fd->mmap_file) { + BLI_mmap_free(fd->mmap_file); + fd->mmap_file = NULL; + } + /* Free all BHeadN data blocks */ #ifndef NDEBUG BLI_freelistN(&fd->bhead_list); diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h index c724cc32051..86f05eda7b7 100644 --- a/source/blender/blenloader/intern/readfile.h +++ b/source/blender/blenloader/intern/readfile.h @@ -41,6 +41,7 @@ struct Object; struct OldNewMap; struct ReportList; struct UserDef; +struct BLI_mmap_file; typedef struct IDNameLib_Map IDNameLib_Map; @@ -83,8 +84,9 @@ typedef struct FileData { /** Regular file reading. */ int filedes; - /** Variables needed for reading from memory / stream. */ + /** Variables needed for reading from memory / stream / memory-mapped files. */ const char *buffer; + struct BLI_mmap_file *mmap_file; /** Variables needed for reading from memfile (undo). */ struct MemFile *memfile; /** Whether we are undoing (< 0) or redoing (> 0), used to choose which 'unchanged' flag to use diff --git a/source/blender/imbuf/intern/IMB_allocimbuf.h b/source/blender/imbuf/intern/IMB_allocimbuf.h index 08aa1936a6f..c92d764a104 100644 --- a/source/blender/imbuf/intern/IMB_allocimbuf.h +++ b/source/blender/imbuf/intern/IMB_allocimbuf.h @@ -32,7 +32,7 @@ struct ImBuf; void imb_refcounter_lock_init(void); void imb_refcounter_lock_exit(void); -#ifdef WIN32 +#ifndef WIN32 void imb_mmap_lock_init(void); void imb_mmap_lock_exit(void); void imb_mmap_lock(void); diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c index 8dfb3ada7d6..bfb7bc93ac7 100644 --- a/source/blender/imbuf/intern/allocimbuf.c +++ b/source/blender/imbuf/intern/allocimbuf.c @@ -53,7 +53,7 @@ void imb_refcounter_lock_exit(void) BLI_spin_end(&refcounter_spin); } -#ifdef WIN32 +#ifndef WIN32 static SpinLock mmap_spin; void imb_mmap_lock_init(void) diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index f0daa4543e1..50210650f05 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -23,13 +23,13 @@ */ #ifdef _WIN32 -# include "mmap_win.h" # include # include # include #endif #include "BLI_fileops.h" +#include "BLI_mmap.h" #include "BLI_path_util.h" #include "BLI_string.h" #include "BLI_utildefines.h" @@ -186,20 +186,19 @@ ImBuf *IMB_loadifffile( size = BLI_file_descriptor_size(file); imb_mmap_lock(); - mem = mmap(NULL, size, PROT_READ, MAP_SHARED, file, 0); + BLI_mmap_file *mmap_file = BLI_mmap_open(file); imb_mmap_unlock(); - - if (mem == (unsigned char *)-1) { + if (mmap_file == NULL) { fprintf(stderr, "%s: couldn't get mapping %s\n", __func__, descr); return NULL; } + mem = BLI_mmap_get_pointer(mmap_file); + ibuf = IMB_ibImageFromMemory(mem, size, flags, colorspace, descr); imb_mmap_lock(); - if (munmap(mem, size)) { - fprintf(stderr, "%s: couldn't unmap file %s\n", __func__, descr); - } + BLI_mmap_free(mmap_file); imb_mmap_unlock(); return ibuf; @@ -292,14 +291,15 @@ static void imb_loadtilefile(ImBuf *ibuf, int file, int tx, int ty, unsigned int size = BLI_file_descriptor_size(file); imb_mmap_lock(); - mem = mmap(NULL, size, PROT_READ, MAP_SHARED, file, 0); + BLI_mmap_file *mmap_file = BLI_mmap_open(file); imb_mmap_unlock(); - - if (mem == (unsigned char *)-1) { + if (mmap_file == NULL) { fprintf(stderr, "Couldn't get memory mapping for %s\n", ibuf->cachename); return; } + mem = BLI_mmap_get_pointer(mmap_file); + const ImFileType *type = IMB_file_type_from_ibuf(ibuf); if (type != NULL) { if (type->load_tile != NULL) { @@ -308,9 +308,7 @@ static void imb_loadtilefile(ImBuf *ibuf, int file, int tx, int ty, unsigned int } imb_mmap_lock(); - if (munmap(mem, size)) { - fprintf(stderr, "Couldn't unmap memory for %s.\n", ibuf->cachename); - } + BLI_mmap_free(mmap_file); imb_mmap_unlock(); } diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt index a7adaa7e258..5d1ed7b44a1 100644 --- a/source/blender/makesdna/intern/CMakeLists.txt +++ b/source/blender/makesdna/intern/CMakeLists.txt @@ -48,12 +48,6 @@ set(SRC ../../../../intern/guardedalloc/intern/mallocn_lockfree_impl.c ) -if(WIN32 AND NOT UNIX) - list(APPEND SRC - ../../../../intern/guardedalloc/intern/mmap_win.c - ) -endif() - # SRC_DNA_INC is defined in the parent dir add_cc_flags_custom_test(makesdna) diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 72cdaecb2c3..94cfd8464ae 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -189,7 +189,6 @@ set(SRC ../../../../intern/guardedalloc/intern/mallocn.c ../../../../intern/guardedalloc/intern/mallocn_guarded_impl.c ../../../../intern/guardedalloc/intern/mallocn_lockfree_impl.c - ../../../../intern/guardedalloc/intern/mmap_win.c # Needed for defaults. ../../../../release/datafiles/userdef/userdef_default.c