diff --git a/extension/data_loader/mman.h b/extension/data_loader/mman.h deleted file mode 100644 index 246068986ea..00000000000 --- a/extension/data_loader/mman.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. - */ - -// This file ensures that mman.h compatible functions are defined in the global -// namespace for windows and posix environments. - -#pragma once - -#include - -#ifndef _WIN32 - -#include -#include - -ET_INLINE size_t get_os_page_size() { - return sysconf(_SC_PAGESIZE); -} - -#else - -#define NOMINMAX -#include -#undef NOMINMAX -#include - -#include - -ET_INLINE long get_os_page_size() { - SYSTEM_INFO si; - GetSystemInfo(&si); - long pagesize = si.dwAllocationGranularity > si.dwPageSize - ? si.dwAllocationGranularity - : si.dwPageSize; - return pagesize; -} - -#endif diff --git a/extension/data_loader/mman_windows.cpp b/extension/data_loader/mman_windows.cpp deleted file mode 100644 index 2a7f462f99c..00000000000 --- a/extension/data_loader/mman_windows.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (c) Google Inc. and affiliates. - * All rights reserved. - * - * This source code is licensed under the MIT license. - */ - -/* - * Adapted from: https://code.google.com/archive/p/mman-win32/ - * - * mman-win32 - * mman library for Windows - * - * A light implementation of the mmap functions for MinGW. - * - * The mmap-win32 library implements a wrapper for mmap functions around the - * memory mapping Windows API. - */ - -#include - -#include -#include -#include - -#ifndef STATUS_SECTION_TOO_BIG -#define STATUS_SECTION_TOO_BIG ((NTSTATUS)0xC0000040L) -#endif - -#ifndef FILE_MAP_EXECUTE -#define FILE_MAP_EXECUTE 0x0020 -#endif /* FILE_MAP_EXECUTE */ - -#define RETURN_IF_FAILED(hr) \ - do { \ - if (FAILED((hr))) { \ - return hr; \ - } \ - } while (false) - -namespace { - -HRESULT try_grow_process_memory_working_set(DWORD dwSizeRequired) { - // Get current working set - size_t minWorkingSetInitial; - size_t maxWorkingSet; - if (!GetProcessWorkingSetSize( - GetCurrentProcess(), &minWorkingSetInitial, &maxWorkingSet)) { - return GetLastError(); - } - - // Calculate new sizes - size_t minWorkingSet = minWorkingSetInitial + dwSizeRequired; - if (minWorkingSet < minWorkingSetInitial) { - return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW); - } - - if (maxWorkingSet < minWorkingSet) { - maxWorkingSet = minWorkingSet; - } - - // Grow working set - if (!SetProcessWorkingSetSize( - GetCurrentProcess(), minWorkingSet, maxWorkingSet)) { - return GetLastError(); - } - return S_OK; -} - -HRESULT virtual_lock(void* pMem, DWORD dwSize) { - if (!VirtualLock(pMem, dwSize)) { - return GetLastError(); - } - return S_OK; -} - -HRESULT virtual_lock_allowing_working_set_growth(void* pMem, DWORD dwSize) { - HRESULT hr = virtual_lock(pMem, dwSize); - - if (hr == HRESULT_FROM_WIN32(STATUS_SECTION_TOO_BIG)) { - // Attempt to grow the process working set and try again - RETURN_IF_FAILED(try_grow_process_memory_working_set(dwSize)); - RETURN_IF_FAILED(virtual_lock(pMem, dwSize)); - } - - return hr; -} - -static int __map_mman_error(const DWORD err, const int deferr) { - if (err == 0) { - return 0; - } - // TODO: implement - return err; -} - -static DWORD __map_mmap_prot_page(const int prot) { - DWORD protect = 0; - - if (prot == PROT_NONE) { - return protect; - } - if ((prot & PROT_EXEC) != 0) { - protect = - ((prot & PROT_WRITE) != 0) ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ; - } else { - protect = ((prot & PROT_WRITE) != 0) ? PAGE_READWRITE : PAGE_READONLY; - } - return protect; -} - -static DWORD __map_mmap_prot_file(const int prot) { - DWORD desiredAccess = 0; - - if (prot == PROT_NONE) { - return desiredAccess; - } - if ((prot & PROT_READ) != 0) { - desiredAccess |= FILE_MAP_READ; - } - if ((prot & PROT_WRITE) != 0) { - desiredAccess |= FILE_MAP_WRITE; - } - if ((prot & PROT_EXEC) != 0) { - desiredAccess |= FILE_MAP_EXECUTE; - } - return desiredAccess; -} - -} // namespace - -void* mmap(void* addr, size_t len, int prot, int flags, int fildes, off_t off) { - HANDLE fm, h; - - void* map = MAP_FAILED; - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4293) -#endif - - const DWORD dwFileOffsetLow = (sizeof(off_t) <= sizeof(DWORD)) - ? (DWORD)off - : (DWORD)(off & 0xFFFFFFFFL); - const DWORD dwFileOffsetHigh = (sizeof(off_t) <= sizeof(DWORD)) - ? (DWORD)0 - : (DWORD)((off >> 32) & 0xFFFFFFFFL); - const DWORD protect = __map_mmap_prot_page(prot); - const DWORD desiredAccess = __map_mmap_prot_file(prot); - - const off_t maxSize = off + (off_t)len; - - const DWORD dwMaxSizeLow = (sizeof(off_t) <= sizeof(DWORD)) - ? (DWORD)maxSize - : (DWORD)(maxSize & 0xFFFFFFFFL); - const DWORD dwMaxSizeHigh = (sizeof(off_t) <= sizeof(DWORD)) - ? (DWORD)0 - : (DWORD)((maxSize >> 32) & 0xFFFFFFFFL); - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - - errno = 0; - - if (len == 0 - /* Unsupported flag combinations */ - || (flags & MAP_FIXED) != 0 - /* Usupported protection combinations */ - || prot == PROT_EXEC) { - errno = EINVAL; - return MAP_FAILED; - } - - h = ((flags & MAP_ANONYMOUS) == 0) ? (HANDLE)_get_osfhandle(fildes) - : INVALID_HANDLE_VALUE; - - if ((flags & MAP_ANONYMOUS) == 0 && h == INVALID_HANDLE_VALUE) { - errno = EBADF; - return MAP_FAILED; - } - - fm = CreateFileMapping(h, NULL, protect, dwMaxSizeHigh, dwMaxSizeLow, NULL); - - if (fm == NULL) { - errno = __map_mman_error(GetLastError(), EPERM); - return MAP_FAILED; - } - - map = - MapViewOfFile(fm, desiredAccess, dwFileOffsetHigh, dwFileOffsetLow, len); - - CloseHandle(fm); - - if (map == NULL) { - errno = __map_mman_error(GetLastError(), EPERM); - return MAP_FAILED; - } - - return map; -} - -int munmap(void* addr, size_t len) { - if (UnmapViewOfFile(addr)) - return 0; - - errno = __map_mman_error(GetLastError(), EPERM); - - return -1; -} - -int mprotect(void* addr, size_t len, int prot) { - DWORD newProtect = __map_mmap_prot_page(prot); - DWORD oldProtect = 0; - - if (VirtualProtect(addr, len, newProtect, &oldProtect)) - return 0; - - errno = __map_mman_error(GetLastError(), EPERM); - - return -1; -} - -int msync(void* addr, size_t len, int flags) { - if (FlushViewOfFile(addr, len)) - return 0; - - errno = __map_mman_error(GetLastError(), EPERM); - - return -1; -} - -int mlock(const void* addr, size_t len) { - HRESULT hr = virtual_lock_allowing_working_set_growth((LPVOID)addr, len); - if (SUCCEEDED(hr)) { - return 0; - } - - errno = __map_mman_error(hr, EPERM); - - return -1; -} - -int munlock(const void* addr, size_t len) { - if (VirtualUnlock((LPVOID)addr, len)) - return 0; - - errno = __map_mman_error(GetLastError(), EPERM); - - return -1; -} diff --git a/extension/data_loader/mman_windows.h b/extension/data_loader/mman_windows.h deleted file mode 100644 index 563db5d8b21..00000000000 --- a/extension/data_loader/mman_windows.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) Google Inc. and affiliates. - * All rights reserved. - * - * This source code is licensed under the MIT license. - */ - -/* - * Adapted from: https://code.google.com/archive/p/mman-win32/ - * - * mman-win32 - * mman library for Windows - * - * A light implementation of the mmap functions for MinGW. - * - * The mmap-win32 library implements a wrapper for mmap functions around the - * memory mapping Windows API. - */ - -#pragma once - -#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. -#define _WIN32_WINNT \ - 0x0501 // Change this to the appropriate value to target other versions of - // Windows. -#endif - -/* All the headers include this file. */ -#ifndef _MSC_VER -#include <_mingw.h> -#endif - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#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) - -/* Flags for msync. */ -#define MS_ASYNC 1 -#define MS_SYNC 2 -#define MS_INVALIDATE 4 - -void* mmap(void* addr, size_t len, int prot, int flags, int fildes, off_t off); -int munmap(void* addr, size_t len); -int mprotect(void* addr, size_t len, int prot); -int msync(void* addr, size_t len, int flags); -int mlock(const void* addr, size_t len); -int munlock(const void* addr, size_t len); - -#ifdef __cplusplus -}; -#endif diff --git a/extension/data_loader/mmap_data_loader.cpp b/extension/data_loader/mmap_data_loader.cpp index 53fd7bdf624..e990117d586 100644 --- a/extension/data_loader/mmap_data_loader.cpp +++ b/extension/data_loader/mmap_data_loader.cpp @@ -13,10 +13,11 @@ #include #include +#include #include #include +#include -#include #include #include #include @@ -62,16 +63,14 @@ MmapDataLoader::~MmapDataLoader() { std::free(const_cast(file_name_)); // fd_ can be -1 if this instance was moved from, but closing a negative fd is // safe (though it will return an error). - if (fd_ != -1) { - ::close(fd_); - } + ::close(fd_); } Result MmapDataLoader::from( const char* file_name, MmapDataLoader::MlockConfig mlock_config) { // Cache the page size. - long page_size = get_os_page_size(); + long page_size = sysconf(_SC_PAGESIZE); if (page_size < 0) { ET_LOG(Error, "Could not get page size: %s (%d)", ::strerror(errno), errno); return Error::AccessFailed; @@ -183,22 +182,12 @@ Result MmapDataLoader::load( Range range = get_overlapping_pages(static_cast(offset), size, page_size_); - size_t map_size = range.size; - if (range.start + map_size > file_size_) { - // Clamp to the end of the file. - // - // The Windows implementation of mmap uses CreateFileMapping which returns - // error STATUS_SECTION_TOO_BIG (0xc0000040) if we try to map past the end - // of the last page of a file mapped in as read-only. - map_size = file_size_ - range.start; - } - // Map the pages read-only. MAP_PRIVATE vs. MAP_SHARED doesn't matter since // the data is read-only, but use PRIVATE just to further avoid accidentally // modifying the file. void* pages = ::mmap( nullptr, - map_size, + range.size, PROT_READ, MAP_PRIVATE, fd_, diff --git a/extension/data_loader/targets.bzl b/extension/data_loader/targets.bzl index c23e4536520..fcc7cba5419 100644 --- a/extension/data_loader/targets.bzl +++ b/extension/data_loader/targets.bzl @@ -69,12 +69,7 @@ def define_common_targets(): runtime.cxx_library( name = "mmap_data_loader", - srcs = [ - "mmap_data_loader.cpp" - ] + (["mman_windows.cpp"] if host_info().os.is_windows else []), - headers = [ - "mman.h", - ] + (["mman_windows.h"] if host_info().os.is_windows else []), + srcs = ["mmap_data_loader.cpp"], exported_headers = ["mmap_data_loader.h"], visibility = [ "//executorch/test/...", diff --git a/extension/data_loader/test/mmap_data_loader_test.cpp b/extension/data_loader/test/mmap_data_loader_test.cpp index c01b3454493..a76121109a8 100644 --- a/extension/data_loader/test/mmap_data_loader_test.cpp +++ b/extension/data_loader/test/mmap_data_loader_test.cpp @@ -10,9 +10,10 @@ #include +#include + #include -#include #include #include #include @@ -33,7 +34,7 @@ class MmapDataLoaderTest : public ::testing::Test { executorch::runtime::runtime_init(); // Get the page size and ensure it's a power of 2. - long page_size = get_os_page_size(); + long page_size = sysconf(_SC_PAGESIZE); ASSERT_GT(page_size, 0); ASSERT_EQ(page_size & ~(page_size - 1), page_size); page_size_ = page_size;