This MR adds support for creating file mapping objects backed by large pages on Linux, by making the following changes:
## wineserver
* On Linux, `create_temp_file` will first attempt to use memfds as the backing fd. If it fails, it'll return to the current codepath, creating a temporary file in either the server or config directory. * The created memfd will be sealed against writes, if the caller requesting the appropriate page protection flags. * This removes the requirement that FDs be only created on filesystems/directories that aren't `noexec`. * In the server method `create_mapping` , if large pages have been requested by the caller, hold that the calling thread's token holds `SeLockMemoryPrivilege` . * Additionally, add `SeLockMemoryPrivilege` to the list of privileges enabled for the Administrator.
## `ntdll`
* Add `virtual_get_min_large_page_size` and its exported wrapper `wine_unix_get_min_large_page_size`. * On Linux, the minimum page size is determined by going through `/sys/kernel/mm/hugepages`. If hugepage support was not detected, `STATUS_NOT_SUPPORTED` is returned instead. On other platforms, the older hard-coded value of 2*1024*1024 is returned instead. * `NtCreateSection` will validate certain parameters if large pages are requested. Specifically, it will return STATUS_INVALID_PARAMETER if the requested mapping is not anonymous/unnamed, or the size is not a multiple of the minimum supported page size.
## `kernelbase`
* `GetLargePageMinimum` will use `wine_unix_get_min_large_page_size`.
## `kernel32/tests`
* Add new test test_large_page_file_mapping, which validates privilege enforcements and parameter validation while creating large pages backed file mapping obejcts. The tests are skipped if `GetLargePageMinimum` returns 0.
-- v5: create_user_data_mapping: Set the LargePageMinimum field. Remove declaration for wine_unix_get_min_large_page_size. Add checks for linux/memfd.h and memfd_create on Linux. :NtCreateSection: remove trailing whitespace. Remove virtual_get_large_page_min_size and its exported wine syscall
From: Vibhav Pant vibhavp@gmail.com
--- server/mapping.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 3 deletions(-)
diff --git a/server/mapping.c b/server/mapping.c index ff99b45ce51..2280360f6cd 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -21,6 +21,7 @@ #include "config.h"
#include <assert.h> +#include <errno.h> #include <fcntl.h> #include <stdarg.h> #include <stdio.h> @@ -317,13 +318,90 @@ static int check_current_dir_for_exec(void) return (ret != MAP_FAILED); }
+#if defined( __linux__ ) && defined( _GNU_SOURCE ) +static void make_memfd_name( const char *prefix, ULONG sec_flags, char *dest ) +{ + /* memfd names are restricted to 250 bytes including \0, but are only meant for debugging, with + * duplicate names not causing any side-effects. */ + + if (prefix != NULL) + { + snprintf( dest, 250, "map-%s-%lx-%lld", prefix, sec_flags, current_time); + } + else + { + snprintf( dest, 250, "map-%lx-%lld", sec_flags, current_time ); + } +} + +static int create_memfd( ULONG file_access, ULONG sec_flags, file_pos_t size ) +{ + int fd; + char memfd_name[256]; + unsigned int memfd_flags = MFD_ALLOW_SEALING; + unsigned int seal_flags = F_SEAL_SEAL | F_SEAL_WRITE; + + make_memfd_name( NULL, sec_flags, memfd_name ); + + if (sec_flags & SEC_LARGE_PAGES) + { + memfd_flags |= MFD_HUGETLB; + } + fd = memfd_create( memfd_name, memfd_flags ); + if (fd == -1) + { + if (errno == EINVAL && (sec_flags & SEC_LARGE_PAGES)) + { + /* MFD_HUGETLB & MFD_ALLOW_SEALING is only available in Linux >= 4.16. Lets try creating + * one without HUGETLB */ + fd = memfd_create( memfd_name, memfd_flags & ~MFD_HUGETLB ); + if (fd == -1) + { + file_set_error(); + return -1; + } + } + else + { + return -1; + } + } + if (ftruncate(fd, size) == -1) + { + file_set_error(); + close( fd ); + return -1; + } + if (file_access & FILE_WRITE_DATA) + { + seal_flags &= ~F_SEAL_WRITE; + } + + if (fcntl( fd, F_ADD_SEALS, F_SEAL_SEAL, seal_flags ) == -1) + { + file_set_error(); + close( fd ); + return -1; + } + return fd; +} +#endif /* defined( __linux__ ) && defined( _GNU_SOURCE ) */ + /* create a temp file for anonymous mappings */ -static int create_temp_file( file_pos_t size ) +static int create_temp_file( ULONG file_access, ULONG sec_flags, file_pos_t size ) { static int temp_dir_fd = -1; char tmpfn[16]; int fd;
+#if defined( __linux__ ) && defined( _GNU_SOURCE ) + fd = create_memfd( file_access, sec_flags, size ); + if (fd != -1) + { + return fd; + } +#endif + if (temp_dir_fd == -1) { temp_dir_fd = server_dir_fd; @@ -608,7 +686,7 @@ static int build_shared_mapping( struct mapping *mapping, int fd,
/* create a temp file for the mapping */
- if ((shared_fd = create_temp_file( total_size )) == -1) return 0; + if ((shared_fd = create_temp_file( FILE_WRITE_DATA, 0, total_size )) == -1) return 0; if (!(file = create_file_for_fd( shared_fd, FILE_GENERIC_READ|FILE_GENERIC_WRITE, 0 ))) return 0;
if (!(buffer = malloc( max_size ))) goto error; @@ -1044,7 +1122,7 @@ static struct mapping *create_mapping( struct object *root, const struct unicode } if ((flags & SEC_RESERVE) && !(mapping->committed = create_ranges())) goto error; mapping->size = (mapping->size + page_mask) & ~((mem_size_t)page_mask); - if ((unix_fd = create_temp_file( mapping->size )) == -1) goto error; + if ((unix_fd = create_temp_file( mapping->size, file_access, flags )) == -1) goto error; if (!(mapping->fd = create_anonymous_fd( &mapping_fd_ops, unix_fd, &mapping->obj, FILE_SYNCHRONOUS_IO_NONALERT ))) goto error; allow_fd_caching( mapping->fd );
From: Vibhav Pant vibhavp@gmail.com
--- server/security.h | 1 + server/token.c | 2 ++ 2 files changed, 3 insertions(+)
diff --git a/server/security.h b/server/security.h index 58ab1594eae..6cf14a44dfe 100644 --- a/server/security.h +++ b/server/security.h @@ -23,6 +23,7 @@
#include <sys/types.h>
+extern const struct luid SeLockMemoryPrivilege; extern const struct luid SeIncreaseQuotaPrivilege; extern const struct luid SeSecurityPrivilege; extern const struct luid SeTakeOwnershipPrivilege; diff --git a/server/token.c b/server/token.c index 4df8d2e0c6e..3260c516956 100644 --- a/server/token.c +++ b/server/token.c @@ -42,6 +42,7 @@
#define MAX_SUBAUTH_COUNT 1
+const struct luid SeLockMemoryPrivilege = { 4, 0}; const struct luid SeIncreaseQuotaPrivilege = { 5, 0 }; const struct luid SeTcbPrivilege = { 7, 0 }; const struct luid SeSecurityPrivilege = { 8, 0 }; @@ -756,6 +757,7 @@ struct token *token_create_admin( unsigned primary, int impersonation_level, int { SeManageVolumePrivilege, 0 }, { SeImpersonatePrivilege, SE_PRIVILEGE_ENABLED }, { SeCreateGlobalPrivilege, SE_PRIVILEGE_ENABLED }, + { SeLockMemoryPrivilege, SE_PRIVILEGE_ENABLED }, }; /* note: we don't include non-builtin groups here for the user - * telling us these is the job of a client-side program */
From: Vibhav Pant vibhavp@gmail.com
On Linux (for now), virtual_get_min_large_page_size will iterate through /sys/kernel/mm/hugepages and return the minimum huge page size supported by the system. The exported function wine_unix_get_min_large_page_size is a wrapper around this function. --- dlls/ntdll/ntdll.spec | 3 ++ dlls/ntdll/ntsyscalls.h | 6 ++- dlls/ntdll/unix/unix_private.h | 1 + dlls/ntdll/unix/virtual.c | 74 ++++++++++++++++++++++++++++++++++ include/winternl.h | 2 + 5 files changed, 84 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 3471905c762..07fc0150926 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -1741,3 +1741,6 @@ # Filesystem @ stdcall -syscall wine_nt_to_unix_file_name(ptr ptr ptr long) @ stdcall -syscall wine_unix_to_nt_file_name(str ptr ptr) + +# Memory management +@ stdcall -syscall wine_unix_get_min_large_page_size(ptr) diff --git a/dlls/ntdll/ntsyscalls.h b/dlls/ntdll/ntsyscalls.h index 55e1436848b..8f7619a4866 100644 --- a/dlls/ntdll/ntsyscalls.h +++ b/dlls/ntdll/ntsyscalls.h @@ -242,7 +242,8 @@ SYSCALL_ENTRY( 0x00ee, NtWriteVirtualMemory, 20 ) \ SYSCALL_ENTRY( 0x00ef, NtYieldExecution, 0 ) \ SYSCALL_ENTRY( 0x00f0, wine_nt_to_unix_file_name, 16 ) \ - SYSCALL_ENTRY( 0x00f1, wine_unix_to_nt_file_name, 12 ) + SYSCALL_ENTRY( 0x00f1, wine_unix_get_min_large_page_size, 4 ) \ + SYSCALL_ENTRY( 0x00f2, wine_unix_to_nt_file_name, 12 )
#define ALL_SYSCALLS64 \ SYSCALL_ENTRY( 0x0000, NtAcceptConnectPort, 48 ) \ @@ -481,4 +482,5 @@ SYSCALL_ENTRY( 0x00e9, NtWriteVirtualMemory, 40 ) \ SYSCALL_ENTRY( 0x00ea, NtYieldExecution, 0 ) \ SYSCALL_ENTRY( 0x00eb, wine_nt_to_unix_file_name, 32 ) \ - SYSCALL_ENTRY( 0x00ec, wine_unix_to_nt_file_name, 24 ) + SYSCALL_ENTRY( 0x00ec, wine_unix_get_min_large_page_size, 8 ) \ + SYSCALL_ENTRY( 0x00ed, wine_unix_to_nt_file_name, 24 ) diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index b278ab8df84..80b366f8b74 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -256,6 +256,7 @@ extern void *anon_mmap_alloc( size_t size, int prot ); extern void virtual_init(void); extern ULONG_PTR get_system_affinity_mask(void); extern void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info, BOOL wow64 ); +extern NTSTATUS virtual_get_min_large_page_size( SIZE_T *size ); extern NTSTATUS virtual_map_builtin_module( HANDLE mapping, void **module, SIZE_T *size, SECTION_IMAGE_INFORMATION *info, ULONG_PTR limit_low, ULONG_PTR limit_high, WORD machine, BOOL prefer_native ); diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 4b23d9954df..d5c968866b8 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -63,6 +63,10 @@ # include <mach/mach_init.h> # include <mach/mach_vm.h> #endif +#ifdef __linux__ +#include <sys/types.h> +#include <dirent.h> +#endif
#include "ntstatus.h" #define WIN32_NO_STATUS @@ -3394,6 +3398,76 @@ void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info, BOOL wow64 ) else info->HighestUserAddress = (char *)user_space_limit - 1; }
+NTSTATUS WINAPI wine_unix_get_min_large_page_size( SIZE_T *size ) +{ + return virtual_get_min_large_page_size( size ); +} + +NTSTATUS virtual_get_min_large_page_size( SIZE_T *size ) +{ +#ifdef __linux__ + DIR *sysfs_hugepages; + struct dirent *supported_size; + SIZE_T min_size; + SIZE_T total_supported_sizes = 0; +#endif + + if (size == NULL) + { + return STATUS_INVALID_PARAMETER; + } + +#ifdef __linux__ + errno = 0; + sysfs_hugepages = opendir( "/sys/kernel/mm/hugepages" ); + if (sysfs_hugepages == NULL) + { + switch (errno) + { + case ENOENT: /* No huge pages support */ + return STATUS_NOT_SUPPORTED; + case ENOMEM: + return STATUS_NO_MEMORY; + default: + return STATUS_INTERNAL_ERROR; + } + } + supported_size = readdir( sysfs_hugepages ); + while (supported_size != NULL) + { + SIZE_T page_size; + + /* Entries are of the form "hugepages-${size}kB" */ + if (strncmp( supported_size->d_name, "hugepages-", 10 ) != 0) + { + supported_size = readdir( sysfs_hugepages ); + continue; + } + page_size = strtol( &supported_size->d_name[10], NULL, 10 ); + if (page_size == 0 || page_size == LONG_MAX || page_size == LONG_MIN) + { + ERR( "could not parse page size from /sys/kernel/mm/hugepages entry %s\n", + supported_size->d_name ); + supported_size = readdir( sysfs_hugepages ); + continue; + } + page_size *= 1024; + min_size = ( total_supported_sizes == 0 ) ? page_size + : ( page_size < min_size ? page_size : min_size ); + total_supported_sizes++; + supported_size = readdir( sysfs_hugepages ); + } + + closedir(sysfs_hugepages); + if (total_supported_sizes == 0) + return STATUS_NOT_SUPPORTED; + *size = min_size; +#else /* __linux__ */ + *size = 2 * 1024 * 1024; +#endif /* !defined(__linux) */ + return STATUS_SUCCESS; +} +
/*********************************************************************** * virtual_map_builtin_module diff --git a/include/winternl.h b/include/winternl.h index 22cdceeaedb..72bdb2b1673 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -5148,6 +5148,8 @@ NTSYSAPI NTSTATUS WINAPI wine_nt_to_unix_file_name( const OBJECT_ATTRIBUTES *att UINT disposition ); NTSYSAPI NTSTATUS WINAPI wine_unix_to_nt_file_name( const char *name, WCHAR *buffer, ULONG *size );
+NTSYSAPI NTSTATUS WINAPI wine_unix_get_min_large_page_size( SIZE_T *size ); +
/*********************************************************************** * Inline functions
From: Vibhav Pant vibhavp@gmail.com
Instead of returning a hardcoded value, use the newly added function wine_unix_get_min_large_page_size to get the minimum supported large page size, returning 0 if large pages are not supported on the host platform. --- dlls/kernelbase/memory.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c index 4f4bba9a13b..b4efa765c15 100644 --- a/dlls/kernelbase/memory.c +++ b/dlls/kernelbase/memory.c @@ -77,7 +77,11 @@ BOOL WINAPI DECLSPEC_HOTPATCH FlushViewOfFile( const void *base, SIZE_T size ) */ SIZE_T WINAPI GetLargePageMinimum(void) { - return 2 * 1024 * 1024; + NTSTATUS status; + SIZE_T min_size; + + status = wine_unix_get_min_large_page_size( &min_size ); + return status == STATUS_SUCCESS ? min_size : 0; }
From: Vibhav Pant vibhavp@gmail.com
In create_mapping, if the caller requires that the file be backed up by large pages, ensure that they hold the SeLockMemoryPrivilege. --- server/mapping.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/server/mapping.c b/server/mapping.c index 2280360f6cd..6b239e11807 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -1362,6 +1362,12 @@ DECL_HANDLER(create_mapping)
if (!objattr) return;
+ if ((req->flags & SEC_LARGE_PAGES) && !thread_single_check_privilege( current, SeLockMemoryPrivilege )) + { + set_error( STATUS_PRIVILEGE_NOT_HELD ); + return; + } + if ((mapping = create_mapping( root, &name, objattr->attributes, req->size, req->flags, req->file_handle, req->file_access, sd ))) {
From: Vibhav Pant vibhavp@gmail.com
If the file mapping flags have SEC_LARGE_PAGES enabled, ensure that the mapping is anonymous and the requested size is a multiple of the minimum large page size supported by the host platform. --- dlls/ntdll/unix/sync.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index e070233104b..3727ff28acb 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -2017,6 +2017,26 @@ NTSTATUS WINAPI NtCreateSection( HANDLE *handle, ACCESS_MASK access, const OBJEC
*handle = 0;
+ if (sec_flags & SEC_LARGE_PAGES) + { + SIZE_T min_size; + NTSTATUS status; + + if (file != NULL || size == NULL) + { + return STATUS_INVALID_PARAMETER; + } + + status = virtual_get_min_large_page_size( &min_size ); + if (status != STATUS_SUCCESS) + { + return status == STATUS_NOT_SUPPORTED ? STATUS_INVALID_PARAMETER : status; + } + if (size->QuadPart % min_size != 0) + { + return STATUS_INVALID_PARAMETER; + } + } switch (protect & 0xff) { case PAGE_READONLY:
From: Vibhav Pant vibhavp@gmail.com
The test will only run if the platform has a non-zero minimum large page size, and will check whether the correct privilege checks are enforced if large page backed mappings are requested, and whether only mapping sizes that are multiples of the minimum large page size are accepted. --- dlls/kernel32/tests/process.c | 64 +++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c index 8e168622c17..c0916bc60f0 100644 --- a/dlls/kernel32/tests/process.c +++ b/dlls/kernel32/tests/process.c @@ -82,6 +82,7 @@ static BOOL (WINAPI *pGetNumaProcessorNode)(UCHAR, PUCHAR); static NTSTATUS (WINAPI *pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG); static NTSTATUS (WINAPI *pNtQueryInformationThread)(HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG); static NTSTATUS (WINAPI *pNtQuerySystemInformationEx)(SYSTEM_INFORMATION_CLASS, void*, ULONG, void*, ULONG, ULONG*); +static NTSTATUS (WINAPI *pRtlAdjustPrivilege)(ULONG,BOOLEAN,BOOLEAN,PBOOLEAN); static DWORD (WINAPI *pWTSGetActiveConsoleSessionId)(void); static HANDLE (WINAPI *pCreateToolhelp32Snapshot)(DWORD, DWORD); static BOOL (WINAPI *pProcess32First)(HANDLE, PROCESSENTRY32*); @@ -252,6 +253,7 @@ static BOOL init(void) pNtQueryInformationProcess = (void *)GetProcAddress(hntdll, "NtQueryInformationProcess"); pNtQueryInformationThread = (void *)GetProcAddress(hntdll, "NtQueryInformationThread"); pNtQuerySystemInformationEx = (void *)GetProcAddress(hntdll, "NtQuerySystemInformationEx"); + pRtlAdjustPrivilege = (void *)GetProcAddress(hntdll, "RtlAdjustPrivilege");
pGetNativeSystemInfo = (void *) GetProcAddress(hkernel32, "GetNativeSystemInfo"); pGetSystemRegistryQuota = (void *) GetProcAddress(hkernel32, "GetSystemRegistryQuota"); @@ -4347,6 +4349,67 @@ static void test_largepages(void) ok((size == 0) || (size == 2*1024*1024) || (size == 4*1024*1024), "GetLargePageMinimum reports %Id size\n", size); }
+static void test_large_page_file_mapping( void ) +{ + SIZE_T size; + BOOLEAN enabled; + NTSTATUS status; + DWORD err; + HANDLE file; + HANDLE token; + HANDLE process_token; + + if (!pGetLargePageMinimum) + { + win_skip( "No GetLargePageMinimum support.\n" ); + return; + } + if (!pRtlAdjustPrivilege) + { + win_skip( "No RtlAdjustPrivilege support.\n" ); + return; + } + + size = pGetLargePageMinimum(); + if (size == 0) + { + trace( "No large pages support, skipping test.\n" ); + return; + } + ok( OpenProcessToken( GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_QUERY, &process_token ), + "OpenProcessToken failed (%ld)\n", GetLastError() ); + ok( DuplicateToken( process_token, SecurityImpersonation, &token ), + "DuplicateToken failed (%ld)\n", GetLastError() ); + ok( ImpersonateLoggedOnUser( token ), "ImpersonateLoggedOnUser failed (%ld)\n", + GetLastError() ); + status = pRtlAdjustPrivilege( SE_LOCK_MEMORY_PRIVILEGE, TRUE, TRUE, &enabled ); + if (status != STATUS_SUCCESS) + { + trace( "Couldn't get SE_LOCK_MEMORY_PRIVILEGE (%ld), skipping large page file " + "mapping test.\n", + status ); + } + else + { + file = + CreateFileMappingW( INVALID_HANDLE_VALUE, NULL, + PAGE_READWRITE | SEC_LARGE_PAGES | SEC_COMMIT, 0, size - 1, NULL ); + err = GetLastError(); + ok( file == NULL && err == ERROR_INVALID_PARAMETER, + "CreateFileMappingW should fail with ERROR_INVALID_PARAMETER (got %ld instead)\n", + err ); + if (file != NULL) CloseHandle( file ); + + file = + CreateFileMappingW( INVALID_HANDLE_VALUE, NULL, + PAGE_READWRITE | SEC_LARGE_PAGES | SEC_COMMIT, 0, size * 2, NULL ); + ok( file != NULL, "CreateFileMappingW failed (%ld)\n", GetLastError() ); + if ( file != NULL ) CloseHandle( file ); + } + + ok( RevertToSelf(), "RevertToSelf failed (%ld)\n", GetLastError() ); +} + struct proc_thread_attr { DWORD_PTR attr; @@ -5668,6 +5731,7 @@ START_TEST(process) test_GetLogicalProcessorInformationEx(); test_GetSystemCpuSetInformation(); test_largepages(); + test_large_page_file_mapping(); test_ProcThreadAttributeList(); test_SuspendProcessState(); test_SuspendProcessNewThread();
From: Vibhav Pant vibhavp@gmail.com
--- server/mapping.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/server/mapping.c b/server/mapping.c index 6b239e11807..a2958629c4d 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -30,6 +30,9 @@ #include <sys/stat.h> #include <sys/mman.h> #include <unistd.h> +#ifdef __linux__ +#include <linux/memfd.h> +#endif
#include "ntstatus.h" #define WIN32_NO_STATUS @@ -341,6 +344,10 @@ static int create_memfd( ULONG file_access, ULONG sec_flags, file_pos_t size ) unsigned int memfd_flags = MFD_ALLOW_SEALING; unsigned int seal_flags = F_SEAL_SEAL | F_SEAL_WRITE;
+#ifdef MFD_EXEC + memfd_flags |= MFD_EXEC; +#endif + make_memfd_name( NULL, sec_flags, memfd_name );
if (sec_flags & SEC_LARGE_PAGES) @@ -357,7 +364,6 @@ static int create_memfd( ULONG file_access, ULONG sec_flags, file_pos_t size ) fd = memfd_create( memfd_name, memfd_flags & ~MFD_HUGETLB ); if (fd == -1) { - file_set_error(); return -1; } }
From: Vibhav Pant vibhavp@gmail.com
--- dlls/ntdll/unix/virtual.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index d5c968866b8..0d8f905e578 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -3408,7 +3408,7 @@ NTSTATUS virtual_get_min_large_page_size( SIZE_T *size ) #ifdef __linux__ DIR *sysfs_hugepages; struct dirent *supported_size; - SIZE_T min_size; + SIZE_T min_size = 0; SIZE_T total_supported_sizes = 0; #endif
From: Vibhav Pant vibhavp@gmail.com
Instead, use the LargePageMinimum field in user_shared_data to get the minimum large page size. --- dlls/kernelbase/memory.c | 7 +--- dlls/ntdll/ntdll.spec | 3 -- dlls/ntdll/ntsyscalls.h | 6 +-- dlls/ntdll/unix/sync.c | 12 ++---- dlls/ntdll/unix/unix_private.h | 1 - dlls/ntdll/unix/virtual.c | 71 ---------------------------------- 6 files changed, 7 insertions(+), 93 deletions(-)
diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c index b4efa765c15..316aec7d40a 100644 --- a/dlls/kernelbase/memory.c +++ b/dlls/kernelbase/memory.c @@ -41,6 +41,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(heap); WINE_DECLARE_DEBUG_CHANNEL(virtual); WINE_DECLARE_DEBUG_CHANNEL(globalmem);
+static const struct _KUSER_SHARED_DATA *user_shared_data = (struct _KUSER_SHARED_DATA *)0x7ffe0000;
/*********************************************************************** * Virtual memory functions @@ -77,11 +78,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH FlushViewOfFile( const void *base, SIZE_T size ) */ SIZE_T WINAPI GetLargePageMinimum(void) { - NTSTATUS status; - SIZE_T min_size; - - status = wine_unix_get_min_large_page_size( &min_size ); - return status == STATUS_SUCCESS ? min_size : 0; + return user_shared_data->LargePageMinimum; }
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 07fc0150926..3471905c762 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -1741,6 +1741,3 @@ # Filesystem @ stdcall -syscall wine_nt_to_unix_file_name(ptr ptr ptr long) @ stdcall -syscall wine_unix_to_nt_file_name(str ptr ptr) - -# Memory management -@ stdcall -syscall wine_unix_get_min_large_page_size(ptr) diff --git a/dlls/ntdll/ntsyscalls.h b/dlls/ntdll/ntsyscalls.h index 8f7619a4866..55e1436848b 100644 --- a/dlls/ntdll/ntsyscalls.h +++ b/dlls/ntdll/ntsyscalls.h @@ -242,8 +242,7 @@ SYSCALL_ENTRY( 0x00ee, NtWriteVirtualMemory, 20 ) \ SYSCALL_ENTRY( 0x00ef, NtYieldExecution, 0 ) \ SYSCALL_ENTRY( 0x00f0, wine_nt_to_unix_file_name, 16 ) \ - SYSCALL_ENTRY( 0x00f1, wine_unix_get_min_large_page_size, 4 ) \ - SYSCALL_ENTRY( 0x00f2, wine_unix_to_nt_file_name, 12 ) + SYSCALL_ENTRY( 0x00f1, wine_unix_to_nt_file_name, 12 )
#define ALL_SYSCALLS64 \ SYSCALL_ENTRY( 0x0000, NtAcceptConnectPort, 48 ) \ @@ -482,5 +481,4 @@ SYSCALL_ENTRY( 0x00e9, NtWriteVirtualMemory, 40 ) \ SYSCALL_ENTRY( 0x00ea, NtYieldExecution, 0 ) \ SYSCALL_ENTRY( 0x00eb, wine_nt_to_unix_file_name, 32 ) \ - SYSCALL_ENTRY( 0x00ec, wine_unix_get_min_large_page_size, 8 ) \ - SYSCALL_ENTRY( 0x00ed, wine_unix_to_nt_file_name, 24 ) + SYSCALL_ENTRY( 0x00ec, wine_unix_to_nt_file_name, 24 ) diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index 3727ff28acb..055aa4ce85d 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -2019,20 +2019,14 @@ NTSTATUS WINAPI NtCreateSection( HANDLE *handle, ACCESS_MASK access, const OBJEC
if (sec_flags & SEC_LARGE_PAGES) { - SIZE_T min_size; - NTSTATUS status; - + SIZE_T min_size = user_shared_data->LargePageMinimum; + if (file != NULL || size == NULL) { return STATUS_INVALID_PARAMETER; }
- status = virtual_get_min_large_page_size( &min_size ); - if (status != STATUS_SUCCESS) - { - return status == STATUS_NOT_SUPPORTED ? STATUS_INVALID_PARAMETER : status; - } - if (size->QuadPart % min_size != 0) + if (min_size == 0 || size->QuadPart % min_size != 0) { return STATUS_INVALID_PARAMETER; } diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 80b366f8b74..b278ab8df84 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -256,7 +256,6 @@ extern void *anon_mmap_alloc( size_t size, int prot ); extern void virtual_init(void); extern ULONG_PTR get_system_affinity_mask(void); extern void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info, BOOL wow64 ); -extern NTSTATUS virtual_get_min_large_page_size( SIZE_T *size ); extern NTSTATUS virtual_map_builtin_module( HANDLE mapping, void **module, SIZE_T *size, SECTION_IMAGE_INFORMATION *info, ULONG_PTR limit_low, ULONG_PTR limit_high, WORD machine, BOOL prefer_native ); diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 0d8f905e578..0b4eef422c9 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -3398,77 +3398,6 @@ void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info, BOOL wow64 ) else info->HighestUserAddress = (char *)user_space_limit - 1; }
-NTSTATUS WINAPI wine_unix_get_min_large_page_size( SIZE_T *size ) -{ - return virtual_get_min_large_page_size( size ); -} - -NTSTATUS virtual_get_min_large_page_size( SIZE_T *size ) -{ -#ifdef __linux__ - DIR *sysfs_hugepages; - struct dirent *supported_size; - SIZE_T min_size = 0; - SIZE_T total_supported_sizes = 0; -#endif - - if (size == NULL) - { - return STATUS_INVALID_PARAMETER; - } - -#ifdef __linux__ - errno = 0; - sysfs_hugepages = opendir( "/sys/kernel/mm/hugepages" ); - if (sysfs_hugepages == NULL) - { - switch (errno) - { - case ENOENT: /* No huge pages support */ - return STATUS_NOT_SUPPORTED; - case ENOMEM: - return STATUS_NO_MEMORY; - default: - return STATUS_INTERNAL_ERROR; - } - } - supported_size = readdir( sysfs_hugepages ); - while (supported_size != NULL) - { - SIZE_T page_size; - - /* Entries are of the form "hugepages-${size}kB" */ - if (strncmp( supported_size->d_name, "hugepages-", 10 ) != 0) - { - supported_size = readdir( sysfs_hugepages ); - continue; - } - page_size = strtol( &supported_size->d_name[10], NULL, 10 ); - if (page_size == 0 || page_size == LONG_MAX || page_size == LONG_MIN) - { - ERR( "could not parse page size from /sys/kernel/mm/hugepages entry %s\n", - supported_size->d_name ); - supported_size = readdir( sysfs_hugepages ); - continue; - } - page_size *= 1024; - min_size = ( total_supported_sizes == 0 ) ? page_size - : ( page_size < min_size ? page_size : min_size ); - total_supported_sizes++; - supported_size = readdir( sysfs_hugepages ); - } - - closedir(sysfs_hugepages); - if (total_supported_sizes == 0) - return STATUS_NOT_SUPPORTED; - *size = min_size; -#else /* __linux__ */ - *size = 2 * 1024 * 1024; -#endif /* !defined(__linux) */ - return STATUS_SUCCESS; -} - - /*********************************************************************** * virtual_map_builtin_module */
From: Vibhav Pant vibhavp@gmail.com
--- dlls/ntdll/unix/sync.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index 055aa4ce85d..8e68db5cec2 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -2019,8 +2019,7 @@ NTSTATUS WINAPI NtCreateSection( HANDLE *handle, ACCESS_MASK access, const OBJEC
if (sec_flags & SEC_LARGE_PAGES) { - SIZE_T min_size = user_shared_data->LargePageMinimum; - + SIZE_T min_size = user_shared_data->LargePageMinimum; if (file != NULL || size == NULL) { return STATUS_INVALID_PARAMETER;
From: Vibhav Pant vibhavp@gmail.com
--- configure.ac | 2 + include/config.h.in | 153 +++++++++++++++++++++++--------------------- 2 files changed, 83 insertions(+), 72 deletions(-)
diff --git a/configure.ac b/configure.ac index 3f54230b46b..9cc7df4e10a 100644 --- a/configure.ac +++ b/configure.ac @@ -384,6 +384,7 @@ AC_CHECK_HEADERS(\ linux/input.h \ linux/ioctl.h \ linux/major.h \ + linux/memfd.h \ linux/param.h \ linux/serial.h \ linux/types.h \ @@ -2079,6 +2080,7 @@ AC_CHECK_FUNCS(\ getrandom \ kqueue \ mach_continuous_time \ + memfd_create \ pipe2 \ port_create \ posix_fadvise \ diff --git a/include/config.h.in b/include/config.h.in index ef783c75a42..6135c9c1001 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -36,10 +36,10 @@ /* Define to 1 if you have the <cups/ppd.h> header file. */ #undef HAVE_CUPS_PPD_H
-/* Define to 1 if you have the `dladdr1' function. */ +/* Define to 1 if you have the 'dladdr1' function. */ #undef HAVE_DLADDR1
-/* Define to 1 if you have the `dlinfo' function. */ +/* Define to 1 if you have the 'dlinfo' function. */ #undef HAVE_DLINFO
/* Define to 1 if you have the <EGL/egl.h> header file. */ @@ -48,7 +48,7 @@ /* Define to 1 if you have the <elf.h> header file. */ #undef HAVE_ELF_H
-/* Define to 1 if you have the `epoll_create' function. */ +/* Define to 1 if you have the 'epoll_create' function. */ #undef HAVE_EPOLL_CREATE
/* Define to 1 if you have the <float.h> header file. */ @@ -57,43 +57,43 @@ /* Define if FreeType 2 is installed */ #undef HAVE_FREETYPE
-/* Define to 1 if you have the `fstatfs' function. */ +/* Define to 1 if you have the 'fstatfs' function. */ #undef HAVE_FSTATFS
/* Define to 1 if you have the <ft2build.h> header file. */ #undef HAVE_FT2BUILD_H
-/* Define to 1 if the system has the type `FT_TrueTypeEngineType'. */ +/* Define to 1 if the system has the type 'FT_TrueTypeEngineType'. */ #undef HAVE_FT_TRUETYPEENGINETYPE
-/* Define to 1 if you have the `futimens' function. */ +/* Define to 1 if you have the 'futimens' function. */ #undef HAVE_FUTIMENS
-/* Define to 1 if you have the `futimes' function. */ +/* Define to 1 if you have the 'futimes' function. */ #undef HAVE_FUTIMES
-/* Define to 1 if you have the `futimesat' function. */ +/* Define to 1 if you have the 'futimesat' function. */ #undef HAVE_FUTIMESAT
-/* Define to 1 if you have the `getaddrinfo' function. */ +/* Define to 1 if you have the 'getaddrinfo' function. */ #undef HAVE_GETADDRINFO
-/* Define to 1 if you have the `getattrlist' function. */ +/* Define to 1 if you have the 'getattrlist' function. */ #undef HAVE_GETATTRLIST
-/* Define to 1 if you have the `getauxval' function. */ +/* Define to 1 if you have the 'getauxval' function. */ #undef HAVE_GETAUXVAL
-/* Define to 1 if you have the `getifaddrs' function. */ +/* Define to 1 if you have the 'getifaddrs' function. */ #undef HAVE_GETIFADDRS
-/* Define to 1 if you have the `getrandom' function. */ +/* Define to 1 if you have the 'getrandom' function. */ #undef HAVE_GETRANDOM
/* Define to 1 if you have the <gettext-po.h> header file. */ #undef HAVE_GETTEXT_PO_H
-/* Define to 1 if you have the `gnutls_cipher_init' function. */ +/* Define to 1 if you have the 'gnutls_cipher_init' function. */ #undef HAVE_GNUTLS_CIPHER_INIT
/* Define if we have the libgphoto2_port development environment */ @@ -111,7 +111,7 @@ /* Define to 1 if you have the <inttypes.h> header file. */ #undef HAVE_INTTYPES_H
-/* Define to 1 if you have the `kqueue' function. */ +/* Define to 1 if you have the 'kqueue' function. */ #undef HAVE_KQUEUE
/* Define to 1 if you have the <krb5/krb5.h> header file. */ @@ -180,6 +180,9 @@ /* Define to 1 if you have the <linux/major.h> header file. */ #undef HAVE_LINUX_MAJOR_H
+/* Define to 1 if you have the <linux/memfd.h> header file. */ +#undef HAVE_LINUX_MEMFD_H + /* Define to 1 if you have the <linux/param.h> header file. */ #undef HAVE_LINUX_PARAM_H
@@ -210,7 +213,7 @@ /* Define to 1 if you have the <machine/sysarch.h> header file. */ #undef HAVE_MACHINE_SYSARCH_H
-/* Define to 1 if you have the `mach_continuous_time' function. */ +/* Define to 1 if you have the 'mach_continuous_time' function. */ #undef HAVE_MACH_CONTINUOUS_TIME
/* Define to 1 if you have the <mach/mach.h> header file. */ @@ -219,6 +222,9 @@ /* Define to 1 if you have the <mach-o/loader.h> header file. */ #undef HAVE_MACH_O_LOADER_H
+/* Define to 1 if you have the 'memfd_create' function. */ +#undef HAVE_MEMFD_CREATE + /* Define to 1 if you have the <mntent.h> header file. */ #undef HAVE_MNTENT_H
@@ -294,34 +300,34 @@ /* Define to 1 if you have the <OpenCL/opencl.h> header file. */ #undef HAVE_OPENCL_OPENCL_H
-/* Define to 1 if `numaudioengines' is a member of `oss_sysinfo'. */ +/* Define to 1 if 'numaudioengines' is a member of 'oss_sysinfo'. */ #undef HAVE_OSS_SYSINFO_NUMAUDIOENGINES
/* Define to 1 if you have the <pcap/pcap.h> header file. */ #undef HAVE_PCAP_PCAP_H
-/* Define to 1 if you have the `pipe2' function. */ +/* Define to 1 if you have the 'pipe2' function. */ #undef HAVE_PIPE2
-/* Define to 1 if you have the `port_create' function. */ +/* Define to 1 if you have the 'port_create' function. */ #undef HAVE_PORT_CREATE
/* Define to 1 if you have the <port.h> header file. */ #undef HAVE_PORT_H
-/* Define to 1 if you have the `posix_fadvise' function. */ +/* Define to 1 if you have the 'posix_fadvise' function. */ #undef HAVE_POSIX_FADVISE
-/* Define to 1 if you have the `posix_fallocate' function. */ +/* Define to 1 if you have the 'posix_fallocate' function. */ #undef HAVE_POSIX_FALLOCATE
-/* Define to 1 if you have the `prctl' function. */ +/* Define to 1 if you have the 'prctl' function. */ #undef HAVE_PRCTL
-/* Define to 1 if you have the `proc_pidinfo' function. */ +/* Define to 1 if you have the 'proc_pidinfo' function. */ #undef HAVE_PROC_PIDINFO
-/* Define to 1 if you have the `pthread_getthreadid_np' function. */ +/* Define to 1 if you have the 'pthread_getthreadid_np' function. */ #undef HAVE_PTHREAD_GETTHREADID_NP
/* Define to 1 if you have the <pthread_np.h> header file. */ @@ -330,7 +336,7 @@ /* Define to 1 if you have the <pwd.h> header file. */ #undef HAVE_PWD_H
-/* Define to 1 if the system has the type `request_sense'. */ +/* Define to 1 if the system has the type 'request_sense'. */ #undef HAVE_REQUEST_SENSE
/* Define if you have the resolver library and header */ @@ -348,10 +354,10 @@ /* Define to 1 if you have the `sched_setaffinity' function. */ #undef HAVE_SCHED_SETAFFINITY
-/* Define to 1 if you have the `sched_yield' function. */ +/* Define to 1 if you have the 'sched_yield' function. */ #undef HAVE_SCHED_YIELD
-/* Define to 1 if `cmd' is a member of `scsireq_t'. */ +/* Define to 1 if 'cmd' is a member of 'scsireq_t'. */ #undef HAVE_SCSIREQ_T_CMD
/* Define to 1 if you have the <scsi/scsi.h> header file. */ @@ -366,19 +372,19 @@ /* Define to 1 if you have the <SDL.h> header file. */ #undef HAVE_SDL_H
-/* Define to 1 if you have the `setproctitle' function. */ +/* Define to 1 if you have the 'setproctitle' function. */ #undef HAVE_SETPROCTITLE
-/* Define to 1 if you have the `setprogname' function. */ +/* Define to 1 if you have the 'setprogname' function. */ #undef HAVE_SETPROGNAME
-/* Define to 1 if `interface_id' is a member of `sg_io_hdr_t'. */ +/* Define to 1 if 'interface_id' is a member of 'sg_io_hdr_t'. */ #undef HAVE_SG_IO_HDR_T_INTERFACE_ID
-/* Define to 1 if `si_fd' is a member of `siginfo_t'. */ +/* Define to 1 if 'si_fd' is a member of 'siginfo_t'. */ #undef HAVE_SIGINFO_T_SI_FD
-/* Define to 1 if you have the `sigprocmask' function. */ +/* Define to 1 if you have the 'sigprocmask' function. */ #undef HAVE_SIGPROCMASK
/* Define to 1 if you have the <stdint.h> header file. */ @@ -396,100 +402,100 @@ /* Define to 1 if you have the <string.h> header file. */ #undef HAVE_STRING_H
-/* Define to 1 if `icp6s_error' is a member of `struct icmp6stat'. */ +/* Define to 1 if 'icp6s_error' is a member of 'struct icmp6stat'. */ #undef HAVE_STRUCT_ICMP6STAT_ICP6S_ERROR
-/* Define to 1 if `icps_error' is a member of `struct icmpstat'. */ +/* Define to 1 if 'icps_error' is a member of 'struct icmpstat'. */ #undef HAVE_STRUCT_ICMPSTAT_ICPS_ERROR
-/* Define to 1 if `ifr_hwaddr' is a member of `struct ifreq'. */ +/* Define to 1 if 'ifr_hwaddr' is a member of 'struct ifreq'. */ #undef HAVE_STRUCT_IFREQ_IFR_HWADDR
-/* Define to 1 if `ipi6_addr' is a member of `struct in6_pktinfo'. */ +/* Define to 1 if 'ipi6_addr' is a member of 'struct in6_pktinfo'. */ #undef HAVE_STRUCT_IN6_PKTINFO_IPI6_ADDR
-/* Define to 1 if `ip6s_total' is a member of `struct ip6stat'. */ +/* Define to 1 if 'ip6s_total' is a member of 'struct ip6stat'. */ #undef HAVE_STRUCT_IP6STAT_IP6S_TOTAL
-/* Define to 1 if `ips_total' is a member of `struct ipstat'. */ +/* Define to 1 if 'ips_total' is a member of 'struct ipstat'. */ #undef HAVE_STRUCT_IPSTAT_IPS_TOTAL
-/* Define to 1 if `ips_total' is a member of `struct ip_stats'. */ +/* Define to 1 if 'ips_total' is a member of 'struct ip_stats'. */ #undef HAVE_STRUCT_IP_STATS_IPS_TOTAL
-/* Define to 1 if `mt_blkno' is a member of `struct mtget'. */ +/* Define to 1 if 'mt_blkno' is a member of 'struct mtget'. */ #undef HAVE_STRUCT_MTGET_MT_BLKNO
-/* Define to 1 if `mt_blksiz' is a member of `struct mtget'. */ +/* Define to 1 if 'mt_blksiz' is a member of 'struct mtget'. */ #undef HAVE_STRUCT_MTGET_MT_BLKSIZ
-/* Define to 1 if `mt_gstat' is a member of `struct mtget'. */ +/* Define to 1 if 'mt_gstat' is a member of 'struct mtget'. */ #undef HAVE_STRUCT_MTGET_MT_GSTAT
-/* Define to 1 if `sin6_scope_id' is a member of `struct sockaddr_in6'. */ +/* Define to 1 if 'sin6_scope_id' is a member of 'struct sockaddr_in6'. */ #undef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
-/* Define to 1 if `sun_len' is a member of `struct sockaddr_un'. */ +/* Define to 1 if 'sun_len' is a member of 'struct sockaddr_un'. */ #undef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
-/* Define to 1 if `st_atim' is a member of `struct stat'. */ +/* Define to 1 if 'st_atim' is a member of 'struct stat'. */ #undef HAVE_STRUCT_STAT_ST_ATIM
-/* Define to 1 if `st_atimespec' is a member of `struct stat'. */ +/* Define to 1 if 'st_atimespec' is a member of 'struct stat'. */ #undef HAVE_STRUCT_STAT_ST_ATIMESPEC
-/* Define to 1 if `st_birthtim' is a member of `struct stat'. */ +/* Define to 1 if 'st_birthtim' is a member of 'struct stat'. */ #undef HAVE_STRUCT_STAT_ST_BIRTHTIM
-/* Define to 1 if `st_birthtime' is a member of `struct stat'. */ +/* Define to 1 if 'st_birthtime' is a member of 'struct stat'. */ #undef HAVE_STRUCT_STAT_ST_BIRTHTIME
-/* Define to 1 if `st_birthtimespec' is a member of `struct stat'. */ +/* Define to 1 if 'st_birthtimespec' is a member of 'struct stat'. */ #undef HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC
-/* Define to 1 if `st_ctim' is a member of `struct stat'. */ +/* Define to 1 if 'st_ctim' is a member of 'struct stat'. */ #undef HAVE_STRUCT_STAT_ST_CTIM
-/* Define to 1 if `st_ctimespec' is a member of `struct stat'. */ +/* Define to 1 if 'st_ctimespec' is a member of 'struct stat'. */ #undef HAVE_STRUCT_STAT_ST_CTIMESPEC
-/* Define to 1 if `st_mtim' is a member of `struct stat'. */ +/* Define to 1 if 'st_mtim' is a member of 'struct stat'. */ #undef HAVE_STRUCT_STAT_ST_MTIM
-/* Define to 1 if `st_mtimespec' is a member of `struct stat'. */ +/* Define to 1 if 'st_mtimespec' is a member of 'struct stat'. */ #undef HAVE_STRUCT_STAT_ST_MTIMESPEC
-/* Define to 1 if `__st_birthtim' is a member of `struct stat'. */ +/* Define to 1 if '__st_birthtim' is a member of 'struct stat'. */ #undef HAVE_STRUCT_STAT___ST_BIRTHTIM
-/* Define to 1 if `__st_birthtime' is a member of `struct stat'. */ +/* Define to 1 if '__st_birthtime' is a member of 'struct stat'. */ #undef HAVE_STRUCT_STAT___ST_BIRTHTIME
-/* Define to 1 if `mem_unit' is a member of `struct sysinfo'. */ +/* Define to 1 if 'mem_unit' is a member of 'struct sysinfo'. */ #undef HAVE_STRUCT_SYSINFO_MEM_UNIT
-/* Define to 1 if `totalram' is a member of `struct sysinfo'. */ +/* Define to 1 if 'totalram' is a member of 'struct sysinfo'. */ #undef HAVE_STRUCT_SYSINFO_TOTALRAM
-/* Define to 1 if `tcps_connattempt' is a member of `struct tcpstat'. */ +/* Define to 1 if 'tcps_connattempt' is a member of 'struct tcpstat'. */ #undef HAVE_STRUCT_TCPSTAT_TCPS_CONNATTEMPT
-/* Define to 1 if `tcps_connattempt' is a member of `struct tcp_stats'. */ +/* Define to 1 if 'tcps_connattempt' is a member of 'struct tcp_stats'. */ #undef HAVE_STRUCT_TCP_STATS_TCPS_CONNATTEMPT
-/* Define to 1 if `udps_ipackets' is a member of `struct udpstat'. */ +/* Define to 1 if 'udps_ipackets' is a member of 'struct udpstat'. */ #undef HAVE_STRUCT_UDPSTAT_UDPS_IPACKETS
-/* Define to 1 if the system has the type `struct xinpgen'. */ +/* Define to 1 if the system has the type 'struct xinpgen'. */ #undef HAVE_STRUCT_XINPGEN
-/* Define to 1 if `_u._ext.nscount6' is a member of `struct __res_state'. */ +/* Define to 1 if '_u._ext.nscount6' is a member of 'struct __res_state'. */ #undef HAVE_STRUCT___RES_STATE__U__EXT_NSCOUNT6
/* Define to 1 if you have the <syscall.h> header file. */ #undef HAVE_SYSCALL_H
-/* Define to 1 if you have the `sysinfo' function. */ +/* Define to 1 if you have the 'sysinfo' function. */ #undef HAVE_SYSINFO
/* Define to 1 if you have the <sys/attr.h> header file. */ @@ -621,10 +627,10 @@ /* Define to 1 if you have the <sys/xattr.h> header file. */ #undef HAVE_SYS_XATTR_H
-/* Define to 1 if you have the `tcdrain' function. */ +/* Define to 1 if you have the 'tcdrain' function. */ #undef HAVE_TCDRAIN
-/* Define to 1 if you have the `thr_kill2' function. */ +/* Define to 1 if you have the 'thr_kill2' function. */ #undef HAVE_THR_KILL2
/* Define to 1 if you have the `udev' library (-ludev). */ @@ -669,10 +675,10 @@ /* Define to 1 if you have the <X11/extensions/XShm.h> header file. */ #undef HAVE_X11_EXTENSIONS_XSHM_H
-/* Define to 1 if `xcookie' is a member of `XEvent'. */ +/* Define to 1 if 'xcookie' is a member of 'XEvent'. */ #undef HAVE_XEVENT_XCOOKIE
-/* Define to 1 if `callback' is a member of `XICCallback'. */ +/* Define to 1 if 'callback' is a member of 'XICCallback'. */ #undef HAVE_XICCALLBACK_CALLBACK
/* Define to 1 if you have the <xkbcommon/xkbcommon.h> header file. */ @@ -801,10 +807,10 @@ /* Define to the soname of the libXxf86vm library. */ #undef SONAME_LIBXXF86VM
-/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */ +/* Define to 1 if the 'S_IS*' macros in <sys/stat.h> do not work properly. */ #undef STAT_MACROS_BROKEN
-/* Define to 1 if all of the C90 standard headers exist (not just the ones +/* Define to 1 if all of the C89 standard headers exist (not just the ones required in a freestanding environment). This macro is provided for backward compatibility; new code need not use it. */ #undef STDC_HEADERS @@ -821,13 +827,16 @@ /* Define to 1 to enable GNU extensions on Linux */ #undef _GNU_SOURCE
-/* Define for large files, on AIX-style hosts. */ +/* Define to 1 on platforms where this makes off_t a 64-bit type. */ #undef _LARGE_FILES
-/* Define to 64 to enable 64-bit time_t */ +/* Number of bits in time_t, on hosts where this is settable. */ #undef _TIME_BITS
-/* Define to `__inline__' or `__inline' if that's what the C compiler +/* Define to 1 on platforms where this makes time_t a 64-bit type. */ +#undef __MINGW_USE_VC2005_COMPAT + +/* Define to '__inline__' or '__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus #undef inline
From: Vibhav Pant vibhavp@gmail.com
--- include/winternl.h | 3 --- 1 file changed, 3 deletions(-)
diff --git a/include/winternl.h b/include/winternl.h index 72bdb2b1673..63ccd3637a9 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -5148,9 +5148,6 @@ NTSYSAPI NTSTATUS WINAPI wine_nt_to_unix_file_name( const OBJECT_ATTRIBUTES *att UINT disposition ); NTSYSAPI NTSTATUS WINAPI wine_unix_to_nt_file_name( const char *name, WCHAR *buffer, ULONG *size );
-NTSYSAPI NTSTATUS WINAPI wine_unix_get_min_large_page_size( SIZE_T *size ); - - /*********************************************************************** * Inline functions */
From: Vibhav Pant vibhavp@gmail.com
--- server/mapping.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-)
diff --git a/server/mapping.c b/server/mapping.c index a2958629c4d..42ab1d29d0b 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -30,8 +30,10 @@ #include <sys/stat.h> #include <sys/mman.h> #include <unistd.h> -#ifdef __linux__ +#ifdef __linux__ /* For detecting large page support. */ #include <linux/memfd.h> +#include <dirent.h> +#include <limits.h> #endif
#include "ntstatus.h" @@ -1340,6 +1342,66 @@ int get_page_size(void) return page_mask + 1; }
+#ifdef __linux__ +static size_t linux_get_min_hugepage_size( void ) +{ + DIR *sysfs_hugepages; + struct dirent *supported_size; + size_t min_size = 0; + size_t total_supported_sizes = 0; + + errno = 0; + sysfs_hugepages = opendir("/sys/kernel/mm/hugepages"); + if (sysfs_hugepages == NULL) + { + return -1; + } + + while(1) + { + long hugepage_size; + + supported_size = readdir( sysfs_hugepages ); + if ( supported_size == NULL ) + { + break; + } + if (strncmp( supported_size->d_name, "hugepages-", 10) != 0) + { + continue; + } + errno = 0; + hugepage_size = strtol( &supported_size->d_name[10], NULL, 10 ); + if (hugepage_size == 0 || hugepage_size == LONG_MAX || hugepage_size == LONG_MIN) + { + if (errno != 0) + { + fprintf( stderr, + "could not parse page size from directory entry '%s': %s\n", + supported_size->d_name, strerror( errno ) ); + } + continue; + } + hugepage_size *= 1024; + min_size = ( total_supported_sizes == 0 ) + ? hugepage_size + : ( hugepage_size < min_size ? hugepage_size : min_size ); + total_supported_sizes++; + } + + closedir(sysfs_hugepages); + return min_size; +} +#endif /* __linux__ */ + +static size_t get_min_large_page_size( void ) +{ +#ifdef __linux__ + return linux_get_min_hugepage_size(); +#endif + return 0; +} + struct object *create_user_data_mapping( struct object *root, const struct unicode_str *name, unsigned int attr, const struct security_descriptor *sd ) { @@ -1351,8 +1413,15 @@ struct object *create_user_data_mapping( struct object *root, const struct unico ptr = mmap( NULL, mapping->size, PROT_WRITE, MAP_SHARED, get_unix_fd( mapping->fd ), 0 ); if (ptr != MAP_FAILED) { + ULONG min_large_page_size; + user_shared_data = ptr; user_shared_data->SystemCall = 1; + min_large_page_size = get_min_large_page_size(); + if (min_large_page_size != 0) + { + user_shared_data->LargePageMinimum = min_large_page_size; + } } return &mapping->obj; }