[Mesa-dev] [PATCH] util/u_atomic: provide 64bit atomics where they're missing

Grazvydas Ignotas notasas at gmail.com
Wed Mar 29 23:13:35 UTC 2017


There are still some distributions trying to support unfortunate people
with old or exotic CPUs that don't have 64bit atomic operations. When
compiling for such a machine, gcc conveniently inserts a library call to
a helper, but it's implementation is missing and we get a linker error.
This allows us to provide our implementation, which is marked weak to
prefer a better implementation, should one exist.

Cc: Matt Turner <mattst88 at gmail.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=93089
Signed-off-by: Grazvydas Ignotas <notasas at gmail.com>
---
 configure.ac              | 12 ++++++++
 src/util/Makefile.sources |  1 +
 src/util/u_atomic.c       | 71 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 84 insertions(+)
 create mode 100644 src/util/u_atomic.c

diff --git a/configure.ac b/configure.ac
index ab9a91e..89b615b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -413,10 +413,22 @@ int main() {
 if test "x$GCC_ATOMIC_BUILTINS_SUPPORTED" = x1; then
     DEFINES="$DEFINES -DUSE_GCC_ATOMIC_BUILTINS"
 fi
 AM_CONDITIONAL([GCC_ATOMIC_BUILTINS_SUPPORTED], [test x$GCC_ATOMIC_BUILTINS_SUPPORTED = x1])
 
+dnl Check if host supports 64bit atomics
+dnl note that lack of support usually results in link (not compile) error
+AC_LINK_IFELSE([AC_LANG_SOURCE([[
+#include <stdint.h>
+uint64_t v;
+int main() {
+    return __sync_add_and_fetch(&v, (uint64_t)1);
+}]])], GCC_64BIT_ATOMICS_SUPPORTED=1)
+if test "x$GCC_64BIT_ATOMICS_SUPPORTED" != x1; then
+    DEFINES="$DEFINES -DMISSING_64BIT_ATOMICS"
+fi
+
 dnl Check for Endianness
 AC_C_BIGENDIAN(
    little_endian=no,
    little_endian=yes,
    little_endian=no,
diff --git a/src/util/Makefile.sources b/src/util/Makefile.sources
index 8ee45d5..e905734 100644
--- a/src/util/Makefile.sources
+++ b/src/util/Makefile.sources
@@ -41,10 +41,11 @@ MESA_UTIL_FILES := \
 	string_to_uint_map.h \
 	strndup.h \
 	strtod.c \
 	strtod.h \
 	texcompress_rgtc_tmp.h \
+	u_atomic.c \
 	u_atomic.h \
 	u_endian.h \
 	u_queue.c \
 	u_queue.h \
 	u_string.h \
diff --git a/src/util/u_atomic.c b/src/util/u_atomic.c
new file mode 100644
index 0000000..77ef119
--- /dev/null
+++ b/src/util/u_atomic.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2017 The Mesa Project
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#if defined(MISSING_64BIT_ATOMICS) && defined(HAVE_PTHREAD)
+
+#include <stdint.h>
+#include <pthread.h>
+
+#if defined(HAVE_FUNC_ATTRIBUTE_WEAK) && !defined(__CYGWIN__)
+#define WEAK __attribute__((weak))
+#else
+#define WEAK
+#endif
+
+static pthread_mutex_t sync_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+WEAK uint64_t __sync_add_and_fetch_8(uint64_t *ptr, uint64_t val)
+{
+	uint64_t r;
+
+	pthread_mutex_lock(&sync_mutex);
+	*ptr += val;
+	r = *ptr;
+	pthread_mutex_unlock(&sync_mutex);
+
+	return r;
+}
+
+WEAK uint64_t __sync_sub_and_fetch_8(uint64_t *ptr, uint64_t val)
+{
+	uint64_t r;
+
+	pthread_mutex_lock(&sync_mutex);
+	*ptr -= val;
+	r = *ptr;
+	pthread_mutex_unlock(&sync_mutex);
+
+	return r;
+}
+
+WEAK uint64_t __atomic_fetch_add_8(uint64_t *ptr, uint64_t val, int memorder)
+{
+	return __sync_add_and_fetch(ptr, val);
+}
+
+WEAK uint64_t __atomic_fetch_sub_8(uint64_t *ptr, uint64_t val, int memorder)
+{
+	return __sync_sub_and_fetch(ptr, val);
+}
+
+#endif
-- 
2.7.4



More information about the mesa-dev mailing list