-
Notifications
You must be signed in to change notification settings - Fork 536
[Windows Build] Implement MMAP for mmap_data_loader.cpp #5164
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/* | ||
* 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 <executorch/runtime/platform/compiler.h> | ||
|
||
#ifndef _WIN32 | ||
|
||
#include <sys/mman.h> | ||
#include <unistd.h> | ||
|
||
ET_INLINE long get_os_page_size(){return sysconf(_SC_PAGESIZE)} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now that we're wrapping this, I'd like to return |
||
|
||
#else | ||
|
||
#define NOMINMAX | ||
#include <windows.h> | ||
#undef NOMINMAX | ||
#include <io.h> | ||
|
||
#include <executorch/extension/data_loader/mman_windows.h> | ||
|
||
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 |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,251 @@ | ||||||||||||||||||||||||||||
/* | ||||||||||||||||||||||||||||
* 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 <errno.h> | ||||||||||||||||||||||||||||
#include <io.h> | ||||||||||||||||||||||||||||
#include <windows.h> | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
#include "mman_windows.h" | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
Comment on lines
+19
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||
#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; | ||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
/* | ||
* 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. | ||
*/ | ||
|
||
#ifndef _SYS_MMAN_H_ | ||
#define _SYS_MMAN_H_ | ||
Comment on lines
+20
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use |
||
|
||
#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 <sys/types.h> | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
Comment on lines
+36
to
+38
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ExecuTorch is always C++, so no need for this or the matching one below |
||
|
||
#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 | ||
|
||
#endif /* _SYS_MMAN_H_ */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this will compile without a semicolon. And the formatting is off