Rémi Bernon : dinput: Simplify the internal thread and don't require loader lock.

Alexandre Julliard julliard at winehq.org
Fri Dec 10 15:07:50 CST 2021


Module: wine
Branch: master
Commit: b67cda8975f9551ce6f48a18ffd3a1fcc7a278b0
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=b67cda8975f9551ce6f48a18ffd3a1fcc7a278b0

Author: Rémi Bernon <rbernon at codeweavers.com>
Date:   Fri Dec 10 09:44:44 2021 +0100

dinput: Simplify the internal thread and don't require loader lock.

When thread shuts down, instead of holding and releasing a module ref.

This keeps the thread alive until the module is unloaded, instead of
keeping track of live IDirectInput instances.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/dinput/dinput_main.c    | 115 +++++++++++++++----------------------------
 dlls/dinput/dinput_private.h |   3 --
 2 files changed, 39 insertions(+), 79 deletions(-)

diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 55d566afa4a..cab8886f9db 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -78,9 +78,18 @@ HINSTANCE DINPUT_instance;
 
 static HWND di_em_win;
 
-static BOOL check_hook_thread(void);
+static HANDLE dinput_thread;
+static DWORD dinput_thread_id;
+
 static CRITICAL_SECTION dinput_hook_crit;
-static struct list direct_input_list = LIST_INIT( direct_input_list );
+static CRITICAL_SECTION_DEBUG dinput_critsect_debug =
+{
+    0, 0, &dinput_hook_crit,
+    { &dinput_critsect_debug.ProcessLocksList, &dinput_critsect_debug.ProcessLocksList },
+      0, 0, { (DWORD_PTR)(__FILE__ ": dinput_hook_crit") }
+};
+static CRITICAL_SECTION dinput_hook_crit = { &dinput_critsect_debug, -1, 0, 0, 0, 0 };
+
 static struct list acquired_mouse_list = LIST_INIT( acquired_mouse_list );
 static struct list acquired_rawmouse_list = LIST_INIT( acquired_rawmouse_list );
 static struct list acquired_keyboard_list = LIST_INIT( acquired_keyboard_list );
@@ -453,18 +462,7 @@ static HRESULT initialize_directinput_instance(IDirectInputImpl *This, DWORD dwV
 
         list_init( &This->device_players );
 
-        /* Add self to the list of the IDirectInputs */
-        EnterCriticalSection( &dinput_hook_crit );
-        list_add_head( &direct_input_list, &This->entry );
-        LeaveCriticalSection( &dinput_hook_crit );
-
         This->initialized = TRUE;
-
-        if (!check_hook_thread())
-        {
-            uninitialize_directinput_instance( This );
-            return DIERR_GENERIC;
-        }
     }
 
     return DI_OK;
@@ -475,17 +473,11 @@ static void uninitialize_directinput_instance(IDirectInputImpl *This)
     if (This->initialized)
     {
         struct DevicePlayer *device_player, *device_player2;
-        /* Remove self from the list of the IDirectInputs */
-        EnterCriticalSection( &dinput_hook_crit );
-        list_remove( &This->entry );
-        LeaveCriticalSection( &dinput_hook_crit );
 
         LIST_FOR_EACH_ENTRY_SAFE( device_player, device_player2,
                 &This->device_players, struct DevicePlayer, entry )
             free( device_player );
 
-        check_hook_thread();
-
         This->initialized = FALSE;
     }
 }
@@ -1262,13 +1254,13 @@ static LRESULT CALLBACK callwndproc_proc( int code, WPARAM wparam, LPARAM lparam
     return CallNextHookEx( 0, code, wparam, lparam );
 }
 
-static DWORD WINAPI hook_thread_proc(void *param)
+static DWORD WINAPI dinput_thread_proc( void *params )
 {
+    HANDLE events[128], start_event = params;
     static HHOOK kbd_hook, mouse_hook;
     struct dinput_device *impl, *next;
     SIZE_T events_count = 0;
     HANDLE finished_event;
-    HANDLE events[128];
     HRESULT hr;
     DWORD ret;
     MSG msg;
@@ -1277,7 +1269,7 @@ static DWORD WINAPI hook_thread_proc(void *param)
 
     /* Force creation of the message queue */
     PeekMessageW( &msg, 0, 0, 0, PM_NOREMOVE );
-    SetEvent(param);
+    SetEvent( start_event );
 
     while ((ret = MsgWaitForMultipleObjectsEx( events_count, events, INFINITE, QS_ALLINPUT, 0 )) <= events_count)
     {
@@ -1354,61 +1346,36 @@ static DWORD WINAPI hook_thread_proc(void *param)
 done:
     DestroyWindow( di_em_win );
     di_em_win = NULL;
-
-    FreeLibraryAndExitThread(DINPUT_instance, 0);
+    return 0;
 }
 
-static DWORD hook_thread_id;
-static HANDLE hook_thread_event;
-
-static CRITICAL_SECTION_DEBUG dinput_critsect_debug =
+static BOOL WINAPI dinput_thread_start_once( INIT_ONCE *once, void *param, void **context )
 {
-    0, 0, &dinput_hook_crit,
-    { &dinput_critsect_debug.ProcessLocksList, &dinput_critsect_debug.ProcessLocksList },
-      0, 0, { (DWORD_PTR)(__FILE__ ": dinput_hook_crit") }
-};
-static CRITICAL_SECTION dinput_hook_crit = { &dinput_critsect_debug, -1, 0, 0, 0, 0 };
+    HANDLE start_event;
 
-static BOOL check_hook_thread(void)
-{
-    static HANDLE hook_thread;
-    HMODULE module;
-    HANDLE wait_handle = NULL;
+    start_event = CreateEventW( NULL, FALSE, FALSE, NULL );
+    if (!start_event) ERR( "failed to create start event, error %u\n", GetLastError() );
 
-    EnterCriticalSection(&dinput_hook_crit);
+    dinput_thread = CreateThread( NULL, 0, dinput_thread_proc, start_event, 0, &dinput_thread_id );
+    if (!dinput_thread) ERR( "failed to create internal thread, error %u\n", GetLastError() );
 
-    TRACE("IDirectInputs left: %d\n", list_count(&direct_input_list));
-    if (!list_empty(&direct_input_list) && !hook_thread)
-    {
-        GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (const WCHAR*)DINPUT_instance, &module);
-        hook_thread_event = CreateEventW(NULL, FALSE, FALSE, NULL);
-        hook_thread = CreateThread(NULL, 0, hook_thread_proc, hook_thread_event, 0, &hook_thread_id);
-    }
-    else if (list_empty(&direct_input_list) && hook_thread)
-    {
-        DWORD tid = hook_thread_id;
+    WaitForSingleObject( start_event, INFINITE );
+    CloseHandle( start_event );
 
-        if (hook_thread_event) /* if thread is not started yet */
-        {
-            WaitForSingleObject(hook_thread_event, INFINITE);
-            CloseHandle(hook_thread_event);
-            hook_thread_event = NULL;
-        }
-
-        hook_thread_id = 0;
-        PostThreadMessageW(tid, WM_USER+0x10, 0, 0);
-        wait_handle = hook_thread;
-        hook_thread = NULL;
-    }
+    return TRUE;
+}
 
-    LeaveCriticalSection(&dinput_hook_crit);
+static void dinput_thread_start(void)
+{
+    static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
+    InitOnceExecuteOnce( &init_once, dinput_thread_start_once, NULL, NULL );
+}
 
-    if (wait_handle)
-    {
-        WaitForSingleObject(wait_handle, INFINITE);
-        CloseHandle(wait_handle);
-    }
-    return hook_thread_id != 0;
+static void dinput_thread_stop(void)
+{
+    PostThreadMessageW( dinput_thread_id, WM_USER + 0x10, 0, 0 );
+    WaitForSingleObject( dinput_thread, INFINITE );
+    CloseHandle( dinput_thread );
 }
 
 void check_dinput_hooks( IDirectInputDevice8W *iface, BOOL acquired )
@@ -1418,6 +1385,8 @@ void check_dinput_hooks( IDirectInputDevice8W *iface, BOOL acquired )
     struct dinput_device *impl = impl_from_IDirectInputDevice8W( iface );
     HANDLE hook_change_finished_event = NULL;
 
+    dinput_thread_start();
+
     EnterCriticalSection(&dinput_hook_crit);
 
     if (impl->dwCoopLevel & DISCL_FOREGROUND)
@@ -1437,13 +1406,6 @@ void check_dinput_hooks( IDirectInputDevice8W *iface, BOOL acquired )
         callwndproc_hook = NULL;
     }
 
-    if (hook_thread_event) /* if thread is not started yet */
-    {
-        WaitForSingleObject(hook_thread_event, INFINITE);
-        CloseHandle(hook_thread_event);
-        hook_thread_event = NULL;
-    }
-
     if (impl->use_raw_input)
     {
         if (acquired)
@@ -1470,7 +1432,7 @@ void check_dinput_hooks( IDirectInputDevice8W *iface, BOOL acquired )
     }
 
     hook_change_finished_event = CreateEventW( NULL, FALSE, FALSE, NULL );
-    PostThreadMessageW( hook_thread_id, WM_USER+0x10, 1, (LPARAM)hook_change_finished_event );
+    PostThreadMessageW( dinput_thread_id, WM_USER + 0x10, 1, (LPARAM)hook_change_finished_event );
 
     LeaveCriticalSection(&dinput_hook_crit);
 
@@ -1505,6 +1467,7 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved)
         break;
       case DLL_PROCESS_DETACH:
         if (reserved) break;
+        dinput_thread_stop();
         unregister_di_em_win_class();
         DeleteCriticalSection(&dinput_hook_crit);
         break;
diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h
index c25fe6320ca..4b36a69c0e1 100644
--- a/dlls/dinput/dinput_private.h
+++ b/dlls/dinput/dinput_private.h
@@ -40,10 +40,7 @@ struct IDirectInputImpl
     IDirectInputJoyConfig8      IDirectInputJoyConfig8_iface;
 
     LONG                        ref;
-
     BOOL                        initialized;
-    struct list                 entry;          /* entry into list of all IDirectInputs */
-
     DWORD                       evsequence;     /* unique sequence number for events */
     DWORD                       dwVersion;      /* direct input version number */
     struct list                 device_players; /* device instance guid to player name */




More information about the wine-cvs mailing list