mariadb: simplify handling of atomics/libatomic, fix ppc32 build

Platforms such as ppc32 and mips do not have the __sync builtins
in gcc, which breaks compilation. However, that code is not even
necessary, as proper implementations of the higher level atomic
primitives are available as builtins in any modern toolchain
(and definitely ours) and mariadb in fact already uses those
when available.

So basically ditch all this effectively dead code to fix build
on those platforms. While at it, remove the wrong checks in
cmake and fix properly linking against libatomic only when
needed (this also affects ARMv5/6) and simplify the template.

These changes have already been done upstream, but we're
sticking with an older version for now because of libmysqlclient
ABI compat, so fix this downstream until we can upgrade.

Also add another patch for ppc/ppc64+musl to use a gcc builtin
instead of a glibc extension.

[ci skip]
This commit is contained in:
q66 2019-10-15 18:55:48 +02:00 committed by Helmut Pozimski
parent bae56e5665
commit a8a793b66f
4 changed files with 428 additions and 15 deletions

View file

@ -0,0 +1,294 @@
--- include/my_atomic.h
+++ include/my_atomic.h
@@ -104,217 +104,6 @@
but can be added, if necessary.
*/
-#define intptr void *
-/**
- Currently we don't support 8-bit and 16-bit operations.
- It can be added later if needed.
-*/
-#undef MY_ATOMIC_HAS_8_16
-
-/*
- * Attempt to do atomic ops without locks
- */
-#include "atomic/nolock.h"
-
-#ifndef make_atomic_cas_body
-/* nolock.h was not able to generate even a CAS function, fall back */
-#error atomic ops for this platform are not implemented
-#endif
-
-/* define missing functions by using the already generated ones */
-#ifndef make_atomic_add_body
-#define make_atomic_add_body(S) \
- int ## S tmp=*a; \
- while (!my_atomic_cas ## S(a, &tmp, tmp+v)) ; \
- v=tmp;
-#endif
-#ifndef make_atomic_fas_body
-#define make_atomic_fas_body(S) \
- int ## S tmp=*a; \
- while (!my_atomic_cas ## S(a, &tmp, v)) ; \
- v=tmp;
-#endif
-#ifndef make_atomic_load_body
-#define make_atomic_load_body(S) \
- ret= 0; /* avoid compiler warning */ \
- (void)(my_atomic_cas ## S(a, &ret, ret));
-#endif
-#ifndef make_atomic_store_body
-#define make_atomic_store_body(S) \
- (void)(my_atomic_fas ## S (a, v));
-#endif
-
-/*
- transparent_union doesn't work in g++
- Bug ?
-
- Darwin's gcc doesn't want to put pointers in a transparent_union
- when built with -arch ppc64. Complains:
- warning: 'transparent_union' attribute ignored
-*/
-#if defined(__GNUC__) && !defined(__cplusplus) && \
- ! (defined(__APPLE__) && (defined(_ARCH_PPC64) ||defined (_ARCH_PPC)))
-/*
- we want to be able to use my_atomic_xxx functions with
- both signed and unsigned integers. But gcc will issue a warning
- "passing arg N of `my_atomic_XXX' as [un]signed due to prototype"
- if the signedness of the argument doesn't match the prototype, or
- "pointer targets in passing argument N of my_atomic_XXX differ in signedness"
- if int* is used where uint* is expected (or vice versa).
- Let's shut these warnings up
-*/
-#define make_transparent_unions(S) \
- typedef union { \
- int ## S i; \
- uint ## S u; \
- } U_ ## S __attribute__ ((transparent_union)); \
- typedef union { \
- int ## S volatile *i; \
- uint ## S volatile *u; \
- } Uv_ ## S __attribute__ ((transparent_union));
-#define uintptr intptr
-make_transparent_unions(8)
-make_transparent_unions(16)
-make_transparent_unions(32)
-make_transparent_unions(64)
-make_transparent_unions(ptr)
-#undef uintptr
-#undef make_transparent_unions
-#define a U_a.i
-#define cmp U_cmp.i
-#define v U_v.i
-#define set U_set.i
-#else
-#define U_8 int8
-#define U_16 int16
-#define U_32 int32
-#define U_64 int64
-#define U_ptr intptr
-#define Uv_8 int8
-#define Uv_16 int16
-#define Uv_32 int32
-#define Uv_64 int64
-#define Uv_ptr intptr
-#define U_a volatile *a
-#define U_cmp *cmp
-#define U_v v
-#define U_set set
-#endif /* __GCC__ transparent_union magic */
-
-#define make_atomic_cas(S) \
-static inline int my_atomic_cas ## S(Uv_ ## S U_a, \
- Uv_ ## S U_cmp, U_ ## S U_set) \
-{ \
- int8 ret; \
- make_atomic_cas_body(S); \
- return ret; \
-}
-
-#define make_atomic_add(S) \
-static inline int ## S my_atomic_add ## S( \
- Uv_ ## S U_a, U_ ## S U_v) \
-{ \
- make_atomic_add_body(S); \
- return v; \
-}
-
-#define make_atomic_fas(S) \
-static inline int ## S my_atomic_fas ## S( \
- Uv_ ## S U_a, U_ ## S U_v) \
-{ \
- make_atomic_fas_body(S); \
- return v; \
-}
-
-#define make_atomic_load(S) \
-static inline int ## S my_atomic_load ## S(Uv_ ## S U_a) \
-{ \
- int ## S ret; \
- make_atomic_load_body(S); \
- return ret; \
-}
-
-#define make_atomic_store(S) \
-static inline void my_atomic_store ## S( \
- Uv_ ## S U_a, U_ ## S U_v) \
-{ \
- make_atomic_store_body(S); \
-}
-
-#ifdef MY_ATOMIC_HAS_8_16
-make_atomic_cas(8)
-make_atomic_cas(16)
-#endif
-make_atomic_cas(32)
-make_atomic_cas(64)
-make_atomic_cas(ptr)
-
-#ifdef MY_ATOMIC_HAS_8_16
-make_atomic_add(8)
-make_atomic_add(16)
-#endif
-make_atomic_add(32)
-make_atomic_add(64)
-
-#ifdef MY_ATOMIC_HAS_8_16
-make_atomic_load(8)
-make_atomic_load(16)
-#endif
-make_atomic_load(32)
-make_atomic_load(64)
-make_atomic_load(ptr)
-
-#ifdef MY_ATOMIC_HAS_8_16
-make_atomic_fas(8)
-make_atomic_fas(16)
-#endif
-make_atomic_fas(32)
-make_atomic_fas(64)
-make_atomic_fas(ptr)
-
-#ifdef MY_ATOMIC_HAS_8_16
-make_atomic_store(8)
-make_atomic_store(16)
-#endif
-make_atomic_store(32)
-make_atomic_store(64)
-make_atomic_store(ptr)
-
-#ifdef _atomic_h_cleanup_
-#include _atomic_h_cleanup_
-#undef _atomic_h_cleanup_
-#endif
-
-#undef U_8
-#undef U_16
-#undef U_32
-#undef U_64
-#undef U_ptr
-#undef Uv_8
-#undef Uv_16
-#undef Uv_32
-#undef Uv_64
-#undef Uv_ptr
-#undef a
-#undef cmp
-#undef v
-#undef set
-#undef U_a
-#undef U_cmp
-#undef U_v
-#undef U_set
-#undef make_atomic_add
-#undef make_atomic_cas
-#undef make_atomic_load
-#undef make_atomic_store
-#undef make_atomic_fas
-#undef make_atomic_add_body
-#undef make_atomic_cas_body
-#undef make_atomic_load_body
-#undef make_atomic_store_body
-#undef make_atomic_fas_body
-#undef intptr
-
/*
the macro below defines (as an expression) the code that
will be run in spin-loops. Intel manuals recummend to have PAUSE there.
@@ -328,7 +117,8 @@ make_atomic_store(ptr)
#define MY_ATOMIC_NOT_1CPU 1
extern int my_atomic_initialize();
-#ifdef __ATOMIC_SEQ_CST
+#define MY_ATOMIC_MODE "gcc-atomics-smp"
+
#define MY_MEMORY_ORDER_RELAXED __ATOMIC_RELAXED
#define MY_MEMORY_ORDER_CONSUME __ATOMIC_CONSUME
#define MY_MEMORY_ORDER_ACQUIRE __ATOMIC_ACQUIRE
@@ -364,43 +154,27 @@ extern int my_atomic_initialize();
__atomic_compare_exchange_n((P), (E), (D), false, (S), (F))
#define my_atomic_casptr_strong_explicit(P, E, D, S, F) \
__atomic_compare_exchange_n((P), (E), (D), false, (S), (F))
-#else
-#define MY_MEMORY_ORDER_RELAXED
-#define MY_MEMORY_ORDER_CONSUME
-#define MY_MEMORY_ORDER_ACQUIRE
-#define MY_MEMORY_ORDER_RELEASE
-#define MY_MEMORY_ORDER_ACQ_REL
-#define MY_MEMORY_ORDER_SEQ_CST
-
-#define my_atomic_store32_explicit(P, D, O) my_atomic_store32((P), (D))
-#define my_atomic_store64_explicit(P, D, O) my_atomic_store64((P), (D))
-#define my_atomic_storeptr_explicit(P, D, O) my_atomic_storeptr((P), (D))
-
-#define my_atomic_load32_explicit(P, O) my_atomic_load32((P))
-#define my_atomic_load64_explicit(P, O) my_atomic_load64((P))
-#define my_atomic_loadptr_explicit(P, O) my_atomic_loadptr((P))
-
-#define my_atomic_fas32_explicit(P, D, O) my_atomic_fas32((P), (D))
-#define my_atomic_fas64_explicit(P, D, O) my_atomic_fas64((P), (D))
-#define my_atomic_fasptr_explicit(P, D, O) my_atomic_fasptr((P), (D))
-
-#define my_atomic_add32_explicit(P, A, O) my_atomic_add32((P), (A))
-#define my_atomic_add64_explicit(P, A, O) my_atomic_add64((P), (A))
-#define my_atomic_addptr_explicit(P, A, O) my_atomic_addptr((P), (A))
-#define my_atomic_cas32_weak_explicit(P, E, D, S, F) \
- my_atomic_cas32((P), (E), (D))
-#define my_atomic_cas64_weak_explicit(P, E, D, S, F) \
- my_atomic_cas64((P), (E), (D))
-#define my_atomic_casptr_weak_explicit(P, E, D, S, F) \
- my_atomic_casptr((P), (E), (D))
+#define my_atomic_store32(P, D) __atomic_store_n((P), (D), __ATOMIC_SEQ_CST)
+#define my_atomic_store64(P, D) __atomic_store_n((P), (D), __ATOMIC_SEQ_CST)
+#define my_atomic_storeptr(P, D) __atomic_store_n((P), (D), __ATOMIC_SEQ_CST)
-#define my_atomic_cas32_strong_explicit(P, E, D, S, F) \
- my_atomic_cas32((P), (E), (D))
-#define my_atomic_cas64_strong_explicit(P, E, D, S, F) \
- my_atomic_cas64((P), (E), (D))
-#define my_atomic_casptr_strong_explicit(P, E, D, S, F) \
- my_atomic_casptr((P), (E), (D))
-#endif
+#define my_atomic_load32(P) __atomic_load_n((P), __ATOMIC_SEQ_CST)
+#define my_atomic_load64(P) __atomic_load_n((P), __ATOMIC_SEQ_CST)
+#define my_atomic_loadptr(P) __atomic_load_n((P), __ATOMIC_SEQ_CST)
+
+#define my_atomic_fas32(P, D) __atomic_exchange_n((P), (D), __ATOMIC_SEQ_CST)
+#define my_atomic_fas64(P, D) __atomic_exchange_n((P), (D), __ATOMIC_SEQ_CST)
+#define my_atomic_fasptr(P, D) __atomic_exchange_n((P), (D), __ATOMIC_SEQ_CST)
+
+#define my_atomic_add32(P, A) __atomic_fetch_add((P), (A), __ATOMIC_SEQ_CST)
+#define my_atomic_add64(P, A) __atomic_fetch_add((P), (A), __ATOMIC_SEQ_CST)
+
+#define my_atomic_cas32(P, E, D) \
+ __atomic_compare_exchange_n((P), (E), (D), 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
+#define my_atomic_cas64(P, E, D) \
+ __atomic_compare_exchange_n((P), (E), (D), 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
+#define my_atomic_casptr(P, E, D) \
+ __atomic_compare_exchange_n((P), (E), (D), 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
#endif /* MY_ATOMIC_INCLUDED */

View file

@ -0,0 +1,103 @@
Source: Debian, q66
This ensures arches that need libatomic properly get it where necessary.
It also removes the sync builtin checks that are not necessary when
using C11 atomics (like we always are because we're on a modern gcc)
that break build on e.g. ppc32 and mips.
--- configure.cmake
+++ configure.cmake
@@ -992,35 +992,19 @@ SET(SIGNAL_WITH_VIO_CLOSE 1)
MARK_AS_ADVANCED(NO_ALARM)
-
-IF(WITH_ATOMIC_OPS STREQUAL "up")
- SET(MY_ATOMIC_MODE_DUMMY 1 CACHE BOOL "Assume single-CPU mode, no concurrency")
-ELSEIF(WITH_ATOMIC_OPS STREQUAL "smp")
-ELSEIF(NOT WITH_ATOMIC_OPS)
- CHECK_CXX_SOURCE_COMPILES("
- int main()
- {
- int foo= -10; int bar= 10;
- long long int foo64= -10; long long int bar64= 10;
- if (!__sync_fetch_and_add(&foo, bar) || foo)
- return -1;
- bar= __sync_lock_test_and_set(&foo, bar);
- if (bar || foo != 10)
- return -1;
- bar= __sync_val_compare_and_swap(&bar, foo, 15);
- if (bar)
- return -1;
- if (!__sync_fetch_and_add(&foo64, bar64) || foo64)
- return -1;
- bar64= __sync_lock_test_and_set(&foo64, bar64);
- if (bar64 || foo64 != 10)
- return -1;
- bar64= __sync_val_compare_and_swap(&bar64, foo, 15);
- if (bar64)
- return -1;
- return 0;
- }"
- HAVE_GCC_ATOMIC_BUILTINS)
+CHECK_CXX_SOURCE_COMPILES("
+int main()
+{
+ long long int var= 1;
+ long long int *ptr= &var;
+ return (int)__atomic_load_n(ptr, __ATOMIC_SEQ_CST);
+}"
+HAVE_GCC_C11_ATOMICS_WITHOUT_LIBATOMIC)
+IF (HAVE_GCC_C11_ATOMICS_WITHOUT_LIBATOMIC)
+ SET(HAVE_GCC_C11_ATOMICS True)
+ELSE()
+ SET(OLD_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
+ LIST(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
CHECK_CXX_SOURCE_COMPILES("
int main()
{
@@ -1028,14 +1012,13 @@ ELSEIF(NOT WITH_ATOMIC_OPS)
long long int *ptr= &var;
return (int)__atomic_load_n(ptr, __ATOMIC_SEQ_CST);
}"
- HAVE_GCC_C11_ATOMICS)
-ELSE()
- MESSAGE(FATAL_ERROR "${WITH_ATOMIC_OPS} is not a valid value for WITH_ATOMIC_OPS!")
+ HAVE_GCC_C11_ATOMICS_WITH_LIBATOMIC)
+ IF(HAVE_GCC_C11_ATOMICS_WITH_LIBATOMIC)
+ SET(HAVE_GCC_C11_ATOMICS True)
+ ENDIF()
+ SET(CMAKE_REQUIRED_LIBRARIES ${OLD_CMAKE_REQUIRED_LIBRARIES})
ENDIF()
-SET(WITH_ATOMIC_OPS "${WITH_ATOMIC_OPS}" CACHE STRING "Implement atomic operations using atomic CPU instructions for multi-processor (smp) or uniprocessor (up) configuration. By default gcc built-in sync functions are used, if available and 'smp' configuration otherwise.")
-MARK_AS_ADVANCED(WITH_ATOMIC_OPS MY_ATOMIC_MODE_DUMMY)
-
IF(WITH_VALGRIND)
SET(HAVE_valgrind 1)
ENDIF()
--- mysys/CMakeLists.txt
+++ mysys/CMakeLists.txt
@@ -74,6 +74,10 @@ TARGET_LINK_LIBRARIES(mysys dbug strings mysys_ssl ${ZLIB_LIBRARY}
${LIBNSL} ${LIBM} ${LIBRT} ${LIBDL} ${LIBSOCKET} ${LIBEXECINFO})
DTRACE_INSTRUMENT(mysys)
+IF (HAVE_GCC_C11_ATOMICS_WITH_LIBATOMIC)
+ TARGET_LINK_LIBRARIES(mysys atomic)
+ENDIF()
+
IF(HAVE_BFD_H)
TARGET_LINK_LIBRARIES(mysys bfd)
ENDIF(HAVE_BFD_H)
--- sql/CMakeLists.txt
+++ sql/CMakeLists.txt
@@ -172,6 +172,9 @@ ELSE()
SET(MYSQLD_SOURCE main.cc ${DTRACE_PROBES_ALL})
ENDIF()
+IF (HAVE_GCC_C11_ATOMICS_WITH_LIBATOMIC)
+ TARGET_LINK_LIBRARIES(sql atomic)
+ENDIF()
IF(MSVC AND NOT WITHOUT_DYNAMIC_PLUGINS)

View file

@ -0,0 +1,27 @@
This header does not exist on musl, but there has been a
builtin for this in gcc for ages, so just use that instead.
--- storage/innobase/include/ut0ut.h
+++ storage/innobase/include/ut0ut.h
@@ -89,8 +89,7 @@ struct ut_when_dtor {
independent way by using YieldProcessor. */
# define UT_RELAX_CPU() YieldProcessor()
# elif defined(__powerpc__)
-#include <sys/platform/ppc.h>
-# define UT_RELAX_CPU() __ppc_get_timebase()
+# define UT_RELAX_CPU() __builtin_ppc_get_timebase()
# else
# define UT_RELAX_CPU() ((void)0) /* avoid warning for an empty statement */
# endif
--- storage/xtradb/include/ut0ut.h
+++ storage/xtradb/include/ut0ut.h
@@ -86,8 +86,7 @@ struct ut_when_dtor {
independent way by using YieldProcessor. */
# define UT_RELAX_CPU() YieldProcessor()
# elif defined(__powerpc__)
-#include <sys/platform/ppc.h>
-# define UT_RELAX_CPU() __ppc_get_timebase()
+# define UT_RELAX_CPU() __builtin_ppc_get_timebase()
# else
# define UT_RELAX_CPU() ((void)0) /* avoid warning for an empty statement */
# endif

View file

@ -1,7 +1,7 @@
# Template file for 'mariadb'
pkgname=mariadb
version=10.1.30
revision=6
revision=7
build_style=cmake
configure_args="-DMYSQL_DATADIR=/var/lib/mysql
-DMYSQL_UNIX_ADDR=/run/mysqld/mysqld.sock -DDEFAULT_CHARSET=utf8
@ -18,8 +18,9 @@ configure_args="-DMYSQL_DATADIR=/var/lib/mysql
-DWITH_EXTRA_CHARSETS=complex -DWITH_LIBWRAP=OFF -DSTACK_DIRECTION=1
-DWITHOUT_PBXT_STORAGE_ENGINE=1 -DWITH_INNOBASE_STORAGE_ENGINE=1"
lib32disabled=yes
hostmakedepends="perl bison ncurses-devel libressl-devel"
makedepends="zlib-devel ncurses-devel libressl-devel readline-devel pcre-devel"
hostmakedepends="perl bison ncurses-devel libressl-devel libatomic-devel"
makedepends="zlib-devel ncurses-devel libressl-devel readline-devel pcre-devel
libatomic-devel"
depends="mariadb-client"
provides="mysql-${version}_${revision}"
replaces="mysql>=0"
@ -34,19 +35,7 @@ distfiles="http://archive.mariadb.org/$pkgname-$version/source/$pkgname-$version
checksum=173a5e5a24819e0a469c3bd09b5c98491676c37c6095882a2ea34c5af0996c88
CFLAGS="-w"
case "$XBPS_TARGET_MACHINE" in
armv[56]*|ppc|ppc-musl) LDFLAGS="-L${XBPS_CROSS_BASE}/usr/lib -latomic"
hostmakedepends+=" libatomic-devel"
makedepends+=" libatomic-devel"
;;
esac
pre_configure() {
case "$XBPS_TARGET_MACHINE" in
armv[56]*|ppc|ppc-musl) find -name CMakeLists.txt -exec sed -i "{}" \
-e "/TARGET_LINK_LIBRARIES/s;); atomic);" \;
;;
esac
# We need some host binaries before starting cross compilation.
if [ "$CROSS_BUILD" ]; then
# XXX still broken: jemalloc configure execs host bins.