#include <algorithm>
|
#include <vector>
|
#include "il2cpp-config.h"
|
#include "MemoryMapImpl.h"
|
#include "os/File.h"
|
#include "os/MemoryMappedFile.h"
|
#include "os/Mutex.h"
|
#include "utils/StringUtils.h"
|
#include "utils/Memory.h"
|
|
namespace il2cpp
|
{
|
namespace icalls
|
{
|
namespace System
|
{
|
namespace Core
|
{
|
namespace System
|
{
|
namespace IO
|
{
|
namespace MemoryMappedFiles
|
{
|
static os::FastMutex s_Mutex;
|
static std::vector<os::FileHandle*> s_OwnedFileHandles;
|
|
typedef struct
|
{
|
void *address;
|
void *free_handle;
|
size_t length;
|
} MmapInstance;
|
|
static int32_t ConvertMemoryMappedFileAccessToIL2CPPFileAccess(os::MemoryMappedFileAccess access)
|
{
|
switch (access)
|
{
|
case os::MMAP_FILE_ACCESS_READ:
|
case os::MMAP_FILE_ACCESS_READ_EXECUTE:
|
return kFileAccessRead;
|
case os::MMAP_FILE_ACCESS_READ_WRITE:
|
case os::MMAP_FILE_ACCESS_COPY_ON_WRITE:
|
case os::MMAP_FILE_ACCESS_READ_WRITE_EXECUTE:
|
return kFileAccessRead | kFileAccessWrite;
|
case os::MMAP_FILE_ACCESS_WRITE:
|
return kFileAccessWrite;
|
default:
|
IL2CPP_ASSERT("unknown MemoryMappedFileAccess");
|
}
|
|
return kFileAccessRead;
|
}
|
|
static void CloseFileHandleIfOwned(os::FileHandle* file)
|
{
|
std::vector<os::FileHandle*>::iterator ownedHandleEntry = std::find(s_OwnedFileHandles.begin(), s_OwnedFileHandles.end(), file);
|
if (ownedHandleEntry != s_OwnedFileHandles.end())
|
{
|
int error = 0;
|
os::File::Close(file, &error);
|
s_OwnedFileHandles.erase(ownedHandleEntry);
|
IL2CPP_ASSERT(error == 0);
|
}
|
}
|
|
bool MemoryMapImpl::Unmap(intptr_t mmap_handle)
|
{
|
IL2CPP_ASSERT(mmap_handle);
|
|
MmapInstance *h = (MmapInstance*)mmap_handle;
|
|
bool result = os::MemoryMappedFile::UnmapView(h->address, h->length);
|
|
IL2CPP_FREE(h);
|
|
return result;
|
}
|
|
int32_t MemoryMapImpl::MapInternal(intptr_t handle, int64_t offset, int64_t* size, int32_t access, intptr_t* mmap_handle, intptr_t* base_address)
|
{
|
IL2CPP_ASSERT(handle);
|
|
MmapInstance* h = (MmapInstance*)IL2CPP_MALLOC_ZERO(sizeof(MmapInstance));
|
|
os::MemoryMappedFileError error = os::NO_MEMORY_MAPPED_FILE_ERROR;
|
int64_t actualOffset = offset;
|
h->address = os::MemoryMappedFile::View((os::FileHandle*)handle, size, offset, (os::MemoryMappedFileAccess)access, &actualOffset, &error);
|
h->length = (size_t)*size;
|
|
if (h->address)
|
{
|
*mmap_handle = (intptr_t)h;
|
*base_address = (intptr_t)((char*)h->address + (offset - actualOffset));
|
}
|
else
|
{
|
IL2CPP_FREE(h);
|
}
|
|
return error;
|
}
|
|
static os::FileHandle* OpenHandle(os::FileHandle* handle, Il2CppString* mapName, os::MemoryMappedFileMode mode, int64_t* capacity, int32_t access, int32_t options, int32_t* error)
|
{
|
os::MemoryMappedFileError memoryMappedFileError = os::NO_MEMORY_MAPPED_FILE_ERROR;
|
std::string utf8MapNameString = mapName != NULL ? utils::StringUtils::Utf16ToUtf8(mapName->chars) : std::string();
|
const char* utf8MapName = !utf8MapNameString.empty() ? utf8MapNameString.c_str() : NULL;
|
os::FileHandle* memoryMappedFileData = os::MemoryMappedFile::Create(handle, utf8MapName, mode, capacity, (os::MemoryMappedFileAccess)access, options, &memoryMappedFileError);
|
|
*error = (int32_t)memoryMappedFileError;
|
return memoryMappedFileData;
|
}
|
|
intptr_t MemoryMapImpl::OpenFileInternal(Il2CppString* path, int32_t mode, Il2CppString* mapName, int64_t* capacity, int32_t access, int32_t options, int32_t* error)
|
{
|
IL2CPP_ASSERT(path || mapName);
|
|
*error = 0;
|
|
os::FileHandle* file = NULL;
|
if (path != NULL)
|
{
|
os::FastAutoLock lock(&s_Mutex);
|
std::string filePath = utils::StringUtils::Utf16ToUtf8(path->chars);
|
file = os::File::Open(filePath, mode, ConvertMemoryMappedFileAccessToIL2CPPFileAccess((os::MemoryMappedFileAccess)access), 0, options, error);
|
|
s_OwnedFileHandles.push_back(file);
|
}
|
|
os::FileHandle* result = NULL;
|
if (*error == 0)
|
{
|
result = OpenHandle(file, mapName, (os::MemoryMappedFileMode)mode, capacity, access, options, error);
|
if (result != NULL && result != file)
|
CloseFileHandleIfOwned(file);
|
}
|
|
return (intptr_t)result;
|
}
|
|
intptr_t MemoryMapImpl::OpenHandleInternal(intptr_t handle, Il2CppString* mapName, int64_t* capacity, int32_t access, int32_t options, int32_t* error)
|
{
|
IL2CPP_ASSERT(handle);
|
|
return (intptr_t)OpenHandle((os::FileHandle*)handle, mapName, os::FILE_MODE_OPEN, capacity, access, options, error);
|
}
|
|
void MemoryMapImpl::CloseMapping(intptr_t handle)
|
{
|
IL2CPP_ASSERT(handle);
|
|
os::FileHandle* file = (os::FileHandle*)handle;
|
|
os::MemoryMappedFile::Close(file);
|
CloseFileHandleIfOwned(file);
|
}
|
|
void MemoryMapImpl::ConfigureHandleInheritability(intptr_t handle, int32_t inheritability)
|
{
|
IL2CPP_ASSERT(handle);
|
|
os::MemoryMappedFile::ConfigureHandleInheritability((os::FileHandle*)handle, inheritability);
|
}
|
|
void MemoryMapImpl::Flush(intptr_t mmap_handle)
|
{
|
IL2CPP_ASSERT(mmap_handle);
|
|
MmapInstance *h = (MmapInstance*)mmap_handle;
|
os::MemoryMappedFile::Flush(h->address, h->length);
|
}
|
} // namespace MemoryMappedFiles
|
} // namespace IO
|
} // namespace System
|
} // namespace Core
|
} // namespace System
|
} // namespace icalls
|
} // namespace il2cpp
|