Alexandre Julliard : gdi32: Don' t store the display driver in the global list to avoid the need for locking .

Alexandre Julliard julliard at winehq.org
Thu May 6 11:13:21 CDT 2010


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu May  6 13:48:24 2010 +0200

gdi32: Don't store the display driver in the global list to avoid the need for locking.

---

 dlls/gdi32/driver.c |   48 +++++++++++++++++++++++++++---------------------
 1 files changed, 27 insertions(+), 21 deletions(-)

diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c
index bb7af56..f23cdc1 100644
--- a/dlls/gdi32/driver.c
+++ b/dlls/gdi32/driver.c
@@ -209,7 +209,6 @@ static struct graphics_driver *create_driver( HMODULE module )
     }
     else memset( &driver->funcs, 0, sizeof(driver->funcs) );
 
-    list_add_head( &drivers, &driver->entry );
     return driver;
 }
 
@@ -221,6 +220,7 @@ static struct graphics_driver *create_driver( HMODULE module )
  */
 static struct graphics_driver *load_display_driver(void)
 {
+    struct graphics_driver *driver;
     char buffer[MAX_PATH], libname[32], *name, *next;
     HMODULE module = 0;
     HKEY hkey;
@@ -247,13 +247,18 @@ static struct graphics_driver *load_display_driver(void)
         name = next;
     }
 
-    if (!(display_driver = create_driver( module )))
+    if (!(driver = create_driver( module )))
     {
         MESSAGE( "Could not create graphics driver '%s'\n", buffer );
         FreeLibrary( module );
         ExitProcess(1);
     }
-
+    if (InterlockedCompareExchangePointer( (void **)&display_driver, driver, NULL ))
+    {
+        /* somebody beat us to it */
+        FreeLibrary( driver->module );
+        HeapFree( GetProcessHeap(), 0, driver );
+    }
     return display_driver;
 }
 
@@ -264,47 +269,48 @@ static struct graphics_driver *load_display_driver(void)
 const DC_FUNCTIONS *DRIVER_load_driver( LPCWSTR name )
 {
     HMODULE module;
-    struct graphics_driver *driver;
+    struct graphics_driver *driver, *new_driver;
     static const WCHAR displayW[] = { 'd','i','s','p','l','a','y',0 };
     static const WCHAR display1W[] = {'\\','\\','.','\\','D','I','S','P','L','A','Y','1',0};
 
-    EnterCriticalSection( &driver_section );
-
     /* display driver is a special case */
-    if (!strcmpiW( name, displayW ) ||
-        !strcmpiW( name, display1W ))
+    if (!strcmpiW( name, displayW ) || !strcmpiW( name, display1W ))
     {
         driver = load_display_driver();
-        LeaveCriticalSection( &driver_section );
         return &driver->funcs;
     }
-
     if ((module = GetModuleHandleW( name )))
     {
+        if (display_driver && display_driver->module == module) return &display_driver->funcs;
+        EnterCriticalSection( &driver_section );
         LIST_FOR_EACH_ENTRY( driver, &drivers, struct graphics_driver, entry )
         {
-            if (driver->module == module)
-            {
-                LeaveCriticalSection( &driver_section );
-                return &driver->funcs;
-            }
+            if (driver->module == module) goto done;
         }
+        LeaveCriticalSection( &driver_section );
     }
 
-    if (!(module = LoadLibraryW( name )))
+    if (!(module = LoadLibraryW( name ))) return NULL;
+
+    if (!(new_driver = create_driver( module )))
     {
-        LeaveCriticalSection( &driver_section );
+        FreeLibrary( module );
         return NULL;
     }
 
-    if (!(driver = create_driver( module )))
+    /* check if someone else added it in the meantime */
+    EnterCriticalSection( &driver_section );
+    LIST_FOR_EACH_ENTRY( driver, &drivers, struct graphics_driver, entry )
     {
+        if (driver->module != module) continue;
         FreeLibrary( module );
-        LeaveCriticalSection( &driver_section );
-        return NULL;
+        HeapFree( GetProcessHeap(), 0, new_driver );
+        goto done;
     }
-
+    driver = new_driver;
+    list_add_head( &drivers, &driver->entry );
     TRACE( "loaded driver %p for %s\n", driver, debugstr_w(name) );
+done:
     LeaveCriticalSection( &driver_section );
     return &driver->funcs;
 }




More information about the wine-cvs mailing list