Piotr Pawlow : wined3d: Use a separate mutex for wndproc_table access.

Alexandre Julliard julliard at winehq.org
Tue Jun 21 12:25:41 CDT 2011


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

Author: Piotr Pawlow <pp at siedziba.pl>
Date:   Fri Jun 17 21:49:38 2011 +0200

wined3d: Use a separate mutex for wndproc_table access.

If CreateDevice is called with hFocusWindow belonging to another thread,
then any code that does SendMessage (or equivalent) to the window while
holding the main wined3d mutex causes a deadlock, because wined3d_wndproc
tries to acquire the same mutex for wndproc_table access.

---

 dlls/wined3d/wined3d_main.c |   44 +++++++++++++++++++++++++++++++-----------
 1 files changed, 32 insertions(+), 12 deletions(-)

diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c
index 4f7b1cb..ad3643d 100644
--- a/dlls/wined3d/wined3d_main.c
+++ b/dlls/wined3d/wined3d_main.c
@@ -60,6 +60,16 @@ static CRITICAL_SECTION_DEBUG wined3d_cs_debug =
 };
 static CRITICAL_SECTION wined3d_cs = {&wined3d_cs_debug, -1, 0, 0, 0, 0};
 
+static CRITICAL_SECTION wined3d_wndproc_cs;
+static CRITICAL_SECTION_DEBUG wined3d_wndproc_cs_debug =
+{
+    0, 0, &wined3d_wndproc_cs,
+    {&wined3d_wndproc_cs_debug.ProcessLocksList,
+    &wined3d_wndproc_cs_debug.ProcessLocksList},
+    0, 0, {(DWORD_PTR)(__FILE__ ": wined3d_wndproc_cs")}
+};
+static CRITICAL_SECTION wined3d_wndproc_cs = {&wined3d_wndproc_cs_debug, -1, 0, 0, 0, 0};
+
 /* When updating default value here, make sure to update winecfg as well,
  * where appropriate. */
 struct wined3d_settings wined3d_settings =
@@ -381,6 +391,16 @@ void WINAPI wined3d_mutex_unlock(void)
     LeaveCriticalSection(&wined3d_cs);
 }
 
+static void wined3d_wndproc_mutex_lock(void)
+{
+    EnterCriticalSection(&wined3d_wndproc_cs);
+}
+
+static void wined3d_wndproc_mutex_unlock(void)
+{
+    LeaveCriticalSection(&wined3d_wndproc_cs);
+}
+
 static struct wined3d_wndproc *wined3d_find_wndproc(HWND window)
 {
     unsigned int i;
@@ -403,12 +423,12 @@ static LRESULT CALLBACK wined3d_wndproc(HWND window, UINT message, WPARAM wparam
     BOOL unicode;
     WNDPROC proc;
 
-    wined3d_mutex_lock();
+    wined3d_wndproc_mutex_lock();
     entry = wined3d_find_wndproc(window);
 
     if (!entry)
     {
-        wined3d_mutex_unlock();
+        wined3d_wndproc_mutex_unlock();
         ERR("Window %p is not registered with wined3d.\n", window);
         return DefWindowProcW(window, message, wparam, lparam);
     }
@@ -416,7 +436,7 @@ static LRESULT CALLBACK wined3d_wndproc(HWND window, UINT message, WPARAM wparam
     device = entry->device;
     unicode = entry->unicode;
     proc = entry->proc;
-    wined3d_mutex_unlock();
+    wined3d_wndproc_mutex_unlock();
 
     return device_process_message(device, window, unicode, message, wparam, lparam, proc);
 }
@@ -425,11 +445,11 @@ BOOL wined3d_register_window(HWND window, struct wined3d_device *device)
 {
     struct wined3d_wndproc *entry;
 
-    wined3d_mutex_lock();
+    wined3d_wndproc_mutex_lock();
 
     if (wined3d_find_wndproc(window))
     {
-        wined3d_mutex_unlock();
+        wined3d_wndproc_mutex_unlock();
         WARN("Window %p is already registered with wined3d.\n", window);
         return TRUE;
     }
@@ -444,7 +464,7 @@ BOOL wined3d_register_window(HWND window, struct wined3d_device *device)
 
         if (!new_entries)
         {
-            wined3d_mutex_unlock();
+            wined3d_wndproc_mutex_unlock();
             ERR("Failed to grow table.\n");
             return FALSE;
         }
@@ -465,7 +485,7 @@ BOOL wined3d_register_window(HWND window, struct wined3d_device *device)
         entry->proc = (WNDPROC)SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR)wined3d_wndproc);
     entry->device = device;
 
-    wined3d_mutex_unlock();
+    wined3d_wndproc_mutex_unlock();
 
     return TRUE;
 }
@@ -475,11 +495,11 @@ void wined3d_unregister_window(HWND window)
     struct wined3d_wndproc *entry, *last;
     LONG_PTR proc;
 
-    wined3d_mutex_lock();
+    wined3d_wndproc_mutex_lock();
 
     if (!(entry = wined3d_find_wndproc(window)))
     {
-        wined3d_mutex_unlock();
+        wined3d_wndproc_mutex_unlock();
         ERR("Window %p is not registered with wined3d.\n", window);
         return;
     }
@@ -489,7 +509,7 @@ void wined3d_unregister_window(HWND window)
         proc = GetWindowLongPtrW(window, GWLP_WNDPROC);
         if (proc != (LONG_PTR)wined3d_wndproc)
         {
-            wined3d_mutex_unlock();
+            wined3d_wndproc_mutex_unlock();
             WARN("Not unregistering window %p, window proc %#lx doesn't match wined3d window proc %p.\n",
                     window, proc, wined3d_wndproc);
             return;
@@ -502,7 +522,7 @@ void wined3d_unregister_window(HWND window)
         proc = GetWindowLongPtrA(window, GWLP_WNDPROC);
         if (proc != (LONG_PTR)wined3d_wndproc)
         {
-            wined3d_mutex_unlock();
+            wined3d_wndproc_mutex_unlock();
             WARN("Not unregistering window %p, window proc %#lx doesn't match wined3d window proc %p.\n",
                     window, proc, wined3d_wndproc);
             return;
@@ -514,7 +534,7 @@ void wined3d_unregister_window(HWND window)
     last = &wndproc_table.entries[--wndproc_table.count];
     if (entry != last) *entry = *last;
 
-    wined3d_mutex_unlock();
+    wined3d_wndproc_mutex_unlock();
 }
 
 /* At process attach */




More information about the wine-cvs mailing list