]> granicus.if.org Git - gc/commitdiff
Turn off parallel marker, thread-local allocation if used AO ops emulated
authorIvan Maidanski <ivmai@mail.ru>
Wed, 21 Nov 2018 09:16:01 +0000 (12:16 +0300)
committerIvan Maidanski <ivmai@mail.ru>
Wed, 21 Nov 2018 09:44:46 +0000 (12:44 +0300)
* configure.ac (use_parallel_mark, use_thread_local_alloc): New
variable (set to enable_parallel_mark and enable_thread_local_alloc,
respectively, if threads are enabled).
* configure.ac (PARALLEL_MARK, THREAD_LOCAL_ALLOC): Group and move
AC_DEFINE down (the definition depends on the final value of
use_parallel_mark or use_thread_local_alloc, respectively).
* configure.ac (THREAD_LOCAL_ALLOC): Move AM_CONDITIONAL down to use
the final value of use_thread_local_alloc; do not check THREADS.
* configure.ac (handle-fork): Move AC_ARG_ENABLE and its processing
down to use the final value of use_parallel_mark (the latter is used
instead of enable_parallel_mark).
* configure.ac [$with_libatomic_ops!=none && $need_atomic_ops_asm!=true]
(use_thread_local_alloc): Set explicitly to "no" if
BASE_ATOMIC_OPS_EMULATED is defined.
* configure.ac [$with_libatomic_ops!=none && $need_atomic_ops_asm!=true
&& $use_parallel_mark!=no] (use_parallel_mark): Set explicitly to "no"
in case of a failure of AC_TRY_LINK of a code snippet calling
AO_fetch_and_add and AO_compare_and_swap (provided AO_REQUIRE_CAS is
defined).
* include/private/gc_pmark.h [USE_MARK_BYTES && PARALLEL_MARK
&& AO_HAVE_char_store] (SET_MARK_BIT_EXIT_IF_SET): Do not use
AO_char_load() and AO_char_store() if BASE_ATOMIC_OPS_EMULATED.

configure.ac
include/private/gc_pmark.h

index 0fd566635a6b9a5c12c5ee225a4a21f34afc0c39..1d92e2bdfb26f38947c5211e6eba3d0880b638b0 100644 (file)
@@ -186,6 +186,8 @@ CFLAGS="$old_CFLAGS"
 
 THREADDLLIBS=
 need_atomic_ops_asm=false
+use_parallel_mark=no
+use_thread_local_alloc=no
 # Libraries needed to support dynamic loading and/or threads.
 case "$THREADS" in
  no | none | single)
@@ -203,12 +205,8 @@ case "$THREADS" in
         AC_DEFINE(GC_THREADS)
         AC_DEFINE([_REENTRANT], [1],
                   [Required define if using POSIX threads.])
-        if test "${enable_parallel_mark}" != no; then
-          AC_DEFINE(PARALLEL_MARK)
-        fi
-        if test "${enable_thread_local_alloc}" != no; then
-          AC_DEFINE(THREAD_LOCAL_ALLOC)
-        fi
+        use_parallel_mark=$enable_parallel_mark
+        use_thread_local_alloc=$enable_thread_local_alloc
         default_threadlibs=true
         AC_MSG_WARN("Explicit GC_INIT() calls may be required.")
         ;;
@@ -252,13 +250,9 @@ case "$THREADS" in
       *-*-mingw*)
         AC_DEFINE(GC_WIN32_PTHREADS)
         # Using pthreads-win32 (or other non-Cygwin pthreads) library.
-        if test "${enable_parallel_mark}" != no; then
-          AC_DEFINE(PARALLEL_MARK)
-        fi
-        if test "${enable_thread_local_alloc}" != no; then
-          AC_DEFINE(THREAD_LOCAL_ALLOC)
-        fi
         THREADDLLIBS="-lpthread"
+        use_parallel_mark=$enable_parallel_mark
+        use_thread_local_alloc=$enable_thread_local_alloc
         win32_threads=true
         ;;
       *-*-darwin*)
@@ -285,15 +279,11 @@ case "$THREADS" in
     ;;
  win32)
     AC_DEFINE(GC_THREADS)
-    if test "${enable_parallel_mark}" != no; then
-      AC_DEFINE(PARALLEL_MARK)
-    fi
-    if test "${enable_thread_local_alloc}" != no; then
-      if test "${enable_parallel_mark}" != no \
-              -o "${enable_shared}" != yes -o "${enable_static}" != no; then
-        # Imply THREAD_LOCAL_ALLOC unless GC_DLL.
-        AC_DEFINE(THREAD_LOCAL_ALLOC)
-      fi
+    use_parallel_mark=$enable_parallel_mark
+    if test "${enable_parallel_mark}" != no \
+            -o "${enable_shared}" != yes -o "${enable_static}" != no; then
+      # Imply THREAD_LOCAL_ALLOC unless GC_DLL.
+      use_thread_local_alloc=$enable_thread_local_alloc
     fi
     if test "${enable_win32_dllmain}" = yes; then
       AC_DEFINE(GC_INSIDE_DLL, 1,
@@ -309,12 +299,8 @@ case "$THREADS" in
     AC_MSG_RESULT($THREADDLLIBS)
     # Use pthread GCC switch
     THREADDLLIBS=-pthread
-    if test "${enable_parallel_mark}" != no; then
-        AC_DEFINE(PARALLEL_MARK)
-    fi
-    if test "${enable_thread_local_alloc}" != no; then
-        AC_DEFINE(THREAD_LOCAL_ALLOC)
-    fi
+    use_parallel_mark=$enable_parallel_mark
+    use_thread_local_alloc=$enable_thread_local_alloc
     AC_MSG_WARN("Explicit GC_INIT() calls may be required.")
     AM_CFLAGS="-pthread $AM_CFLAGS"
     ;;
@@ -323,22 +309,14 @@ case "$THREADS" in
     THREADDLLIBS=-lpthread
     AC_DEFINE(GC_THREADS)
     AC_DEFINE(_REENTRANT)
-    if test "${enable_parallel_mark}" != no; then
-      AC_DEFINE(PARALLEL_MARK)
-    fi
-    if test "${enable_thread_local_alloc}" != no; then
-      AC_DEFINE(THREAD_LOCAL_ALLOC)
-    fi
+    use_parallel_mark=$enable_parallel_mark
+    use_thread_local_alloc=$enable_thread_local_alloc
     ;;
  rtems)
     THREADS=posix
     AC_DEFINE(GC_THREADS)
-    if test "${enable_parallel_mark}" != no; then
-      AC_DEFINE(PARALLEL_MARK)
-    fi
-    if test "${enable_thread_local_alloc}" != no; then
-      AC_DEFINE(THREAD_LOCAL_ALLOC)
-    fi
+    use_parallel_mark=$enable_parallel_mark
+    use_thread_local_alloc=$enable_thread_local_alloc
     ;;
  decosf1 | irix | mach | os2 | solaris | dce | vxworks)
     AC_MSG_ERROR(thread package $THREADS not yet supported)
@@ -352,8 +330,6 @@ AM_CONDITIONAL(THREADS, test x$THREADS != xnone)
 AM_CONDITIONAL(PTHREADS, test x$THREADS = xposix)
 AM_CONDITIONAL(DARWIN_THREADS, test x$darwin_threads = xtrue)
 AM_CONDITIONAL(WIN32_THREADS, test x$win32_threads = xtrue)
-AM_CONDITIONAL(THREAD_LOCAL_ALLOC,
-            test x$enable_thread_local_alloc != xno -a x$THREADS != xnone)
 
 compiler_suncc=no
 pthread_start_standalone=no
@@ -856,40 +832,6 @@ if test "${enable_large_config}" = yes; then
               [Define to optimize for large heaps or root sets.])
 fi
 
-AC_ARG_ENABLE(handle-fork,
-    [AC_HELP_STRING([--enable-handle-fork[=yes|no|auto|manual]],
-                    [attempt to ensure a usable collector after fork()
-                     in multi-threaded programs (default: auto;
-                     manual: GC_atfork_prepare/parent/child should be
-                     called by the client)])])
-if test "${enable_handle_fork}" = yes; then
-    AC_DEFINE(HANDLE_FORK, 1,
-              [Define to install pthread_atfork() handlers by default.])
-elif test "${enable_handle_fork}" = no; then
-    AC_DEFINE(NO_HANDLE_FORK, 1,
-              [Prohibit installation of pthread_atfork() handlers.])
-elif test "${enable_handle_fork}" != manual -a x$THREADS = xposix; then
-    # If the option is omitted, pthread_atfork handlers are installed
-    # by default for the targets where pthread_atfork is known to work.
-    case "$host" in
-      *-*-android*)
-        # Android NDK does not provide pthread_atfork.
-        ;;
-      *-*-darwin*)
-        # The incremental mode (which is off if parallel marking) conflicts
-        # with fork handling on Darwin.
-        if test "${enable_parallel_mark}" != no; then
-          AC_DEFINE(HANDLE_FORK)
-        fi
-        ;;
-      *-*-aix* | *-*-cygwin* | *-*-freebsd* | *-*-haiku* | \
-      *-*-hpux11* | *-*-irix* | *-*-kfreebsd*-gnu | \
-      *-*-*linux* | *-*-netbsd* | *-*-openbsd* | *-*-osf* | *-*-solaris*)
-        AC_DEFINE(HANDLE_FORK)
-        ;;
-    esac
-fi
-
 dnl This is something of a hack.  When cross-compiling we turn off
 dnl some functionality.  We also enable the "small" configuration.
 dnl These is only correct when targeting an embedded system.  FIXME.
@@ -1124,11 +1066,62 @@ AS_IF([test x$with_libatomic_ops != xnone -a x$need_atomic_ops_asm != xtrue],
   AO_store_release(&x,AO_load_acquire(&x)+1)],
         [ AC_MSG_RESULT(yes) ],
         [ AC_MSG_RESULT(no)
+          use_thread_local_alloc=no
           AC_DEFINE([BASE_ATOMIC_OPS_EMULATED], [1],
                     [AO load, store and/or test-and-set primitives are
                      implemented in libatomic_ops using locks.]) ])
+      AS_IF([test x$use_parallel_mark != xno],
+        [ AC_MSG_CHECKING(
+                [for lock-free compare-and-swap and fetch-and-add primitives])
+          AC_TRY_LINK(
+ [#define AO_REQUIRE_CAS
+  #include "atomic_ops.h"],
+ [AO_t x=0;(void)AO_fetch_and_add(&x,1);(void)AO_compare_and_swap(&x,1,2)],
+                    [ AC_MSG_RESULT(yes) ],
+                    [ AC_MSG_RESULT(no)
+                      use_parallel_mark=no ]) ])
       CFLAGS="$old_CFLAGS" ])
 
+AS_IF([test x$use_parallel_mark != xno],
+      [ AC_DEFINE(PARALLEL_MARK) ])
+AS_IF([test x$use_thread_local_alloc != xno],
+      [ AC_DEFINE(THREAD_LOCAL_ALLOC) ])
+AM_CONDITIONAL(THREAD_LOCAL_ALLOC, test x$use_thread_local_alloc != xno)
+
+AC_ARG_ENABLE(handle-fork,
+    [ AC_HELP_STRING([--enable-handle-fork[=yes|no|auto|manual]],
+                     [attempt to ensure a usable collector after fork()
+                      in multi-threaded programs (default: auto;
+                      manual: GC_atfork_prepare/parent/child should be
+                      called by the client)]) ])
+if test "${enable_handle_fork}" = yes; then
+    AC_DEFINE(HANDLE_FORK, 1,
+              [Define to install pthread_atfork() handlers by default.])
+elif test "${enable_handle_fork}" = no; then
+    AC_DEFINE(NO_HANDLE_FORK, 1,
+              [Prohibit installation of pthread_atfork() handlers.])
+elif test "${enable_handle_fork}" != manual -a x$THREADS = xposix; then
+    # If the option is omitted, pthread_atfork handlers are installed
+    # by default for the targets where pthread_atfork is known to work.
+    case "$host" in
+      *-*-android*)
+        # Android NDK does not provide pthread_atfork.
+        ;;
+      *-*-darwin*)
+        # The incremental mode (which is off if parallel marking) conflicts
+        # with fork handling on Darwin.
+        if test x$use_parallel_mark != xno; then
+          AC_DEFINE(HANDLE_FORK)
+        fi
+        ;;
+      *-*-aix* | *-*-cygwin* | *-*-freebsd* | *-*-haiku* | \
+      *-*-hpux11* | *-*-irix* | *-*-kfreebsd*-gnu | \
+      *-*-*linux* | *-*-netbsd* | *-*-openbsd* | *-*-osf* | *-*-solaris*)
+        AC_DEFINE(HANDLE_FORK)
+        ;;
+    esac
+fi
+
 dnl Produce the Files
 dnl -----------------
 
index c301c4dd44f8ad5a4f09a32db7ae336fdfd848e2..15e798605668889766a1b291df3ed2714a07fdfd 100644 (file)
@@ -150,7 +150,7 @@ GC_INLINE mse * GC_push_obj(ptr_t obj, hdr * hhdr,  mse * mark_stack_top,
 /* Set mark bit, exit (using "break" statement) if it is already set.   */
 #ifdef USE_MARK_BYTES
 # if defined(PARALLEL_MARK) && defined(AO_HAVE_char_store) \
-     && !defined(AO_USE_PTHREAD_DEFS)
+     && !defined(BASE_ATOMIC_OPS_EMULATED)
     /* There is a race here, and we may set the bit twice in the        */
     /* concurrent case.  This can result in the object being pushed     */
     /* twice.  But that is only a performance issue.                    */