memzero(&PL_mbrlen_ps, sizeof(PL_mbrlen_ps));
RETVAL = 0;
#else
- LOCALE_LOCK;
+ MBLEN_LOCK;
RETVAL = mblen(NULL, 0);
- LOCALE_UNLOCK;
+ MBLEN_UNLOCK;
#endif
}
else { /* Not resetting state */
#else
/* Locking prevents races, but locales can be switched out
* without locking, so this isn't a cure all */
- LOCALE_LOCK;
+ MBLEN_LOCK;
RETVAL = mblen(string, len);
- LOCALE_UNLOCK;
+ MBLEN_UNLOCK;
#endif
}
}
memzero(&PL_mbrtowc_ps, sizeof(PL_mbrtowc_ps));
RETVAL = 0;
#else
- LOCALE_LOCK;
+ MBTOWC_LOCK;
RETVAL = mbtowc(NULL, NULL, 0);
- LOCALE_UNLOCK;
+ MBTOWC_UNLOCK;
#endif
}
else { /* Not resetting state */
#else
/* Locking prevents races, but locales can be switched out
* without locking, so this isn't a cure all */
- LOCALE_LOCK;
+ MBTOWC_LOCK;
RETVAL = mbtowc(&wc, string, len);
- LOCALE_UNLOCK;
+ MBTOWC_UNLOCK;
#endif
if (RETVAL >= 0) {
sv_setiv_mg(pwc, wc);
* But probably memzero would too */
RETVAL = wcrtomb(NULL, L'\0', &PL_wcrtomb_ps);
#else
- LOCALE_LOCK;
+ WCTOMB_LOCK;
RETVAL = wctomb(NULL, L'\0');
- LOCALE_UNLOCK;
+ WCTOMB_UNLOCK;
#endif
}
else { /* Not resetting state */
#else
/* Locking prevents races, but locales can be switched out without
* locking, so this isn't a cure all */
- LOCALE_LOCK;
+ WCTOMB_LOCK;
RETVAL = wctomb(buffer, wchar);
- LOCALE_UNLOCK;
+ WCTOMB_UNLOCK;
#endif
if (RETVAL >= 0) {
sv_setpvn_mg(s, buffer, RETVAL);
* correct locale for that thread. Any operation that was locale-sensitive
* would have to be changed so that it would look like this:
*
- * LOCALE_LOCK;
+ * SETLOCALE_LOCK;
* setlocale to the correct locale for this operation
* do operation
- * LOCALE_UNLOCK
+ * SETLOCALE_UNLOCK
*
* This leaves the global locale in the most recently used operation's, but it
* was locked long enough to get the result. If that result is static, it
/* It might be that this is called from an already-locked section of code.
* We would have to detect and skip the LOCK/UNLOCK if so */
- LOCALE_LOCK;
+ SETLOCALE_LOCK;
curlocales[index] = savepv(my_setlocale(category, new_locale));
#endif
- LOCALE_UNLOCK;
+ SETLOCALE_UNLOCK;
return curlocales[index];
}
STORE_LC_NUMERIC_FORCE_TO_UNDERLYING();
}
- LOCALE_LOCK; /* Prevent interference from another thread executing
- this code section (the only call to nl_langinfo in
- the core) */
-
+ /* Prevent interference from another thread executing this code
+ * section. */
+ NL_LANGINFO_LOCK;
/* Copy to a per-thread buffer, which is also one that won't be
* destroyed by a subsequent setlocale(), such as the
* RESTORE_LC_NUMERIC may do just below. */
retval = save_to_buffer(nl_langinfo(item),
&PL_langinfo_buf, &PL_langinfo_bufsize, 0);
-
- LOCALE_UNLOCK;
+ NL_LANGINFO_UNLOCK;
if (toggle) {
RESTORE_LC_NUMERIC();
case MON_5: case MON_6: case MON_7: case MON_8:
case MON_9: case MON_10: case MON_11: case MON_12:
- LOCALE_LOCK;
+ LOCALE_LOCK_;
init_tm(&tm); /* Precaution against core dumps */
tm.tm_sec = 30;
tm.tm_mon = 0;
switch (item) {
default:
- LOCALE_UNLOCK;
+ LOCALE_UNLOCK_;
Perl_croak(aTHX_
"panic: %s: %d: switch case: %d problem",
__FILE__, __LINE__, item);
* wday was chosen because its range is all a single digit.
* Things like tm_sec have two digits as the minimum: '00' */
- LOCALE_UNLOCK;
+ LOCALE_UNLOCK_;
retval = PL_langinfo_buf;
# else
- LOCALE_LOCK;
+ MBTOWC_LOCK;
PERL_UNUSED_RESULT(mbtowc(&wc, NULL, 0));/* Reset any shift state */
SETERRNO(0, 0);
len = mbtowc(&wc, STR_WITH_LEN(REPLACEMENT_CHARACTER_UTF8));
SAVE_ERRNO;
- LOCALE_UNLOCK;
+ MBTOWC_UNLOCK;
# endif
* same code at the same time. (On thread-safe perls, the LOCK is a
* no-op.) Since this is the only place in core that changes LC_MESSAGES
* (unless the user has called setlocale(), this works to prevent races. */
- LOCALE_LOCK;
+ SETLOCALE_LOCK;
DEBUG_Lv(PerlIO_printf(Perl_debug_log,
"my_strerror called with errnum %d\n", errnum));
}
}
- LOCALE_UNLOCK;
+ SETLOCALE_UNLOCK;
# endif /* End of doesn't have strerror_l */
# ifdef DEBUGGING
# define LC_NUMERIC_UNLOCK NOOP
# define LOCALECONV_LOCK NOOP
# define LOCALECONV_UNLOCK NOOP
+# define LOCALE_READ_LOCK NOOP
+# define LOCALE_READ_UNLOCK NOOP
+# define MBLEN_LOCK NOOP
+# define MBLEN_UNLOCK NOOP
+# define MBTOWC_LOCK NOOP
+# define MBTOWC_UNLOCK NOOP
+# define NL_LANGINFO_LOCK NOOP
+# define NL_LANGINFO_UNLOCK NOOP
+# define SETLOCALE_LOCK NOOP
+# define SETLOCALE_UNLOCK NOOP
+# define WCTOMB_LOCK NOOP
+# define WCTOMB_UNLOCK NOOP
#else
/* Here, we will need critical sections in locale handling, because one or
* will be called frequently, and the locked interval should be short, and
* modern platforms will have reentrant versions (which don't lock) for
* almost all of them, so khw thinks a single mutex should suffice. */
-# define LOCALE_LOCK \
+# define LOCALE_LOCK_ \
STMT_START { \
DEBUG_Lv(PerlIO_printf(Perl_debug_log, \
"%s: %d: locking locale\n", __FILE__, __LINE__)); \
MUTEX_LOCK(&PL_locale_mutex); \
} STMT_END
-# define LOCALE_UNLOCK \
+# define LOCALE_UNLOCK_ \
STMT_START { \
DEBUG_Lv(PerlIO_printf(Perl_debug_log, \
"%s: %d: unlocking locale\n", __FILE__, __LINE__)); \
MUTEX_UNLOCK(&PL_locale_mutex); \
} STMT_END
-# define LOCALECONV_LOCK LOCALE_LOCK
-# define LOCALECONV_UNLOCK LOCALE_UNLOCK
+ /* We do define a different macro for each case; then if we want to have
+ * separate mutexes for some of them, the only changes needed are here.
+ * Define just the necessary macros. The compiler should then croak if the
+ * #ifdef's in the code are incorrect */
+# if defined(HAS_LOCALECONV) && ( ! defined(HAS_LOCALECONV_L) \
+ || defined(TS_W32_BROKEN_LOCALECONV))
+# define LOCALECONV_LOCK LOCALE_LOCK_
+# define LOCALECONV_UNLOCK LOCALE_UNLOCK_
+# endif
+# if defined(HAS_NL_LANGINFO) && ( ! defined(HAS_THREAD_SAFE_NL_LANGINFO_L) \
+ || ! defined(HAS_POSIX_2008_LOCALE))
+# define NL_LANGINFO_LOCK LOCALE_LOCK_
+# define NL_LANGINFO_UNLOCK LOCALE_UNLOCK_
+# endif
+# if defined(HAS_MBLEN) && ! defined(HAS_MBRLEN)
+# define MBLEN_LOCK LOCALE_LOCK_
+# define MBLEN_UNLOCK LOCALE_UNLOCK_
+# endif
+# if defined(HAS_MBTOWC) && ! defined(HAS_MBRTOWC)
+# define MBTOWC_LOCK LOCALE_LOCK_
+# define MBTOWC_UNLOCK LOCALE_UNLOCK_
+# endif
+# if defined(HAS_WCTOMB) && ! defined(HAS_WCRTOMB)
+# define WCTOMB_LOCK LOCALE_LOCK_
+# define WCTOMB_UNLOCK LOCALE_UNLOCK_
+# endif
# if defined(USE_THREAD_SAFE_LOCALE)
/* On locale thread-safe systems, we don't need these workarounds */
# define LOCALE_TERM_LC_NUMERIC_ NOOP
# define LC_NUMERIC_UNLOCK NOOP
# define LOCALE_INIT_LC_NUMERIC_ NOOP
# define LOCALE_TERM_LC_NUMERIC_ NOOP
+
+ /* There may be instance core where we this is invoked yet should do
+ * nothing. Rather than have #ifdef's around them, define it here */
+# define SETLOCALE_LOCK NOOP
+# define SETLOCALE_UNLOCK NOOP
# else
+# define SETLOCALE_LOCK LOCALE_LOCK_
+# define SETLOCALE_UNLOCK LOCALE_UNLOCK_
/* On platforms without per-thread locales, when another thread can switch
* our locale, we need another mutex to create critical sections where we
* Clang improperly gives warnings for this, if not silenced:
* https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#conditional-locks
*
- * If LC_NUMERIC_LOCK is combined with LOCALE_LOCK, calls to
+ * If LC_NUMERIC_LOCK is combined with one of the LOCKs above, calls to
* that and its corresponding unlock should be contained entirely within
* the locked portion of LC_NUMERIC. Those mutexes should be used only in
* very short sections of code, while LC_NUMERIC_LOCK may span more