@@ -6372,6 +6372,93 @@ EXTCONST U8 PL_deBruijn_bitpos_tab64[];
6372
6372
# define PERL_SET_THX (t ) NOOP
6373
6373
#endif
6374
6374
6375
+ #ifdef WIN32
6376
+ /* Windows mutexes are all general semaphores; we don't currently bother
6377
+ * with reproducing the same panic behavior as on other systems */
6378
+ # define PERL_REENTRANT_LOCK (name, mutex, counter, \
6379
+ cond_to_panic_if_already_locked) \
6380
+ MUTEX_LOCK (mutex)
6381
+ # define PERL_REENTRANT_UNLOCK (name, mutex, counter ) MUTEX_UNLOCK(mutex)
6382
+ #else
6383
+
6384
+ /* Simulate a general (or recursive) semaphore on 'mutex' whose name will
6385
+ * be displayed as 'name' in any messages. There must be a per-thread
6386
+ * variable 'counter', initialized to 0 upon thread creation that this
6387
+ * macro otherwise controls and keeps set to the recursion depth of the
6388
+ * mutex. 'cond_to_panic_if_already_locked' should be set to '0' for a
6389
+ * fully reentrant semaphore. Otherwise set it to a bit of code which will
6390
+ * be evaluated if the macro is called recursively. If it evaluates to
6391
+ * 'true', it means something is seriously wrong, and the process panics.
6392
+ *
6393
+ * It locks the mutex if the 'counter' is zero, and then increments
6394
+ * 'counter'. Each corresponding UNLOCK decrements 'counter' until it is
6395
+ * 0, at which point it actually unlocks the mutex. Since the variable is
6396
+ * per-thread, initialized to 0, there is no race with other threads.
6397
+ *
6398
+ * Clang improperly gives warnings for this, if not silenced:
6399
+ * https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#conditional-locks
6400
+ */
6401
+ # define PERL_REENTRANT_LOCK (name, mutex, counter, \
6402
+ cond_to_panic_if_already_locked) \
6403
+ STMT_START { \
6404
+ CLANG_DIAG_IGNORE (-Wthread-safety) \
6405
+ if (LIKELY (counter <= 0 )) { \
6406
+ UNLESS_PERL_MEM_LOG (DEBUG_Lv (PerlIO_printf (Perl_debug_log, \
6407
+ " %s: %d: locking " name " ; lock depth=1\n " , \
6408
+ __FILE__, __LINE__)); \
6409
+ ) \
6410
+ MUTEX_LOCK (mutex); \
6411
+ counter = 1 ; \
6412
+ UNLESS_PERL_MEM_LOG (DEBUG_Lv (PerlIO_printf (Perl_debug_log, \
6413
+ " %s: %d: " name " locked; lock depth=1\n " , \
6414
+ __FILE__, __LINE__)); \
6415
+ ) \
6416
+ } \
6417
+ else { \
6418
+ counter++; \
6419
+ UNLESS_PERL_MEM_LOG (DEBUG_Lv (PerlIO_printf (Perl_debug_log, \
6420
+ " %s: %d: avoided locking " name " ; new lock" \
6421
+ " depth=%d, but will panic if '%s' is true\n " , \
6422
+ __FILE__, __LINE__, counter, \
6423
+ STRINGIFY (cond_to_panic_if_already_locked))); \
6424
+ ) \
6425
+ if (cond_to_panic_if_already_locked) { \
6426
+ Perl_croak_nocontext (" panic: %s: %d: attempting to lock" \
6427
+ name " incompatibly: %s\n " , \
6428
+ __FILE__, __LINE__, \
6429
+ STRINGIFY (cond_to_panic_if_already_locked));\
6430
+ } \
6431
+ } \
6432
+ CLANG_DIAG_RESTORE \
6433
+ } STMT_END
6434
+
6435
+ # define PERL_REENTRANT_UNLOCK (name, mutex, counter ) \
6436
+ STMT_START { \
6437
+ if (LIKELY (counter == 1 )) { \
6438
+ UNLESS_PERL_MEM_LOG (DEBUG_Lv (PerlIO_printf (Perl_debug_log, \
6439
+ " %s: %d: unlocking " name " ; new lock depth=0\n " , \
6440
+ __FILE__, __LINE__)); \
6441
+ ) \
6442
+ counter = 0 ; \
6443
+ MUTEX_UNLOCK (mutex); \
6444
+ } \
6445
+ else if (counter <= 0 ) { \
6446
+ Perl_croak_nocontext (" panic: %s: %d: attempting to unlock" \
6447
+ " already unlocked " name " ; depth was" \
6448
+ " %d\n " , __FILE__, __LINE__, \
6449
+ counter); \
6450
+ } \
6451
+ else { \
6452
+ counter--; \
6453
+ UNLESS_PERL_MEM_LOG (DEBUG_Lv (PerlIO_printf (Perl_debug_log, \
6454
+ " %s: %d: avoided unlocking " name " ; new lock depth=%d\n " , \
6455
+ __FILE__, __LINE__, counter)); \
6456
+ ) \
6457
+ } \
6458
+ } STMT_END
6459
+
6460
+ #endif
6461
+
6375
6462
#ifndef EBCDIC
6376
6463
6377
6464
/* The tables below are adapted from
@@ -7067,85 +7154,14 @@ the plain locale pragma without a parameter (S<C<use locale>>) is in effect.
7067
7154
#else /* Below: Threaded, and locales are supported */
7068
7155
7069
7156
/* A locale mutex is required on all such threaded builds. */
7070
- # ifdef WIN32
7157
+ # define LOCALE_LOCK_ (cond_to_panic_if_already_locked ) \
7158
+ PERL_REENTRANT_LOCK (" locale" , \
7159
+ &PL_locale_mutex, PL_locale_mutex_depth, \
7160
+ cond_to_panic_if_already_locked)
7161
+ # define LOCALE_UNLOCK_ \
7162
+ PERL_REENTRANT_UNLOCK (" locale" , \
7163
+ &PL_locale_mutex, PL_locale_mutex_depth)
7071
7164
7072
- /* Windows mutexes are all general semaphores */
7073
- # define LOCALE_LOCK_ (dummy ) MUTEX_LOCK(&PL_locale_mutex)
7074
- # define LOCALE_UNLOCK_ MUTEX_UNLOCK (&PL_locale_mutex)
7075
- # else
7076
-
7077
- /* This mutex simulates a general (or recursive) semaphore. The current
7078
- * thread will lock the mutex if the per-thread variable is zero, and then
7079
- * increments that variable. Each corresponding UNLOCK decrements the
7080
- * variable until it is 0, at which point it actually unlocks the mutex.
7081
- * Since the variable is per-thread, initialized to 0, there is no race
7082
- * with other threads.
7083
- *
7084
- * The single argument is a condition to test for, and if true, to panic.
7085
- * Call it with the constant 0 to suppress the check.
7086
- *
7087
- * Clang improperly gives warnings for this, if not silenced:
7088
- * https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#conditional-locks
7089
- */
7090
- # define LOCALE_LOCK_ (cond_to_panic_if_already_locked ) \
7091
- STMT_START { \
7092
- CLANG_DIAG_IGNORE (-Wthread-safety) \
7093
- if (LIKELY (PL_locale_mutex_depth <= 0 )) { \
7094
- UNLESS_PERL_MEM_LOG (DEBUG_Lv (PerlIO_printf (Perl_debug_log, \
7095
- " %s: %d: locking locale; lock depth=1\n " , \
7096
- __FILE__, __LINE__)); \
7097
- ) \
7098
- MUTEX_LOCK (&PL_locale_mutex); \
7099
- PL_locale_mutex_depth = 1 ; \
7100
- UNLESS_PERL_MEM_LOG (DEBUG_Lv (PerlIO_printf (Perl_debug_log, \
7101
- " %s: %d: locale locked; lock depth=1\n " , \
7102
- __FILE__, __LINE__)); \
7103
- ) \
7104
- } \
7105
- else { \
7106
- PL_locale_mutex_depth++; \
7107
- UNLESS_PERL_MEM_LOG (DEBUG_Lv (PerlIO_printf (Perl_debug_log, \
7108
- " %s: %d: avoided locking locale; new lock" \
7109
- " depth=%d, but will panic if '%s' is true\n " , \
7110
- __FILE__, __LINE__, PL_locale_mutex_depth, \
7111
- STRINGIFY (cond_to_panic_if_already_locked))); \
7112
- ) \
7113
- if (cond_to_panic_if_already_locked) { \
7114
- Perl_croak_nocontext (" panic: %s: %d: Trying to lock" \
7115
- " locale incompatibly: " \
7116
- STRINGIFY (cond_to_panic_if_already_locked)\
7117
- " \n " , __FILE__, __LINE__); \
7118
- } \
7119
- } \
7120
- CLANG_DIAG_RESTORE \
7121
- } STMT_END
7122
-
7123
- # define LOCALE_UNLOCK_ \
7124
- STMT_START { \
7125
- if (LIKELY (PL_locale_mutex_depth == 1 )) { \
7126
- UNLESS_PERL_MEM_LOG (DEBUG_Lv (PerlIO_printf (Perl_debug_log, \
7127
- " %s: %d: unlocking locale; new lock depth=0\n " , \
7128
- __FILE__, __LINE__)); \
7129
- ) \
7130
- PL_locale_mutex_depth = 0 ; \
7131
- MUTEX_UNLOCK (&PL_locale_mutex); \
7132
- } \
7133
- else if (PL_locale_mutex_depth <= 0 ) { \
7134
- Perl_croak_nocontext (" panic: %s: %d: attempting to unlock" \
7135
- " already unlocked locale; depth was" \
7136
- " %d\n " , __FILE__, __LINE__, \
7137
- PL_locale_mutex_depth); \
7138
- } \
7139
- else { \
7140
- PL_locale_mutex_depth--; \
7141
- UNLESS_PERL_MEM_LOG (DEBUG_Lv (PerlIO_printf (Perl_debug_log, \
7142
- " %s: %d: avoided unlocking locale; new lock depth=%d\n " ,\
7143
- __FILE__, __LINE__, PL_locale_mutex_depth)); \
7144
- ) \
7145
- } \
7146
- } STMT_END
7147
-
7148
- # endif
7149
7165
# if defined(USE_THREADS) && ! defined(USE_THREAD_SAFE_LOCALE)
7150
7166
7151
7167
/* By definition, a thread-unsafe locale means we need a critical
0 commit comments