Replace sync builtins with atomic builtins
authorJanne Blomqvist <jb@gcc.gnu.org>
Thu, 22 Nov 2018 07:58:29 +0000 (09:58 +0200)
committerJanne Blomqvist <jb@gcc.gnu.org>
Thu, 22 Nov 2018 07:58:29 +0000 (09:58 +0200)
The old __sync builtins have been deprecated for a long time now in
favor of the __atomic builtins following the C++11/C11 memory model.
This patch converts libgfortran to use the modern __atomic builtins.

At the same time I weakened the consistency to relaxed for
incrementing and decrementing the counter, and acquire-release when
decrementing to check whether the counter is 0 and the unit can be
freed.  This is similar to e.g. std::shared_ptr in C++.

Regtested on x86_64-pc-linux-gnu.

libgfortran/ChangeLog:

2018-11-22  Janne Blomqvist  <jb@gcc.gnu.org>

* acinclude.m4 (LIBGFOR_CHECK_ATOMIC_FETCH_ADD): Rename and test
presence of atomic builtins instead of sync builtins.
* configure.ac (LIBGFOR_CHECK_ATOMIC_FETCH_ADD): Call new test.
* io/io.h (inc_waiting_locked): Use __atomic_fetch_add.
(predec_waiting_locked): Use __atomic_add_fetch.
(dec_waiting_unlocked): Use __atomic_fetch_add.
* config.h.in: Regenerated.
* configure: Regenerated.
        * Makefile.in: Regenerated.

From-SVN: r266367

libgfortran/ChangeLog
libgfortran/Makefile.in
libgfortran/acinclude.m4
libgfortran/config.h.in
libgfortran/configure
libgfortran/configure.ac
libgfortran/io/io.h

index 8536e8befe98e81024c30b46c6d5ffa6ba731956..59c16f35072e2870269f685982e8b703a8ddf436 100644 (file)
@@ -1,3 +1,15 @@
+2018-11-22  Janne Blomqvist  <jb@gcc.gnu.org>
+
+       * acinclude.m4 (LIBGFOR_CHECK_ATOMIC_FETCH_ADD): Rename and test
+       presence of atomic builtins instead of sync builtins.
+       * configure.ac (LIBGFOR_CHECK_ATOMIC_FETCH_ADD): Call new test.
+       * io/io.h (inc_waiting_locked): Use __atomic_fetch_add.
+       (predec_waiting_locked): Use __atomic_add_fetch.
+       (dec_waiting_unlocked): Use __atomic_fetch_add.
+       * config.h.in: Regenerated.
+       * configure: Regenerated.
+       * Makefile.in: Regenerated.
+
 2018-11-09  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
 
        PR libfortran/78351
index 84c13426f42d737317696bf6e69f22135a940ba7..2424f7e6ba8f0f1cf4b555e9364be5221c674c89 100644 (file)
@@ -690,6 +690,7 @@ pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@
+runstatedir = @runstatedir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 srcdir = @srcdir@
index dd5429ac0d28fb8fd64316dea56a4772dda113e3..5b0c094e71697e73a3845cf1f22fae326dc90c30 100644 (file)
@@ -59,17 +59,17 @@ extern void bar(void) __attribute__((alias("foo")));]],
       [Define to 1 if the target supports __attribute__((alias(...))).])
   fi])
 
-dnl Check whether the target supports __sync_fetch_and_add.
-AC_DEFUN([LIBGFOR_CHECK_SYNC_FETCH_AND_ADD], [
-  AC_CACHE_CHECK([whether the target supports __sync_fetch_and_add],
-                libgfor_cv_have_sync_fetch_and_add, [
+dnl Check whether the target supports __atomic_fetch_add.
+AC_DEFUN([LIBGFOR_CHECK_ATOMIC_FETCH_ADD], [
+  AC_CACHE_CHECK([whether the target supports __atomic_fetch_add],
+                libgfor_cv_have_atomic_fetch_add, [
   AC_LINK_IFELSE([AC_LANG_PROGRAM([[int foovar = 0;]], [[
-if (foovar <= 0) return __sync_fetch_and_add (&foovar, 1);
-if (foovar > 10) return __sync_add_and_fetch (&foovar, -1);]])],
-             libgfor_cv_have_sync_fetch_and_add=yes, libgfor_cv_have_sync_fetch_and_add=no)])
-  if test $libgfor_cv_have_sync_fetch_and_add = yes; then
-    AC_DEFINE(HAVE_SYNC_FETCH_AND_ADD, 1,
-             [Define to 1 if the target supports __sync_fetch_and_add])
+if (foovar <= 0) return __atomic_fetch_add (&foovar, 1, __ATOMIC_ACQ_REL);
+if (foovar > 10) return __atomic_add_fetch (&foovar, -1, __ATOMIC_ACQ_REL);]])],
+             libgfor_cv_have_atomic_fetch_add=yes, libgfor_cv_have_atomic_fetch_add=no)])
+  if test $libgfor_cv_have_atomic_fetch_add = yes; then
+    AC_DEFINE(HAVE_ATOMIC_FETCH_ADD, 1,
+             [Define to 1 if the target supports __atomic_fetch_add])
   fi])
 
 dnl Check for pragma weak.
index f8f98246fd7181c3ce61f8d31d8e6cdd2de133cc..cbd720a26702e9471bc843045f5c3bdf1f2ce0ef 100644 (file)
@@ -72,6 +72,9 @@
 /* Define to 1 if you have the `atanl' function. */
 #undef HAVE_ATANL
 
+/* Define to 1 if the target supports __atomic_fetch_add */
+#undef HAVE_ATOMIC_FETCH_ADD
+
 /* Define to 1 if the target supports __attribute__((alias(...))). */
 #undef HAVE_ATTRIBUTE_ALIAS
 
 /* Define to 1 if you have the `symlink' function. */
 #undef HAVE_SYMLINK
 
-/* Define to 1 if the target supports __sync_fetch_and_add */
-#undef HAVE_SYNC_FETCH_AND_ADD
-
 /* Define to 1 if you have the <sys/random.h> header file. */
 #undef HAVE_SYS_RANDOM_H
 
index 45085d699d6b19dc20dd9094db56e007c04c4dae..62e80a0b275f2effc22c6d7b8461f7c3859a1bbc 100755 (executable)
@@ -780,6 +780,7 @@ infodir
 docdir
 oldincludedir
 includedir
+runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -870,6 +871,7 @@ datadir='${datarootdir}'
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
 docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -1122,6 +1124,15 @@ do
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
 
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+    ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+    runstatedir=$ac_optarg ;;
+
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1259,7 +1270,7 @@ fi
 for ac_var in  exec_prefix prefix bindir sbindir libexecdir datarootdir \
                datadir sysconfdir sharedstatedir localstatedir includedir \
                oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-               libdir localedir mandir
+               libdir localedir mandir runstatedir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -1412,6 +1423,7 @@ Fine tuning of the installation directories:
   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIR            object code libraries [EPREFIX/lib]
   --includedir=DIR        C header files [PREFIX/include]
   --oldincludedir=DIR     C header files for non-gcc [/usr/include]
@@ -12684,7 +12696,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12687 "configure"
+#line 12699 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12790,7 +12802,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12793 "configure"
+#line 12805 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -16039,7 +16051,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
                       && LARGE_OFF_T % 2147483647 == 1)
                      ? 1 : -1];
@@ -16085,7 +16097,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
                       && LARGE_OFF_T % 2147483647 == 1)
                      ? 1 : -1];
@@ -16109,7 +16121,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
                       && LARGE_OFF_T % 2147483647 == 1)
                      ? 1 : -1];
@@ -16154,7 +16166,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
                       && LARGE_OFF_T % 2147483647 == 1)
                      ? 1 : -1];
@@ -16178,7 +16190,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
                       && LARGE_OFF_T % 2147483647 == 1)
                      ? 1 : -1];
@@ -26283,11 +26295,11 @@ $as_echo "#define HAVE_ATTRIBUTE_ALIAS 1" >>confdefs.h
 
   fi
 
-# Check out sync builtins support.
+# Check out atomic builtins support.
 
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the target supports __sync_fetch_and_add" >&5
-$as_echo_n "checking whether the target supports __sync_fetch_and_add... " >&6; }
-if ${libgfor_cv_have_sync_fetch_and_add+:} false; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the target supports __atomic_fetch_add" >&5
+$as_echo_n "checking whether the target supports __atomic_fetch_add... " >&6; }
+if ${libgfor_cv_have_atomic_fetch_add+:} false; then :
   $as_echo_n "(cached) " >&6
 else
 
@@ -26301,25 +26313,25 @@ int
 main ()
 {
 
-if (foovar <= 0) return __sync_fetch_and_add (&foovar, 1);
-if (foovar > 10) return __sync_add_and_fetch (&foovar, -1);
+if (foovar <= 0) return __atomic_fetch_add (&foovar, 1, __ATOMIC_ACQ_REL);
+if (foovar > 10) return __atomic_add_fetch (&foovar, -1, __ATOMIC_ACQ_REL);
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  libgfor_cv_have_sync_fetch_and_add=yes
+  libgfor_cv_have_atomic_fetch_add=yes
 else
-  libgfor_cv_have_sync_fetch_and_add=no
+  libgfor_cv_have_atomic_fetch_add=no
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgfor_cv_have_sync_fetch_and_add" >&5
-$as_echo "$libgfor_cv_have_sync_fetch_and_add" >&6; }
-  if test $libgfor_cv_have_sync_fetch_and_add = yes; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgfor_cv_have_atomic_fetch_add" >&5
+$as_echo "$libgfor_cv_have_atomic_fetch_add" >&6; }
+  if test $libgfor_cv_have_atomic_fetch_add = yes; then
 
-$as_echo "#define HAVE_SYNC_FETCH_AND_ADD 1" >>confdefs.h
+$as_echo "#define HAVE_ATOMIC_FETCH_ADD 1" >>confdefs.h
 
   fi
 
index 76007d38f6fbe7bcc7883d466c5e6e78c26e19c9..30ff87347603a2d35f4d8c4add874e40bce5541d 100644 (file)
@@ -608,8 +608,8 @@ fi
 LIBGFOR_CHECK_ATTRIBUTE_VISIBILITY
 LIBGFOR_CHECK_ATTRIBUTE_ALIAS
 
-# Check out sync builtins support.
-LIBGFOR_CHECK_SYNC_FETCH_AND_ADD
+# Check out atomic builtins support.
+LIBGFOR_CHECK_ATOMIC_FETCH_ADD
 
 # Check out #pragma weak.
 LIBGFOR_GTHREAD_WEAK
index 902eb4128489905aa518784acc96b8fc7f4bd786..282c1455763f9594616541d53c5791b341f08976 100644 (file)
@@ -961,8 +961,8 @@ internal_proto(free_ionml);
 static inline void
 inc_waiting_locked (gfc_unit *u)
 {
-#ifdef HAVE_SYNC_FETCH_AND_ADD
-  (void) __sync_fetch_and_add (&u->waiting, 1);
+#ifdef HAVE_ATOMIC_FETCH_ADD
+  (void) __atomic_fetch_add (&u->waiting, 1, __ATOMIC_RELAXED);
 #else
   u->waiting++;
 #endif
@@ -971,8 +971,20 @@ inc_waiting_locked (gfc_unit *u)
 static inline int
 predec_waiting_locked (gfc_unit *u)
 {
-#ifdef HAVE_SYNC_FETCH_AND_ADD
-  return __sync_add_and_fetch (&u->waiting, -1);
+#ifdef HAVE_ATOMIC_FETCH_ADD
+  /* Note that the pattern
+
+     if (predec_waiting_locked (u) == 0)
+         // destroy u
+        
+     could be further optimized by making this be an __ATOMIC_RELEASE,
+     and then inserting a
+
+     __atomic_thread_fence (__ATOMIC_ACQUIRE);
+
+     inside the branch before destroying.  But for now, lets keep it
+     simple.  */
+  return __atomic_add_fetch (&u->waiting, -1, __ATOMIC_ACQ_REL);
 #else
   return --u->waiting;
 #endif
@@ -981,8 +993,8 @@ predec_waiting_locked (gfc_unit *u)
 static inline void
 dec_waiting_unlocked (gfc_unit *u)
 {
-#ifdef HAVE_SYNC_FETCH_AND_ADD
-  (void) __sync_fetch_and_add (&u->waiting, -1);
+#ifdef HAVE_ATOMIC_FETCH_ADD
+  (void) __atomic_fetch_add (&u->waiting, -1, __ATOMIC_RELAXED);
 #else
   __gthread_mutex_lock (&unit_lock);
   u->waiting--;