mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
Added patch to implement shared memory wineserver communication for various user32 functions.
This commit is contained in:
parent
1c4a8d2f9a
commit
5fe90fc2e8
1
debian/changelog
vendored
1
debian/changelog
vendored
@ -21,6 +21,7 @@ wine-staging (1.7.39) UNRELEASED; urgency=low
|
||||
* Added patch to improve stub for ID3DXEffectImpl_CloneEffect.
|
||||
* Added patch with additional tests for server-PeekMessage.
|
||||
* Added patch to only zero the buffer up 32767 bytes in GetTempPathW.
|
||||
* Added patch to implement shared memory wineserver communication for various user32 functions.
|
||||
* Removed patch to avoid hardcoded values for sizeof(GUID) (accepted upstream).
|
||||
* Removed patches for SLGetWindowsInformationDWORD (accepted upstream).
|
||||
* Removed patches for _ismbckata and _mbctohira (fixed upstream).
|
||||
|
@ -175,6 +175,7 @@ patch_enable_all ()
|
||||
enable_server_Misc_ACL="$1"
|
||||
enable_server_OpenProcess="$1"
|
||||
enable_server_PeekMessage="$1"
|
||||
enable_server_Shared_Memory="$1"
|
||||
enable_server_Stored_ACLs="$1"
|
||||
enable_server_Unexpected_Wakeup="$1"
|
||||
enable_setupapi_SetupPromptForDisk="$1"
|
||||
@ -577,6 +578,9 @@ patch_enable ()
|
||||
server-PeekMessage)
|
||||
enable_server_PeekMessage="$2"
|
||||
;;
|
||||
server-Shared_Memory)
|
||||
enable_server_Shared_Memory="$2"
|
||||
;;
|
||||
server-Stored_ACLs)
|
||||
enable_server_Stored_ACLs="$2"
|
||||
;;
|
||||
@ -979,6 +983,21 @@ if test "$enable_shell32_Progress_Dialog" -eq 1; then
|
||||
enable_kernel32_CopyFileEx=1
|
||||
fi
|
||||
|
||||
if test "$enable_server_Shared_Memory" -eq 1; then
|
||||
if test "$enable_dinput_Events" -gt 1; then
|
||||
abort "Patchset dinput-Events disabled, but server-Shared_Memory depends on that."
|
||||
fi
|
||||
if test "$enable_ntdll_Threading" -gt 1; then
|
||||
abort "Patchset ntdll-Threading disabled, but server-Shared_Memory depends on that."
|
||||
fi
|
||||
if test "$enable_user32_Key_State" -gt 1; then
|
||||
abort "Patchset user32-Key_State disabled, but server-Shared_Memory depends on that."
|
||||
fi
|
||||
enable_dinput_Events=1
|
||||
enable_ntdll_Threading=1
|
||||
enable_user32_Key_State=1
|
||||
fi
|
||||
|
||||
if test "$enable_server_JobObjects" -eq 1; then
|
||||
if test "$enable_kernel32_Console_Handles" -gt 1; then
|
||||
abort "Patchset kernel32-Console_Handles disabled, but server-JobObjects depends on that."
|
||||
@ -3712,6 +3731,47 @@ if test "$enable_server_PeekMessage" -eq 1; then
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset user32-Key_State
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#29871] Invalidate key state cache globally after calling LL hooks
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/user32/hook.c, dlls/user32/input.c, dlls/user32/message.c, dlls/user32/user_private.h
|
||||
# |
|
||||
if test "$enable_user32_Key_State" -eq 1; then
|
||||
patch_apply user32-Key_State/0001-user32-After-calling-LL-hooks-the-key-state-cache-ha.patch
|
||||
(
|
||||
echo '+ { "Sebastian Lackner", "user32: After calling LL hooks the key state cache has to be invalidated globally.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset server-Shared_Memory
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/ntdll/ntdll_misc.h, dlls/ntdll/server.c, dlls/ntdll/thread.c, dlls/ntdll/virtual.c, dlls/user32/input.c,
|
||||
# | dlls/user32/message.c, dlls/user32/user_private.h, include/wine/server.h, include/winternl.h, server/fd.c,
|
||||
# | server/file.h, server/main.c, server/mapping.c, server/protocol.def, server/queue.c, server/thread.c, server/thread.h
|
||||
# |
|
||||
if test "$enable_server_Shared_Memory" -eq 1; then
|
||||
patch_apply server-Shared_Memory/0001-ntdll-Implement-virtual_map_shared_memory.patch
|
||||
patch_apply server-Shared_Memory/0002-server-Implement-support-for-global-and-local-shared.patch
|
||||
patch_apply server-Shared_Memory/0003-user32-Get-rid-of-wineserver-call-for-GetInputState.patch
|
||||
patch_apply server-Shared_Memory/0004-user32-Avoid-unnecessary-wineserver-calls-in-PeekMes.patch
|
||||
patch_apply server-Shared_Memory/0005-user32-Get-rid-of-wineserver-call-for-GetLastInputIn.patch
|
||||
patch_apply server-Shared_Memory/0006-ntdll-Only-enable-wineserver-shared-memory-communica.patch
|
||||
patch_apply server-Shared_Memory/0007-server-Use-syscall-number-from-sys-syscall.h-if-poss.patch
|
||||
(
|
||||
echo '+ { "Sebastian Lackner", "ntdll: Implement virtual_map_shared_memory.", 1 },';
|
||||
echo '+ { "Michael Müller", "server: Implement support for global and local shared memory blocks based on memfd.", 1 },';
|
||||
echo '+ { "Sebastian Lackner", "user32: Get rid of wineserver call for GetInputState.", 1 },';
|
||||
echo '+ { "Sebastian Lackner", "user32: Avoid unnecessary wineserver calls in PeekMessage/GetMessage.", 1 },';
|
||||
echo '+ { "Michael Müller", "user32: Get rid of wineserver call for GetLastInputInfo.", 1 },';
|
||||
echo '+ { "Sebastian Lackner", "ntdll: Only enable wineserver shared memory communication when a special environment variable is set.", 1 },';
|
||||
echo '+ { "Sebastian Lackner", "server: Use syscall number from sys/syscall.h if possible.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset server-Unexpected_Wakeup
|
||||
# |
|
||||
# | Modified files:
|
||||
@ -3981,21 +4041,6 @@ if test "$enable_user32_GetTipText" -eq 1; then
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset user32-Key_State
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#29871] Invalidate key state cache globally after calling LL hooks
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/user32/hook.c, dlls/user32/input.c, dlls/user32/message.c, dlls/user32/user_private.h
|
||||
# |
|
||||
if test "$enable_user32_Key_State" -eq 1; then
|
||||
patch_apply user32-Key_State/0001-user32-After-calling-LL-hooks-the-key-state-cache-ha.patch
|
||||
(
|
||||
echo '+ { "Sebastian Lackner", "user32: After calling LL hooks the key state cache has to be invalidated globally.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset user32-Mouse_Message_Hwnd
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
|
@ -0,0 +1,89 @@
|
||||
From 3298a6ca8d888b2636c870d34cb4f78272409bfd Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Wed, 18 Mar 2015 23:03:01 +0100
|
||||
Subject: ntdll: Implement virtual_map_shared_memory.
|
||||
|
||||
Preparation for shared memory wineserver communication.
|
||||
---
|
||||
dlls/ntdll/ntdll_misc.h | 1 +
|
||||
dlls/ntdll/virtual.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 53 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
|
||||
index 674fcbc..41ef5cb 100644
|
||||
--- a/dlls/ntdll/ntdll_misc.h
|
||||
+++ b/dlls/ntdll/ntdll_misc.h
|
||||
@@ -166,6 +166,7 @@ extern NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, ANSI_S
|
||||
extern void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS virtual_create_builtin_view( void *base ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS virtual_alloc_thread_stack( TEB *teb, SIZE_T reserve_size, SIZE_T commit_size ) DECLSPEC_HIDDEN;
|
||||
+extern NTSTATUS virtual_map_shared_memory( int fd, PVOID *addr_ptr, ULONG zero_bits, SIZE_T *size_ptr, ULONG protect ) DECLSPEC_HIDDEN;
|
||||
extern void virtual_clear_thread_stack(void) DECLSPEC_HIDDEN;
|
||||
extern BOOL virtual_handle_stack_fault( void *addr ) DECLSPEC_HIDDEN;
|
||||
extern BOOL virtual_is_valid_code_address( const void *addr, SIZE_T size ) DECLSPEC_HIDDEN;
|
||||
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
|
||||
index ab6bf9b..eb81294 100644
|
||||
--- a/dlls/ntdll/virtual.c
|
||||
+++ b/dlls/ntdll/virtual.c
|
||||
@@ -2739,6 +2739,58 @@ done:
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
+ * virtual_map_shared_memory
|
||||
+ */
|
||||
+NTSTATUS virtual_map_shared_memory( int fd, PVOID *addr_ptr, ULONG zero_bits,
|
||||
+ SIZE_T *size_ptr, ULONG protect )
|
||||
+{
|
||||
+ SIZE_T size, mask = get_mask( zero_bits );
|
||||
+ struct file_view *view;
|
||||
+ unsigned int vprot;
|
||||
+ sigset_t sigset;
|
||||
+ NTSTATUS res;
|
||||
+ int prot;
|
||||
+
|
||||
+ size = ROUND_SIZE( 0, *size_ptr );
|
||||
+ if (size < *size_ptr)
|
||||
+ return STATUS_INVALID_PARAMETER;
|
||||
+
|
||||
+ server_enter_uninterrupted_section( &csVirtual, &sigset );
|
||||
+
|
||||
+ get_vprot_flags( protect, &vprot, FALSE );
|
||||
+ vprot |= VPROT_COMMITTED;
|
||||
+ res = map_view( &view, *addr_ptr, size, mask, FALSE, vprot );
|
||||
+ if (!res)
|
||||
+ {
|
||||
+ /* Map the shared memory */
|
||||
+
|
||||
+ prot = VIRTUAL_GetUnixProt( vprot );
|
||||
+ if (force_exec_prot && !(vprot & VPROT_NOEXEC) && (vprot & VPROT_READ))
|
||||
+ {
|
||||
+ TRACE( "forcing exec permission on mapping %p-%p\n",
|
||||
+ (char *)view->base, (char *)view->base + size - 1 );
|
||||
+ prot |= PROT_EXEC;
|
||||
+ }
|
||||
+
|
||||
+ if (mmap( view->base, size, prot, MAP_FIXED | MAP_SHARED, fd, 0 ) != (void *)-1)
|
||||
+ {
|
||||
+ memset( view->prot, vprot, size >> page_shift );
|
||||
+ *addr_ptr = view->base;
|
||||
+ *size_ptr = size;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ ERR( "virtual_map_shared_memory %p %lx failed\n", view->base, size );
|
||||
+ delete_view( view );
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ server_leave_uninterrupted_section( &csVirtual, &sigset );
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/***********************************************************************
|
||||
* NtUnmapViewOfSection (NTDLL.@)
|
||||
* ZwUnmapViewOfSection (NTDLL.@)
|
||||
*/
|
||||
--
|
||||
2.3.2
|
||||
|
@ -0,0 +1,411 @@
|
||||
From 52d65729080fcbc24bda5578d81eff7414d9ca5e Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Thu, 19 Mar 2015 01:22:34 +0100
|
||||
Subject: server: Implement support for global and local shared memory blocks
|
||||
based on memfd.
|
||||
|
||||
---
|
||||
dlls/ntdll/ntdll_misc.h | 1 +
|
||||
dlls/ntdll/server.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
dlls/ntdll/thread.c | 4 ++++
|
||||
include/wine/server.h | 11 +++++++++
|
||||
include/winternl.h | 2 +-
|
||||
server/fd.c | 27 +++++++++++++++++++++
|
||||
server/file.h | 8 +++++++
|
||||
server/main.c | 1 +
|
||||
server/mapping.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
server/protocol.def | 15 ++++++++++++
|
||||
server/thread.c | 7 ++++++
|
||||
server/thread.h | 2 ++
|
||||
12 files changed, 205 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
|
||||
index 41ef5cb..18e00c9 100644
|
||||
--- a/dlls/ntdll/ntdll_misc.h
|
||||
+++ b/dlls/ntdll/ntdll_misc.h
|
||||
@@ -97,6 +97,7 @@ extern int server_remove_fd_from_cache( HANDLE handle ) DECLSPEC_HIDDEN;
|
||||
extern int server_get_unix_fd( HANDLE handle, unsigned int access, int *unix_fd,
|
||||
int *needs_close, enum server_fd_type *type, unsigned int *options ) DECLSPEC_HIDDEN;
|
||||
extern int server_pipe( int fd[2] ) DECLSPEC_HIDDEN;
|
||||
+extern void *server_get_shared_memory( HANDLE thread ) DECLSPEC_HIDDEN;
|
||||
|
||||
/* security descriptors */
|
||||
NTSTATUS NTDLL_create_struct_sd(PSECURITY_DESCRIPTOR nt_sd, struct security_descriptor **server_sd,
|
||||
diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c
|
||||
index 69d01be..0b8e007 100644
|
||||
--- a/dlls/ntdll/server.c
|
||||
+++ b/dlls/ntdll/server.c
|
||||
@@ -941,6 +941,66 @@ done:
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
+ * server_get_shared_memory_fd
|
||||
+ *
|
||||
+ * Receive a file descriptor to a server shared memory block.
|
||||
+ */
|
||||
+static int server_get_shared_memory_fd( HANDLE thread, int *unix_fd )
|
||||
+{
|
||||
+ obj_handle_t dummy;
|
||||
+ sigset_t sigset;
|
||||
+ int ret;
|
||||
+
|
||||
+ server_enter_uninterrupted_section( &fd_cache_section, &sigset );
|
||||
+
|
||||
+ SERVER_START_REQ( get_shared_memory )
|
||||
+ {
|
||||
+ req->tid = HandleToULong(thread);
|
||||
+ if (!(ret = wine_server_call( req )))
|
||||
+ {
|
||||
+ *unix_fd = receive_fd( &dummy );
|
||||
+ if (*unix_fd == -1) ret = STATUS_NOT_SUPPORTED;
|
||||
+ }
|
||||
+ }
|
||||
+ SERVER_END_REQ;
|
||||
+
|
||||
+ server_leave_uninterrupted_section( &fd_cache_section, &sigset );
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/***********************************************************************
|
||||
+ * server_get_shared_memory
|
||||
+ *
|
||||
+ * Get address of a shared memory block.
|
||||
+ */
|
||||
+void *server_get_shared_memory( HANDLE thread )
|
||||
+{
|
||||
+ static shmglobal_t *shmglobal = (void *)-1;
|
||||
+ void *mem = NULL;
|
||||
+ int fd = -1;
|
||||
+
|
||||
+ /* The global memory block is only requested once. No locking is
|
||||
+ * required because this function is called very early during the
|
||||
+ * process initialization for the first time. */
|
||||
+ if (!thread && shmglobal != (void *)-1)
|
||||
+ return shmglobal;
|
||||
+
|
||||
+ if (!server_get_shared_memory_fd( thread, &fd ))
|
||||
+ {
|
||||
+ SIZE_T size = thread ? sizeof(shmlocal_t) : sizeof(shmglobal_t);
|
||||
+ virtual_map_shared_memory( fd, &mem, 0, &size, PAGE_READONLY );
|
||||
+ close( fd );
|
||||
+ }
|
||||
+
|
||||
+ if (!thread)
|
||||
+ shmglobal = mem;
|
||||
+
|
||||
+ return mem;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/***********************************************************************
|
||||
* wine_server_fd_to_handle (NTDLL.@)
|
||||
*
|
||||
* Allocate a file handle for a Unix file descriptor.
|
||||
@@ -1472,6 +1532,10 @@ size_t server_init_thread( void *entry_point )
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
+ /* initialize thread shared memory pointers */
|
||||
+ NtCurrentTeb()->Reserved5[0] = server_get_shared_memory( 0 );
|
||||
+ NtCurrentTeb()->Reserved5[1] = server_get_shared_memory( NtCurrentTeb()->ClientId.UniqueThread );
|
||||
+
|
||||
is_wow64 = !is_win64 && (server_cpus & (1 << CPU_x86_64)) != 0;
|
||||
ntdll_get_thread_data()->wow64_redir = is_wow64;
|
||||
|
||||
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
|
||||
index 74e64c9..b030afd 100644
|
||||
--- a/dlls/ntdll/thread.c
|
||||
+++ b/dlls/ntdll/thread.c
|
||||
@@ -370,6 +370,7 @@ void terminate_thread( int status )
|
||||
void exit_thread( int status )
|
||||
{
|
||||
static void *prev_teb;
|
||||
+ shmlocal_t *shmlocal;
|
||||
sigset_t sigset;
|
||||
TEB *teb;
|
||||
|
||||
@@ -393,6 +394,9 @@ void exit_thread( int status )
|
||||
LdrShutdownThread();
|
||||
RtlFreeThreadActivationContextStack();
|
||||
|
||||
+ shmlocal = interlocked_xchg_ptr( &NtCurrentTeb()->Reserved5[1], NULL );
|
||||
+ if (shmlocal) NtUnmapViewOfSection( NtCurrentProcess(), shmlocal );
|
||||
+
|
||||
pthread_sigmask( SIG_BLOCK, &server_block_set, NULL );
|
||||
|
||||
if ((teb = interlocked_xchg_ptr( &prev_teb, NtCurrentTeb() )))
|
||||
diff --git a/include/wine/server.h b/include/wine/server.h
|
||||
index d573d1f..695389a 100644
|
||||
--- a/include/wine/server.h
|
||||
+++ b/include/wine/server.h
|
||||
@@ -120,6 +120,17 @@ static inline void *wine_server_get_ptr( client_ptr_t ptr )
|
||||
return (void *)(ULONG_PTR)ptr;
|
||||
}
|
||||
|
||||
+/* returns a pointer to the wineserver global shared memory block */
|
||||
+static inline shmglobal_t *wine_get_shmglobal(void)
|
||||
+{
|
||||
+ return (shmglobal_t *)NtCurrentTeb()->Reserved5[0];
|
||||
+}
|
||||
+
|
||||
+/* returns a pointer to the wineserver local shared memory block */
|
||||
+static inline shmlocal_t *wine_get_shmlocal(void)
|
||||
+{
|
||||
+ return (shmlocal_t *)NtCurrentTeb()->Reserved5[1];
|
||||
+}
|
||||
|
||||
/* macros for server requests */
|
||||
|
||||
diff --git a/include/winternl.h b/include/winternl.h
|
||||
index f88001f..f1cc143 100644
|
||||
--- a/include/winternl.h
|
||||
+++ b/include/winternl.h
|
||||
@@ -353,7 +353,7 @@ typedef struct _TEB
|
||||
PVOID Spare4; /* f7c/1750 */
|
||||
PVOID ReservedForOle; /* f80/1758 */
|
||||
ULONG WaitingOnLoaderLock; /* f84/1760 */
|
||||
- PVOID Reserved5[3]; /* f88/1768 */
|
||||
+ PVOID Reserved5[3]; /* f88/1768 used for wineserver shared memory */
|
||||
PVOID *TlsExpansionSlots; /* f94/1780 */
|
||||
ULONG ImpersonationLocale; /* f98/1788 */
|
||||
ULONG IsImpersonating; /* f9c/178c */
|
||||
diff --git a/server/fd.c b/server/fd.c
|
||||
index e3b722c..14c473b 100644
|
||||
--- a/server/fd.c
|
||||
+++ b/server/fd.c
|
||||
@@ -2293,6 +2293,33 @@ DECL_HANDLER(get_handle_fd)
|
||||
}
|
||||
}
|
||||
|
||||
+/* get file descriptor to shared memory block */
|
||||
+DECL_HANDLER(get_shared_memory)
|
||||
+{
|
||||
+ if (req->tid)
|
||||
+ {
|
||||
+ struct thread *thread = get_thread_from_id( req->tid );
|
||||
+ if (thread)
|
||||
+ {
|
||||
+ if (thread->shm_fd != -1 || allocate_shared_memory( &thread->shm_fd,
|
||||
+ (void **)&thread->shm, sizeof(*thread->shm) ))
|
||||
+ {
|
||||
+ send_client_fd( current->process, thread->shm_fd, 0 );
|
||||
+ }
|
||||
+ else
|
||||
+ set_error( STATUS_NOT_SUPPORTED );
|
||||
+ release_object( thread );
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ if (shmglobal_fd != -1)
|
||||
+ send_client_fd( current->process, shmglobal_fd, 0 );
|
||||
+ else
|
||||
+ set_error( STATUS_NOT_SUPPORTED );
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* perform an ioctl on a file */
|
||||
DECL_HANDLER(ioctl)
|
||||
{
|
||||
diff --git a/server/file.h b/server/file.h
|
||||
index 85e4257..9c110bc 100644
|
||||
--- a/server/file.h
|
||||
+++ b/server/file.h
|
||||
@@ -134,6 +134,14 @@ extern obj_handle_t open_mapping_file( struct process *process, struct mapping *
|
||||
extern struct mapping *grab_mapping_unless_removable( struct mapping *mapping );
|
||||
extern int get_page_size(void);
|
||||
|
||||
+/* shared memory functions */
|
||||
+
|
||||
+extern int allocate_shared_memory( int *fd, void **memory, size_t size );
|
||||
+extern void release_shared_memory( int fd, void *memory, size_t size );
|
||||
+extern void init_shared_memory( void );
|
||||
+extern shmglobal_t *shmglobal;
|
||||
+extern int shmglobal_fd;
|
||||
+
|
||||
/* change notification functions */
|
||||
|
||||
extern void do_change_notify( int unix_fd );
|
||||
diff --git a/server/main.c b/server/main.c
|
||||
index 7aed338..f984bfc 100644
|
||||
--- a/server/main.c
|
||||
+++ b/server/main.c
|
||||
@@ -145,6 +145,7 @@ int main( int argc, char *argv[] )
|
||||
init_signals();
|
||||
init_directories();
|
||||
init_registry();
|
||||
+ init_shared_memory();
|
||||
main_loop();
|
||||
return 0;
|
||||
}
|
||||
diff --git a/server/mapping.c b/server/mapping.c
|
||||
index 64b3003..be624e5 100644
|
||||
--- a/server/mapping.c
|
||||
+++ b/server/mapping.c
|
||||
@@ -31,6 +31,20 @@
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
|
||||
+#if defined(__linux__) && (defined(__i386__) || defined(__x86_64__))
|
||||
+#ifdef __x86_64__
|
||||
+#define __NR_memfd_create 319
|
||||
+#else
|
||||
+#define __NR_memfd_create 356
|
||||
+#endif
|
||||
+#define F_LINUX_SPECIFIC_BASE 1024
|
||||
+#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
|
||||
+#define MFD_ALLOW_SEALING 0x0002U
|
||||
+#define F_SEAL_SEAL 0x0001
|
||||
+#define F_SEAL_SHRINK 0x0002
|
||||
+#define F_SEAL_GROW 0x0004
|
||||
+#endif
|
||||
+
|
||||
#include "ntstatus.h"
|
||||
#define WIN32_NO_STATUS
|
||||
#include "windef.h"
|
||||
@@ -112,6 +126,10 @@ static struct list shared_list = LIST_INIT(shared_list);
|
||||
|
||||
static size_t page_mask;
|
||||
|
||||
+/* global shared memory */
|
||||
+shmglobal_t *shmglobal;
|
||||
+int shmglobal_fd;
|
||||
+
|
||||
#define ROUND_SIZE(size) (((size) + page_mask) & ~page_mask)
|
||||
|
||||
|
||||
@@ -156,6 +174,52 @@ static int check_current_dir_for_exec(void)
|
||||
return (ret != MAP_FAILED);
|
||||
}
|
||||
|
||||
+/* allocates a block of shared memory */
|
||||
+int allocate_shared_memory( int *fd, void **memory, size_t size )
|
||||
+{
|
||||
+#if defined(__linux__) && (defined(__i386__) || defined(__x86_64__))
|
||||
+ void *shm_mem;
|
||||
+ int shm_fd;
|
||||
+
|
||||
+ shm_fd = syscall( __NR_memfd_create, "wineserver_shm", MFD_ALLOW_SEALING );
|
||||
+ if (shm_fd == -1) goto err;
|
||||
+ if (grow_file( shm_fd, size ))
|
||||
+ {
|
||||
+ if (fcntl( shm_fd, F_ADD_SEALS, F_SEAL_SEAL | F_SEAL_SHRINK | F_SEAL_GROW ) >= 0)
|
||||
+ {
|
||||
+ shm_mem = mmap( 0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0 );
|
||||
+ if (shm_mem != MAP_FAILED)
|
||||
+ {
|
||||
+ memset( shm_mem, 0, size );
|
||||
+ *fd = shm_fd;
|
||||
+ *memory = shm_mem;
|
||||
+ return 1;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ close( shm_fd );
|
||||
+err:
|
||||
+#endif
|
||||
+ *memory = NULL;
|
||||
+ *fd = -1;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* releases a block of shared memory */
|
||||
+void release_shared_memory( int fd, void *memory, size_t size )
|
||||
+{
|
||||
+#if defined(__linux__) && (defined(__i386__) || defined(__x86_64__))
|
||||
+ if (memory) munmap( memory, size );
|
||||
+ if (fd != -1) close( fd );
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+/* intialize shared memory management */
|
||||
+void init_shared_memory( void )
|
||||
+{
|
||||
+ allocate_shared_memory( &shmglobal_fd, (void **)&shmglobal, sizeof(*shmglobal) );
|
||||
+}
|
||||
+
|
||||
/* create a temp file for anonymous mappings */
|
||||
static int create_temp_file( file_pos_t size )
|
||||
{
|
||||
diff --git a/server/protocol.def b/server/protocol.def
|
||||
index 2cd8272..91ba01d 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -69,6 +69,15 @@ struct request_max_size
|
||||
#define FIRST_USER_HANDLE 0x0020 /* first possible value for low word of user handle */
|
||||
#define LAST_USER_HANDLE 0xffef /* last possible value for low word of user handle */
|
||||
|
||||
+typedef struct
|
||||
+{
|
||||
+ int dummy;
|
||||
+} shmglobal_t;
|
||||
+
|
||||
+typedef struct
|
||||
+{
|
||||
+ int dummy;
|
||||
+} shmlocal_t;
|
||||
|
||||
/* debug event data */
|
||||
typedef union
|
||||
@@ -1150,6 +1159,12 @@ enum server_fd_type
|
||||
};
|
||||
|
||||
|
||||
+/* Get file descriptor for shared memory */
|
||||
+@REQ(get_shared_memory)
|
||||
+ thread_id_t tid; /* thread id or 0 */
|
||||
+@END
|
||||
+
|
||||
+
|
||||
/* Flush a file buffers */
|
||||
@REQ(flush_file)
|
||||
obj_handle_t handle; /* handle to the file */
|
||||
diff --git a/server/thread.c b/server/thread.c
|
||||
index 906b79d..f99a677 100644
|
||||
--- a/server/thread.c
|
||||
+++ b/server/thread.c
|
||||
@@ -194,6 +194,8 @@ static inline void init_thread_structure( struct thread *thread )
|
||||
thread->suspend = 0;
|
||||
thread->desktop_users = 0;
|
||||
thread->token = NULL;
|
||||
+ thread->shm_fd = -1;
|
||||
+ thread->shm = NULL;
|
||||
|
||||
thread->creation_time = current_time;
|
||||
thread->exit_time = 0;
|
||||
@@ -295,6 +297,8 @@ static void cleanup_thread( struct thread *thread )
|
||||
thread->inflight[i].client = thread->inflight[i].server = -1;
|
||||
}
|
||||
}
|
||||
+ release_shared_memory( thread->shm_fd, thread->shm, sizeof(*thread->shm) );
|
||||
+
|
||||
thread->req_data = NULL;
|
||||
thread->reply_data = NULL;
|
||||
thread->request_fd = NULL;
|
||||
@@ -303,6 +307,9 @@ static void cleanup_thread( struct thread *thread )
|
||||
thread->context = NULL;
|
||||
thread->suspend_context = NULL;
|
||||
thread->desktop = 0;
|
||||
+ thread->shm_fd = -1;
|
||||
+ thread->shm = NULL;
|
||||
+
|
||||
}
|
||||
|
||||
/* destroy a thread when its refcount is 0 */
|
||||
diff --git a/server/thread.h b/server/thread.h
|
||||
index 996d95b..0107a45 100644
|
||||
--- a/server/thread.h
|
||||
+++ b/server/thread.h
|
||||
@@ -87,6 +87,8 @@ struct thread
|
||||
timeout_t creation_time; /* Thread creation time */
|
||||
timeout_t exit_time; /* Thread exit time */
|
||||
struct token *token; /* security token associated with this thread */
|
||||
+ int shm_fd; /* file descriptor for thread local shared memory */
|
||||
+ shmlocal_t *shm; /* thread local shared memory pointer */
|
||||
};
|
||||
|
||||
struct thread_snapshot
|
||||
--
|
||||
2.3.2
|
||||
|
@ -0,0 +1,120 @@
|
||||
From 494442ff993ad741dda2f6676e4d7d0cd7294ae8 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Thu, 19 Mar 2015 01:32:51 +0100
|
||||
Subject: user32: Get rid of wineserver call for GetInputState.
|
||||
|
||||
---
|
||||
dlls/user32/input.c | 14 +++++++++++++-
|
||||
server/protocol.def | 2 +-
|
||||
server/queue.c | 14 ++++++++++++++
|
||||
3 files changed, 28 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/user32/input.c b/dlls/user32/input.c
|
||||
index b07c147..ace4fb8 100644
|
||||
--- a/dlls/user32/input.c
|
||||
+++ b/dlls/user32/input.c
|
||||
@@ -444,17 +444,29 @@ DWORD WINAPI GetQueueStatus( UINT flags )
|
||||
*/
|
||||
BOOL WINAPI GetInputState(void)
|
||||
{
|
||||
+ shmlocal_t *shm = wine_get_shmlocal();
|
||||
DWORD ret;
|
||||
|
||||
__wine_check_for_events( QS_INPUT );
|
||||
|
||||
+ /* req->clear is not set, so we can safely get the
|
||||
+ * wineserver status without an additional call. */
|
||||
+ if (shm)
|
||||
+ {
|
||||
+ ret = shm->queue_bits;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
SERVER_START_REQ( get_queue_status )
|
||||
{
|
||||
req->clear = 0;
|
||||
wine_server_call( req );
|
||||
- ret = reply->wake_bits & (QS_KEY | QS_MOUSEBUTTON);
|
||||
+ ret = reply->wake_bits;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
+
|
||||
+done:
|
||||
+ ret &= (QS_KEY | QS_MOUSEBUTTON);
|
||||
return ret;
|
||||
}
|
||||
|
||||
diff --git a/server/protocol.def b/server/protocol.def
|
||||
index 91ba01d..7d077d7 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -76,7 +76,7 @@ typedef struct
|
||||
|
||||
typedef struct
|
||||
{
|
||||
- int dummy;
|
||||
+ int queue_bits; /* queue wake bits */
|
||||
} shmlocal_t;
|
||||
|
||||
/* debug event data */
|
||||
diff --git a/server/queue.c b/server/queue.c
|
||||
index 3a321cd..fff5eb8 100644
|
||||
--- a/server/queue.c
|
||||
+++ b/server/queue.c
|
||||
@@ -117,6 +117,7 @@ struct thread_input
|
||||
struct msg_queue
|
||||
{
|
||||
struct object obj; /* object header */
|
||||
+ struct thread *thread; /* reference to the thread owning the queue */
|
||||
struct fd *fd; /* optional file descriptor to poll */
|
||||
unsigned int wake_bits; /* wakeup bits */
|
||||
unsigned int wake_mask; /* wakeup mask */
|
||||
@@ -278,6 +279,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
|
||||
if ((queue = alloc_object( &msg_queue_ops )))
|
||||
{
|
||||
queue->fd = NULL;
|
||||
+ queue->thread = thread;
|
||||
queue->wake_bits = 0;
|
||||
queue->wake_mask = 0;
|
||||
queue->changed_bits = 0;
|
||||
@@ -309,6 +311,7 @@ void free_msg_queue( struct thread *thread )
|
||||
{
|
||||
remove_thread_hooks( thread );
|
||||
if (!thread->queue) return;
|
||||
+ thread->queue->thread = NULL;
|
||||
release_object( thread->queue );
|
||||
thread->queue = NULL;
|
||||
}
|
||||
@@ -419,11 +422,21 @@ static inline int is_signaled( struct msg_queue *queue )
|
||||
return ((queue->wake_bits & queue->wake_mask) || (queue->changed_bits & queue->changed_mask));
|
||||
}
|
||||
|
||||
+/* synchronize the queue state with the shared memory */
|
||||
+static inline void update_shm_queue_bits( struct msg_queue *queue )
|
||||
+{
|
||||
+ shmlocal_t *shm;
|
||||
+ if (!queue->thread) return;
|
||||
+ if ((shm = queue->thread->shm))
|
||||
+ shm->queue_bits = queue->wake_bits;
|
||||
+}
|
||||
+
|
||||
/* set some queue bits */
|
||||
static inline void set_queue_bits( struct msg_queue *queue, unsigned int bits )
|
||||
{
|
||||
queue->wake_bits |= bits;
|
||||
queue->changed_bits |= bits;
|
||||
+ update_shm_queue_bits( queue );
|
||||
if (is_signaled( queue )) wake_up( &queue->obj, 0 );
|
||||
}
|
||||
|
||||
@@ -432,6 +445,7 @@ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits
|
||||
{
|
||||
queue->wake_bits &= ~bits;
|
||||
queue->changed_bits &= ~bits;
|
||||
+ update_shm_queue_bits( queue );
|
||||
}
|
||||
|
||||
/* check whether msg is a keyboard message */
|
||||
--
|
||||
2.3.2
|
||||
|
@ -0,0 +1,59 @@
|
||||
From 07da6f20d2cb5decee8362297af6c27a83da0137 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Thu, 19 Mar 2015 02:07:24 +0100
|
||||
Subject: user32: Avoid unnecessary wineserver calls in PeekMessage/GetMessage.
|
||||
|
||||
---
|
||||
dlls/user32/message.c | 13 +++++++++++++
|
||||
dlls/user32/user_private.h | 3 ++-
|
||||
2 files changed, 15 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/user32/message.c b/dlls/user32/message.c
|
||||
index d59e342..4bc17e9 100644
|
||||
--- a/dlls/user32/message.c
|
||||
+++ b/dlls/user32/message.c
|
||||
@@ -2734,6 +2734,18 @@ static BOOL peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags
|
||||
unsigned int hw_id = 0; /* id of previous hardware message */
|
||||
void *buffer;
|
||||
size_t buffer_size = 256;
|
||||
+ shmlocal_t *shm = wine_get_shmlocal();
|
||||
+
|
||||
+ /* From time to time we are forced to do a wineserver call in
|
||||
+ * order to update last_msg_time stored for each server thread. */
|
||||
+ if (shm && GetTickCount() - thread_info->last_get_msg < 500)
|
||||
+ {
|
||||
+ int filter = flags >> 16;
|
||||
+ if (!filter) filter = QS_ALLINPUT;
|
||||
+ filter |= QS_SENDMESSAGE;
|
||||
+ if (filter & QS_INPUT) filter |= QS_INPUT;
|
||||
+ if (!(shm->queue_bits & filter)) return FALSE;
|
||||
+ }
|
||||
|
||||
if (!(buffer = HeapAlloc( GetProcessHeap(), 0, buffer_size ))) return FALSE;
|
||||
|
||||
@@ -2746,6 +2758,7 @@ static BOOL peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags
|
||||
size_t size = 0;
|
||||
const message_data_t *msg_data = buffer;
|
||||
|
||||
+ if (shm) thread_info->last_get_msg = GetTickCount();
|
||||
SERVER_START_REQ( get_message )
|
||||
{
|
||||
req->flags = flags;
|
||||
diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h
|
||||
index aa43578..7b8c425 100644
|
||||
--- a/dlls/user32/user_private.h
|
||||
+++ b/dlls/user32/user_private.h
|
||||
@@ -190,8 +190,9 @@ struct user_thread_info
|
||||
HWND top_window; /* Desktop window */
|
||||
HWND msg_window; /* HWND_MESSAGE parent window */
|
||||
RAWINPUT *rawinput;
|
||||
+ DWORD last_get_msg; /* Last message time */
|
||||
|
||||
- ULONG pad[5]; /* Available for more data */
|
||||
+ ULONG pad[4]; /* Available for more data */
|
||||
};
|
||||
|
||||
extern INT global_key_state_epoch DECLSPEC_HIDDEN;
|
||||
--
|
||||
2.3.2
|
||||
|
@ -0,0 +1,57 @@
|
||||
From 4ea257275cb1453288507cf536974ee3c013d449 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Thu, 19 Mar 2015 02:18:37 +0100
|
||||
Subject: user32: Get rid of wineserver call for GetLastInputInfo.
|
||||
|
||||
---
|
||||
dlls/user32/input.c | 7 +++++++
|
||||
server/protocol.def | 4 ++--
|
||||
2 files changed, 9 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/user32/input.c b/dlls/user32/input.c
|
||||
index ace4fb8..2512887 100644
|
||||
--- a/dlls/user32/input.c
|
||||
+++ b/dlls/user32/input.c
|
||||
@@ -477,6 +477,7 @@ done:
|
||||
BOOL WINAPI GetLastInputInfo(PLASTINPUTINFO plii)
|
||||
{
|
||||
BOOL ret;
|
||||
+ shmglobal_t *shm = wine_get_shmglobal();
|
||||
|
||||
TRACE("%p\n", plii);
|
||||
|
||||
@@ -486,6 +487,12 @@ BOOL WINAPI GetLastInputInfo(PLASTINPUTINFO plii)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
+ if (shm)
|
||||
+ {
|
||||
+ plii->dwTime = shm->last_input_time;
|
||||
+ return TRUE;
|
||||
+ }
|
||||
+
|
||||
SERVER_START_REQ( get_last_input_time )
|
||||
{
|
||||
ret = !wine_server_call_err( req );
|
||||
diff --git a/server/protocol.def b/server/protocol.def
|
||||
index 7d077d7..cf6d783 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -71,12 +71,12 @@ struct request_max_size
|
||||
|
||||
typedef struct
|
||||
{
|
||||
- int dummy;
|
||||
+ unsigned int last_input_time; /* last input time */
|
||||
} shmglobal_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
- int queue_bits; /* queue wake bits */
|
||||
+ int queue_bits; /* queue wake bits */
|
||||
} shmlocal_t;
|
||||
|
||||
/* debug event data */
|
||||
--
|
||||
2.3.2
|
||||
|
@ -0,0 +1,49 @@
|
||||
From c7b1b681995a397cfc3fa9e9bba3415102217da1 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Thu, 19 Mar 2015 02:55:36 +0100
|
||||
Subject: ntdll: Only enable wineserver shared memory communication when a
|
||||
special environment variable is set.
|
||||
|
||||
---
|
||||
dlls/ntdll/server.c | 18 ++++++++++++++++++
|
||||
1 file changed, 18 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c
|
||||
index 0b8e007..349fcc7 100644
|
||||
--- a/dlls/ntdll/server.c
|
||||
+++ b/dlls/ntdll/server.c
|
||||
@@ -968,6 +968,21 @@ static int server_get_shared_memory_fd( HANDLE thread, int *unix_fd )
|
||||
return ret;
|
||||
}
|
||||
|
||||
+/* The shared memory wineserver communication is still highly experimental
|
||||
+ * and might cause unexpected results when the client/server status gets
|
||||
+ * out of synchronization. The feature will be disabled by default until it
|
||||
+ * is tested a bit more. */
|
||||
+static inline BOOL experimental_SHARED_MEMORY( void )
|
||||
+{
|
||||
+ static int enabled = -1;
|
||||
+ if (enabled == -1)
|
||||
+ {
|
||||
+ const char *str = getenv( "STAGING_SHARED_MEMORY" );
|
||||
+ enabled = str && (atoi(str) != 0);
|
||||
+ }
|
||||
+ return enabled;
|
||||
+}
|
||||
+
|
||||
|
||||
/***********************************************************************
|
||||
* server_get_shared_memory
|
||||
@@ -980,6 +995,9 @@ void *server_get_shared_memory( HANDLE thread )
|
||||
void *mem = NULL;
|
||||
int fd = -1;
|
||||
|
||||
+ if (!experimental_SHARED_MEMORY())
|
||||
+ return NULL;
|
||||
+
|
||||
/* The global memory block is only requested once. No locking is
|
||||
* required because this function is called very early during the
|
||||
* process initialization for the first time. */
|
||||
--
|
||||
2.3.2
|
||||
|
@ -0,0 +1,47 @@
|
||||
From 3fa7e694712c386d6dc6e3e4d708d2d8ad529bfe Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Thu, 19 Mar 2015 03:08:35 +0100
|
||||
Subject: server: Use syscall number from sys/syscall.h if possible.
|
||||
|
||||
---
|
||||
server/mapping.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/server/mapping.c b/server/mapping.c
|
||||
index be624e5..063dbb8 100644
|
||||
--- a/server/mapping.c
|
||||
+++ b/server/mapping.c
|
||||
@@ -29,20 +29,30 @@
|
||||
#ifdef HAVE_SYS_MMAN_H
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
+#ifdef HAVE_SYS_SYSCALL_H
|
||||
+# include <sys/syscall.h>
|
||||
+#endif
|
||||
#include <unistd.h>
|
||||
|
||||
#if defined(__linux__) && (defined(__i386__) || defined(__x86_64__))
|
||||
+
|
||||
+/* __NR_memfd_create might not yet be available when buildservers use an old kernel */
|
||||
+#ifndef __NR_memfd_create
|
||||
#ifdef __x86_64__
|
||||
#define __NR_memfd_create 319
|
||||
#else
|
||||
#define __NR_memfd_create 356
|
||||
#endif
|
||||
+#endif
|
||||
+
|
||||
+/* the following declarations are only available in linux/fcntl.h, but not fcntl.h */
|
||||
#define F_LINUX_SPECIFIC_BASE 1024
|
||||
#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
|
||||
#define MFD_ALLOW_SEALING 0x0002U
|
||||
#define F_SEAL_SEAL 0x0001
|
||||
#define F_SEAL_SHRINK 0x0002
|
||||
#define F_SEAL_GROW 0x0004
|
||||
+
|
||||
#endif
|
||||
|
||||
#include "ntstatus.h"
|
||||
--
|
||||
2.3.2
|
||||
|
3
patches/server-Shared_Memory/definition
Normal file
3
patches/server-Shared_Memory/definition
Normal file
@ -0,0 +1,3 @@
|
||||
Depends: ntdll-Threading
|
||||
Depends: user32-Key_State
|
||||
Depends: dinput-Events
|
Loading…
Reference in New Issue
Block a user