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.
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@
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)
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,
- # $Id: alpha_mach_dep.s,v 1.2 1993/01/18 22:54:51 dosser Exp $
.arch ev6
.text
.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; \
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
#! /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>.
#
# 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"
# 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.
# 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]...
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
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.
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 $@
# Define the identity of the package.
PACKAGE='gc'
- VERSION='6.5'
+ VERSION='6.6'
cat >>confdefs.h <<_ACEOF
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
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=$?
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
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
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
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
} >&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
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'`\\"
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
# 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
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
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@
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
- 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
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).
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 */
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() {
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@
/* */
/*********************************/
-#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 */
};
#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
+
/*********************************/
/* */
# 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
# if defined(__powerpc64__)
# define ALIGNMENT 8
# define CPP_WORDSZ 64
+# ifndef HBLKSIZE
+# define HBLKSIZE 4096
+# endif
# else
# define ALIGNMENT 4
# endif
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"
# 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"
# endif
# ifdef LINUX
# define OS_TYPE "LINUX"
-# define HEURISTIC1
+# define LINUX_STACKBOTTOM
# undef STACK_GRAN
# define STACK_GRAN 0x10000000
# define USE_GENERIC_PUSH_REGS
# 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
#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. */
# endif
# endif
+#if defined(RS6000) || defined(POWERPC)
+# include <ucontext.h>
+#endif
+
#if defined(__MWERKS__) && !defined(POWERPC)
asm static void PushMacRegisters()
# 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. */
# 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
// 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,
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. */
#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 */
}
# 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 */
#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
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;
/* 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);
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
/* 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) {
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) {
#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? */
# 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 */
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);
/* 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
# endif
}
+/* Defined in misc.c */
+extern CRITICAL_SECTION GC_write_cs;
+
void GC_stop_world()
{
DWORD thread_id = GetCurrentThreadId();
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) {
# endif
thread_table[i].suspended = TRUE;
}
+# ifndef CYGWIN32
+ LeaveCriticalSection(&GC_write_cs);
+# endif /* !CYGWIN32 */
}
void GC_start_world()