Added patch to implement shared memory wineserver communication for various user32 functions.

This commit is contained in:
Sebastian Lackner 2015-03-19 03:13:07 +01:00
parent 1c4a8d2f9a
commit 5fe90fc2e8
10 changed files with 896 additions and 15 deletions

1
debian/changelog vendored
View File

@ -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).

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,3 @@
Depends: ntdll-Threading
Depends: user32-Key_State
Depends: dinput-Events