[PATCH 12/22] ntdll: Change global cached_modref atomically.

Paul Gofman pgofman at codeweavers.com
Fri Oct 1 13:20:57 CDT 2021


Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 dlls/ntdll/loader.c | 59 +++++++++++++++++++++++++++++----------------
 1 file changed, 38 insertions(+), 21 deletions(-)

diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 9397c927c3e..a8222ec30df 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -206,7 +206,9 @@ static RTL_SRWLOCK ldr_data_srw_lock;
 static RTL_BITMAP tls_bitmap;
 static RTL_BITMAP tls_expansion_bitmap;
 
-static WINE_MODREF *cached_modref;
+static WINE_MODREF * volatile cached_modref;
+
+/* Used with exclusive loader lock only. */
 static WINE_MODREF *current_modref;
 static WINE_MODREF *last_failed_modref;
 
@@ -470,6 +472,26 @@ static void lock_loader_restore_exclusive(void)
     locked_exclusive = TRUE;
 }
 
+/*************************************************************************
+ *		get_cached_modref
+ *
+ */
+static WINE_MODREF *get_cached_modref(void)
+{
+    return cached_modref;
+}
+
+/*************************************************************************
+ *		put_cached_modref
+ *
+ * Returns the new argument regardless of whether it was actually cached or not.
+ */
+static WINE_MODREF *put_cached_modref( WINE_MODREF *old, WINE_MODREF *new )
+{
+    InterlockedCompareExchangePointer( (void **)&cached_modref, new, old );
+    return new;
+}
+
 #define RTL_UNLOAD_EVENT_TRACE_NUMBER 64
 
 typedef struct _RTL_UNLOAD_EVENT_TRACE
@@ -753,17 +775,18 @@ static void call_ldr_notifications( ULONG reason, LDR_DATA_TABLE_ENTRY *module )
  */
 static WINE_MODREF *get_modref( HMODULE hmod )
 {
+    WINE_MODREF *cached = get_cached_modref();
     PLIST_ENTRY mark, entry;
     PLDR_DATA_TABLE_ENTRY mod;
 
-    if (cached_modref && cached_modref->ldr.DllBase == hmod) return cached_modref;
+    if (cached && cached->ldr.DllBase == hmod) return cached;
 
     mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
     {
         mod = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
         if (mod->DllBase == hmod)
-            return cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
+            return put_cached_modref( cached, CONTAINING_RECORD(mod, WINE_MODREF, ldr) );
     }
     return NULL;
 }
@@ -777,23 +800,21 @@ static WINE_MODREF *get_modref( HMODULE hmod )
  */
 static WINE_MODREF *find_basename_module( LPCWSTR name )
 {
+    WINE_MODREF *cached = get_cached_modref();
     PLIST_ENTRY mark, entry;
     UNICODE_STRING name_str;
 
     RtlInitUnicodeString( &name_str, name );
 
-    if (cached_modref && RtlEqualUnicodeString( &name_str, &cached_modref->ldr.BaseDllName, TRUE ))
-        return cached_modref;
+    if (cached && RtlEqualUnicodeString( &name_str, &cached->ldr.BaseDllName, TRUE ))
+        return cached;
 
     mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
     {
         LDR_DATA_TABLE_ENTRY *mod = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
         if (RtlEqualUnicodeString( &name_str, &mod->BaseDllName, TRUE ))
-        {
-            cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
-            return cached_modref;
-        }
+            return put_cached_modref( cached, CONTAINING_RECORD(mod, WINE_MODREF, ldr) );
     }
     return NULL;
 }
@@ -807,6 +828,7 @@ static WINE_MODREF *find_basename_module( LPCWSTR name )
  */
 static WINE_MODREF *find_fullname_module( const UNICODE_STRING *nt_name )
 {
+    WINE_MODREF *cached = get_cached_modref();
     PLIST_ENTRY mark, entry;
     UNICODE_STRING name = *nt_name;
 
@@ -814,18 +836,15 @@ static WINE_MODREF *find_fullname_module( const UNICODE_STRING *nt_name )
     name.Length -= 4 * sizeof(WCHAR);  /* for \??\ prefix */
     name.Buffer += 4;
 
-    if (cached_modref && RtlEqualUnicodeString( &name, &cached_modref->ldr.FullDllName, TRUE ))
-        return cached_modref;
+    if (cached && RtlEqualUnicodeString( &name, &cached->ldr.FullDllName, TRUE ))
+        return cached;
 
     mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
     {
         LDR_DATA_TABLE_ENTRY *mod = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
         if (RtlEqualUnicodeString( &name, &mod->FullDllName, TRUE ))
-        {
-            cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
-            return cached_modref;
-        }
+            return put_cached_modref( cached, CONTAINING_RECORD(mod, WINE_MODREF, ldr) );
     }
     return NULL;
 }
@@ -839,9 +858,10 @@ static WINE_MODREF *find_fullname_module( const UNICODE_STRING *nt_name )
  */
 static WINE_MODREF *find_fileid_module( const struct file_id *id )
 {
+    WINE_MODREF *cached = get_cached_modref();
     LIST_ENTRY *mark, *entry;
 
-    if (cached_modref && !memcmp( &cached_modref->id, id, sizeof(*id) )) return cached_modref;
+    if (cached && !memcmp( &cached->id, id, sizeof(*id) )) return cached;
 
     mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
@@ -850,10 +870,7 @@ static WINE_MODREF *find_fileid_module( const struct file_id *id )
         WINE_MODREF *wm = CONTAINING_RECORD( mod, WINE_MODREF, ldr );
 
         if (!memcmp( &wm->id, id, sizeof(*id) ))
-        {
-            cached_modref = wm;
-            return wm;
-        }
+            return put_cached_modref( cached, wm );
     }
     return NULL;
 }
@@ -3821,7 +3838,7 @@ static void free_modref( WINE_MODREF *wm )
     free_tls_slot( &wm->ldr );
     RtlReleaseActivationContext( wm->ldr.ActivationContext );
     NtUnmapViewOfSection( NtCurrentProcess(), wm->ldr.DllBase );
-    if (cached_modref == wm) cached_modref = NULL;
+    if (get_cached_modref() == wm) put_cached_modref( wm, NULL );
     RtlFreeUnicodeString( &wm->ldr.FullDllName );
     RtlFreeHeap( GetProcessHeap(), 0, wm->deps );
     RtlFreeHeap( GetProcessHeap(), 0, wm );
-- 
2.31.1




More information about the wine-devel mailing list