Use mmap() IO for reading uncompressed .blends

Instead of submitting tons of tiny IO syscalls, we can speed things up
significantly by `mmap`ing the .blend file into virtual memory and directly
accessing it.

In my local testing, this speeds up loading the Dweebs file with all its
linked files from 19sec to 10sec (on Linux).

As far as I can see, this should be supported on Linux, OSX and BSD.
For Windows, a second code path uses `CreateFileMapping` and
`MapViewOfFile` to achieve the same result.

Reviewed By: mont29, brecht

Differential Revision: https://developer.blender.org/D8246
This commit is contained in:
Lukas Stockner 2021-01-14 22:02:48 +01:00 committed by Lukas Stockner
parent 33a558bf21
commit 0f2ae614a1
13 changed files with 376 additions and 375 deletions

View File

@ -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}
)

View File

@ -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 <errno.h>
# include <io.h>
# include <stdio.h>
# include <sys/types.h>
# include <windows.h>
# 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

View File

@ -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 <sys/types.h>
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

View File

@ -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__ */

View File

@ -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

View File

@ -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 <string.h>
#ifndef WIN32
# include <stdlib.h>
# include <signal.h>
# include <sys/mman.h> // for mmap
# include <unistd.h> // for read close
#else
# include "BLI_winstuff.h"
# include <io.h> // 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);
}

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -23,13 +23,13 @@
*/
#ifdef _WIN32
# include "mmap_win.h"
# include <io.h>
# include <stddef.h>
# include <sys/types.h>
#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();
}

View File

@ -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)

View File

@ -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