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