Re: PTHREAD_MUTEX_INITIALIZER and constinit

2025年6月15日 10:14:29 -0700

On 2025年6月14日, Jeremy Drake via Cygwin wrote:
> Consider the following -std=c++20:
> #include <pthread.h>
>
> constinit pthread_mutex_t foo = PTHREAD_MUTEX_INITIALIZER;
>
> With g++ 12.4.0, this succeeds, but with clang 20.1.6 it fails:
> pthreadtest.cpp:3:27: error: variable does not have a constant initializer
> 3 | constinit pthread_mutex_t foo = PTHREAD_MUTEX_INITIALIZER;
> | ^ ~~~~~~~~~~~~~~~~~~~~~~~~~
> pthreadtest.cpp:3:1: note: required by 'constinit' specifier here
> 3 | constinit pthread_mutex_t foo = PTHREAD_MUTEX_INITIALIZER;
> | ^~~~~~~~~
> pthreadtest.cpp:3:33: note: cast that performs the conversions of a 
> reinterpret_cast is not allowed in a constant expression
> 3 | constinit pthread_mutex_t foo = PTHREAD_MUTEX_INITIALIZER;
> | ^
> /usr/include/pthread.h:49:35: note: expanded from macro 
> 'PTHREAD_MUTEX_INITIALIZER'
> 49 | #define PTHREAD_MUTEX_INITIALIZER PTHREAD_NORMAL_MUTEX_INITIALIZER_NP
> | ^
> /usr/include/pthread.h:47:45: note: expanded from macro 
> 'PTHREAD_NORMAL_MUTEX_INITIALIZER_NP'
> 47 | #define PTHREAD_NORMAL_MUTEX_INITIALIZER_NP (pthread_mutex_t)19
> | ^
> 1 error generated.
>
> It seems the standard disallows this sort of cast pretty comprehensively.
> Is there some way that Cygwin's pthread initializer macros can be made
> compatible with constinit?
I was thinking changing the typedef to be uintptr_t instead of a pointer
would allow constinit initialization to a constant integer, and be the
same ABI-wise, but it would probably change C++ mangled names for
functions taking those types as parameters.
What did work for me, and I'll admit it's pretty gross, is
#include <pthread.h>
#ifdef __i386__
#define SYMPREFIX "_"
#else
#define SYMPREFIX ""
#endif
__asm__( SYMPREFIX "__pthread_normal_mutex_initializer_np=19");
extern "C" struct __pthread_mutex_t __pthread_normal_mutex_initializer_np;
#undef PTHREAD_NORMAL_MUTEX_INITIALIZER_NP
#define PTHREAD_NORMAL_MUTEX_INITIALIZER_NP 
(&__pthread_normal_mutex_initializer_np)
constinit pthread_mutex_t foo = PTHREAD_MUTEX_INITIALIZER;
Basically, hiding the value from the compiler and making it think it is
in fact dealing with a real pointer.
-- 
Problem reports: https://cygwin.com/problems.html
FAQ: https://cygwin.com/faq/
Documentation: https://cygwin.com/docs.html
Unsubscribe info: https://cygwin.com/ml/#unsubscribe-simple

Reply via email to