[PATCH 1/5] wined3d: Only take the wined3d mutex during the WM_DISPLAYCHANGE handler in device_process_message().

Henri Verbeet hverbeet at codeweavers.com
Tue Jan 24 14:47:45 CST 2012


We can deadlock if we send messages while holding the wined3d mutex and the
message loop is on another thread. Ideally we probably shouldn't send messages
while holding the wined3d mutex at all, but that may be hard to enforce with
the way wined3d locking is currently set up.
---
 dlls/wined3d/device.c |   16 ++++++----------
 1 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 348ee08..e5f3506 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1198,7 +1198,7 @@ HRESULT CDECL wined3d_device_acquire_focus_window(struct wined3d_device *device,
         return E_FAIL;
     }
 
-    device->focus_window = window;
+    InterlockedExchangePointer((void **)&device->focus_window, window);
     SetWindowPos(window, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
 
     return WINED3D_OK;
@@ -1209,7 +1209,7 @@ void CDECL wined3d_device_release_focus_window(struct wined3d_device *device)
     TRACE("device %p.\n", device);
 
     if (device->focus_window) wined3d_unregister_window(device->focus_window);
-    device->focus_window = NULL;
+    InterlockedExchangePointer((void **)&device->focus_window, NULL);
 }
 
 HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device,
@@ -5890,12 +5890,8 @@ void get_drawable_size_backbuffer(const struct wined3d_context *context, UINT *w
 LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL unicode,
         UINT message, WPARAM wparam, LPARAM lparam, WNDPROC proc)
 {
-    wined3d_mutex_lock();
-
     if (device->filter_messages)
     {
-        wined3d_mutex_unlock();
-
         TRACE("Filtering message: window %p, message %#x, wparam %#lx, lparam %#lx.\n",
                 window, message, wparam, lparam);
         if (unicode)
@@ -5909,16 +5905,16 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL
         TRACE("unregister window %p.\n", window);
         wined3d_unregister_window(window);
 
-        if (device->focus_window == window) device->focus_window = NULL;
-        else ERR("Window %p is not the focus window for device %p.\n", window, device);
+        if (InterlockedCompareExchangePointer((void **)&device->focus_window, NULL, window) != window)
+            ERR("Window %p is not the focus window for device %p.\n", window, device);
     }
     else if (message == WM_DISPLAYCHANGE)
     {
+        wined3d_mutex_lock();
         device->device_parent->ops->mode_changed(device->device_parent);
+        wined3d_mutex_unlock();
     }
 
-    wined3d_mutex_unlock();
-
     if (unicode)
         return CallWindowProcW(proc, window, message, wparam, lparam);
     else
-- 
1.7.3.4




More information about the wine-patches mailing list