From 34e35871651eac526a753c06710cac081848d75f Mon Sep 17 00:00:00 2001 From: Nicholas Clark Date: Sat, 8 Jan 2022 21:08:19 +0000 Subject: PERL_SET_CONTEXT(t) needs to set PL_current_context from C++ too We want to use C11 thread local storage where possible, as its read overhead is lower. However C++ uses incompatible syntax for TLS, so we have to hide the variable from C++ extensions, and have the read code "fall back" to the pthread_getspecific() approach. However, C++ extensions also need to be able to call PERL_SET_CONTEXT(t) and have everything still work the same as C extensions. Hence they *also* need to set PL_current_context - a variable that has to be hidden from them. Hence change the version of the PERL_SET_CONTEXT macro used by C++ extensions from inline code to a call to Perl_set_context(), and have that set PL_current_context (when used). Technically this commit also fixes a bug in that Perl_set_context() is API and should have been setting PL_current_context since that variable was first introduced. In practice, likely nothing uses this API, as there is no code on CPAN that calls it, and the macro PERL_SET_CONTEXT() is much more prominent. --- thread.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'thread.h') diff --git a/thread.h b/thread.h index cfa3287b5c..dd98a43b6d 100644 --- a/thread.h +++ b/thread.h @@ -387,7 +387,9 @@ extern PERL_THREAD_LOCAL void *PL_current_context; # define PERL_GET_CONTEXT PL_current_context -/* Set our thread-specific value anyway, in case code is reading it directly. */ +/* We must also call pthread_setspecific() always, as C++ code has to read it + * with pthreads (the #else side just below) */ + # define PERL_SET_CONTEXT(t) \ STMT_START { \ int _eC_; \ @@ -403,14 +405,14 @@ extern PERL_THREAD_LOCAL void *PL_current_context; # define PERL_GET_CONTEXT PTHREAD_GETSPECIFIC(PL_thr_key) # endif +/* For C++ extensions built on a system where the C compiler provides thread + * local storage that call PERL_SET_CONTEXT() also need to set + * PL_current_context, so need to call into C code to do this. + * To avoid exploding code complexity, do this also on C platforms that don't + * support thread local storage. PERL_SET_CONTEXT is not called that often. */ + # ifndef PERL_SET_CONTEXT -# define PERL_SET_CONTEXT(t) \ - STMT_START { \ - int _eC_; \ - if ((_eC_ = pthread_setspecific(PL_thr_key, (void *)(t)))) \ - Perl_croak_nocontext("panic: pthread_setspecific (%d) [%s:%d]", \ - _eC_, __FILE__, __LINE__); \ - } STMT_END +# define PERL_SET_CONTEXT(t) Perl_set_context((void*)t) # endif /* PERL_SET_CONTEXT */ #endif /* PERL_THREAD_LOCAL */ -- cgit v1.2.1