Changeset 3915


Ignore:
Timestamp:
Oct 24, 2014, 8:27:59 PM (10 years ago)
Author:
bird
Message:

0.6/locale.c: Rewrote the locale commiting code to not temporarily leave members with invalid NULL pointers and to prefer old string allocations if the value didn't change. Also, postpone the freeing of old locale resources till we're done comitting all. This effort is to reduce potential trouble with setlocale() being called on one thread while another is using it, however, this is not claiming to fix these kind of issues.

Files:
2 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified branches/libc-0.6/src/emx/src/lib/locale/setlocale.c

    r3788 r3915  
    8484#define CODEPAGE_MAX_LENGTH     64
    8585
     86/** Macro for swapping generic struct field. */
     87#define SWAP_SIMPLE_MEMBERS(a_pHot, a_pCold, a_Type, a_Member) \
     88    do { \
     89        a_Type const Tmp    = (a_pHot)->a_Member; \
     90        (a_pHot)->a_Member  = (a_pCold)->a_Member; \
     91        (a_pCold)->a_Member = Tmp; \
     92    } while (0)
     93
     94/** Macro for swapping a string pointer if the new value differs or differs in
     95 *  it's readonlyness. */
     96#define MAYBE_SWAP_STRING_MEMBERS(a_pHot, a_pCold, a_Member, a_fOverride) \
     97    do { \
     98        char *pszTmp = (a_pHot)->a_Member; \
     99        if ((a_fOverride) || strcmp(pszTmp, (a_pCold)->a_Member) != 0) \
     100        { \
     101            (a_pHot)->a_Member  = (a_pCold)->a_Member; \
     102            (a_pCold)->a_Member = pszTmp; \
     103        } \
     104    } while (0)
     105
     106/** Macro for swapping a fixed array of string pointer if the new value differs
     107 *  or differs in it's readonlyness. */
     108#define MAYBE_SWAP_STRING_ARRAY_MEMBERS(a_pHot, a_pCold, a_apszMember, a_fOverride) \
     109    do { \
     110        unsigned iMember = sizeof((a_pHot)->a_apszMember) / sizeof((a_pHot)->a_apszMember[0]); \
     111        while (iMember-- > 0) \
     112            MAYBE_SWAP_STRING_MEMBERS(a_pHot, a_pCold, a_apszMember[iMember], a_fOverride); \
     113    } while (0)
     114
     115
    86116/*******************************************************************************
    87117*   Structures and Typedefs                                                    *
     
    482512
    483513    return 0;
     514}
     515
     516/**
     517 * Swaps the content of two locale collate structures.
     518 *
     519 * @param   pHot        The hot structure (target).
     520 * @param   pCold       The cold structure (source, will be freed).
     521 */
     522static void localeCollateSwap(__LIBC_LOCALECOLLATE *pHot, __LIBC_PLOCALECOLLATE pCold)
     523{
     524    __LIBC_LOCALECOLLATE Tmp;
     525    memcpy(&Tmp, pHot, sizeof(Tmp));
     526    memcpy(pHot, pCold, sizeof(Tmp));
     527    memcpy(pCold, &Tmp, sizeof(Tmp));
    484528}
    485529
     
    721765}
    722766
     767/**
     768 * Swaps the content of two locale Ctype structures.
     769 *
     770 * @param   pHot        The hot structure (target).
     771 * @param   pCold       The cold structure (source, will be freed).
     772 */
     773static void localeCtypeSwap(__LIBC_LOCALECTYPE *pHot, __LIBC_PLOCALECTYPE pCold)
     774{
     775    __LIBC_LOCALECTYPE Tmp;
     776    memcpy(&Tmp, pHot, sizeof(Tmp));
     777    memcpy(pHot, pCold, sizeof(Tmp));
     778    memcpy(pCold, &Tmp, sizeof(Tmp));
     779}
    723780
    724781/**
     
    841898
    842899/**
     900 * Commits the changed LC_TIME locale attributes.
     901 *
     902 * @param   pHot        The hot structure (target).
     903 * @param   pCold       The cold structure (source, will be freed).
     904 */
     905static void localeTimeCommit(__LIBC_LOCALETIME *pHot, __LIBC_PLOCALETIME pCold)
     906{
     907    int const fOverride = pHot->fConsts != pCold->fConsts;
     908    SWAP_SIMPLE_MEMBERS(pHot, pCold, int, fConsts);
     909    MAYBE_SWAP_STRING_ARRAY_MEMBERS(pHot, pCold, smonths, fOverride);
     910    MAYBE_SWAP_STRING_ARRAY_MEMBERS(pHot, pCold, lmonths, fOverride);
     911    MAYBE_SWAP_STRING_ARRAY_MEMBERS(pHot, pCold, swdays, fOverride);
     912    MAYBE_SWAP_STRING_ARRAY_MEMBERS(pHot, pCold, lwdays, fOverride);
     913    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, date_time_fmt, fOverride);
     914    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, date_fmt, fOverride);
     915    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, time_fmt, fOverride);
     916    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, am, fOverride);
     917    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, pm, fOverride);
     918    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, ampm_fmt, fOverride);
     919    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, era, fOverride);
     920    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, era_date_fmt, fOverride);
     921    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, era_date_time_fmt, fOverride);
     922    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, era_time_fmt, fOverride);
     923    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, alt_digits, fOverride);
     924    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, datesep, fOverride);
     925    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, timesep, fOverride);
     926    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, listsep, fOverride);
     927}
     928
     929/**
    843930 * Frees the CRT resources held up by a time structure.
    844931 * @param   pTime   The time structure.
     
    853940        char **ppsz = (char **)pTime;
    854941        char **ppszEnd = (char **)pTime->fConsts;
    855         while (ppsz < ppszEnd)
     942        while ((uintptr_t)ppsz < (uintptr_t)ppszEnd)
    856943        {
    857944            void *pv = *ppsz;
     
    868955
    869956/**
     957 * Commits the changed LC_NUMERIC locale attributes.
     958 *
     959 * @param   pHot        The hot structure (target).
     960 * @param   pCold       The cold structure (source, will be freed).
     961 */
     962static void localeNumericCommit(__LIBC_LOCALELCONV volatile *pHot, __LIBC_PLOCALELCONV pCold)
     963{
     964    int const fOverride = pHot->fNumericConsts != pCold->fNumericConsts;
     965    SWAP_SIMPLE_MEMBERS(pHot, pCold, int, fNumericConsts);
     966    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, s.decimal_point, fOverride);
     967    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, s.thousands_sep, fOverride);
     968    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, s.grouping, fOverride);
     969}
     970
     971/**
    870972 * Frees all heap strings in the monetary part of the lconv structure.
    871973 * @param   pLconv  What to work on.
     
    880982    pLconv->fNumericConsts = 0;
    881983#undef FREE
     984}
     985
     986/**
     987 * Commits the changed LC_MONETARY locale attributes.
     988 *
     989 * @param   pHot        The hot structure (target).
     990 * @param   pCold       The cold structure (source, will be freed).
     991 */
     992static void localeMonetaryCommit(__LIBC_LOCALELCONV volatile *pHot, __LIBC_PLOCALELCONV pCold)
     993{
     994    int const fOverride = pHot->fMonetaryConsts != pCold->fMonetaryConsts;
     995    SWAP_SIMPLE_MEMBERS(pHot, pCold, int,    fMonetaryConsts);
     996    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold,   s.int_curr_symbol, fOverride);
     997    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold,   s.currency_symbol, fOverride);
     998    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold,   s.mon_decimal_point, fOverride);
     999    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold,   s.mon_thousands_sep, fOverride);
     1000    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold,   s.mon_grouping, fOverride);
     1001    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold,   s.positive_sign, fOverride);
     1002    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold,   s.negative_sign, fOverride);
     1003    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.int_frac_digits);
     1004    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.frac_digits);
     1005    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.p_cs_precedes);
     1006    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.p_sep_by_space);
     1007    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.n_cs_precedes);
     1008    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.n_sep_by_space);
     1009    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.p_sign_posn);
     1010    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.n_sign_posn);
     1011    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.int_p_cs_precedes);
     1012    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.int_n_cs_precedes);
     1013    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.int_p_sep_by_space);
     1014    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.int_n_sep_by_space);
     1015    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.int_p_sign_posn);
     1016    SWAP_SIMPLE_MEMBERS(pHot, pCold, char,   s.int_n_sign_posn);
     1017    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold,   pszCrncyStr, fOverride);
    8821018}
    8831019
     
    10711207
    10721208/**
     1209 * Commits the changed LC_MESSAGES locale attributes.
     1210 *
     1211 * @param   pHot        The hot structure (target).
     1212 * @param   pCold       The cold structure (source, will be freed).
     1213 */
     1214static void localeMessagesCommit(__LIBC_LOCALEMSG *pHot, __LIBC_PLOCALEMSG pCold)
     1215{
     1216    int const fOverride = pHot->fConsts != pCold->fConsts;
     1217    SWAP_SIMPLE_MEMBERS(pHot, pCold, int, fConsts);
     1218    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, pszYesExpr, fOverride);
     1219    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, pszNoExpr, fOverride);
     1220    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, pszYesStr, fOverride);
     1221    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, pszNoStr, fOverride);
     1222}
     1223
     1224/**
    10731225 * Frees all heap strings in the monetary part of the lconv structure.
    10741226 * @param   pLconv  What to work on.
     
    11261278
    11271279    return 0;
     1280}
     1281
     1282
     1283/**
     1284 * Swaps the locate name between two locale instances unless they are equal.
     1285 *
     1286 * @param   pHot        The hot structure (target).
     1287 * @param   pCold       The cold structure (source, will be freed).
     1288 * @param   iCategory   The cateogry which name shall be swapped.
     1289 */
     1290static void localeGlobalNameCommit(__LIBC_LOCALEGLOBAL volatile *pHot, __LIBC_PLOCALEGLOBAL pCold, int iCategory)
     1291{
     1292    MAYBE_SWAP_STRING_MEMBERS(pHot, pCold, apszNames[iCategory + 1], 0);
    11281293}
    11291294
     
    16441809static char *localeCommit(struct temp_locale *pTemp, int iCategory)
    16451810{
    1646     char   *pszRet;
    1647     char   *pszAll;
    1648     int     cch;
    1649     int     iCat;
     1811    char           *pszRet;
     1812    char           *pszAll;
     1813    int             cch;
     1814    int             iCat;
    16501815
    16511816    /*
     
    16551820
    16561821    /*
    1657      * Copy all the data.
     1822     * Swap all the data (caller frees the old data).
    16581823     */
    16591824    if (pTemp->afProcessed[LC_COLLATE + 1])
    16601825    {
    1661         localeCollateFree(&__libc_gLocaleCollate);
    1662         memcpy(&__libc_gLocaleCollate, &pTemp->Collate, sizeof(__libc_gLocaleCollate));
    1663         pTemp->afProcessed[LC_COLLATE + 1] = 0;
    1664         gLocale.apszNames[LC_COLLATE + 1] = pTemp->Global.apszNames[LC_COLLATE + 1];
     1826        localeCollateSwap(&__libc_gLocaleCollate, &pTemp->Collate);
     1827        localeGlobalNameCommit(&gLocale, &pTemp->Global, LC_COLLATE);
    16651828    }
    16661829
    16671830    if (pTemp->afProcessed[LC_CTYPE + 1])
    16681831    {
    1669         localeCtypeFree(&__libc_GLocaleCtype);
    1670         memcpy(&__libc_GLocaleCtype, &pTemp->Ctype, sizeof(__libc_GLocaleCtype));
    16711832        MB_CUR_MAX = pTemp->Ctype.mbcs ? pTemp->Ctype.mbcs : 1;
    16721833        if (    IS_C_LOCALE(pTemp->Global.apszNames[LC_CTYPE + 1])
     
    16751836        else
    16761837            __libc_GLocaleWCtype.uMask = ~0xffU;
    1677         pTemp->afProcessed[LC_CTYPE + 1] = 0;
    1678         gLocale.apszNames[LC_CTYPE + 1] = pTemp->Global.apszNames[LC_CTYPE + 1];
     1838
     1839        localeCtypeSwap(&__libc_GLocaleCtype, &pTemp->Ctype);
     1840        localeGlobalNameCommit(&gLocale, &pTemp->Global, LC_CTYPE);
    16791841    }
    16801842
    16811843    if (pTemp->afProcessed[LC_TIME + 1])
    16821844    {
    1683         localeTimeFree(&__libc_gLocaleTime);
    1684         memcpy(&__libc_gLocaleTime, &pTemp->Time, sizeof(__libc_gLocaleTime));
    1685         pTemp->afProcessed[LC_TIME + 1] = 0;
    1686         gLocale.apszNames[LC_TIME + 1] = pTemp->Global.apszNames[LC_TIME + 1];
     1845        localeTimeCommit(&__libc_gLocaleTime, &pTemp->Time);
     1846        localeGlobalNameCommit(&gLocale, &pTemp->Global, LC_TIME);
    16871847    }
    16881848
    16891849    if (pTemp->afProcessed[LC_NUMERIC + 1])
    16901850    {
    1691         localeNumericFree(&__libc_gLocaleLconv);
    1692         __libc_gLocaleLconv.fNumericConsts   = pTemp->Lconv.fNumericConsts;
    1693         __libc_gLocaleLconv.s.decimal_point  = pTemp->Lconv.s.decimal_point;
    1694         __libc_gLocaleLconv.s.thousands_sep  = pTemp->Lconv.s.thousands_sep;
    1695         __libc_gLocaleLconv.s.grouping       = pTemp->Lconv.s.grouping;
    1696         pTemp->afProcessed[LC_NUMERIC + 1] = 0;
    1697         gLocale.apszNames[LC_NUMERIC + 1] = pTemp->Global.apszNames[LC_NUMERIC + 1];
     1851        localeNumericCommit(&__libc_gLocaleLconv, &pTemp->Lconv);
     1852        localeGlobalNameCommit(&gLocale, &pTemp->Global, LC_NUMERIC);
    16981853    }
    16991854
    17001855    if (pTemp->afProcessed[LC_MONETARY + 1])
    17011856    {
    1702         localeMonetaryFree(&__libc_gLocaleLconv);
    1703         __libc_gLocaleLconv.fMonetaryConsts      = pTemp->Lconv.fMonetaryConsts;
    1704         __libc_gLocaleLconv.s.int_curr_symbol    = pTemp->Lconv.s.int_curr_symbol;
    1705         __libc_gLocaleLconv.s.currency_symbol    = pTemp->Lconv.s.currency_symbol;
    1706         __libc_gLocaleLconv.s.mon_decimal_point  = pTemp->Lconv.s.mon_decimal_point;
    1707         __libc_gLocaleLconv.s.mon_thousands_sep  = pTemp->Lconv.s.mon_thousands_sep;
    1708         __libc_gLocaleLconv.s.mon_grouping       = pTemp->Lconv.s.mon_grouping;
    1709         __libc_gLocaleLconv.s.positive_sign      = pTemp->Lconv.s.positive_sign;
    1710         __libc_gLocaleLconv.s.negative_sign      = pTemp->Lconv.s.negative_sign;
    1711         __libc_gLocaleLconv.s.int_frac_digits    = pTemp->Lconv.s.int_frac_digits;
    1712         __libc_gLocaleLconv.s.frac_digits        = pTemp->Lconv.s.frac_digits;
    1713         __libc_gLocaleLconv.s.p_cs_precedes      = pTemp->Lconv.s.p_cs_precedes;
    1714         __libc_gLocaleLconv.s.p_sep_by_space     = pTemp->Lconv.s.p_sep_by_space;
    1715         __libc_gLocaleLconv.s.n_cs_precedes      = pTemp->Lconv.s.n_cs_precedes;
    1716         __libc_gLocaleLconv.s.n_sep_by_space     = pTemp->Lconv.s.n_sep_by_space;
    1717         __libc_gLocaleLconv.s.p_sign_posn        = pTemp->Lconv.s.p_sign_posn;
    1718         __libc_gLocaleLconv.s.n_sign_posn        = pTemp->Lconv.s.n_sign_posn;
    1719         __libc_gLocaleLconv.s.int_p_cs_precedes  = pTemp->Lconv.s.int_p_cs_precedes;
    1720         __libc_gLocaleLconv.s.int_n_cs_precedes  = pTemp->Lconv.s.int_n_cs_precedes;
    1721         __libc_gLocaleLconv.s.int_p_sep_by_space = pTemp->Lconv.s.int_p_sep_by_space;
    1722         __libc_gLocaleLconv.s.int_n_sep_by_space = pTemp->Lconv.s.int_n_sep_by_space;
    1723         __libc_gLocaleLconv.s.int_p_sign_posn    = pTemp->Lconv.s.int_p_sign_posn;
    1724         __libc_gLocaleLconv.s.int_n_sign_posn    = pTemp->Lconv.s.int_n_sign_posn;
    1725         __libc_gLocaleLconv.pszCrncyStr          = pTemp->Lconv.pszCrncyStr;
    1726         pTemp->afProcessed[LC_MONETARY + 1] = 0;
    1727         gLocale.apszNames[LC_MONETARY + 1] = pTemp->Global.apszNames[LC_MONETARY + 1];
     1857        localeMonetaryCommit(&__libc_gLocaleLconv, &pTemp->Lconv);
     1858        localeGlobalNameCommit(&gLocale, &pTemp->Global, LC_MONETARY);
    17281859    }
    17291860    if (pTemp->afProcessed[LC_MESSAGES + 1])
    17301861    {
    1731         localeMessagesFree(&__libc_gLocaleMsg);
    1732         memcpy(&__libc_gLocaleMsg, &pTemp->Msg, sizeof(__libc_gLocaleMsg));
    1733         pTemp->afProcessed[LC_MESSAGES + 1] = 0;
    1734         gLocale.apszNames[LC_MESSAGES + 1] = pTemp->Global.apszNames[LC_MESSAGES + 1];
    1735     }
    1736 
     1862        localeMessagesCommit(&__libc_gLocaleMsg, &pTemp->Msg);
     1863        localeGlobalNameCommit(&gLocale, &pTemp->Global, LC_MESSAGES);
     1864    }
    17371865
    17381866    /*
     
    17701898        }
    17711899        *psz = '\0';
    1772         localeGlobalFree(&gLocale, LC_ALL);
    1773         gLocale.apszNames[LC_ALL + 1] = pszAll;
     1900        pTemp->Global.apszNames[LC_ALL + 1] = pszAll;
     1901        localeGlobalNameCommit(&gLocale, &pTemp->Global, LC_ALL);
    17741902    }
    17751903    else if (strcmp(gLocale.apszNames[LC_ALL + 1], pszAll))
    17761904    {
    1777         localeGlobalFree(&gLocale, LC_ALL);
     1905        pTemp->Global.apszNames[LC_ALL + 1] = gLocale.apszNames[LC_ALL + 1];
    17781906        gLocale.apszNames[LC_ALL + 1] = strdup(pszAll);
    17791907    }
     
    18081936    if (pTemp->afProcessed[LC_MESSAGES + 1])
    18091937        localeMessagesFree(&pTemp->Msg);
     1938    localeGlobalFree(&pTemp->Global, LC_ALL);
    18101939    for (iCat = 0; iCat < _LC_LAST; iCat++)
    18111940        if (pTemp->afProcessed[iCat + 1])
     
    18161945/**
    18171946 * This setlocale() implementation differs from the specs in that any
    1818  * options specified by '@...' other than EURO/euro is ignored.
     1947 * options specified by '@...' other than EURO/euro are ignored.
    18191948 */
    18201949char *_STD(setlocale)(int iCategory, const char *pszLocale)
  • TabularUnified trunk/libc/tests/libc/smoketests/setlocale-1.c

    r3897 r3915  
    6161{
    6262    char   *psz1;
     63    char   *psz1Copy;
    6364    char   *psz2;
    6465    int     rc = 0;
     
    6667    setlocale(LC_ALL, "en_US");
    6768    psz1 = setlocale(LC_CTYPE, "de_DE");
     69    psz1Copy = psz1 ? strdup(psz1) : NULL;
     70
    6871    psz2 = setlocale(LC_CTYPE, "de_DE");
    69     if (psz1 && psz2 && !strcmp(psz1, psz2))
    70         printf("2nd setlocale returns the same. %s errno=%d\n", psz1, errno);
     72    if (psz1 == psz2 && psz2 && !strcmp(psz1Copy, psz2))
     73        printf("2nd setlocale returns the same pointer, great (%s). errno=%d\n", psz1, errno);
     74    else if (psz1 && psz2 && !strcmp(psz1Copy, psz2))
     75    {
     76#if 1 /* kLibC behaviour */
     77        printf("error: 2nd setlocale returns different points, but same value (%s): %p != %p errno=%d\n",
     78               psz2, psz1, psz2, errno);
     79        rc++;
     80#else
     81        printf("2nd setlocale returns the same value. %s errno=%d\n", psz2, errno);
     82#endif
     83    }
    7184    else
    7285    {
    73         printf("error: 2nd setlocale returns differntly. %s != %s errno=%d\n", psz1, psz2, errno);
     86        printf("error: 2nd setlocale returns differntly. %s != %s (%p, %p) errno=%d\n", psz1, psz2, psz1, psz2, errno);
    7487        rc++;
    7588    }
     89    free(psz1Copy);
    7690
    7791    return rc;
Note: See TracChangeset for help on using the changeset viewer.