Module: wine Branch: master Commit: 8dc9e8786b13ac64fa953c1d2d7156fd470e1016 URL: http://source.winehq.org/git/wine.git/?a=commit;h=8dc9e8786b13ac64fa953c1d2d...
Author: Alexandre Julliard julliard@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; }