summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am10
-rw-r--r--Makefile.in7
-rw-r--r--alpha_mach_dep.S25
-rwxr-xr-xconfigure113
-rw-r--r--configure.in15
-rw-r--r--doc/Makefile.in2
-rw-r--r--doc/README2
-rw-r--r--doc/README.changes24
-rw-r--r--doc/README.linux4
-rw-r--r--dyn_load.c29
-rw-r--r--include/Makefile.in2
-rw-r--r--include/private/gc_priv.h21
-rw-r--r--include/private/gcconfig.h39
-rw-r--r--include/private/pthread_stop_world.h1
-rw-r--r--mach_dep.c4
-rw-r--r--os_dep.c86
-rw-r--r--pthread_stop_world.c62
-rw-r--r--pthread_support.c10
-rw-r--r--version.h2
-rwxr-xr-xwin32_threads.c9
20 files changed, 325 insertions, 142 deletions
diff --git a/Makefile.am b/Makefile.am
index 7ce6935..89594f9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -105,10 +105,18 @@ include/gc_pthread_redirects.h include/gc_config_macros.h \
include/gc_mark.h @addincludes@
## FIXME: we shouldn't have to do this, but automake forces us to.
+if COMPILER_XLC
+ ## XLC neither requires nor tolerates the unnecessary assembler goop
+ ASM_CPP_OPTIONS =
+else
+ ## We use -Wp,-P to strip #line directives. Irix `as' chokes on
+ ## these.
+ ASM_CPP_OPTIONS = -Wp,-P -x assembler-with-cpp
+endif
.s.lo:
## We use -Wp,-P to strip #line directives. Irix `as' chokes on
## these.
- $(LTCOMPILE) -Wp,-P -x assembler-with-cpp -c $<
+ $(LTCOMPILE) $(ASM_CPP_OPTIONS) -c $<
## We have our own definition of LTCOMPILE because we want to use our
## CFLAGS, not those passed in from the top level make.
diff --git a/Makefile.in b/Makefile.in
index 5a73b02..c89c84c 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -171,6 +171,8 @@ CCAS = @CCAS@
CCASFLAGS = @CCASFLAGS@ $(DEFS)
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
+COMPILER_XLC_FALSE = @COMPILER_XLC_FALSE@
+COMPILER_XLC_TRUE = @COMPILER_XLC_TRUE@
CPLUSPLUS_FALSE = @CPLUSPLUS_FALSE@
CPLUSPLUS_TRUE = @CPLUSPLUS_TRUE@
CPP = @CPP@
@@ -359,6 +361,8 @@ test_cpp_SOURCES = tests/test_cpp.cc
test_cpp_LDADD = ./libgc.la ./libgccpp.la $(THREADDLLIBS) $(UNWINDLIBS) $(EXTRA_TEST_LIBS)
TESTS = gctest $(extra_checks)
all_objs = @addobjs@ $(libgc_la_OBJECTS)
+@COMPILER_XLC_FALSE@ASM_CPP_OPTIONS = -Wp,-P -x assembler-with-cpp
+@COMPILER_XLC_TRUE@ASM_CPP_OPTIONS =
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(MY_CFLAGS) $(GC_CFLAGS)
@@ -1051,9 +1055,8 @@ $(all_objs) : include/private/gcconfig.h include/private/gc_priv.h \
include/private/gc_hdrs.h include/gc.h include/gc_gcj.h \
include/gc_pthread_redirects.h include/gc_config_macros.h \
include/gc_mark.h @addincludes@
-
.s.lo:
- $(LTCOMPILE) -Wp,-P -x assembler-with-cpp -c $<
+ $(LTCOMPILE) $(ASM_CPP_OPTIONS) -c $<
#
# :GOTCHA: GNU make rule for making .s out of .S is flawed,
diff --git a/alpha_mach_dep.S b/alpha_mach_dep.S
index 5354730..d4def24 100644
--- a/alpha_mach_dep.S
+++ b/alpha_mach_dep.S
@@ -1,4 +1,3 @@
- # $Id: alpha_mach_dep.s,v 1.2 1993/01/18 22:54:51 dosser Exp $
.arch ev6
.text
@@ -12,13 +11,13 @@ GC_push_regs:
.mask 0x04000000, 0
.frame $sp, 16, $26, 0
- # $0 integer result
- # $1-$8 temp regs - not preserved cross calls
- # $9-$15 call saved regs
- # $16-$21 argument regs - not preserved cross calls
- # $22-$28 temp regs - not preserved cross calls
- # $29 global pointer - not preserved cross calls
- # $30 stack pointer
+/* $0 integer result */
+/* $1-$8 temp regs - not preserved cross calls */
+/* $9-$15 call saved regs */
+/* $16-$21 argument regs - not preserved cross calls */
+/* $22-$28 temp regs - not preserved cross calls */
+/* $29 global pointer - not preserved cross calls */
+/* $30 stack pointer */
# define call_push(x) \
mov x, $16; \
@@ -33,12 +32,12 @@ GC_push_regs:
call_push($14)
call_push($15)
- # $f0-$f1 floating point results
- # $f2-$f9 call saved regs
- # $f10-$f30 temp regs - not preserved cross calls
+/* $f0-$f1 floating point results */
+/* $f2-$f9 call saved regs */
+/* $f10-$f30 temp regs - not preserved cross calls */
- # Use the most efficient transfer method for this hardware.
- # Bit 1 detects the FIX extension, which includes ftoit.
+ /* Use the most efficient transfer method for this hardware. */
+ /* Bit 1 detects the FIX extension, which includes ftoit. */
amask 2, $0
bne $0, $use_stack
diff --git a/configure b/configure
index 61f4146..059365d 100755
--- a/configure
+++ b/configure
@@ -1,7 +1,7 @@
#! /bin/sh
# From configure.in Revision: 1.2 .
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.59 for gc 6.5.
+# Generated by GNU Autoconf 2.59 for gc 6.6.
#
# Report bugs to <Hans.Boehm@hp.com>.
#
@@ -429,8 +429,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='gc'
PACKAGE_TARNAME='gc'
-PACKAGE_VERSION='6.5'
-PACKAGE_STRING='gc 6.5'
+PACKAGE_VERSION='6.6'
+PACKAGE_STRING='gc 6.6'
PACKAGE_BUGREPORT='Hans.Boehm@hp.com'
ac_unique_file="gcj_mlc.c"
@@ -471,7 +471,7 @@ ac_includes_default="\
# include <unistd.h>
#endif"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar GC_VERSION CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CCAS CCASFLAGS AR ac_ct_AR RANLIB ac_ct_RANLIB MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT GC_CFLAGS THREADDLLIBS POWERPC_DARWIN_TRUE POWERPC_DARWIN_FALSE EXTRA_TEST_LIBS target_all CPLUSPLUS_TRUE CPLUSPLUS_FALSE INCLUDES CXXINCLUDES addobjs addincludes addlibs addtests LN_S ECHO CPP EGREP LIBTOOL MY_CFLAGS UNWINDLIBS USE_LIBDIR_TRUE USE_LIBDIR_FALSE LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar GC_VERSION CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CCAS CCASFLAGS AR ac_ct_AR RANLIB ac_ct_RANLIB MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT GC_CFLAGS THREADDLLIBS POWERPC_DARWIN_TRUE POWERPC_DARWIN_FALSE COMPILER_XLC_TRUE COMPILER_XLC_FALSE EXTRA_TEST_LIBS target_all CPLUSPLUS_TRUE CPLUSPLUS_FALSE INCLUDES CXXINCLUDES addobjs addincludes addlibs addtests LN_S ECHO CPP EGREP LIBTOOL MY_CFLAGS UNWINDLIBS USE_LIBDIR_TRUE USE_LIBDIR_FALSE LIBOBJS LTLIBOBJS'
ac_subst_files=''
# Initialize some variables set by options.
@@ -956,7 +956,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures gc 6.5 to adapt to many kinds of systems.
+\`configure' configures gc 6.6 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1023,7 +1023,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of gc 6.5:";;
+ short | recursive ) echo "Configuration of gc 6.6:";;
esac
cat <<\_ACEOF
@@ -1167,7 +1167,7 @@ fi
test -n "$ac_init_help" && exit 0
if $ac_init_version; then
cat <<\_ACEOF
-gc configure 6.5
+gc configure 6.6
generated by GNU Autoconf 2.59
Copyright (C) 2003 Free Software Foundation, Inc.
@@ -1181,7 +1181,7 @@ cat >&5 <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by gc $as_me 6.5, which was
+It was created by gc $as_me 6.6, which was
generated by GNU Autoconf 2.59. Invocation command line was
$ $0 $@
@@ -1953,7 +1953,7 @@ fi
# Define the identity of the package.
PACKAGE='gc'
- VERSION='6.5'
+ VERSION='6.6'
cat >>confdefs.h <<_ACEOF
@@ -4184,13 +4184,83 @@ else
fi
+echo "$as_me:$LINENO: checking for xlc" >&5
+echo $ECHO_N "checking for xlc... $ECHO_C" >&6
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ #ifndef __xlC__
+ # error
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ compiler_xlc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+compiler_xlc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $compiler_xlc" >&5
+echo "${ECHO_T}$compiler_xlc" >&6
+
+
+if test $compiler_xlc = yes; then
+ COMPILER_XLC_TRUE=
+ COMPILER_XLC_FALSE='#'
+else
+ COMPILER_XLC_TRUE='#'
+ COMPILER_XLC_FALSE=
+fi
+
+if test $compiler_xlc = yes -a "$powerpc_darwin" = true; then
+ # the darwin stack-frame-walking code is completely broken on xlc
+ cat >>confdefs.h <<\_ACEOF
+#define DARWIN_DONT_PARSE_STACK 1
+_ACEOF
+
+fi
+
# We never want libdl on darwin. It is a fake libdl that just ends up making
# dyld calls anyway
case "$host" in
*-*-darwin*) ;;
*)
-
-echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+ echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6
if test "${ac_cv_lib_dl_dlopen+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -5982,7 +6052,7 @@ test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
case $host in
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 5985 "configure"' > conftest.$ac_ext
+ echo '#line 6055 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -6555,7 +6625,7 @@ chmod -w .
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
compiler_c_o=no
-if { (eval echo configure:6558: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
+if { (eval echo configure:6628: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
if test -s out/conftest.err; then
@@ -8482,7 +8552,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 8485 "configure"
+#line 8555 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -8580,7 +8650,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 8583 "configure"
+#line 8653 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -9910,6 +9980,13 @@ echo "$as_me: error: conditional \"POWERPC_DARWIN\" was never defined.
Usually this means the macro was only invoked conditionally." >&2;}
{ (exit 1); exit 1; }; }
fi
+if test -z "${COMPILER_XLC_TRUE}" && test -z "${COMPILER_XLC_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"COMPILER_XLC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"COMPILER_XLC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
if test -z "${CPLUSPLUS_TRUE}" && test -z "${CPLUSPLUS_FALSE}"; then
{ { echo "$as_me:$LINENO: error: conditional \"CPLUSPLUS\" was never defined.
Usually this means the macro was only invoked conditionally." >&5
@@ -10195,7 +10272,7 @@ _ASBOX
} >&5
cat >&5 <<_CSEOF
-This file was extended by gc $as_me 6.5, which was
+This file was extended by gc $as_me 6.6, which was
generated by GNU Autoconf 2.59. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -10253,7 +10330,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-gc config.status 6.5
+gc config.status 6.6
configured by $0, generated by GNU Autoconf 2.59,
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
@@ -10528,6 +10605,8 @@ s,@GC_CFLAGS@,$GC_CFLAGS,;t t
s,@THREADDLLIBS@,$THREADDLLIBS,;t t
s,@POWERPC_DARWIN_TRUE@,$POWERPC_DARWIN_TRUE,;t t
s,@POWERPC_DARWIN_FALSE@,$POWERPC_DARWIN_FALSE,;t t
+s,@COMPILER_XLC_TRUE@,$COMPILER_XLC_TRUE,;t t
+s,@COMPILER_XLC_FALSE@,$COMPILER_XLC_FALSE,;t t
s,@EXTRA_TEST_LIBS@,$EXTRA_TEST_LIBS,;t t
s,@target_all@,$target_all,;t t
s,@CPLUSPLUS_TRUE@,$CPLUSPLUS_TRUE,;t t
diff --git a/configure.in b/configure.in
index 1fd9ece..d81e2ea 100644
--- a/configure.in
+++ b/configure.in
@@ -17,7 +17,7 @@ dnl Process this file with autoconf to produce configure.
# Initialization
# ==============
-AC_INIT(gc,6.5,Hans.Boehm@hp.com)
+AC_INIT(gc,6.6,Hans.Boehm@hp.com)
## version must conform to [0-9]+[.][0-9]+(alpha[0-9]+)?
AC_CONFIG_SRCDIR(gcj_mlc.c)
AC_CANONICAL_TARGET
@@ -184,6 +184,19 @@ case "$host" in
esac
AM_CONDITIONAL(POWERPC_DARWIN,test x$powerpc_darwin = xtrue)
+AC_MSG_CHECKING(for xlc)
+AC_TRY_COMPILE([],[
+ #ifndef __xlC__
+ # error
+ #endif
+], [compiler_xlc=yes], [compiler_xlc=no])
+AC_MSG_RESULT($compiler_xlc)
+AM_CONDITIONAL(COMPILER_XLC,test $compiler_xlc = yes)
+if test $compiler_xlc = yes -a "$powerpc_darwin" = true; then
+ # the darwin stack-frame-walking code is completely broken on xlc
+ AC_DEFINE(DARWIN_DONT_PARSE_STACK)
+fi
+
# We never want libdl on darwin. It is a fake libdl that just ends up making
# dyld calls anyway
case "$host" in
diff --git a/doc/Makefile.in b/doc/Makefile.in
index c712a66..179cfad 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -86,6 +86,8 @@ CCAS = @CCAS@
CCASFLAGS = @CCASFLAGS@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
+COMPILER_XLC_FALSE = @COMPILER_XLC_FALSE@
+COMPILER_XLC_TRUE = @COMPILER_XLC_TRUE@
CPLUSPLUS_FALSE = @CPLUSPLUS_FALSE@
CPLUSPLUS_TRUE = @CPLUSPLUS_TRUE@
CPP = @CPP@
diff --git a/doc/README b/doc/README
index a65757e..a19cb30 100644
--- a/doc/README
+++ b/doc/README
@@ -28,7 +28,7 @@ are GPL'ed, but with an exception that should cover all uses in the
collector. (If you are concerned about such things, I recommend you look
at the notice in config.guess or ltmain.sh.)
-This is version 6.5 of a conservative garbage collector for C and C++.
+This is version 6.6 of a conservative garbage collector for C and C++.
You might find a more recent version of this at
diff --git a/doc/README.changes b/doc/README.changes
index 0bb4df5..97b0b68 100644
--- a/doc/README.changes
+++ b/doc/README.changes
@@ -2221,6 +2221,30 @@ Since GC6.4:
- Fix stack_size assertion in GC_pthread_create.
- Fix assertion in GC_steal_mark_stack.
+Since 6.5
+ - Fix CPU count detection for Irix and FreeBSD. (Thanks to Dan Bonachea.)
+ - Integrate Dan Bonachea's patch for the IBM XLC compiler on Darwin.
+ - Integrated Andreas Tobler's FreeBSD/PowerPC patch.
+ - Don't access the GC thread structure from the restart handler. It's
+ unsafe, since the handler may run too late. (Thanks to Ben Maurer for
+ tracking this down.)
+ - Applied Christian Thalinger's patch to change comment syntax in
+ alpha_mach_dep.S.
+ - Added test for GC_no_dls in GC_dyld_image_add for DARWIN. (Thanks to
+ Juan Jose Garcia Ripoli).
+ - Use LINUX_STACKBOTTOM for Linux/SH and LINUX/ARM. (Thanks to Sugioka
+ Toshinobu and Christian Thalinger.)
+ - Rewrote GC_parse_map_entry. This assumed a fixed column layout of
+ /proc/self/maps on Linux. This ceased to be true about 2 years ago.
+ The old code is probably quite problemetic with -DREDIRECT_MALLOC. It
+ is also used by default for IA64, though I haven't seen actual failures
+ there.
+ - More consistently define HBLKSIZE to 4096 on 64 bit architectures with
+ 4K pages. (Thanks to Andrew Haley.)
+ - With win32 threads, GC_stop_world needs to acquire GC_write_cs. (Thanks
+ to Ben Hutchings for the observation and patch.)
+ - Move up struct callinfo declaration to make gcc 4.0.2. happy.
+
To do:
- The USE_MUNMAP code should really use a separate data structure
indexed by physical page to keep track of time since last use of
diff --git a/doc/README.linux b/doc/README.linux
index 1d0fd4c..ec4e7e6 100644
--- a/doc/README.linux
+++ b/doc/README.linux
@@ -19,10 +19,10 @@ Linux threads. These should not be touched by the client program.
To use threads, you need to abide by the following requirements:
-1) You need to use LinuxThreads (which are included in libc6).
+1) You need to use LinuxThreads or NPTL (which are included in libc6).
The collector relies on some implementation details of the LinuxThreads
- package. It is unlikely that this code will work on other
+ package. This code may not work on other
pthread implementations (in particular it will *not* work with
MIT pthreads).
diff --git a/dyn_load.c b/dyn_load.c
index f8b4aa7..749bf82 100644
--- a/dyn_load.c
+++ b/dyn_load.c
@@ -1141,21 +1141,22 @@ static const char *GC_dyld_name_for_hdr(struct mach_header *hdr) {
static void GC_dyld_image_add(struct mach_header* hdr, unsigned long slide) {
unsigned long start,end,i;
const struct section *sec;
+ if (GC_no_dls) return;
for(i=0;i<sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]);i++) {
sec = getsectbynamefromheader(
hdr,GC_dyld_sections[i].seg,GC_dyld_sections[i].sect);
- if(sec == NULL || sec->size == 0) continue;
- start = slide + sec->addr;
- end = start + sec->size;
-# ifdef DARWIN_DEBUG
- GC_printf4("Adding section at %p-%p (%lu bytes) from image %s\n",
+ if(sec == NULL || sec->size == 0) continue;
+ start = slide + sec->addr;
+ end = start + sec->size;
+# ifdef DARWIN_DEBUG
+ GC_printf4("Adding section at %p-%p (%lu bytes) from image %s\n",
start,end,sec->size,GC_dyld_name_for_hdr(hdr));
-# endif
+# endif
GC_add_roots((char*)start,(char*)end);
- }
-# ifdef DARWIN_DEBUG
- GC_print_static_roots();
-# endif
+ }
+# ifdef DARWIN_DEBUG
+ GC_print_static_roots();
+# endif
}
/* This should never be called by a thread holding the lock */
@@ -1168,15 +1169,15 @@ static void GC_dyld_image_remove(struct mach_header* hdr, unsigned long slide) {
if(sec == NULL || sec->size == 0) continue;
start = slide + sec->addr;
end = start + sec->size;
-# ifdef DARWIN_DEBUG
+# ifdef DARWIN_DEBUG
GC_printf4("Removing section at %p-%p (%lu bytes) from image %s\n",
start,end,sec->size,GC_dyld_name_for_hdr(hdr));
# endif
GC_remove_roots((char*)start,(char*)end);
}
-# ifdef DARWIN_DEBUG
- GC_print_static_roots();
-# endif
+# ifdef DARWIN_DEBUG
+ GC_print_static_roots();
+# endif
}
void GC_register_dynamic_libraries() {
diff --git a/include/Makefile.in b/include/Makefile.in
index 1f6c7d2..271ad35 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -88,6 +88,8 @@ CCAS = @CCAS@
CCASFLAGS = @CCASFLAGS@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
+COMPILER_XLC_FALSE = @COMPILER_XLC_FALSE@
+COMPILER_XLC_TRUE = @COMPILER_XLC_TRUE@
CPLUSPLUS_FALSE = @CPLUSPLUS_FALSE@
CPLUSPLUS_TRUE = @CPLUSPLUS_TRUE@
CPP = @CPP@
diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h
index e5bd52b..3d634ce 100644
--- a/include/private/gc_priv.h
+++ b/include/private/gc_priv.h
@@ -258,17 +258,6 @@ typedef char * ptr_t; /* A generic pointer to which we can add */
/* */
/*********************************/
-#ifdef SAVE_CALL_CHAIN
-
-/* Fill in the pc and argument information for up to NFRAMES of my */
-/* callers. Ignore my frame and my callers frame. */
-struct callinfo;
-void GC_save_callers GC_PROTO((struct callinfo info[NFRAMES]));
-
-void GC_print_callers GC_PROTO((struct callinfo info[NFRAMES]));
-
-#endif
-
#ifdef NEED_CALLINFO
struct callinfo {
word ci_pc; /* Caller, not callee, pc */
@@ -282,6 +271,16 @@ void GC_print_callers GC_PROTO((struct callinfo info[NFRAMES]));
};
#endif
+#ifdef SAVE_CALL_CHAIN
+
+/* Fill in the pc and argument information for up to NFRAMES of my */
+/* callers. Ignore my frame and my callers frame. */
+void GC_save_callers GC_PROTO((struct callinfo info[NFRAMES]));
+
+void GC_print_callers GC_PROTO((struct callinfo info[NFRAMES]));
+
+#endif
+
/*********************************/
/* */
diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h
index 9546c20..c028e5d 100644
--- a/include/private/gcconfig.h
+++ b/include/private/gcconfig.h
@@ -249,6 +249,10 @@
# define POWERPC
# define mach_type_known
# endif
+# if defined(FREEBSD) && (defined(powerpc) || defined(__powerpc__))
+# define POWERPC
+# define mach_type_known
+# endif
# if defined(LINUX) && defined(__mc68000__)
# define M68K
# define mach_type_known
@@ -767,6 +771,9 @@
# if defined(__powerpc64__)
# define ALIGNMENT 8
# define CPP_WORDSZ 64
+# ifndef HBLKSIZE
+# define HBLKSIZE 4096
+# endif
# else
# define ALIGNMENT 4
# endif
@@ -814,6 +821,22 @@
should be looked into some more */
# define NO_PTHREAD_TRYLOCK
# endif
+# ifdef FREEBSD
+# define ALIGNMENT 4
+# define OS_TYPE "FREEBSD"
+# ifndef GC_FREEBSD_THREADS
+# define MPROTECT_VDB
+# endif
+# define SIG_SUSPEND SIGUSR1
+# define SIG_THR_RESTART SIGUSR2
+# define FREEBSD_STACKBOTTOM
+# ifdef __ELF__
+# define DYNAMIC_LOADING
+# endif
+ extern char etext[];
+ extern char * GC_FreeBSDGetDataStart();
+# define DATASTART GC_FreeBSDGetDataStart(0x1000, &etext)
+# endif
# ifdef NETBSD
# define ALIGNMENT 4
# define OS_TYPE "NETBSD"
@@ -1739,12 +1762,14 @@
# define MACH_TYPE "S390"
# define USE_GENERIC_PUSH_REGS
# ifndef __s390x__
-# define ALIGNMENT 4
-# define CPP_WORDSZ 32
+# define ALIGNMENT 4
+# define CPP_WORDSZ 32
# else
-# define ALIGNMENT 8
-# define CPP_WORDSZ 64
-# define HBLKSIZE 4096
+# define ALIGNMENT 8
+# define CPP_WORDSZ 64
+# endif
+# ifndef HBLKSIZE
+# define HBLKSIZE 4096
# endif
# ifdef LINUX
# define OS_TYPE "LINUX"
@@ -1784,7 +1809,7 @@
# endif
# ifdef LINUX
# define OS_TYPE "LINUX"
-# define HEURISTIC1
+# define LINUX_STACKBOTTOM
# undef STACK_GRAN
# define STACK_GRAN 0x10000000
# define USE_GENERIC_PUSH_REGS
@@ -1849,7 +1874,7 @@
# endif
# ifdef LINUX
# define OS_TYPE "LINUX"
-# define STACKBOTTOM ((ptr_t) 0x7c000000)
+# define LINUX_STACKBOTTOM
# define USE_GENERIC_PUSH_REGS
# define DYNAMIC_LOADING
# define SEARCH_FOR_DATA_START
diff --git a/include/private/pthread_stop_world.h b/include/private/pthread_stop_world.h
index 054c7a0..6f9197a 100644
--- a/include/private/pthread_stop_world.h
+++ b/include/private/pthread_stop_world.h
@@ -2,7 +2,6 @@
#define GC_PTHREAD_STOP_WORLD_H
struct thread_stop_info {
- int signal;
word last_stop_count; /* GC_last_stop_count value when thread */
/* last successfully handled a suspend */
/* signal. */
diff --git a/mach_dep.c b/mach_dep.c
index dca02a4..ba1e0b6 100644
--- a/mach_dep.c
+++ b/mach_dep.c
@@ -27,6 +27,10 @@
# endif
# endif
+#if defined(RS6000) || defined(POWERPC)
+# include <ucontext.h>
+#endif
+
#if defined(__MWERKS__) && !defined(POWERPC)
asm static void PushMacRegisters()
diff --git a/os_dep.c b/os_dep.c
index 358ab38..fb50a45 100644
--- a/os_dep.c
+++ b/os_dep.c
@@ -60,6 +60,10 @@
# include <signal.h>
# endif
+#if defined(LINUX) || defined(LINUX_STACKBOTTOM)
+# include <ctype.h>
+#endif
+
/* Blatantly OS dependent routines, except for those that are related */
/* to dynamic loading. */
@@ -80,7 +84,7 @@
# define NEED_FIND_LIMIT
# endif
-#if defined(FREEBSD) && defined(I386)
+#if defined(FREEBSD) && (defined(I386) || defined(powerpc) || defined(__powerpc__))
# include <machine/trap.h>
# if !defined(PCR)
# define NEED_FIND_LIMIT
@@ -245,30 +249,11 @@ word GC_apply_to_maps(word (*fn)(char *))
// XXXXXXXX-XXXXXXXX r-xp 00000000 30:05 260537 name of mapping...\n
// ^^^^^^^^ ^^^^^^^^ ^^^^ ^^
// start end prot maj_dev
-// 0 9 18 32
-//
-// For 64 bit ABIs:
-// 0 17 34 56
//
-// The parser is called with a pointer to the entry and the return value
-// is either NULL or is advanced to the next entry(the byte after the
-// trailing '\n'.)
+// Note that since about auguat 2003 kernels, the columns no longer have
+// fixed offsets on 64-bit kernels. Hence we no longer rely on fixed offsets
+// anywhere, which is safer anyway.
//
-#if CPP_WORDSZ == 32
-# define OFFSET_MAP_START 0
-# define OFFSET_MAP_END 9
-# define OFFSET_MAP_PROT 18
-# define OFFSET_MAP_MAJDEV 32
-# define ADDR_WIDTH 8
-#endif
-
-#if CPP_WORDSZ == 64
-# define OFFSET_MAP_START 0
-# define OFFSET_MAP_END 17
-# define OFFSET_MAP_PROT 34
-# define OFFSET_MAP_MAJDEV 56
-# define ADDR_WIDTH 16
-#endif
/*
* Assign various fields of the first line in buf_ptr to *start, *end,
@@ -277,36 +262,46 @@ word GC_apply_to_maps(word (*fn)(char *))
char *GC_parse_map_entry(char *buf_ptr, word *start, word *end,
char *prot_buf, unsigned int *maj_dev)
{
- char *tok;
+ char *start_start, *end_start, *prot_start, *maj_dev_start;
+ char *p;
+ char *endp;
if (buf_ptr == NULL || *buf_ptr == '\0') {
return NULL;
}
- memcpy(prot_buf, buf_ptr+OFFSET_MAP_PROT, 4);
- /* do the protections first. */
+ p = buf_ptr;
+ while (isspace(*p)) ++p;
+ start_start = p;
+ GC_ASSERT(isxdigit(*start_start));
+ *start = strtoul(start_start, &endp, 16); p = endp;
+ GC_ASSERT(*p=='-');
+
+ ++p;
+ end_start = p;
+ GC_ASSERT(isxdigit(*end_start));
+ *end = strtoul(end_start, &endp, 16); p = endp;
+ GC_ASSERT(isspace(*p));
+
+ while (isspace(*p)) ++p;
+ prot_start = p;
+ GC_ASSERT(*prot_start == 'r' || *prot_start == '-');
+ memcpy(prot_buf, prot_start, 4);
prot_buf[4] = '\0';
-
- if (prot_buf[1] == 'w') {/* we can skip all of this if it's not writable. */
-
- tok = buf_ptr;
- buf_ptr[OFFSET_MAP_START+ADDR_WIDTH] = '\0';
- *start = strtoul(tok, NULL, 16);
-
- tok = buf_ptr+OFFSET_MAP_END;
- buf_ptr[OFFSET_MAP_END+ADDR_WIDTH] = '\0';
- *end = strtoul(tok, NULL, 16);
-
- buf_ptr += OFFSET_MAP_MAJDEV;
- tok = buf_ptr;
- while (*buf_ptr != ':') buf_ptr++;
- *buf_ptr++ = '\0';
- *maj_dev = strtoul(tok, NULL, 16);
+ if (prot_buf[1] == 'w') {/* we can skip the rest if it's not writable. */
+ /* Skip past protection field to offset field */
+ while (!isspace(*p)) ++p; while (isspace(*p)) ++p;
+ GC_ASSERT(isxdigit(*p));
+ /* Skip past offset field, which we ignore */
+ while (!isspace(*p)) ++p; while (isspace(*p)) ++p;
+ maj_dev_start = p;
+ GC_ASSERT(isxdigit(*maj_dev_start));
+ *maj_dev = strtoul(maj_dev_start, NULL, 16);
}
- while (*buf_ptr && *buf_ptr++ != '\n');
+ while (*p && *p++ != '\n');
- return buf_ptr;
+ return p;
}
#endif /* Need to parse /proc/self/maps. */
@@ -855,7 +850,6 @@ ptr_t GC_get_stack_base()
#include <sys/types.h>
#include <sys/stat.h>
-#include <ctype.h>
# define STAT_SKIP 27 /* Number of fields preceding startstack */
/* field in /proc/self/stat */
@@ -1395,7 +1389,7 @@ int * etext_addr;
}
# endif
-# if defined(FREEBSD) && defined(I386) && !defined(PCR)
+# if defined(FREEBSD) && (defined(I386) || defined(powerpc) || defined(__powerpc__)) && !defined(PCR)
/* Its unclear whether this should be identical to the above, or */
/* whether it should apply to non-X86 architectures. */
/* For now we don't assume that there is always an empty page after */
diff --git a/pthread_stop_world.c b/pthread_stop_world.c
index d301f64..b9034dc 100644
--- a/pthread_stop_world.c
+++ b/pthread_stop_world.c
@@ -7,6 +7,11 @@
#include <semaphore.h>
#include <errno.h>
#include <unistd.h>
+#include <sys/time.h>
+#ifndef HPUX
+# include <sys/select.h>
+ /* Doesn't exist on HP/UX 11.11. */
+#endif
#if DEBUG_THREADS
@@ -66,7 +71,22 @@ void GC_remove_allowed_signals(sigset_t *set)
static sigset_t suspend_handler_mask;
-word GC_stop_count; /* Incremented at the beginning of GC_stop_world. */
+volatile sig_atomic_t GC_stop_count;
+ /* Incremented at the beginning of GC_stop_world. */
+
+volatile sig_atomic_t GC_world_is_stopped = FALSE;
+ /* FALSE ==> it is safe for threads to restart, i.e. */
+ /* they will see another suspend signal before they */
+ /* are expected to stop (unless they have voluntarily */
+ /* stopped). */
+
+void GC_brief_async_signal_safe_sleep()
+{
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000 * TIME_LIMIT / 2;
+ select(0, 0, 0, 0, &tv);
+}
#ifdef GC_OSF1_THREADS
GC_bool GC_retry_signals = TRUE;
@@ -175,16 +195,26 @@ void GC_suspend_handler_inner(ptr_t sig_arg)
/* this thread a SIG_THR_RESTART signal. */
/* SIG_THR_RESTART should be masked at this point. Thus there */
/* is no race. */
- do {
- me->stop_info.signal = 0;
- sigsuspend(&suspend_handler_mask); /* Wait for signal */
- } while (me->stop_info.signal != SIG_THR_RESTART);
+ /* We do not continue until we receive a SIG_THR_RESTART, */
+ /* but we do not take that as authoritative. (We may be */
+ /* accidentally restarted by one of the user signals we */
+ /* don't block.) After we receive the signal, we use a */
+ /* primitive and expensive mechanism to wait until it's */
+ /* really safe to proceed. Under normal circumstances, */
+ /* this code should not be executed. */
+ sigsuspend(&suspend_handler_mask); /* Wait for signal */
+ while (GC_world_is_stopped && GC_stop_count == my_stop_count) {
+ GC_brief_async_signal_safe_sleep();
+# if DEBUG_THREADS
+ GC_err_printf0("Sleeping in signal handler");
+# endif
+ }
/* If the RESTART signal gets lost, we can still lose. That should be */
/* less likely than losing the SUSPEND signal, since we don't do much */
/* between the sem_post and sigsuspend. */
- /* We'd need more handshaking to work around that, since we don't want */
- /* to accidentally leave a RESTART signal pending, thus causing us to */
- /* continue prematurely in a future round. */
+ /* We'd need more handshaking to work around that. */
+ /* Simply dropping the sigsuspend call should be safe, but is unlikely */
+ /* to be efficient. */
#if DEBUG_THREADS
GC_printf1("Continuing 0x%lx\n", my_thread);
@@ -194,20 +224,11 @@ void GC_suspend_handler_inner(ptr_t sig_arg)
void GC_restart_handler(int sig)
{
pthread_t my_thread = pthread_self();
- GC_thread me;
if (sig != SIG_THR_RESTART) ABORT("Bad signal in suspend_handler");
- /* Let the GC_suspend_handler() know that we got a SIG_THR_RESTART. */
- /* The lookup here is safe, since I'm doing this on behalf */
- /* of a thread which holds the allocation lock in order */
- /* to stop the world. Thus concurrent modification of the */
- /* data structure is impossible. */
- me = GC_lookup_thread(my_thread);
- me->stop_info.signal = SIG_THR_RESTART;
-
/*
- ** Note: even if we didn't do anything useful here,
+ ** Note: even if we don't do anything useful here,
** it would still be necessary to have a signal handler,
** rather than ignoring the signals, otherwise
** the signals will not be delivered at all, and
@@ -360,6 +381,7 @@ void GC_stop_world()
/* We should have previously waited for it to become zero. */
# endif /* PARALLEL_MARK */
++GC_stop_count;
+ GC_world_is_stopped = TRUE;
n_live_threads = GC_suspend_all();
if (GC_retry_signals) {
@@ -422,6 +444,7 @@ void GC_start_world()
GC_printf0("World starting\n");
# endif
+ GC_world_is_stopped = FALSE;
for (i = 0; i < THREAD_TABLE_SZ; i++) {
for (p = GC_threads[i]; p != 0; p = p -> next) {
if (p -> id != my_thread) {
@@ -431,8 +454,7 @@ void GC_start_world()
#if DEBUG_THREADS
GC_printf1("Sending restart signal to 0x%lx\n", p -> id);
#endif
-
- result = pthread_kill(p -> id, SIG_THR_RESTART);
+ result = pthread_kill(p -> id, SIG_THR_RESTART);
switch(result) {
case ESRCH:
/* Not really there anymore. Possible? */
diff --git a/pthread_support.c b/pthread_support.c
index 5eba6f7..5b3808e 100644
--- a/pthread_support.c
+++ b/pthread_support.c
@@ -116,7 +116,7 @@
# include <semaphore.h>
#endif /* !GC_DARWIN_THREADS */
-#if defined(GC_DARWIN_THREADS)
+#if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS)
# include <sys/sysctl.h>
#endif /* GC_DARWIN_THREADS */
@@ -877,11 +877,11 @@ void GC_thr_init()
GC_nprocs = sysconf(_SC_NPROCESSORS_ONLN);
if (GC_nprocs <= 0) GC_nprocs = 1;
# endif
-# if defined(GC_FREEBSD_THREADS) || defined(GC_IRIX_THREADS)
- /* FIXME: For Irix, that's a ridiculous assumption. */
- GC_nprocs = 1;
+# if defined(GC_IRIX_THREADS)
+ GC_nprocs = sysconf(_SC_NPROC_ONLN);
+ if (GC_nprocs <= 0) GC_nprocs = 1;
# endif
-# if defined(GC_DARWIN_THREADS)
+# if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS)
int ncpus = 1;
size_t len = sizeof(ncpus);
sysctl((int[2]) {CTL_HW, HW_NCPU}, 2, &ncpus, &len, NULL, 0);
diff --git a/version.h b/version.h
index 3d1c606..e1fe24b 100644
--- a/version.h
+++ b/version.h
@@ -2,7 +2,7 @@
/* Eventually this one may become unnecessary. For now we need */
/* it to keep the old-style build process working. */
#define GC_TMP_VERSION_MAJOR 6
-#define GC_TMP_VERSION_MINOR 5
+#define GC_TMP_VERSION_MINOR 6
#define GC_TMP_ALPHA_VERSION GC_NOT_ALPHA
#ifndef GC_NOT_ALPHA
diff --git a/win32_threads.c b/win32_threads.c
index 9fa75a4..ba53d86 100755
--- a/win32_threads.c
+++ b/win32_threads.c
@@ -233,6 +233,9 @@ void GC_push_thread_structures GC_PROTO((void))
# endif
}
+/* Defined in misc.c */
+extern CRITICAL_SECTION GC_write_cs;
+
void GC_stop_world()
{
DWORD thread_id = GetCurrentThreadId();
@@ -241,6 +244,9 @@ void GC_stop_world()
if (!GC_thr_initialized) ABORT("GC_stop_world() called before GC_thr_init()");
GC_please_stop = TRUE;
+# ifndef CYGWIN32
+ EnterCriticalSection(&GC_write_cs);
+# endif /* !CYGWIN32 */
for (i = 0; i <= GC_get_max_thread_index(); i++)
if (thread_table[i].stack_base != 0
&& thread_table[i].id != thread_id) {
@@ -271,6 +277,9 @@ void GC_stop_world()
# endif
thread_table[i].suspended = TRUE;
}
+# ifndef CYGWIN32
+ LeaveCriticalSection(&GC_write_cs);
+# endif /* !CYGWIN32 */
}
void GC_start_world()