In order to avoid a restriction on any reinterpret_cast-like behavior in
constinit expressions, use assembly and the linker to define symbols
with the not-valid-address addresses.

Signed-off-by: Jeremy Drake <[email protected]>
---
This is gross, but I couldn't come up with a way to make this both source
and ABI (including C++ name mangling) compatible.  I'd be happy to be
shown a cleaner way.  I built libc++ without a patch to remove constinit,
and I'm working on building gcc/libstdc++ to confirm it didn't break
anything there.

 winsup/cygwin/Makefile.am        |  4 +++-
 winsup/cygwin/include/pthread.h  | 27 ++++++++++++++++++++-------
 winsup/cygwin/lib/pthreadconst.S | 17 +++++++++++++++++
 3 files changed, 40 insertions(+), 8 deletions(-)
 create mode 100644 winsup/cygwin/lib/pthreadconst.S

diff --git a/winsup/cygwin/Makefile.am b/winsup/cygwin/Makefile.am
index 6438a41487..31747ac98c 100644
--- a/winsup/cygwin/Makefile.am
+++ b/winsup/cygwin/Makefile.am
@@ -78,7 +78,8 @@ LIB_FILES= \
        lib/premain1.c \
        lib/premain2.c \
        lib/premain3.c \
-       lib/pseudo-reloc-dummy.c
+       lib/pseudo-reloc-dummy.c \
+       lib/pthreadconst.S

 FHANDLER_FILES= \
        fhandler/base.cc \
@@ -315,6 +316,7 @@ DLL_FILES= \
        ipc.cc \
        kernel32.cc \
        ldap.cc \
+       lib/pthreadconst.S \
        libstdcxx_wrapper.cc \
        loadavg.cc \
        lsearch.cc \
diff --git a/winsup/cygwin/include/pthread.h b/winsup/cygwin/include/pthread.h
index 8e296303d7..6910a5a886 100644
--- a/winsup/cygwin/include/pthread.h
+++ b/winsup/cygwin/include/pthread.h
@@ -31,8 +31,6 @@ extern "C"
 #define PTHREAD_CANCEL_DEFERRED 0
 #define PTHREAD_CANCEL_DISABLE 1
 #define PTHREAD_CANCELED ((void *)-1)
-/* this should be a value that can never be a valid address */
-#define PTHREAD_COND_INITIALIZER (pthread_cond_t)21
 #define PTHREAD_CREATE_DETACHED 1
 /* the default : joinable */
 #define PTHREAD_CREATE_JOINABLE 0
@@ -42,10 +40,6 @@ extern "C"
 #define PTHREAD_MUTEX_ERRORCHECK 1
 #define PTHREAD_MUTEX_NORMAL 2
 #define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL
-/* this should be too low to ever be a valid address */
-#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP (pthread_mutex_t)18
-#define PTHREAD_NORMAL_MUTEX_INITIALIZER_NP (pthread_mutex_t)19
-#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP (pthread_mutex_t)20
 #define PTHREAD_MUTEX_INITIALIZER PTHREAD_NORMAL_MUTEX_INITIALIZER_NP
 #define PTHREAD_ONCE_INIT { PTHREAD_MUTEX_INITIALIZER, 0 }
 #if defined(_POSIX_THREAD_PRIO_INHERIT) && _POSIX_THREAD_PRIO_INHERIT >= 0
@@ -55,12 +49,31 @@ extern "C"
 #endif
 #define PTHREAD_PROCESS_SHARED 1
 #define PTHREAD_PROCESS_PRIVATE 0
-#define PTHREAD_RWLOCK_INITIALIZER (pthread_rwlock_t)22
 /* process is the default */
 #define PTHREAD_SCOPE_PROCESS 0
 #define PTHREAD_SCOPE_SYSTEM 1
 #define PTHREAD_BARRIER_SERIAL_THREAD (-1)

+#if !defined(__INSIDE_CYGWIN__) || !defined(__cplusplus)
+/* Constants for initializer macros */
+extern struct __pthread_mutex_t __pthread_recursive_mutex_initializer_np;
+extern struct __pthread_mutex_t __pthread_normal_mutex_initializer_np;
+extern struct __pthread_mutex_t __pthread_errorcheck_mutex_initializer_np;
+extern struct __pthread_cond_t __pthread_cond_initializer;
+extern struct __pthread_rwlock_t __pthread_rwlock_initializer;
+#define PTHREAD_COND_INITIALIZER (&__pthread_cond_initializer)
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP 
(&__pthread_recursive_mutex_initializer_np)
+#define PTHREAD_NORMAL_MUTEX_INITIALIZER_NP 
(&__pthread_normal_mutex_initializer_np)
+#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP 
(&__pthread_errorcheck_mutex_initializer_np)
+#define PTHREAD_RWLOCK_INITIALIZER (&__pthread_rwlock_initializer)
+#else
+#define PTHREAD_COND_INITIALIZER (pthread_cond_t)21
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP (pthread_mutex_t)18
+#define PTHREAD_NORMAL_MUTEX_INITIALIZER_NP (pthread_mutex_t)19
+#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP (pthread_mutex_t)20
+#define PTHREAD_RWLOCK_INITIALIZER (pthread_rwlock_t)22
+#endif
+
 /* Register Fork Handlers */
 int pthread_atfork (void (*)(void), void (*)(void), void (*)(void));

diff --git a/winsup/cygwin/lib/pthreadconst.S b/winsup/cygwin/lib/pthreadconst.S
new file mode 100644
index 0000000000..6e55a832a4
--- /dev/null
+++ b/winsup/cygwin/lib/pthreadconst.S
@@ -0,0 +1,17 @@
+#if defined(__i386__)
+#  define SYM(x) _##x
+#else
+#  define SYM(x) x
+#endif
+
+/* these should all be too low to ever be valid addresses */
+.globl SYM(__pthread_recursive_mutex_initializer_np)
+.set __pthread_recursive_mutex_initializer_np, 18
+.globl SYM(__pthread_normal_mutex_initializer_np)
+.set __pthread_normal_mutex_initializer_np, 19
+.globl SYM(__pthread_errorcheck_mutex_initializer_np)
+.set __pthread_errorcheck_mutex_initializer_np, 20
+.globl SYM(__pthread_cond_initializer)
+.set __pthread_cond_initializer, 21
+.globl SYM(__pthread_rwlock_initializer)
+.set __pthread_rwlock_initializer, 22
-- 
2.49.0.windows.1

Reply via email to