[PATCH v2 2/8] msvcrt: Share locale names between threadlocinfo instances.

Chip Davis cdavis at codeweavers.com
Fri Jan 31 16:29:57 CST 2020


Signed-off-by: Chip Davis <cdavis at codeweavers.com>
---
v2: Don't share VC11 locale names.
---
 dlls/msvcr90/tests/msvcr90.c | 64 ++++++++++-------------------
 dlls/msvcrt/locale.c         | 79 ++++++++++++++++++++++++++++--------
 2 files changed, 83 insertions(+), 60 deletions(-)

diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c
index f8e68ed2f630..b030c113853f 100644
--- a/dlls/msvcr90/tests/msvcr90.c
+++ b/dlls/msvcr90/tests/msvcr90.c
@@ -2024,15 +2024,11 @@ static void test__get_current_locale(void)
                 "same locale name pointers for LC_COLLATE\n");
         ok(l->locinfo->lc_category[LC_COLLATE].refcount != l2->locinfo->lc_category[LC_COLLATE].refcount,
                 "same refcount pointers for LC_COLLATE\n");
-        ok(l->locinfo->lc_category[LC_COLLATE].refcount, "null refcount pointer for LC_COLLATE\n");
-        if(l->locinfo->lc_category[LC_COLLATE].refcount)
-            ok(*l->locinfo->lc_category[LC_COLLATE].refcount == 1, "refcount = %d\n",
-                    *l->locinfo->lc_category[LC_COLLATE].refcount);
-        ok(l2->locinfo->lc_category[LC_COLLATE].refcount, "null refcount pointer for LC_COLLATE\n");
-        if(l2->locinfo->lc_category[LC_COLLATE].refcount)
-            ok(*l2->locinfo->lc_category[LC_COLLATE].refcount == 2, "refcount = %d\n",
-                    *l2->locinfo->lc_category[LC_COLLATE].refcount);
     }
+    ok(*l->locinfo->lc_category[LC_COLLATE].refcount == 1, "refcount = %d\n",
+            *l->locinfo->lc_category[LC_COLLATE].refcount);
+    todo_wine ok(*l2->locinfo->lc_category[LC_COLLATE].refcount == 2, "refcount = %d\n",
+            *l2->locinfo->lc_category[LC_COLLATE].refcount);
     for(i = LC_CTYPE; i <= LC_MAX; i++) {
         ok(l->locinfo->lc_category[i].locale == l2->locinfo->lc_category[i].locale,
                 "different locale name pointers for category %d\n", i);
@@ -2095,15 +2091,11 @@ static void test__get_current_locale(void)
                     "same locale name pointers for category %d\n", i);
             ok(l->locinfo->lc_category[i].refcount != l2->locinfo->lc_category[i].refcount,
                     "same refcount pointers for category %d\n", i);
-            ok(l->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
-            if(l->locinfo->lc_category[i].refcount)
-                ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n",
-                        *l->locinfo->lc_category[i].refcount, i);
-            ok(l2->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
-            if(l2->locinfo->lc_category[i].refcount)
-                ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n",
-                        *l2->locinfo->lc_category[i].refcount, i);
         }
+        ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n",
+                *l->locinfo->lc_category[i].refcount, i);
+        todo_wine ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n",
+                *l2->locinfo->lc_category[i].refcount, i);
     }
     for(i = LC_MONETARY; i <= LC_MAX; i++) {
         ok(l->locinfo->lc_category[i].locale == l2->locinfo->lc_category[i].locale,
@@ -2174,15 +2166,11 @@ static void test__get_current_locale(void)
                     "same locale name pointers for category %d\n", i);
             ok(l->locinfo->lc_category[i].refcount != l2->locinfo->lc_category[i].refcount,
                     "same refcount pointers for category %d\n", i);
-            ok(l->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
-            if(l->locinfo->lc_category[i].refcount)
-                ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n",
-                        *l->locinfo->lc_category[i].refcount, i);
-            ok(l2->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
-            if(l2->locinfo->lc_category[i].refcount)
-                ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n",
-                        *l2->locinfo->lc_category[i].refcount, i);
         }
+        ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n",
+                *l->locinfo->lc_category[i].refcount, i);
+        todo_wine ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n",
+                *l2->locinfo->lc_category[i].refcount, i);
     }
     for(i = LC_NUMERIC; i <= LC_MAX; i++) {
         ok(l->locinfo->lc_category[i].locale == l2->locinfo->lc_category[i].locale,
@@ -2261,15 +2249,11 @@ static void test__get_current_locale(void)
                     "same locale name pointers for category %d\n", i);
             ok(l->locinfo->lc_category[i].refcount != l2->locinfo->lc_category[i].refcount,
                     "same refcount pointers for category %d\n", i);
-            ok(l->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
-            if(l->locinfo->lc_category[i].refcount)
-                ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n",
-                        *l->locinfo->lc_category[i].refcount, i);
-            ok(l2->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
-            if(l2->locinfo->lc_category[i].refcount)
-                ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n",
-                        *l2->locinfo->lc_category[i].refcount, i);
         }
+        ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n",
+                *l->locinfo->lc_category[i].refcount, i);
+        todo_wine ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n",
+                *l2->locinfo->lc_category[i].refcount, i);
     }
     ok(l->locinfo->lc_category[LC_TIME].locale == l2->locinfo->lc_category[LC_TIME].locale,
             "different locale name pointers for LC_TIME\n");
@@ -2341,21 +2325,17 @@ static void test__get_current_locale(void)
         ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount);
     }
 
-    todo_wine {
-        for(i = LC_MIN+1; i <= LC_MAX; i++) {
+    for(i = LC_MIN+1; i <= LC_MAX; i++) {
+        todo_wine {
             ok(l->locinfo->lc_category[i].locale != l2->locinfo->lc_category[i].locale,
                     "same locale name pointers for category %d\n", i);
             ok(l->locinfo->lc_category[i].refcount != l2->locinfo->lc_category[i].refcount,
                     "same refcount pointers for category %d\n", i);
-            ok(l->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
-            if(l->locinfo->lc_category[i].refcount)
-                ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n",
-                        *l->locinfo->lc_category[i].refcount, i);
-            ok(l2->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i);
-            if(l2->locinfo->lc_category[i].refcount)
-                ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n",
-                        *l2->locinfo->lc_category[i].refcount, i);
         }
+        ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n",
+                *l->locinfo->lc_category[i].refcount, i);
+        todo_wine ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n",
+                *l2->locinfo->lc_category[i].refcount, i);
     }
 
     todo_wine {
diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c
index f6e7631b4f50..df19326586bf 100644
--- a/dlls/msvcrt/locale.c
+++ b/dlls/msvcrt/locale.c
@@ -418,6 +418,15 @@ static BOOL init_category_name(const char *name, int len,
     return TRUE;
 }
 
+/* INTERNAL: Copy lc_handle, lc_id, and lc_category from one threadlocinfo to another */
+static void copy_threadlocinfo_category(MSVCRT_pthreadlocinfo locinfo, MSVCRT_pthreadlocinfo old_locinfo, int category)
+{
+    locinfo->lc_handle[category] = old_locinfo->lc_handle[category];
+    locinfo->lc_id[category] = old_locinfo->lc_id[category];
+    locinfo->lc_category[category] = old_locinfo->lc_category[category];
+    InterlockedIncrement(locinfo->lc_category[category].refcount);
+}
+
 /* INTERNAL: Set lc_handle, lc_id and lc_category in threadlocinfo struct */
 static BOOL update_threadlocinfo_category(LCID lcid, unsigned short cp,
         MSVCRT_pthreadlocinfo locinfo, int category)
@@ -878,11 +887,14 @@ void free_locinfo(MSVCRT_pthreadlocinfo locinfo)
         return;
 
     for(i=MSVCRT_LC_MIN+1; i<=MSVCRT_LC_MAX; i++) {
-        MSVCRT_free(locinfo->lc_category[i].locale);
-        MSVCRT_free(locinfo->lc_category[i].refcount);
 #if _MSVCR_VER >= 110
         MSVCRT_free(locinfo->lc_name[i]);
 #endif
+        if(!locinfo->lc_category[i].refcount
+                || InterlockedDecrement(locinfo->lc_category[i].refcount))
+            continue;
+        MSVCRT_free(locinfo->lc_category[i].locale);
+        MSVCRT_free(locinfo->lc_category[i].refcount);
     }
 
     if(locinfo->lconv) {
@@ -1200,8 +1212,11 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
 
     if(!category_needs_update(MSVCRT_LC_COLLATE, category, old_locinfo,
                 lcid[MSVCRT_LC_COLLATE], cp[MSVCRT_LC_COLLATE])) {
-        locinfo->lc_handle[MSVCRT_LC_COLLATE] = old_locinfo->lc_handle[MSVCRT_LC_COLLATE];
-        locinfo->lc_id[MSVCRT_LC_COLLATE].wCodePage = old_locinfo->lc_id[MSVCRT_LC_COLLATE].wCodePage;
+        copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_COLLATE);
+        if(!set_lc_locale_name(locinfo, MSVCRT_LC_COLLATE)) {
+            free_locinfo(locinfo);
+            return NULL;
+        }
     } else if(lcid[MSVCRT_LC_COLLATE] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_COLLATE)) {
         if(!update_threadlocinfo_category(lcid[MSVCRT_LC_COLLATE],
                     cp[MSVCRT_LC_COLLATE], locinfo, MSVCRT_LC_COLLATE)) {
@@ -1215,8 +1230,12 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
             free_locinfo(locinfo);
             return NULL;
         }
-    } else
-        locinfo->lc_category[MSVCRT_LC_COLLATE].locale = MSVCRT__strdup("C");
+    } else {
+        if(!init_category_name("C", 1, locinfo, MSVCRT_LC_COLLATE)) {
+            free_locinfo(locinfo);
+            return NULL;
+        }
+    }
 
     if(locale_name[MSVCRT_LC_CTYPE] &&
             !init_category_name(locale_name[MSVCRT_LC_CTYPE],
@@ -1227,8 +1246,11 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
 
     if(!category_needs_update(MSVCRT_LC_CTYPE, category, old_locinfo,
                 lcid[MSVCRT_LC_CTYPE], cp[MSVCRT_LC_CTYPE])) {
-        locinfo->lc_handle[MSVCRT_LC_CTYPE] = old_locinfo->lc_handle[MSVCRT_LC_CTYPE];
-        locinfo->lc_id[MSVCRT_LC_CTYPE].wCodePage = old_locinfo->lc_id[MSVCRT_LC_CTYPE].wCodePage;
+        copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_CTYPE);
+        if(!set_lc_locale_name(locinfo, MSVCRT_LC_CTYPE)) {
+            free_locinfo(locinfo);
+            return NULL;
+        }
     } else if(lcid[MSVCRT_LC_CTYPE] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_CTYPE)) {
         CPINFO cp_info;
         int j;
@@ -1293,7 +1315,10 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
         locinfo->lc_clike = 1;
         locinfo->mb_cur_max = 1;
         locinfo->pctype = MSVCRT__ctype+1;
-        locinfo->lc_category[MSVCRT_LC_CTYPE].locale = MSVCRT__strdup("C");
+        if(!init_category_name("C", 1, locinfo, MSVCRT_LC_CTYPE)) {
+            free_locinfo(locinfo);
+            return NULL;
+        }
 
         for(i=0; i<256; i++) {
             if(locinfo->pctype[i] & MSVCRT__LEADBYTE)
@@ -1317,8 +1342,11 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
 
     if(!category_needs_update(MSVCRT_LC_MONETARY, category, old_locinfo,
                 lcid[MSVCRT_LC_MONETARY], cp[MSVCRT_LC_MONETARY])) {
-        locinfo->lc_handle[MSVCRT_LC_MONETARY] = old_locinfo->lc_handle[MSVCRT_LC_MONETARY];
-        locinfo->lc_id[MSVCRT_LC_MONETARY].wCodePage = old_locinfo->lc_id[MSVCRT_LC_MONETARY].wCodePage;
+        copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_MONETARY);
+        if(!set_lc_locale_name(locinfo, MSVCRT_LC_MONETARY)) {
+            free_locinfo(locinfo);
+            return NULL;
+        }
     } else if(lcid[MSVCRT_LC_MONETARY] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_MONETARY)) {
         if(!update_threadlocinfo_category(lcid[MSVCRT_LC_MONETARY],
                     cp[MSVCRT_LC_MONETARY], locinfo, MSVCRT_LC_MONETARY)) {
@@ -1585,7 +1613,10 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
         locinfo->lconv->_W_negative_sign[0] = '\0';
 #endif
 
-        locinfo->lc_category[MSVCRT_LC_MONETARY].locale = MSVCRT__strdup("C");
+        if(!init_category_name("C", 1, locinfo, MSVCRT_LC_MONETARY)) {
+            free_locinfo(locinfo);
+            return NULL;
+        }
     }
 
     if(locale_name[MSVCRT_LC_NUMERIC] &&
@@ -1597,8 +1628,11 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
 
     if(!category_needs_update(MSVCRT_LC_NUMERIC, category, old_locinfo,
                 lcid[MSVCRT_LC_NUMERIC], cp[MSVCRT_LC_NUMERIC])) {
-        locinfo->lc_handle[MSVCRT_LC_NUMERIC] = old_locinfo->lc_handle[MSVCRT_LC_NUMERIC];
-        locinfo->lc_id[MSVCRT_LC_NUMERIC].wCodePage = old_locinfo->lc_id[MSVCRT_LC_NUMERIC].wCodePage;
+        copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_NUMERIC);
+        if(!set_lc_locale_name(locinfo, MSVCRT_LC_NUMERIC)) {
+            free_locinfo(locinfo);
+            return NULL;
+        }
     } else if(lcid[MSVCRT_LC_NUMERIC] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_NUMERIC)) {
         if(!update_threadlocinfo_category(lcid[MSVCRT_LC_NUMERIC],
                     cp[MSVCRT_LC_NUMERIC], locinfo, MSVCRT_LC_NUMERIC)) {
@@ -1703,7 +1737,10 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
         locinfo->lconv->_W_thousands_sep[0] = '\0';
 #endif
 
-        locinfo->lc_category[MSVCRT_LC_NUMERIC].locale = MSVCRT__strdup("C");
+        if (!init_category_name("C", 1, locinfo, MSVCRT_LC_NUMERIC)) {
+            free_locinfo(locinfo);
+            return NULL;
+        }
     }
 
     if(locale_name[MSVCRT_LC_TIME] &&
@@ -1715,8 +1752,11 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
 
     if(!category_needs_update(MSVCRT_LC_TIME, category, old_locinfo,
                 lcid[MSVCRT_LC_TIME], cp[MSVCRT_LC_TIME])) {
-        locinfo->lc_handle[MSVCRT_LC_TIME] = old_locinfo->lc_handle[MSVCRT_LC_TIME];
-        locinfo->lc_id[MSVCRT_LC_TIME].wCodePage = old_locinfo->lc_id[MSVCRT_LC_TIME].wCodePage;
+        copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_TIME);
+        if(!set_lc_locale_name(locinfo, MSVCRT_LC_TIME)) {
+            free_locinfo(locinfo);
+            return NULL;
+        }
     } else if(lcid[MSVCRT_LC_TIME] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_TIME)) {
         if(!update_threadlocinfo_category(lcid[MSVCRT_LC_TIME],
                     cp[MSVCRT_LC_TIME], locinfo, MSVCRT_LC_TIME)) {
@@ -1735,7 +1775,10 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
             return NULL;
         }
     } else {
-        locinfo->lc_category[MSVCRT_LC_TIME].locale = MSVCRT__strdup("C");
+        if(!init_category_name("C", 1, locinfo, MSVCRT_LC_TIME)) {
+            free_locinfo(locinfo);
+            return NULL;
+        }
         locinfo->lc_time_curr = &cloc_time_data;
     }
 
-- 
2.24.0




More information about the wine-devel mailing list