Makefile.am, [...]: Imported GC 6.0 and merged local changes.

* Makefile.am, acinclude.m4, configure.in: Imported GC 6.0 and
	merged local changes.

From-SVN: r44994
This commit is contained in:
Tom Tromey 2001-08-18 01:04:43 +00:00 committed by Tom Tromey
parent eed5666980
commit 5a2586cf8f
42 changed files with 1279 additions and 712 deletions

View File

@ -1,3 +1,8 @@
2001-08-17 Tom Tromey <tromey@redhat.com>
* Makefile.am, acinclude.m4, configure.in: Imported GC 6.0 and
merged local changes.
2001-08-02 David Billinghurst <David.Billinghurst>
* configure: Rebuilt.

View File

@ -37,13 +37,13 @@ libgcjgc_la_LIBADD = @addobjs@ $(THREADLIBS)
libgcjgc_la_DEPENDENCIES = @addobjs@
libgcjgc_la_LDFLAGS = -version-info 1:1:0 -rpath $(toolexeclibdir)
EXTRA_libgcjgc_la_SOURCES = alpha_mach_dep.s hpux_test_and_clear.s \
EXTRA_libgcjgc_la_SOURCES = alpha_mach_dep.s \
mips_sgi_mach_dep.s mips_ultrix_mach_dep.s powerpc_macosx_mach_dep.s \
rs6000_mach_dep.s sparc_mach_dep.s sparc_netbsd_mach_dep.s \
sparc_sunos4_mach_dep.s
AM_CXXFLAGS = @BOEHM_GC_CFLAGS@
AM_CFLAGS = @BOEHM_GC_CFLAGS@
AM_CXXFLAGS = @GC_CFLAGS@
AM_CFLAGS = @GC_CFLAGS@
check_PROGRAMS = gctest
# The following hack produces a warning from automake, but we need it in order
@ -71,10 +71,10 @@ include/private/gc_hdrs.h include/gc.h include/gc_gcj.h include/gc_mark.h
## CFLAGS, not those passed in from the top level make.
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(MY_CFLAGS) $(BOEHM_GC_CFLAGS)
$(AM_CFLAGS) $(MY_CFLAGS) $(GC_CFLAGS)
LINK = $(LIBTOOL) --mode=link $(CC) $(AM_CFLAGS) $(MY_CFLAGS) $(LDFLAGS) -o $@
AM_CFLAGS = @BOEHM_GC_CFLAGS@
AM_CFLAGS = @GC_CFLAGS@
# Work around what appears to be a GNU make bug handling MAKEFLAGS
# values defined in terms of make variables, as is the case for CC and

View File

@ -62,10 +62,11 @@ CFLAGS= -O -I$(srcdir)/include -DATOMIC_UNCOLLECTABLE -DNO_SIGNALS -DALL_INTERIO
# code from the heap. Currently this only affects the incremental
# collector on UNIX machines. It may greatly improve its performance,
# since this may avoid some expensive cache synchronization.
# -DOPERATOR_NEW_ARRAY declares that the C++ compiler supports the
# new syntax "operator new[]" for allocating and deleting arrays.
# -DGC_NO_OPERATOR_NEW_ARRAY declares that the C++ compiler does not support
# the new syntax "operator new[]" for allocating and deleting arrays.
# See gc_cpp.h for details. No effect on the C part of the collector.
# This is defined implicitly in a few environments.
# This is defined implicitly in a few environments. Must also be defined
# by clients that use gc_cpp.h.
# -DREDIRECT_MALLOC=X causes malloc, realloc, and free to be defined
# as aliases for X, GC_realloc, and GC_free, respectively.
# Calloc is redefined in terms of the new malloc. X should

View File

@ -65,7 +65,6 @@ target_alias = @target_alias@
target_triplet = @target@
AR = @AR@
AS = @AS@
BOEHM_GC_CFLAGS = @BOEHM_GC_CFLAGS@
CC = @CC@
CPP = @CPP@
CXX = @CXX@
@ -76,6 +75,7 @@ EXEEXT = @EXEEXT@
EXTRA_TEST_LIBS = @EXTRA_TEST_LIBS@
GCJ = @GCJ@
GCJFLAGS = @GCJFLAGS@
GC_CFLAGS = @GC_CFLAGS@
INCLUDES = @INCLUDES@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
@ -90,7 +90,7 @@ STRIP = @STRIP@
THREADLIBS = @THREADLIBS@
VERSION = @VERSION@
addobjs = @addobjs@
boehm_gc_basedir = @boehm_gc_basedir@
gc_basedir = @gc_basedir@
mkinstalldirs = @mkinstalldirs@
target_all = @target_all@
@ -125,15 +125,15 @@ libgcjgc_la_LIBADD = @addobjs@ $(THREADLIBS)
libgcjgc_la_DEPENDENCIES = @addobjs@
libgcjgc_la_LDFLAGS = -version-info 1:1:0 -rpath $(toolexeclibdir)
EXTRA_libgcjgc_la_SOURCES = alpha_mach_dep.s hpux_test_and_clear.s \
EXTRA_libgcjgc_la_SOURCES = alpha_mach_dep.s \
mips_sgi_mach_dep.s mips_ultrix_mach_dep.s powerpc_macosx_mach_dep.s \
rs6000_mach_dep.s sparc_mach_dep.s sparc_netbsd_mach_dep.s \
sparc_sunos4_mach_dep.s
AM_CXXFLAGS = @BOEHM_GC_CFLAGS@
AM_CXXFLAGS = @GC_CFLAGS@
AM_CFLAGS = @BOEHM_GC_CFLAGS@
AM_CFLAGS = @GC_CFLAGS@
check_PROGRAMS = gctest
gctest_OBJECTS = test.o
@ -146,7 +146,7 @@ all_objs = @addobjs@ $(libgcjgc_la_OBJECTS)
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(MY_CFLAGS) $(BOEHM_GC_CFLAGS)
$(AM_CFLAGS) $(MY_CFLAGS) $(GC_CFLAGS)
LINK = $(LIBTOOL) --mode=link $(CC) $(AM_CFLAGS) $(MY_CFLAGS) $(LDFLAGS) -o $@
@ -216,7 +216,8 @@ CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
DIST_COMMON = ChangeLog Makefile.am Makefile.in acinclude.m4 aclocal.m4 \
configure configure.in
config.guess config.sub configure configure.in install-sh ltconfig \
ltmain.sh mkinstalldirs
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)

View File

@ -1,10 +1,23 @@
# Copyright (c) 1999-2001 by Red Hat, Inc. All rights reserved.
#
# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
# OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
#
# Permission is hereby granted to use or copy this program
# for any purpose, provided the above notices are retained on all copies.
# Permission to modify the code and to distribute modified code is granted,
# provided the above notices are retained, and a notice that the code was
# modified is included with the above copyright notice.
#
# Original author: Tom Tromey
# FIXME: We temporarily define our own version of AC_PROG_CC. This is
# copied from autoconf 2.12, but does not call AC_PROG_CC_WORKS. We
# are probably using a cross compiler, which will not be able to fully
# link an executable. This should really be fixed in autoconf
# itself.
AC_DEFUN(BOEHM_CONFIGURE,
AC_DEFUN(GC_CONFIGURE,
[
dnl Default to --enable-multilib
AC_ARG_ENABLE(multilib,
@ -18,17 +31,18 @@ AC_ARG_ENABLE(multilib,
dnl We may get other options which we don't document:
dnl --with-target-subdir, --with-multisrctop, --with-multisubdir
dnl I needed to add the -n test to allow configuration in src directory - HB
if test "[$]{srcdir}" = "."; then
if test "[$]{with_target_subdir}" != "."; then
boehm_gc_basedir="[$]{srcdir}/[$]{with_multisrctop}../$1"
if test "[$]{with_target_subdir}" != "." -a -n "[$]{with_target_subdir}"; then
gc_basedir="[$]{srcdir}/[$]{with_multisrctop}../$1"
else
boehm_gc_basedir="[$]{srcdir}/[$]{with_multisrctop}$1"
gc_basedir="[$]{srcdir}/[$]{with_multisrctop}$1"
fi
else
boehm_gc_basedir="[$]{srcdir}/$1"
gc_basedir="[$]{srcdir}/$1"
fi
AC_SUBST(boehm_gc_basedir)
AC_CONFIG_AUX_DIR($boehm_gc_basedir/..)
AC_SUBST(gc_basedir)
AC_CONFIG_AUX_DIR($gc_basedir/..)
if :; then :; else
# This overrides the previous occurrence for automake, but not for
# autoconf, which is exactly what we want.
@ -41,7 +55,7 @@ AC_CANONICAL_SYSTEM
mkinstalldirs="`cd $ac_aux_dir && pwd`/mkinstalldirs"
AC_SUBST(mkinstalldirs)
AM_INIT_AUTOMAKE(boehm-gc, 5.1, no-define)
AM_INIT_AUTOMAKE(gc, 6.0, no-define)
# FIXME: We temporarily define our own version of AC_PROG_CC. This is
# copied from autoconf 2.12, but does not call AC_PROG_CC_WORKS. We
@ -150,22 +164,22 @@ fi
. [$]{srcdir}/configure.host
case [$]{boehm_gc_basedir} in
/* | [A-Za-z]:[/\\]*) boehm_gc_flagbasedir=[$]{boehm_gc_basedir} ;;
*) boehm_gc_flagbasedir='[$](top_builddir)/'[$]{boehm_gc_basedir} ;;
case [$]{gc_basedir} in
/* | [A-Za-z]:[/\\]*) gc_flagbasedir=[$]{gc_basedir} ;;
*) gc_flagbasedir='[$](top_builddir)/'[$]{gc_basedir} ;;
esac
boehm_gc_cflags="[$]{boehm_gc_cflags} -I"'[$](top_builddir)'"/$1/targ-include -I[$]{boehm_gc_flagbasedir}/libc/include"
gc_cflags="[$]{gc_cflags} -I"'[$](top_builddir)'"/$1/targ-include -I[$]{gc_flagbasedir}/libc/include"
case "${host}" in
*-*-cygwin32*)
boehm_gc_cflags="[$]{boehm_gc_cflags} -I[$]{boehm_gc_flagbasedir}/../winsup/include"
gc_cflags="[$]{gc_cflags} -I[$]{gc_flagbasedir}/../winsup/include"
;;
esac
boehm_gc_cflags="[$]{boehm_gc_cflags} -fno-builtin"
dnl gc_cflags="[$]{gc_cflags} -fno-builtin"
BOEHM_GC_CFLAGS=${boehm_gc_cflags}
AC_SUBST(BOEHM_GC_CFLAGS)
GC_CFLAGS=${gc_cflags}
AC_SUBST(GC_CFLAGS)
]))
))))

46
boehm-gc/aclocal.m4 vendored
View File

@ -10,13 +10,26 @@ dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
dnl PARTICULAR PURPOSE.
# Copyright (c) 1999-2001 by Red Hat, Inc. All rights reserved.
#
# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
# OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
#
# Permission is hereby granted to use or copy this program
# for any purpose, provided the above notices are retained on all copies.
# Permission to modify the code and to distribute modified code is granted,
# provided the above notices are retained, and a notice that the code was
# modified is included with the above copyright notice.
#
# Original author: Tom Tromey
# FIXME: We temporarily define our own version of AC_PROG_CC. This is
# copied from autoconf 2.12, but does not call AC_PROG_CC_WORKS. We
# are probably using a cross compiler, which will not be able to fully
# link an executable. This should really be fixed in autoconf
# itself.
AC_DEFUN(BOEHM_CONFIGURE,
AC_DEFUN(GC_CONFIGURE,
[
dnl Default to --enable-multilib
AC_ARG_ENABLE(multilib,
@ -30,17 +43,18 @@ AC_ARG_ENABLE(multilib,
dnl We may get other options which we don't document:
dnl --with-target-subdir, --with-multisrctop, --with-multisubdir
dnl I needed to add the -n test to allow configuration in src directory - HB
if test "[$]{srcdir}" = "."; then
if test "[$]{with_target_subdir}" != "."; then
boehm_gc_basedir="[$]{srcdir}/[$]{with_multisrctop}../$1"
if test "[$]{with_target_subdir}" != "." -a -n "[$]{with_target_subdir}"; then
gc_basedir="[$]{srcdir}/[$]{with_multisrctop}../$1"
else
boehm_gc_basedir="[$]{srcdir}/[$]{with_multisrctop}$1"
gc_basedir="[$]{srcdir}/[$]{with_multisrctop}$1"
fi
else
boehm_gc_basedir="[$]{srcdir}/$1"
gc_basedir="[$]{srcdir}/$1"
fi
AC_SUBST(boehm_gc_basedir)
AC_CONFIG_AUX_DIR($boehm_gc_basedir/..)
AC_SUBST(gc_basedir)
AC_CONFIG_AUX_DIR($gc_basedir/..)
if :; then :; else
# This overrides the previous occurrence for automake, but not for
# autoconf, which is exactly what we want.
@ -53,7 +67,7 @@ AC_CANONICAL_SYSTEM
mkinstalldirs="`cd $ac_aux_dir && pwd`/mkinstalldirs"
AC_SUBST(mkinstalldirs)
AM_INIT_AUTOMAKE(boehm-gc, 5.1, no-define)
AM_INIT_AUTOMAKE(gc, 6.0, no-define)
# FIXME: We temporarily define our own version of AC_PROG_CC. This is
# copied from autoconf 2.12, but does not call AC_PROG_CC_WORKS. We
@ -162,22 +176,22 @@ fi
. [$]{srcdir}/configure.host
case [$]{boehm_gc_basedir} in
/* | [A-Za-z]:[/\\]*) boehm_gc_flagbasedir=[$]{boehm_gc_basedir} ;;
*) boehm_gc_flagbasedir='[$](top_builddir)/'[$]{boehm_gc_basedir} ;;
case [$]{gc_basedir} in
/* | [A-Za-z]:[/\\]*) gc_flagbasedir=[$]{gc_basedir} ;;
*) gc_flagbasedir='[$](top_builddir)/'[$]{gc_basedir} ;;
esac
boehm_gc_cflags="[$]{boehm_gc_cflags} -I"'[$](top_builddir)'"/$1/targ-include -I[$]{boehm_gc_flagbasedir}/libc/include"
gc_cflags="[$]{gc_cflags} -I"'[$](top_builddir)'"/$1/targ-include -I[$]{gc_flagbasedir}/libc/include"
case "${host}" in
*-*-cygwin32*)
boehm_gc_cflags="[$]{boehm_gc_cflags} -I[$]{boehm_gc_flagbasedir}/../winsup/include"
gc_cflags="[$]{gc_cflags} -I[$]{gc_flagbasedir}/../winsup/include"
;;
esac
boehm_gc_cflags="[$]{boehm_gc_cflags} -fno-builtin"
dnl gc_cflags="[$]{gc_cflags} -fno-builtin"
BOEHM_GC_CFLAGS=${boehm_gc_cflags}
AC_SUBST(BOEHM_GC_CFLAGS)
GC_CFLAGS=${gc_cflags}
AC_SUBST(GC_CFLAGS)
]))
))))

View File

@ -1,4 +1,5 @@
# include <stdio.h>
# include "version.h"
int main(argc, argv, envp)
int argc;
@ -8,7 +9,12 @@ char ** envp;
int i;
for (i = 1; i < argc; i++) {
printf("gc/%s ", argv[i]);
if (GC_ALPHA_VERSION == GC_NOT_ALPHA) {
printf("gc%d.%d/%s ", GC_VERSION_MAJOR, GC_VERSION_MINOR, argv[i]);
} else {
printf("gc%d.%dalpha%d/%s ", GC_VERSION_MAJOR,
GC_VERSION_MINOR, GC_ALPHA_VERSION, argv[i]);
}
}
return(0);
}

View File

@ -627,7 +627,8 @@ int n;
while ((ptr_t)lasthbp <= search_end
&& (thishbp = GC_is_black_listed(lasthbp,
(word)eff_size_needed))) {
(word)eff_size_needed))
!= 0) {
lasthbp = thishbp;
}
size_avail -= (ptr_t)lasthbp - (ptr_t)hbp;
@ -654,7 +655,7 @@ int n;
&& orig_avail - size_needed
> (signed_word)BL_LIMIT) {
/* Punt, since anything else risks unreasonable heap growth. */
if (0 != GETENV("GC_NO_BLACKLIST_WARNING")) {
if (0 == GETENV("GC_NO_BLACKLIST_WARNING")) {
WARN("Needed to allocate blacklisted block at 0x%lx\n",
(word)hbp);
}

View File

@ -105,7 +105,7 @@ CLOCK_TYPE GC_start_time; /* Time at which we stopped world. */
int GC_n_attempts = 0; /* Number of attempts at finishing */
/* collection within TIME_LIMIT */
#ifdef SMALL_CONFIG
#if defined(SMALL_CONFIG) || defined(NO_CLOCK)
# define GC_timeout_stop_func GC_never_stop_func
#else
int GC_timeout_stop_func GC_PROTO((void))
@ -250,7 +250,11 @@ void GC_maybe_gc()
GC_gcollect_inner();
n_partial_gcs = 0;
return;
} else if (GC_need_full_gc || n_partial_gcs >= GC_full_freq) {
} else {
# ifdef PARALLEL_MARK
GC_wait_for_reclaim();
# endif
if (GC_need_full_gc || n_partial_gcs >= GC_full_freq) {
# ifdef CONDPRINT
if (GC_print_stats) {
GC_printf2(
@ -260,23 +264,21 @@ void GC_maybe_gc()
}
# endif
GC_promote_black_lists();
# ifdef PARALLEL_MARK
GC_wait_for_reclaim();
# endif
(void)GC_reclaim_all((GC_stop_func)0, TRUE);
GC_clear_marks();
n_partial_gcs = 0;
GC_notify_full_gc();
GC_is_full_gc = TRUE;
} else {
} else {
n_partial_gcs++;
}
}
}
/* We try to mark with the world stopped. */
/* If we run out of time, this turns into */
/* incremental marking. */
#ifndef NO_CLOCK
GET_TIME(GC_start_time);
#endif
# ifndef NO_CLOCK
GET_TIME(GC_start_time);
# endif
if (GC_stopped_mark(GC_timeout_stop_func)) {
# ifdef SAVE_CALL_CHAIN
GC_save_callers(GC_last_stack);
@ -367,7 +369,7 @@ GC_stop_func stop_func;
# define GC_RATE 10
# define MAX_PRIOR_ATTEMPTS 1
/* Maximum number of prior attempts at world stop marking */
/* A value of 1 means that we finish the seconf time, no matter */
/* A value of 1 means that we finish the second time, no matter */
/* how long it takes. Doesn't count the initial root scan */
/* for a full GC. */
@ -386,6 +388,9 @@ int n;
# ifdef SAVE_CALL_CHAIN
GC_save_callers(GC_last_stack);
# endif
# ifdef PARALLEL_MARK
GC_wait_for_reclaim();
# endif
if (GC_n_attempts < MAX_PRIOR_ATTEMPTS) {
GET_TIME(GC_start_time);
if (!GC_stopped_mark(GC_timeout_stop_func)) {
@ -506,6 +511,57 @@ GC_stop_func stop_func;
return(TRUE);
}
/* Set all mark bits for the free list whose first entry is q */
#ifdef __STDC__
void GC_set_fl_marks(ptr_t q)
#else
void GC_set_fl_marks(q)
ptr_t q;
#endif
{
ptr_t p;
struct hblk * h, * last_h = 0;
hdr *hhdr;
int word_no;
for (p = q; p != 0; p = obj_link(p)){
h = HBLKPTR(p);
if (h != last_h) {
last_h = h;
hhdr = HDR(h);
}
word_no = (((word *)p) - ((word *)h));
set_mark_bit_from_hdr(hhdr, word_no);
}
}
/* Clear all mark bits for the free list whose first entry is q */
/* Decrement GC_mem_found by number of words on free list. */
#ifdef __STDC__
void GC_clear_fl_marks(ptr_t q)
#else
void GC_clear_fl_marks(q)
ptr_t q;
#endif
{
ptr_t p;
struct hblk * h, * last_h = 0;
hdr *hhdr;
int word_no;
for (p = q; p != 0; p = obj_link(p)){
h = HBLKPTR(p);
if (h != last_h) {
last_h = h;
hhdr = HDR(h);
}
word_no = (((word *)p) - ((word *)h));
clear_mark_bit_from_hdr(hhdr, word_no);
# ifdef GATHERSTATS
GC_mem_found -= hhdr -> hb_sz;
# endif
}
}
/* Finish up a collection. Assumes lock is held, signals are disabled, */
/* but the world is otherwise running. */
@ -533,21 +589,13 @@ void GC_finish_collection()
/* marked when we're done. */
{
register word size; /* current object size */
register ptr_t p; /* pointer to current object */
register struct hblk * h; /* pointer to block containing *p */
register hdr * hhdr;
register int word_no; /* "index" of *p in *q */
int kind;
ptr_t q;
for (kind = 0; kind < GC_n_kinds; kind++) {
for (size = 1; size <= MAXOBJSZ; size++) {
for (p= GC_obj_kinds[kind].ok_freelist[size];
p != 0; p=obj_link(p)){
h = HBLKPTR(p);
hhdr = HDR(h);
word_no = (((word *)p) - ((word *)h));
set_mark_bit_from_hdr(hhdr, word_no);
}
q = GC_obj_kinds[kind].ok_freelist[size];
if (q != 0) GC_set_fl_marks(q);
}
}
}
@ -565,32 +613,20 @@ void GC_finish_collection()
# endif
/* Clear free list mark bits, in case they got accidentally marked */
/* Note: HBLKPTR(p) == pointer to head of block containing *p */
/* (or GC_find_leak is set and they were intentionally marked.) */
/* (or GC_find_leak is set and they were intentionally marked). */
/* Also subtract memory remaining from GC_mem_found count. */
/* Note that composite objects on free list are cleared. */
/* Thus accidentally marking a free list is not a problem; only */
/* objects on the list itself will be marked, and that's fixed here. */
{
register word size; /* current object size */
register ptr_t p; /* pointer to current object */
register struct hblk * h; /* pointer to block containing *p */
register hdr * hhdr;
register int word_no; /* "index" of *p in *q */
register ptr_t q; /* pointer to current object */
int kind;
for (kind = 0; kind < GC_n_kinds; kind++) {
for (size = 1; size <= MAXOBJSZ; size++) {
for (p= GC_obj_kinds[kind].ok_freelist[size];
p != 0; p=obj_link(p)){
h = HBLKPTR(p);
hhdr = HDR(h);
word_no = (((word *)p) - ((word *)h));
clear_mark_bit_from_hdr(hhdr, word_no);
# ifdef GATHERSTATS
GC_mem_found -= size;
# endif
}
q = GC_obj_kinds[kind].ok_freelist[size];
if (q != 0) GC_clear_fl_marks(q);
}
}
}

330
boehm-gc/configure vendored
View File

@ -37,9 +37,13 @@ ac_help="$ac_help
--enable-maintainer-mode enable make rules and dependencies not useful
(and sometimes confusing) to the casual installer"
ac_help="$ac_help
--enable-java-gc=TYPE choose garbage collector [boehm]"
--enable-threads=TYPE choose threading package"
ac_help="$ac_help
--enable-parallel-mark parallelize marking and free list construction"
ac_help="$ac_help
--with-ecos enable runtime eCos target support"
ac_help="$ac_help
--enable-full-debug include full support for pointer backtracing etc."
# Initialize some variables set by options.
# The variables have the same names as the options, with
@ -562,6 +566,26 @@ fi
ac_aux_dir=
for ac_dir in . $srcdir/.; do
if test -f $ac_dir/install-sh; then
ac_aux_dir=$ac_dir
ac_install_sh="$ac_aux_dir/install-sh -c"
break
elif test -f $ac_dir/install.sh; then
ac_aux_dir=$ac_dir
ac_install_sh="$ac_aux_dir/install.sh -c"
break
fi
done
if test -z "$ac_aux_dir"; then
{ echo "configure: error: can not find install-sh or install.sh in . $srcdir/." 1>&2; exit 1; }
fi
ac_config_guess=$ac_aux_dir/config.guess
ac_config_sub=$ac_aux_dir/config.sub
ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
# Find a good install program. We prefer a C program (faster),
# so one script is as good as another. But avoid the broken or
# incompatible versions:
@ -574,7 +598,7 @@ fi
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
echo "configure:578: checking for a BSD compatible install" >&5
echo "configure:602: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@ -627,7 +651,7 @@ test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
echo "configure:631: checking whether build environment is sane" >&5
echo "configure:655: checking whether build environment is sane" >&5
# Just in case
sleep 1
echo timestamp > conftestfile
@ -684,7 +708,7 @@ test "$program_suffix" != NONE &&
test "$program_transform_name" = "" && program_transform_name="s,x,x,"
echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
echo "configure:688: checking whether ${MAKE-make} sets \${MAKE}" >&5
echo "configure:712: checking whether ${MAKE-make} sets \${MAKE}" >&5
set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@ -717,12 +741,12 @@ else
fi
echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6
echo "configure:721: checking for Cygwin environment" >&5
echo "configure:745: checking for Cygwin environment" >&5
if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 726 "configure"
#line 750 "configure"
#include "confdefs.h"
int main() {
@ -733,7 +757,7 @@ int main() {
return __CYGWIN__;
; return 0; }
EOF
if { (eval echo configure:737: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:761: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_cygwin=yes
else
@ -750,19 +774,19 @@ echo "$ac_t""$ac_cv_cygwin" 1>&6
CYGWIN=
test "$ac_cv_cygwin" = yes && CYGWIN=yes
echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6
echo "configure:754: checking for mingw32 environment" >&5
echo "configure:778: checking for mingw32 environment" >&5
if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 759 "configure"
#line 783 "configure"
#include "confdefs.h"
int main() {
return __MINGW32__;
; return 0; }
EOF
if { (eval echo configure:766: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:790: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_mingw32=yes
else
@ -793,17 +817,17 @@ fi
if test "${srcdir}" = "."; then
if test "${with_target_subdir}" != "."; then
boehm_gc_basedir="${srcdir}/${with_multisrctop}../."
if test "${with_target_subdir}" != "." -a -n "${with_target_subdir}"; then
gc_basedir="${srcdir}/${with_multisrctop}../."
else
boehm_gc_basedir="${srcdir}/${with_multisrctop}."
gc_basedir="${srcdir}/${with_multisrctop}."
fi
else
boehm_gc_basedir="${srcdir}/."
gc_basedir="${srcdir}/."
fi
ac_aux_dir=
for ac_dir in $boehm_gc_basedir/.. $srcdir/$boehm_gc_basedir/..; do
for ac_dir in $gc_basedir/.. $srcdir/$gc_basedir/..; do
if test -f $ac_dir/install-sh; then
ac_aux_dir=$ac_dir
ac_install_sh="$ac_aux_dir/install-sh -c"
@ -815,7 +839,7 @@ for ac_dir in $boehm_gc_basedir/.. $srcdir/$boehm_gc_basedir/..; do
fi
done
if test -z "$ac_aux_dir"; then
{ echo "configure: error: can not find install-sh or install.sh in $boehm_gc_basedir/.. $srcdir/$boehm_gc_basedir/.." 1>&2; exit 1; }
{ echo "configure: error: can not find install-sh or install.sh in $gc_basedir/.. $srcdir/$gc_basedir/.." 1>&2; exit 1; }
fi
ac_config_guess=$ac_aux_dir/config.guess
ac_config_sub=$ac_aux_dir/config.sub
@ -873,7 +897,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
fi
echo $ac_n "checking host system type""... $ac_c" 1>&6
echo "configure:877: checking host system type" >&5
echo "configure:901: checking host system type" >&5
host_alias=$host
case "$host_alias" in
@ -894,7 +918,7 @@ host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$host" 1>&6
echo $ac_n "checking target system type""... $ac_c" 1>&6
echo "configure:898: checking target system type" >&5
echo "configure:922: checking target system type" >&5
target_alias=$target
case "$target_alias" in
@ -912,7 +936,7 @@ target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$target" 1>&6
echo $ac_n "checking build system type""... $ac_c" 1>&6
echo "configure:916: checking build system type" >&5
echo "configure:940: checking build system type" >&5
build_alias=$build
case "$build_alias" in
@ -940,9 +964,9 @@ mkinstalldirs="`cd $ac_aux_dir && pwd`/mkinstalldirs"
PACKAGE=boehm-gc
PACKAGE=gc
VERSION=5.1
VERSION=6.0
if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
{ echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; }
@ -952,7 +976,7 @@ fi
missing_dir=`cd $ac_aux_dir && pwd`
echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
echo "configure:956: checking for working aclocal" >&5
echo "configure:980: checking for working aclocal" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
@ -965,7 +989,7 @@ else
fi
echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
echo "configure:969: checking for working autoconf" >&5
echo "configure:993: checking for working autoconf" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
@ -978,7 +1002,7 @@ else
fi
echo $ac_n "checking for working automake""... $ac_c" 1>&6
echo "configure:982: checking for working automake" >&5
echo "configure:1006: checking for working automake" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
@ -991,7 +1015,7 @@ else
fi
echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
echo "configure:995: checking for working autoheader" >&5
echo "configure:1019: checking for working autoheader" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
@ -1004,7 +1028,7 @@ else
fi
echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
echo "configure:1008: checking for working makeinfo" >&5
echo "configure:1032: checking for working makeinfo" >&5
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
@ -1030,7 +1054,7 @@ fi
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1034: checking for $ac_word" >&5
echo "configure:1058: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1060,7 +1084,7 @@ if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1064: checking for $ac_word" >&5
echo "configure:1088: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1109,7 +1133,7 @@ fi
fi
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
echo "configure:1113: checking whether we are using GNU C" >&5
echo "configure:1137: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1118,7 +1142,7 @@ else
yes;
#endif
EOF
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1122: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1146: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gcc=yes
else
ac_cv_prog_gcc=no
@ -1133,7 +1157,7 @@ if test $ac_cv_prog_gcc = yes; then
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
echo "configure:1137: checking whether ${CC-cc} accepts -g" >&5
echo "configure:1161: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1170,7 +1194,7 @@ do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1174: checking for $ac_word" >&5
echo "configure:1198: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1203,7 +1227,7 @@ test -n "$CXX" || CXX="gcc"
test -z "$CXX" && { echo "configure: error: no acceptable c++ found in \$PATH" 1>&2; exit 1; }
echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6
echo "configure:1207: checking whether we are using GNU C++" >&5
echo "configure:1231: checking whether we are using GNU C++" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1212,7 +1236,7 @@ else
yes;
#endif
EOF
if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:1216: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:1240: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gxx=yes
else
ac_cv_prog_gxx=no
@ -1227,7 +1251,7 @@ if test $ac_cv_prog_gxx = yes; then
ac_save_CXXFLAGS="$CXXFLAGS"
CXXFLAGS=
echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6
echo "configure:1231: checking whether ${CXX-g++} accepts -g" >&5
echo "configure:1255: checking whether ${CXX-g++} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1260,7 +1284,7 @@ fi
# NEWLIB_CONFIGURE, which doesn't work because that means that it will
# be run before AC_CANONICAL_HOST.
echo $ac_n "checking build system type""... $ac_c" 1>&6
echo "configure:1264: checking build system type" >&5
echo "configure:1288: checking build system type" >&5
build_alias=$build
case "$build_alias" in
@ -1281,7 +1305,7 @@ echo "$ac_t""$build" 1>&6
# Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args.
set dummy ${ac_tool_prefix}as; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1285: checking for $ac_word" >&5
echo "configure:1309: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_AS'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1313,7 +1337,7 @@ fi
# Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
set dummy ${ac_tool_prefix}ar; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1317: checking for $ac_word" >&5
echo "configure:1341: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1345,7 +1369,7 @@ fi
# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
set dummy ${ac_tool_prefix}ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1349: checking for $ac_word" >&5
echo "configure:1373: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1377,7 +1401,7 @@ if test -n "$ac_tool_prefix"; then
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1381: checking for $ac_word" >&5
echo "configure:1405: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1422,7 +1446,7 @@ fi
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
echo "configure:1426: checking for a BSD compatible install" >&5
echo "configure:1450: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@ -1476,7 +1500,7 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6
echo "configure:1480: checking whether to enable maintainer-specific portions of Makefiles" >&5
echo "configure:1504: checking whether to enable maintainer-specific portions of Makefiles" >&5
# Check whether --enable-maintainer-mode or --disable-maintainer-mode was given.
if test "${enable_maintainer_mode+set}" = set; then
enableval="$enable_maintainer_mode"
@ -1514,7 +1538,7 @@ if false; then
echo $ac_n "checking for executable suffix""... $ac_c" 1>&6
echo "configure:1518: checking for executable suffix" >&5
echo "configure:1542: checking for executable suffix" >&5
if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1524,7 +1548,7 @@ else
rm -f conftest*
echo 'int main () { return 0; }' > conftest.$ac_ext
ac_cv_exeext=
if { (eval echo configure:1528: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
if { (eval echo configure:1552: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
for file in conftest.*; do
case $file in
*.c | *.o | *.obj | *.ilk | *.pdb) ;;
@ -1548,21 +1572,20 @@ fi
. ${srcdir}/configure.host
case ${boehm_gc_basedir} in
/* | A-Za-z:/\\*) boehm_gc_flagbasedir=${boehm_gc_basedir} ;;
*) boehm_gc_flagbasedir='$(top_builddir)/'${boehm_gc_basedir} ;;
case ${gc_basedir} in
/* | A-Za-z:/\\*) gc_flagbasedir=${gc_basedir} ;;
*) gc_flagbasedir='$(top_builddir)/'${gc_basedir} ;;
esac
boehm_gc_cflags="${boehm_gc_cflags} -I"'$(top_builddir)'"/./targ-include -I${boehm_gc_flagbasedir}/libc/include"
gc_cflags="${gc_cflags} -I"'$(top_builddir)'"/./targ-include -I${gc_flagbasedir}/libc/include"
case "${host}" in
*-*-cygwin32*)
boehm_gc_cflags="${boehm_gc_cflags} -I${boehm_gc_flagbasedir}/../winsup/include"
gc_cflags="${gc_cflags} -I${gc_flagbasedir}/../winsup/include"
;;
esac
boehm_gc_cflags="${boehm_gc_cflags} -fno-builtin"
BOEHM_GC_CFLAGS=${boehm_gc_cflags}
GC_CFLAGS=${gc_cflags}
@ -1647,7 +1670,7 @@ ac_prog=ld
if test "$GCC" = yes; then
# Check if gcc -print-prog-name=ld gives a path.
echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6
echo "configure:1651: checking for ld used by GCC" >&5
echo "configure:1674: checking for ld used by GCC" >&5
case $host in
*-*-mingw*)
# gcc leaves a trailing carriage return which upsets mingw
@ -1677,10 +1700,10 @@ echo "configure:1651: checking for ld used by GCC" >&5
esac
elif test "$with_gnu_ld" = yes; then
echo $ac_n "checking for GNU ld""... $ac_c" 1>&6
echo "configure:1681: checking for GNU ld" >&5
echo "configure:1704: checking for GNU ld" >&5
else
echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
echo "configure:1684: checking for non-GNU ld" >&5
echo "configure:1707: checking for non-GNU ld" >&5
fi
if eval "test \"`echo '$''{'lt_cv_path_LD'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@ -1715,7 +1738,7 @@ else
fi
test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; }
echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6
echo "configure:1719: checking if the linker ($LD) is GNU ld" >&5
echo "configure:1742: checking if the linker ($LD) is GNU ld" >&5
if eval "test \"`echo '$''{'lt_cv_prog_gnu_ld'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1732,7 +1755,7 @@ with_gnu_ld=$lt_cv_prog_gnu_ld
echo $ac_n "checking for $LD option to reload object files""... $ac_c" 1>&6
echo "configure:1736: checking for $LD option to reload object files" >&5
echo "configure:1759: checking for $LD option to reload object files" >&5
if eval "test \"`echo '$''{'lt_cv_ld_reload_flag'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1744,7 +1767,7 @@ reload_flag=$lt_cv_ld_reload_flag
test -n "$reload_flag" && reload_flag=" $reload_flag"
echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6
echo "configure:1748: checking for BSD-compatible nm" >&5
echo "configure:1771: checking for BSD-compatible nm" >&5
if eval "test \"`echo '$''{'lt_cv_path_NM'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1782,7 +1805,7 @@ NM="$lt_cv_path_NM"
echo "$ac_t""$NM" 1>&6
echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
echo "configure:1786: checking whether ln -s works" >&5
echo "configure:1809: checking whether ln -s works" >&5
if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1803,7 +1826,7 @@ else
fi
echo $ac_n "checking how to recognise dependant libraries""... $ac_c" 1>&6
echo "configure:1807: checking how to recognise dependant libraries" >&5
echo "configure:1830: checking how to recognise dependant libraries" >&5
if eval "test \"`echo '$''{'lt_cv_deplibs_check_method'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1967,13 +1990,13 @@ file_magic_cmd=$lt_cv_file_magic_cmd
deplibs_check_method=$lt_cv_deplibs_check_method
echo $ac_n "checking for object suffix""... $ac_c" 1>&6
echo "configure:1971: checking for object suffix" >&5
echo "configure:1994: checking for object suffix" >&5
if eval "test \"`echo '$''{'ac_cv_objext'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
rm -f conftest*
echo 'int i = 1;' > conftest.$ac_ext
if { (eval echo configure:1977: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:2000: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
for ac_file in conftest.*; do
case $ac_file in
*.c) ;;
@ -1997,7 +2020,7 @@ case $deplibs_check_method in
file_magic*)
if test "$file_magic_cmd" = '$MAGIC_CMD'; then
echo $ac_n "checking for ${ac_tool_prefix}file""... $ac_c" 1>&6
echo "configure:2001: checking for ${ac_tool_prefix}file" >&5
echo "configure:2024: checking for ${ac_tool_prefix}file" >&5
if eval "test \"`echo '$''{'lt_cv_path_MAGIC_CMD'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -2059,7 +2082,7 @@ fi
if test -z "$lt_cv_path_MAGIC_CMD"; then
if test -n "$ac_tool_prefix"; then
echo $ac_n "checking for file""... $ac_c" 1>&6
echo "configure:2063: checking for file" >&5
echo "configure:2086: checking for file" >&5
if eval "test \"`echo '$''{'lt_cv_path_MAGIC_CMD'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -2130,7 +2153,7 @@ esac
# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
set dummy ${ac_tool_prefix}ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:2134: checking for $ac_word" >&5
echo "configure:2157: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -2162,7 +2185,7 @@ if test -n "$ac_tool_prefix"; then
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:2166: checking for $ac_word" >&5
echo "configure:2189: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -2197,7 +2220,7 @@ fi
# Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
set dummy ${ac_tool_prefix}strip; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:2201: checking for $ac_word" >&5
echo "configure:2224: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_STRIP'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -2229,7 +2252,7 @@ if test -n "$ac_tool_prefix"; then
# Extract the first word of "strip", so it can be a program name with args.
set dummy strip; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:2233: checking for $ac_word" >&5
echo "configure:2256: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_STRIP'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -2296,8 +2319,8 @@ test x"$pic_mode" = xno && libtool_flags="$libtool_flags --prefer-non-pic"
case $host in
*-*-irix6*)
# Find out which ABI we are using.
echo '#line 2300 "configure"' > conftest.$ac_ext
if { (eval echo configure:2301: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
echo '#line 2323 "configure"' > conftest.$ac_ext
if { (eval echo configure:2324: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
case `/usr/bin/file conftest.$ac_objext` in
*32-bit*)
LD="${LD-ld} -32"
@ -2318,7 +2341,7 @@ case $host in
SAVE_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -belf"
echo $ac_n "checking whether the C compiler needs -belf""... $ac_c" 1>&6
echo "configure:2322: checking whether the C compiler needs -belf" >&5
echo "configure:2345: checking whether the C compiler needs -belf" >&5
if eval "test \"`echo '$''{'lt_cv_cc_needs_belf'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -2331,14 +2354,14 @@ ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$a
cross_compiling=$ac_cv_prog_cc_cross
cat > conftest.$ac_ext <<EOF
#line 2335 "configure"
#line 2358 "configure"
#include "confdefs.h"
int main() {
; return 0; }
EOF
if { (eval echo configure:2342: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:2365: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
lt_cv_cc_needs_belf=yes
else
@ -2368,7 +2391,7 @@ echo "$ac_t""$lt_cv_cc_needs_belf" 1>&6
esac
echo $ac_n "checking how to run the C++ preprocessor""... $ac_c" 1>&6
echo "configure:2372: checking how to run the C++ preprocessor" >&5
echo "configure:2395: checking how to run the C++ preprocessor" >&5
if test -z "$CXXCPP"; then
if eval "test \"`echo '$''{'ac_cv_prog_CXXCPP'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@ -2381,12 +2404,12 @@ ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftes
cross_compiling=$ac_cv_prog_cxx_cross
CXXCPP="${CXX-g++} -E"
cat > conftest.$ac_ext <<EOF
#line 2385 "configure"
#line 2408 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2390: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:2413: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@ -2533,7 +2556,7 @@ fi
echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6
echo "configure:2537: checking whether to enable maintainer-specific portions of Makefiles" >&5
echo "configure:2560: checking whether to enable maintainer-specific portions of Makefiles" >&5
# Check whether --enable-maintainer-mode or --disable-maintainer-mode was given.
if test "${enable_maintainer_mode+set}" = set; then
enableval="$enable_maintainer_mode"
@ -2566,7 +2589,7 @@ if false; then
echo $ac_n "checking for executable suffix""... $ac_c" 1>&6
echo "configure:2570: checking for executable suffix" >&5
echo "configure:2593: checking for executable suffix" >&5
if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -2576,7 +2599,7 @@ else
rm -f conftest*
echo 'int main () { return 0; }' > conftest.$ac_ext
ac_cv_exeext=
if { (eval echo configure:2580: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
if { (eval echo configure:2603: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
for file in conftest.*; do
case $file in
*.c | *.o | *.obj | *.ilk | *.pdb) ;;
@ -2598,10 +2621,34 @@ ac_exeext=$EXEEXT
fi
echo $ac_n "checking for thread model used by GCC""... $ac_c" 1>&6
echo "configure:2603: checking for thread model used by GCC" >&5
THREADS=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
echo "$ac_t""$THREADS" 1>&6
echo $ac_n "checking for threads package to use""... $ac_c" 1>&6
echo "configure:2626: checking for threads package to use" >&5
# Check whether --enable-threads or --disable-threads was given.
if test "${enable_threads+set}" = set; then
enableval="$enable_threads"
THREADS=$enableval
else
echo $ac_n "checking for thread model used by GCC""... $ac_c" 1>&6
echo "configure:2633: checking for thread model used by GCC" >&5
THREADS=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
if test -z "$THREADS"; then
THREADS=no
fi
echo "$ac_t""$THREADS" 1>&6
fi
# Check whether --enable-parallel-mark or --disable-parallel-mark was given.
if test "${enable_parallel_mark+set}" = set; then
enableval="$enable_parallel_mark"
case "$THREADS" in
no | none | single)
{ echo "configure: error: Parallel mark requires --enable-threads=x spec" 1>&2; exit 1; }
;;
esac
fi
INCLUDES=-I${srcdir}/include
THREADLIBS=
@ -2613,15 +2660,57 @@ case "$THREADS" in
THREADS=posix
THREADLIBS=-lpthread
case "$host" in
*-*-linux*)
x86-*-linux* | ia64-*-linux* | i586-*-linux* | i686-*-linux*)
cat >> confdefs.h <<\EOF
#define LINUX_THREADS 1
#define GC_LINUX_THREADS 1
EOF
cat >> confdefs.h <<\EOF
#define _REENTRANT 1
EOF
if test "${enable_parallel_mark}"; then
cat >> confdefs.h <<\EOF
#define PARALLEL_MARK 1
EOF
fi
cat >> confdefs.h <<\EOF
#define THREAD_LOCAL_ALLOC 1
EOF
;;
*-*-linux*)
cat >> confdefs.h <<\EOF
#define GC_LINUX_THREADS 1
EOF
cat >> confdefs.h <<\EOF
#define _REENTRANT 1
EOF
;;
*-*-hpux*)
echo "configure: warning: "Only HP/UX 11 threads are supported."" 1>&2
cat >> confdefs.h <<\EOF
#define GC_HPUX_THREADS 1
EOF
cat >> confdefs.h <<\EOF
#define _POSIX_C_SOURCE 199506L
EOF
if test "${enable_parallel_mark}" = yes; then
cat >> confdefs.h <<\EOF
#define PARALLEL_MARK 1
EOF
fi
cat >> confdefs.h <<\EOF
#define THREAD_LOCAL_ALLOC 1
EOF
THREADLIBS="-lpthread -lrt"
;;
*-*-freebsd*)
echo "configure: warning: "FreeBSD does not yet fully support threads with Boehm GC."" 1>&2
@ -2634,17 +2723,17 @@ EOF
;;
*-*-solaris*)
cat >> confdefs.h <<\EOF
#define SOLARIS_THREADS 1
#define GC_SOLARIS_THREADS 1
EOF
cat >> confdefs.h <<\EOF
#define _SOLARIS_PTHREADS 1
#define GC_SOLARIS_PTHREADS 1
EOF
;;
*-*-irix*)
cat >> confdefs.h <<\EOF
#define IRIX_THREADS 1
#define GC_IRIX_THREADS 1
EOF
;;
@ -2663,7 +2752,7 @@ esac
echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
echo "configure:2667: checking for dlopen in -ldl" >&5
echo "configure:2756: checking for dlopen in -ldl" >&5
ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@ -2671,7 +2760,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-ldl $LIBS"
cat > conftest.$ac_ext <<EOF
#line 2675 "configure"
#line 2764 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@ -2682,7 +2771,7 @@ int main() {
dlopen()
; return 0; }
EOF
if { (eval echo configure:2686: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:2775: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@ -2704,19 +2793,7 @@ fi
# Check whether --enable-java-gc or --disable-java-gc was given.
if test "${enable_java_gc+set}" = set; then
enableval="$enable_java_gc"
GC=$enableval
else
GC=boehm
fi
target_all=
if test "$GC" = "boehm"; then
target_all=libgcjgc.la
fi
target_all=libgcjgc.la
TARGET_ECOS="no"
@ -2815,6 +2892,15 @@ cat >> confdefs.h <<\EOF
#define NO_SIGNALS 1
EOF
cat >> confdefs.h <<\EOF
#define NO_EXECUTE_PERMISSION 1
EOF
cat >> confdefs.h <<\EOF
#define ALL_INTERIOR_POINTERS 1
EOF
cat >> confdefs.h <<\EOF
#define JAVA_FINALIZATION 1
EOF
@ -2823,6 +2909,10 @@ cat >> confdefs.h <<\EOF
#define GC_GCJ_SUPPORT 1
EOF
cat >> confdefs.h <<\EOF
#define ATOMIC_UNCOLLECTABLE 1
EOF
if test -n "${with_cross_host}"; then
cat >> confdefs.h <<\EOF
@ -2843,6 +2933,32 @@ EOF
fi
# Check whether --enable-full-debug or --disable-full-debug was given.
if test "${enable_full_debug+set}" = set; then
enableval="$enable_full_debug"
if test "$enable_full_debug" = "yes"; then
echo "configure: warning: "Must define GC_DEBUG and use debug alloc. in clients."" 1>&2
cat >> confdefs.h <<\EOF
#define KEEP_BACK_PTRS 1
EOF
cat >> confdefs.h <<\EOF
#define DBG_HDRS_ALL 1
EOF
case $host in
x86-*-linux* | i586-*-linux* | i686-*-linux* )
echo "configure: warning: "Client must not use -fomit-frame-pointer."" 1>&2
cat >> confdefs.h <<\EOF
#define SAVE_CALL_COUNT 8
EOF
;;
esac
fi
fi
if test -z "$with_cross_host"; then
@ -3004,7 +3120,7 @@ s%@includedir@%$includedir%g
s%@oldincludedir@%$oldincludedir%g
s%@infodir@%$infodir%g
s%@mandir@%$mandir%g
s%@boehm_gc_basedir@%$boehm_gc_basedir%g
s%@gc_basedir@%$gc_basedir%g
s%@host@%$host%g
s%@host_alias@%$host_alias%g
s%@host_cpu@%$host_cpu%g
@ -3041,7 +3157,7 @@ s%@MAINTAINER_MODE_TRUE@%$MAINTAINER_MODE_TRUE%g
s%@MAINTAINER_MODE_FALSE@%$MAINTAINER_MODE_FALSE%g
s%@MAINT@%$MAINT%g
s%@EXEEXT@%$EXEEXT%g
s%@BOEHM_GC_CFLAGS@%$BOEHM_GC_CFLAGS%g
s%@GC_CFLAGS@%$GC_CFLAGS%g
s%@LN_S@%$LN_S%g
s%@OBJEXT@%$OBJEXT%g
s%@STRIP@%$STRIP%g
@ -3164,7 +3280,7 @@ target=${target}
with_multisubdir=${with_multisubdir}
ac_configure_args="${multilib_arg} ${ac_configure_args}"
CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
boehm_gc_basedir=${boehm_gc_basedir}
gc_basedir=${gc_basedir}
CC="${CC}"
DEFS="$DEFS"
@ -3174,7 +3290,7 @@ cat >> $CONFIG_STATUS <<\EOF
echo "$DEFS" > boehm-cflags
if test -n "$CONFIG_FILES"; then
ac_file=Makefile . ${boehm_gc_basedir}/../config-ml.in
ac_file=Makefile . ${gc_basedir}/../config-ml.in
fi
exit 0
EOF

View File

@ -1,6 +1,7 @@
# configure.host
# This shell script handles all host based configuration for boehm_gc.
# This shell script handles all host based configuration for the garbage
# collector.
# It sets various shell variables based on the the host and the
# configuration options. You can modify this shell script without
# needing to rerun autoconf.
@ -15,16 +16,25 @@
# target_optspace --enable-target-optspace ("yes", "no", "")
# It sets the following shell variables:
# boehm_gc_cflags Special CFLAGS to use when building
# gc_cflags Special CFLAGS to use when building
boehm_gc_cflags=-fexceptions
# We should set -fexceptions if we are using gcc and might be used
# inside something like gcj. This is the zeroth approximation:
case "$host" in
*-*-linux* )
gc_cflags=-fexceptions
;;
*-*-hpux* )
gc_cflags=+ESdbgasm
;;
esac
case "${target_optspace}:${host}" in
yes:*)
boehm_gc_cflags="${boehm_gc_cflags} -Os"
gc_cflags="${gc_cflags} -Os"
;;
:m32r-* | :d10v-* | :d30v-*)
boehm_gc_cflags="${boehm_gc_cflags} -Os"
gc_cflags="${gc_cflags} -Os"
;;
no:* | :*)
# Nothing.

View File

@ -1,8 +1,24 @@
# Copyright (c) 1999-2001 by Red Hat, Inc. All rights reserved.
#
# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
# OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
#
# Permission is hereby granted to use or copy this program
# for any purpose, provided the above notices are retained on all copies.
# Permission to modify the code and to distribute modified code is granted,
# provided the above notices are retained, and a notice that the code was
# modified is included with the above copyright notice.
#
# Original author: Tom Tromey
dnl Process this file with autoconf to produce configure.
AC_INIT(gcj_mlc.c)
BOEHM_CONFIGURE(.)
dnl Can't be done in GC_CONFIGURE because that confuses automake.
AC_CONFIG_AUX_DIR(.)
GC_CONFIGURE(.)
AM_PROG_LIBTOOL
@ -25,9 +41,24 @@ if false; then
AC_EXEEXT
fi
AC_MSG_CHECKING([for thread model used by GCC])
THREADS=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
AC_MSG_RESULT([$THREADS])
AC_MSG_CHECKING([for threads package to use])
AC_ARG_ENABLE(threads, [ --enable-threads=TYPE choose threading package],
THREADS=$enableval,
[ AC_MSG_CHECKING([for thread model used by GCC])
THREADS=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
if test -z "$THREADS"; then
THREADS=no
fi
AC_MSG_RESULT([$THREADS])])
AC_ARG_ENABLE(parallel-mark,
[ --enable-parallel-mark parallelize marking and free list construction],
[case "$THREADS" in
no | none | single)
AC_MSG_ERROR([Parallel mark requires --enable-threads=x spec])
;;
esac]
)
INCLUDES=-I${srcdir}/include
THREADLIBS=
@ -39,9 +70,27 @@ case "$THREADS" in
THREADS=posix
THREADLIBS=-lpthread
case "$host" in
*-*-linux*)
AC_DEFINE(LINUX_THREADS)
x86-*-linux* | ia64-*-linux* | i586-*-linux* | i686-*-linux*)
AC_DEFINE(GC_LINUX_THREADS)
AC_DEFINE(_REENTRANT)
if test "${enable_parallel_mark}"; then
AC_DEFINE(PARALLEL_MARK)
fi
AC_DEFINE(THREAD_LOCAL_ALLOC)
;;
*-*-linux*)
AC_DEFINE(GC_LINUX_THREADS)
AC_DEFINE(_REENTRANT)
;;
*-*-hpux*)
AC_MSG_WARN("Only HP/UX 11 threads are supported.")
AC_DEFINE(GC_HPUX_THREADS)
AC_DEFINE(_POSIX_C_SOURCE,199506L)
if test "${enable_parallel_mark}" = yes; then
AC_DEFINE(PARALLEL_MARK)
fi
AC_DEFINE(THREAD_LOCAL_ALLOC)
THREADLIBS="-lpthread -lrt"
;;
*-*-freebsd*)
AC_MSG_WARN("FreeBSD does not yet fully support threads with Boehm GC.")
@ -50,11 +99,11 @@ case "$THREADS" in
THREADLIBS=-pthread
;;
*-*-solaris*)
AC_DEFINE(SOLARIS_THREADS)
AC_DEFINE(_SOLARIS_PTHREADS)
AC_DEFINE(GC_SOLARIS_THREADS)
AC_DEFINE(GC_SOLARIS_PTHREADS)
;;
*-*-irix*)
AC_DEFINE(IRIX_THREADS)
AC_DEFINE(GC_IRIX_THREADS)
;;
*-*-cygwin*)
THREADLIBS=
@ -73,16 +122,7 @@ AC_SUBST(THREADLIBS)
AC_CHECK_LIB(dl, dlopen, EXTRA_TEST_LIBS="$EXTRA_TEST_LIBS -ldl")
AC_SUBST(EXTRA_TEST_LIBS)
AC_ARG_ENABLE(java-gc,
changequote(<<,>>)dnl
<< --enable-java-gc=TYPE choose garbage collector [boehm]>>,
changequote([,])
GC=$enableval,
GC=boehm)
target_all=
if test "$GC" = "boehm"; then
target_all=libgcjgc.la
fi
target_all=libgcjgc.la
AC_SUBST(target_all)
dnl If the target is an eCos system, use the appropriate eCos
@ -162,12 +202,17 @@ dnl We need to override the top-level CFLAGS. This is how we do it.
MY_CFLAGS="$CFLAGS"
AC_SUBST(MY_CFLAGS)
dnl Define a few things to retarget the library towards
dnl embedded Java.
dnl Include defines that have become de facto standard.
dnl ALL_INTERIOR_POINTERS can be overridden in startup code.
AC_DEFINE(SILENT)
AC_DEFINE(NO_SIGNALS)
AC_DEFINE(NO_EXECUTE_PERMISSION)
AC_DEFINE(ALL_INTERIOR_POINTERS)
dnl By default, make the library as general as possible.
AC_DEFINE(JAVA_FINALIZATION)
AC_DEFINE(GC_GCJ_SUPPORT)
AC_DEFINE(ATOMIC_UNCOLLECTABLE)
dnl This is something of a hack. When cross-compiling we turn off
dnl some functionality. We also enable the "small" configuration.
@ -179,6 +224,20 @@ if test -n "${with_cross_host}"; then
AC_DEFINE(NO_DEBUGGING)
fi
AC_ARG_ENABLE(full-debug,
[ --enable-full-debug include full support for pointer backtracing etc.],
[ if test "$enable_full_debug" = "yes"; then
AC_MSG_WARN("Must define GC_DEBUG and use debug alloc. in clients.")
AC_DEFINE(KEEP_BACK_PTRS)
AC_DEFINE(DBG_HDRS_ALL)
case $host in
x86-*-linux* | i586-*-linux* | i686-*-linux* )
AC_MSG_WARN("Client must not use -fomit-frame-pointer.")
AC_DEFINE(SAVE_CALL_COUNT, 8)
;;
esac ]
fi)
AM_CONDITIONAL(USE_LIBDIR, test -z "$with_cross_host")
if test "${multilib}" = "yes"; then
@ -187,15 +246,12 @@ else
multilib_arg=
fi
AC_OUTPUT(Makefile,
[
dnl Put all the -D options in a file. These are required before
dnl boehm-config.h can be included. This is a huge hack brought
dnl about by overall poor structuring of this entire library.
AC_OUTPUT(Makefile, [
dnl Put all the -D options in a file.
echo "$DEFS" > boehm-cflags
if test -n "$CONFIG_FILES"; then
ac_file=Makefile . ${boehm_gc_basedir}/../config-ml.in
ac_file=Makefile . ${gc_basedir}/../config-ml.in
fi],
srcdir=${srcdir}
host=${host}
@ -203,7 +259,7 @@ target=${target}
with_multisubdir=${with_multisubdir}
ac_configure_args="${multilib_arg} ${ac_configure_args}"
CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
boehm_gc_basedir=${boehm_gc_basedir}
gc_basedir=${gc_basedir}
CC="${CC}"
DEFS="$DEFS"
)

View File

@ -26,7 +26,7 @@ GC_API void GC_register_finalizer_no_order
/* Check whether object with base pointer p has debugging info */
/* p is assumed to point to a legitimate object in our part */
/* of the heap. */
/* This excludes the check as to whether tha back pointer is */
/* This excludes the check as to whether the back pointer is */
/* odd, which is added by the GC_HAS_DEBUG_INFO macro. */
/* Note that if DBG_HDRS_ALL is set, uncollectable objects */
/* on free lists may not have debug information set. Thus it's */
@ -233,7 +233,7 @@ ptr_t p;
ptr_t GC_store_debug_info(p, sz, string, integer)
register ptr_t p; /* base pointer */
word sz; /* bytes */
char * string;
GC_CONST char * string;
word integer;
{
register word * result = (word *)((oh *)p + 1);
@ -252,7 +252,7 @@ word integer;
((oh *)p) -> oh_sz = sz;
((oh *)p) -> oh_sf = START_FLAG ^ (word)result;
((word *)p)[BYTES_TO_WORDS(GC_size(p))-1] =
result[ROUNDED_UP_WORDS(sz)] = END_FLAG ^ (word)result;
result[SIMPLE_ROUNDED_UP_WORDS(sz)] = END_FLAG ^ (word)result;
# endif
UNLOCK();
return((ptr_t)result);
@ -273,7 +273,7 @@ word integer;
/* But that's expensive. And this way things should only appear */
/* inconsistent while we're in the handler. */
# ifdef KEEP_BACK_PTRS
((oh *)p) -> oh_back_ptr = 0;
((oh *)p) -> oh_back_ptr = HIDE_BACK_PTR(NOT_MARKED);
# endif
((oh *)p) -> oh_string = string;
((oh *)p) -> oh_int = integer;
@ -281,7 +281,7 @@ word integer;
((oh *)p) -> oh_sz = sz;
((oh *)p) -> oh_sf = START_FLAG ^ (word)result;
((word *)p)[BYTES_TO_WORDS(GC_size(p))-1] =
result[ROUNDED_UP_WORDS(sz)] = END_FLAG ^ (word)result;
result[SIMPLE_ROUNDED_UP_WORDS(sz)] = END_FLAG ^ (word)result;
# endif
return((ptr_t)result);
}
@ -305,9 +305,9 @@ register oh * ohdr;
if (((word *)ohdr)[BYTES_TO_WORDS(gc_sz)-1] != (END_FLAG ^ (word)body)) {
return((ptr_t)((word *)ohdr + BYTES_TO_WORDS(gc_sz)-1));
}
if (((word *)body)[ROUNDED_UP_WORDS(ohdr -> oh_sz)]
if (((word *)body)[SIMPLE_ROUNDED_UP_WORDS(ohdr -> oh_sz)]
!= (END_FLAG ^ (word)body)) {
return((ptr_t)((word *)body + ROUNDED_UP_WORDS(ohdr -> oh_sz)));
return((ptr_t)((word *)body + SIMPLE_ROUNDED_UP_WORDS(ohdr -> oh_sz)));
}
return(0);
}
@ -964,15 +964,21 @@ struct closure {
GC_make_closure(fn,cd), ofn, ocd);
}
#ifdef GC_ADD_CALLER
# define RA GC_RETURN_ADDR,
#else
# define RA
#endif
GC_PTR GC_debug_malloc_replacement(lb)
size_t lb;
{
return GC_debug_malloc(lb, "unknown", 0);
return GC_debug_malloc(lb, RA "unknown", 0);
}
GC_PTR GC_debug_realloc_replacement(p, lb)
GC_PTR p;
size_t lb;
{
return GC_debug_realloc(p, lb, "unknown", 0);
return GC_debug_realloc(p, lb, RA "unknown", 0);
}

View File

@ -9,6 +9,9 @@ Copyright (c) 1998 by Fergus Henderson. All rights reserved.
The files Makefile.am, and configure.in are
Copyright (c) 2001 by Red Hat Inc. All rights reserved.
The files config.guess and a few others are copyrighted by the Free
Software Foundation.
THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
@ -18,7 +21,13 @@ Permission to modify the code and to distribute modified code is granted,
provided the above notices are retained, and a notice that the code was
modified is included with the above copyright notice.
This is version 6.0alpha7 of a conservative garbage collector for C and C++.
A few of the files needed to use the GNU-style build procedure come with
slightly different licenses, though they are all similar in spirit. A few
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.0 of a conservative garbage collector for C and C++.
You might find a more recent version of this at

View File

@ -17,3 +17,11 @@ June, 1 2000
Dietmar Planitzer
dave.pl@ping.at
Note from Andrew Begel:
One more fix to enable gc.a to link successfully into a shared library for
MacOS X. You have to add -fno-common to the CFLAGS in the Makefile. MacOSX
disallows common symbols in anything that eventually finds its way into a
shared library. (I don't completely understand why, but -fno-common seems to
work and doesn't mess up the garbage collector's functionality).

View File

@ -1291,7 +1291,103 @@ Since 6.0alpha6:
There seemed to be some problems with the encoding of root and finalizer
references.
Since 6.0alpha7:
- Changed GC_debug_malloc_replacement and GC_debug_realloc_replacement
so that they compile under Irix. (Thanks to Dave Love.)
- Updated powerpc_macosx_mach_dep.s so that it works if the collector
is in a dynamic library. (Thanks to Andrew Begel.)
- Transformed README.debugging into debugging.html, updating and
expanding it in the process. Added gcdescr.html and tree.html
from the web site to the GC distribution.
- Fixed several problems related to PRINT_BLACK_LIST. This involved
restructuring some of the marker macros.
- Fixed some problems with the sizing of objects with debug information.
Finalization was broken KEEP_BACK_PTRS or PRINT_BLACK_LIST. Reduced the
object size with SHORT_DEBUG_HDRS by another word.
- The "Needed to allocate blacklisted ..." warning had inadvertently
been turned off by default, due to a buggy test in allchblk.c. Turned
it back on.
- Removed the marker macros to deal with 2 pointers in interleaved fashion.
They were messy and the performance improvement seemed minimal. We'll
leave such scheduling issues to the compiler.
- Changed Linux/PowerPC test to also check for __powerpc__ in response
to a discussion on the gcc mailing list.
- On Matthew Flatt's suggestion removed the "static" from the jmp_buf
declaration in GC_generic_push_regs. This was causing problems in
systems that register all of their own roots. It looks far more correct
to me without the "static" anyway.
- Fixed several problems with thread local allocation of pointerfree or
typed objects. The collector was reclaiming thread-local free lists, since
it wasn't following the link fields.
- There was apparently a long-standing race condition related to multithreaded
incremental collection. A collection could be started and a thread stopped
between the memory unprotect system call and the setting of the
corresponding dirt bit. I believe this did not affect Solaris or PCR, which
use a different dirty-bit implementation. Fixed this by installing
signal handlers with sigaction instead of signal, and disabling the thread
suspend signal while in the write-protect handler. (It is unclear
whether this scenario ever actually occurred. I found it while tracking
down the following:)
- Incremental collection did not cooperate correctly with the PARALLEL_MARK
implementation of GC_malloc_many or the local_malloc primitves. It still
doesn't work well, but it shouldn't lose memory anymore.
- Integrated some changes from the gcc source tree that I had previously
missed. (Thanks to Bryce McKinley for the reminder/diff.)
- Added Makefile.direct as a copy of the default Makefile, which would
normally be overwritten if configure is run.
- Changed the gc.tar target in Makefile.direct to embed the version number
in the gc directory name. This will affect future tar file distributions.
- Changed the Irix dynamic library finding code to no longer try to
eliminate writable text segments under Irix6.x, since that is probably no
longer necessary, and can apparently be unsafe on occasion. (Thanks to
Shiro Kawai for pointing this out.)
- GC_cleanup with GC_DEBUG enabled passed a real object base address to
GC_debug_register_finalizer_ignore_self, which expected a pointer past the
debug header. Call GC_register_finalizer_ignore_self instead, even with
debugging enabled. (Thanks to Jean-Daniel Fekete for catching this.)
- The collector didn't build with call chain saving enabled but NARGS=0.
(Thanks to Maarten Thibaut.)
- Fixed up the GNU-style build files enough so that they work in some
obvious cases.
- Added initial port to Digital Mars compiler for win32. (Thanks to Walter
Bright.)
Since 6.0alpha8:
- added README.macros.
- Made gc.mak a symbolic link to work around winzip's tendency to ignore
hard links.
- Simplified the setting of NEED_FIND_LIMIT in os_dep.c, possibly breaking
it on untested platforms.
- Integrated initial GNU HURD port. (Thanks to Chris Lingard and Igor
Khavkine.)
- A few more fixes for Digital Mars compiler.
- Fixed gcc version recognition. Renamed OPERATOR_NEW_ARRAY to
GC_OPERATOR_NEW_ARRAY. Changed GC_OPERATOR_NEW_ARRAY to be the default.
It can be overridden with -DGC_NO_OPERATOR_NEW_ARRAY. (Thanks to
Cesar Eduardo Barros.)
- Changed the byte size to free-list mapping in thread local allocation
so that size 0 allocations are handled correctly.
- Fixed Linux/MIPS stackbottom for new toolchain. (Thanks to Ryan Murray.)
- Changed finalization registration to invoke GC_oom_fn when it runs out
of memory.
- Removed lvalue cast in finalize.c. This caused some debug configurations
not to build with some non-gcc compilers.
Since 6.0alpha9:
- Two more bug fixes for KEEP_BACK_PTRS and DBG_HDRS_ALL.
- Fixed a stack clearing problem that resulted in SIGILL with a
misaligned stack pointer for multithreaded SPARC builds.
- Integrated another HURD patch (thanks to Igor Khavkine).
To do:
- There seem to be outstanding issues on Solaris/X86, possibly with
finding the data segment starting address. Information/patches would
ne appreciated.
- New_gc_alloc.h is apparently no longer compatible with the latest C++
standard library in gcc3.0. (This isn't technically a bug, since it only
claimed compatibility with the SGI STL. But we may need a new C++ STL
allocator interface.)
- Very large root set sizes (> 16 MB or so) could cause the collector
to abort with an unexpected mark stack overflow. (Thanks again to
Peter Chubb.) NOT YET FIXED. Workaround is to increase the initial

View File

@ -18,6 +18,20 @@ See cord.h for a description of the functions provided. Ec.h describes
to a cord. These allow for efficient construction of cords without
requiring a bound on the size of a cord.
More details on the data structure can be found in
Boehm, Atkinson, and Plass, "Ropes: An Alternative to Strings",
Software Practice and Experience 25, 12, December 1995, pp. 1315-1330.
A fundamentally similar "rope" data structure is also part of SGI's standard
template library implementation, and its descendents, which include the
GNU C++ library. That uses reference counting by default.
There is a short description of that data structure at
http://reality.sgi.com/boehm/ropeimpl.html . (The more official location
http://www.sgi.com/tech/stl/ropeimpl.html is missing a figure.)
All of these are descendents of the "ropes" in Xerox Cedar.
de.c is a very dumb text editor that illustrates the use of cords.
It maintains a list of file versions. Each version is simply a
cord representing the file contents. Nonetheless, standard

View File

@ -1,68 +0,0 @@
Debugging suggestions:
****If you get a segmentation fault or bus error while debugging with a debugger:
If the fault occurred in GC_find_limit, or with incremental collection enabled, this is probably normal. The collector installs handlers to take care of these. You will not see these unless you are using a debugger. Your debugger should allow you to continue. It's preferable to tell the debugger to ignore SIGBUS and SIGSEGV ("handle" in gdb, "ignore" in most versions of dbx) and set a breakpoint in abort. The collector will call abort if the signal had another cause, and there was not other handler previously installed. I recommend debugging without incremental collection if possible. (This applies directly to UNIX systems. Debugging with incremental collection under win32 is worse. See README.win32.)
****If you get warning messages informing you that the collector needed to allocate blacklisted blocks:
0) Ignore these warnings while you are using GC_DEBUG. Some of the routines mentioned below don't have debugging equivalents. (Alternatively, write the missing routines and send them to me.)
1) Replace allocator calls that request large blocks with calls to GC_malloc_ignore_off_page or GC_malloc_atomic_ignore_off_page. You may want to set a breakpoint in GC_default_warn_proc to help you identify such calls. Make sure that a pointer to somewhere near the beginning of the resulting block is maintained in a (preferably volatile) variable as long as the block is needed.
2) If the large blocks are allocated with realloc, I suggest instead allocating them with something like the following. Note that the realloc size increment should be fairly large (e.g. a factor of 3/2) for this to exhibit reasonable performance. But we all know we should do that anyway.
void * big_realloc(void *p, size_t new_size)
{
size_t old_size = GC_size(p);
void * result;
if (new_size <= 10000) return(GC_realloc(p, new_size));
if (new_size <= old_size) return(p);
result = GC_malloc_ignore_off_page(new_size);
if (result == 0) return(0);
memcpy(result,p,old_size);
GC_free(p);
return(result);
}
3) In the unlikely case that even relatively small object (<20KB) allocations are triggering these warnings, then your address space contains lots of "bogus pointers", i.e. values that appear to be pointers but aren't. Usually this can be solved by using GC_malloc_atomic or the routines in gc_typed.h to allocate large pointerfree regions of bitmaps, etc. Sometimes the problem can be solved with trivial changes of encoding in certain values. It is possible, though not pleasant, to identify the source of the bogus pointers by setting a breakpoint in GC_add_to_black_list_stack, and looking at the value of current_p in the GC_mark_from_mark_stack frame. Current_p contains the address of the bogus pointer.
4) If you get only a fixed number of these warnings, you are probably only introducing a bounded leak by ignoring them. If the data structures being allocated are intended to be permanent, then it is also safe to ignore them. The warnings can be turned off by calling GC_set_warn_proc with a procedure that ignores these warnings (e.g. by doing absolutely nothing).
****If the collector dies in GC_malloc while trying to remove a free list element:
1) With > 99% probability, you wrote past the end of an allocated object. Try setting GC_DEBUG and using the debugging facilities in gc.h.
****If the heap grows too much:
1) Consider using GC_malloc_atomic for objects containing nonpointers. This is especially important for large arrays containg compressed data, pseudo-random numbers, and the like. (This isn't all that likely to solve your problem, but it's a useful and easy optimization anyway, and this is a good time to try it.) If you allocate large objects containg only one or two pointers at the beginning, either try the typed allocation primitives is gc.h, or separate out the pointerfree component.
2) If you are using the collector in its default mode, with interior pointer recognition enabled, consider using GC_malloc_ignore_off_page to allocate large objects. (See gc.h and above for details. Large means > 100K in most environments.)
3) GC_print_block_list() will print a list of all currently allocated heap blocks and what size objects they contain. GC_print_hblkfreelist() will print a list of free heap blocks, and whether they are blacklisted. GC_dump calls both of these, and also prints information about heap sections, and root segments.
4) Build the collector with -DKEEP_BACK_PTRS, and use the backptr.h
interface to determine why objects are being retained.
****If the collector appears to be losing objects:
1) Replace all calls to GC_malloc_atomic and typed allocation by GC_malloc calls. If this fixes the problem, gradually reinsert your optimizations.
2) You may also want to try the safe(r) pointer manipulation primitives in gc.h. But those are hard to use until the preprocessor becomes available.
3) Try using the GC_DEBUG facilities. This is less likely to be successful here than if the collector crashes.
[The rest of these are primarily for wizards. You shouldn't need them unless you're doing something really strange, or debugging a collector port.]
4) Don't turn on incremental collection. If that fixes the problem, suspect a bug in the dirty bit implementation. Try compiling with -DCHECKSUMS to check for modified, but supposedly clean, pages.
5) On a SPARC, in a single-threaded environment, GC_print_callers(GC_arrays._last_stack) prints a cryptic stack trace as of the time of the last collection. (You will need a debugger to decipher the result.) The question to ask then is "why should this object have been accessible at the time of the last collection? Where was a pointer to it stored?". This facility should be easy to add for some other collector ports (namely if it's easy to traverse stack frames), but will be hard for others.
6) "print *GC_find_header(p)" in dbx or gdb will print the garbage collector block header information associated with the object p (e.g. object size, etc.)
7) GC_is_marked(p) determines whether p is the base address of a marked object. Note that objects allocated since the last collection should not be marked, and that unmarked objects are reclaimed incrementally. It's usually most interesting to set a breakpoint in GC_finish_collection and then to determine how much of the damaged data structure is marked at that point.
8) Look at the tracing facility in mark.c. (Ignore this suggestion unless you are very familiar with collector internals.)
9) [From Melissa O'Neill:]
If you're using multiple threads, double check that all thread
creation goes through the GC_ wrapper functions rather than
calling the thread-creation functions themselves (e.g.,
GC_pthread_create rather than pthread_create). The gc.h header
file includes suitable preprocessor definitions to accomplish
this mapping transparently -- the question is: are you including
it in all the modules that create threads?

View File

@ -29,6 +29,9 @@ GC_NPROCS=<n> - Linux w/threads only. Explicitly sets the number of processors
when multiple processors are available will preserve
correctness, but may lead to really horrible performance.
GC_NO_BLACKLIST_WARNING - Prevents the collector from issuing
"Needed to allocate blacklisted block at ..." warnings.
The following turn on runtime flags that are also program settable. Checked
only during initialization. We expect that they will usually be set through
other means, but this may help with debugging and testing:

View File

@ -53,7 +53,7 @@
!(defined(ALPHA) && defined(OSF1)) && \
!defined(HPUX) && !(defined(LINUX) && defined(__ELF__)) && \
!defined(RS6000) && !defined(SCO_ELF) && \
!(defined(NETBSD) && defined(__ELF__))
!(defined(NETBSD) && defined(__ELF__)) && !defined(HURD)
--> We only know how to find data segments of dynamic libraries for the
--> above. Additional SVR4 variants might not be too
--> hard to add.
@ -243,7 +243,7 @@ void GC_register_dynamic_libraries()
# endif /* SUNOS */
#if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \
(defined(NETBSD) && defined(__ELF__))
(defined(NETBSD) && defined(__ELF__)) || defined(HURD)
#ifdef USE_PROC_FOR_LIBRARIES
@ -514,6 +514,10 @@ void GC_register_dynamic_libraries()
#include <fcntl.h>
#include <elf.h>
#include <errno.h>
#include <signal.h> /* Only for the following test. */
#ifndef _sigargs
# define IRIX6
#endif
extern void * GC_roots_present();
/* The type is a lie, since the real type doesn't make sense here, */
@ -574,7 +578,8 @@ void GC_register_dynamic_libraries()
if ((flags & (MA_BREAK | MA_STACK | MA_PHYS)) != 0) goto irrelevant;
if ((flags & (MA_READ | MA_WRITE)) != (MA_READ | MA_WRITE))
goto irrelevant;
/* The latter test is empirically useless. Other than the */
/* The latter test is empirically useless in very old Irix */
/* versions. Other than the */
/* main data and stack segments, everything appears to be */
/* mapped readable, writable, executable, and shared(!!). */
/* This makes no sense to me. - HB */
@ -587,7 +592,11 @@ void GC_register_dynamic_libraries()
# endif /* MMAP_STACKS */
limit = start + addr_map[i].pr_size;
if (addr_map[i].pr_off == 0 && strncmp(start, ELFMAG, 4) == 0) {
/* The following seemed to be necessary for very old versions */
/* of Irix, but it has been reported to discard relevant */
/* segments under Irix 6.5. */
# ifndef IRIX6
if (addr_map[i].pr_off == 0 && strncmp(start, ELFMAG, 4) == 0) {
/* Discard text segments, i.e. 0-offset mappings against */
/* executable files which appear to have ELF headers. */
caddr_t arg;
@ -614,7 +623,8 @@ void GC_register_dynamic_libraries()
goto irrelevant;
}
}
}
}
# endif /* !IRIX6 */
GC_add_roots_inner(start, limit, TRUE);
irrelevant: ;
}

View File

@ -202,15 +202,27 @@ signed_word * log_size_ptr;
}
new_dl = (struct disappearing_link *)
GC_INTERNAL_MALLOC(sizeof(struct disappearing_link),NORMAL);
if (new_dl != 0) {
new_dl -> dl_hidden_obj = HIDE_POINTER(obj);
new_dl -> dl_hidden_link = HIDE_POINTER(link);
dl_set_next(new_dl, dl_head[index]);
dl_head[index] = new_dl;
GC_dl_entries++;
} else {
GC_finalization_failures++;
if (0 == new_dl) {
# ifdef THREADS
UNLOCK();
ENABLE_SIGNALS();
# endif
new_dl == GC_oom_fn(sizeof(struct disappearing_link));
if (0 == new_dl) {
GC_finalization_failures++;
return(0);
}
/* It's not likely we'll make it here, but ... */
# ifdef THREADS
DISABLE_SIGNALS();
LOCK();
# endif
}
new_dl -> dl_hidden_obj = HIDE_POINTER(obj);
new_dl -> dl_hidden_link = HIDE_POINTER(link);
dl_set_next(new_dl, dl_head[index]);
dl_head[index] = new_dl;
GC_dl_entries++;
# ifdef THREADS
UNLOCK();
ENABLE_SIGNALS();
@ -245,7 +257,7 @@ signed_word * log_size_ptr;
UNLOCK();
ENABLE_SIGNALS();
# ifdef DBG_HDRS_ALL
dl_next(curr_dl) = 0;
dl_set_next(curr_dl, 0);
# else
GC_free((GC_PTR)curr_dl);
# endif
@ -416,18 +428,30 @@ finalization_mark_proc * mp;
}
new_fo = (struct finalizable_object *)
GC_INTERNAL_MALLOC(sizeof(struct finalizable_object),NORMAL);
if (new_fo != 0) {
new_fo -> fo_hidden_base = (word)HIDE_POINTER(base);
new_fo -> fo_fn = fn;
new_fo -> fo_client_data = (ptr_t)cd;
new_fo -> fo_object_size = hhdr -> hb_sz;
new_fo -> fo_mark_proc = mp;
fo_set_next(new_fo, fo_head[index]);
GC_fo_entries++;
fo_head[index] = new_fo;
} else {
GC_finalization_failures++;
if (0 == new_fo) {
# ifdef THREADS
UNLOCK();
ENABLE_SIGNALS();
# endif
new_fo == GC_oom_fn(sizeof(struct finalizable_object));
if (0 == new_fo) {
GC_finalization_failures++;
return;
}
/* It's not likely we'll make it here, but ... */
# ifdef THREADS
DISABLE_SIGNALS();
LOCK();
# endif
}
new_fo -> fo_hidden_base = (word)HIDE_POINTER(base);
new_fo -> fo_fn = fn;
new_fo -> fo_client_data = (ptr_t)cd;
new_fo -> fo_object_size = hhdr -> hb_sz;
new_fo -> fo_mark_proc = mp;
fo_set_next(new_fo, fo_head[index]);
GC_fo_entries++;
fo_head[index] = new_fo;
# ifdef THREADS
UNLOCK();
ENABLE_SIGNALS();
@ -593,7 +617,7 @@ void GC_finalize()
GC_words_finalized +=
ALIGNED_WORDS(curr_fo -> fo_object_size)
+ ALIGNED_WORDS(sizeof(struct finalizable_object));
GC_ASSERT(GC_is_marked((ptr_t)curr_fo));
GC_ASSERT(GC_is_marked(GC_base((ptr_t)curr_fo)));
curr_fo = next_fo;
} else {
prev_fo = curr_fo;

View File

@ -36,7 +36,6 @@
* 3) FASTLOCK is not a significant win.
*/
#include "private/gc_priv.h"
#include "private/gc_pmark.h"
#include "gc_gcj.h"
#include "private/dbg_mlc.h"

View File

@ -80,10 +80,6 @@
typedef long ptrdiff_t; /* ptrdiff_t is not defined */
# endif
#if defined(__CYGWIN32__) && defined(GC_USE_DLL)
#include "libgc_globals.h"
#endif
#if defined(__MINGW32__) && defined(WIN32_THREADS)
# ifdef GC_BUILD
# define GC_API __declspec(dllexport)
@ -92,8 +88,9 @@
# endif
#endif
#if defined(_MSC_VER) && (defined(_DLL) && !defined(NOT_GC_DLL) \
|| defined(GC_DLL))
#if (defined(__DMC__) || defined(_MSC_VER)) \
&& (defined(_DLL) && !defined(GC_NOT_DLL) \
|| defined(GC_DLL))
# ifdef GC_BUILD
# define GC_API extern __declspec(dllexport)
# else
@ -347,6 +344,10 @@ GC_API void GC_end_stubborn_change GC_PROTO((GC_PTR));
/* Return a pointer to the base (lowest address) of an object given */
/* a pointer to a location within the object. */
/* I.e. map an interior pointer to the corresponding bas pointer. */
/* Note that with debugging allocation, this returns a pointer to the */
/* actual base of the object, i.e. the debug information, not to */
/* the base of the user object. */
/* Return 0 if displaced_pointer doesn't point to within a valid */
/* object. */
GC_API GC_PTR GC_base GC_PROTO((GC_PTR displaced_pointer));
@ -701,7 +702,7 @@ GC_API GC_warn_proc GC_set_warn_proc GC_PROTO((GC_warn_proc p));
/* Returns old warning procedure. */
/* The following is intended to be used by a higher level */
/* (e.g. cedar-like) finalization facility. It is expected */
/* (e.g. Java-like) finalization facility. It is expected */
/* that finalization code will arrange for hidden pointers to */
/* disappear. Otherwise objects can be accessed after they */
/* have been collected. */

View File

@ -83,7 +83,7 @@ Cautions:
1. Be sure the collector has been augmented with "make c++".
2. If your compiler supports the new "operator new[]" syntax, then
add -DOPERATOR_NEW_ARRAY to the Makefile.
add -DGC_OPERATOR_NEW_ARRAY to the Makefile.
If your compiler doesn't support "operator new[]", beware that an
array of type T, where T is derived from "gc", may or may not be
@ -137,10 +137,17 @@ by UseGC. GC is an alias for UseGC, unless GC_NAME_CONFLICT is defined.
#define _cdecl
#endif
#if ! defined( OPERATOR_NEW_ARRAY ) \
&& (__BORLANDC__ >= 0x450 || (__GNUC__ >= 2 && __GNUC_MINOR__ >= 6) \
|| __WATCOMC__ >= 1050 || _MSC_VER >= 1100)
# define OPERATOR_NEW_ARRAY
#if ! defined( GC_NO_OPERATOR_NEW_ARRAY ) \
&& !defined(_ENABLE_ARRAYNEW) /* Digimars */ \
&& (defined(__BORLANDC__) && (__BORLANDC__ < 0x450) \
|| (defined(__GNUC__) && \
(__GNUC__ < 2 || __GNUC__ == 2 && __GNUC_MINOR__ < 6)) \
|| (defined(__WATCOMC__) && __WATCOMC__ < 1050))
# define GC_NO_OPERATOR_NEW_ARRAY
#endif
#if !defined(GC_NO_OPERATOR_NEW_ARRAY) && !defined(GC_OPERATOR_NEW_ARRAY)
# define GC_OPERATOR_NEW_ARRAY
#endif
enum GCPlacement {UseGC,
@ -154,11 +161,11 @@ class gc {public:
inline void* operator new( size_t size, GCPlacement gcp );
inline void operator delete( void* obj );
#ifdef OPERATOR_NEW_ARRAY
#ifdef GC_OPERATOR_NEW_ARRAY
inline void* operator new[]( size_t size );
inline void* operator new[]( size_t size, GCPlacement gcp );
inline void operator delete[]( void* obj );
#endif /* OPERATOR_NEW_ARRAY */
#endif /* GC_OPERATOR_NEW_ARRAY */
};
/*
Instances of classes derived from "gc" will be allocated in the
@ -204,7 +211,7 @@ inline void* operator new(
classes derived from "gc_cleanup" or containing members derived
from "gc_cleanup". */
#ifdef OPERATOR_NEW_ARRAY
#ifdef GC_OPERATOR_NEW_ARRAY
#ifdef _MSC_VER
/** This ensures that the system default operator new[] doesn't get
@ -257,7 +264,7 @@ inline void* operator new[](
/*
The operator new for arrays, identical to the above. */
#endif /* OPERATOR_NEW_ARRAY */
#endif /* GC_OPERATOR_NEW_ARRAY */
/****************************************************************************
@ -280,7 +287,7 @@ inline void gc::operator delete( void* obj ) {
GC_FREE( obj );}
#ifdef OPERATOR_NEW_ARRAY
#ifdef GC_OPERATOR_NEW_ARRAY
inline void* gc::operator new[]( size_t size ) {
return gc::operator new( size );}
@ -291,7 +298,7 @@ inline void* gc::operator new[]( size_t size, GCPlacement gcp ) {
inline void gc::operator delete[]( void* obj ) {
gc::operator delete( obj );}
#endif /* OPERATOR_NEW_ARRAY */
#endif /* GC_OPERATOR_NEW_ARRAY */
inline gc_cleanup::~gc_cleanup() {
@ -305,11 +312,12 @@ inline gc_cleanup::gc_cleanup() {
void* oldData;
void* base = GC_base( (void *) this );
if (0 != base) {
GC_REGISTER_FINALIZER_IGNORE_SELF(
// Don't call the debug version, since this is a real base address.
GC_register_finalizer_ignore_self(
base, (GC_finalization_proc)cleanup, (void*) ((char*) this - (char*) base),
&oldProc, &oldData );
if (0 != oldProc) {
GC_REGISTER_FINALIZER_IGNORE_SELF( base, oldProc, oldData, 0, 0 );}}}
GC_register_finalizer_ignore_self( base, oldProc, oldData, 0, 0 );}}}
inline void* operator new(
size_t size,
@ -331,7 +339,7 @@ inline void* operator new(
return obj;}
#ifdef OPERATOR_NEW_ARRAY
#ifdef GC_OPERATOR_NEW_ARRAY
inline void* operator new[](
size_t size,
@ -341,7 +349,7 @@ inline void* operator new[](
{
return ::operator new( size, gcp, cleanup, clientData );}
#endif /* OPERATOR_NEW_ARRAY */
#endif /* GC_OPERATOR_NEW_ARRAY */
#endif /* GC_CPP_H */

View File

@ -19,7 +19,7 @@
* not use it. Clients that define their own object kinds with
* debugging allocators will probably want to include this, however.
* No attempt is made to keep the namespace clean. This should not be
* included from header filrd that are frequently included by clients.
* included from header files that are frequently included by clients.
*/
#ifndef _DBG_MLC_H
@ -32,11 +32,31 @@
# include "gc_backptr.h"
# endif
#ifndef HIDE_POINTER
/* Gc.h was previously included, and hence the I_HIDE_POINTERS */
/* definition had no effect. Repeat the gc.h definitions here to */
/* get them anyway. */
typedef GC_word GC_hidden_pointer;
# define HIDE_POINTER(p) (~(GC_hidden_pointer)(p))
# define REVEAL_POINTER(p) ((GC_PTR)(HIDE_POINTER(p)))
#endif /* HIDE_POINTER */
# define START_FLAG ((word)0xfedcedcb)
# define END_FLAG ((word)0xbcdecdef)
/* Stored both one past the end of user object, and one before */
/* the end of the object as seen by the allocator. */
# if defined(KEEP_BACK_PTRS) || defined(PRINT_BLACK_LIST)
/* Pointer "source"s that aren't real locations. */
/* Used in oh_back_ptr fields and as "source" */
/* argument to some marking functions. */
# define NOT_MARKED (ptr_t)(0)
# define MARKED_FOR_FINALIZATION (ptr_t)(2)
/* Object was marked because it is finalizable. */
# define MARKED_FROM_REGISTER (ptr_t)(4)
/* Object was marked from a rgister. Hence the */
/* source of the reference doesn't have an address. */
# endif /* KEEP_BACK_PTRS || PRINT_BLACK_LIST */
/* Object header */
typedef struct {
@ -48,16 +68,13 @@ typedef struct {
/* overwrite a value with the least significant */
/* bit clear, thus ensuring that we never overwrite */
/* a free list link field. */
/* Note that blocks dropped by black-listing will */
/* also have the lsb clear once debugging has */
/* started. */
/* The following are special back pointer values. */
/* Note that the "hidden" (i.e. bitwise */
/* complemented version) of these is actually */
/* stored. */
# define NOT_MARKED (ptr_t)(0)
# define MARKED_FOR_FINALIZATION (ptr_t)(2)
/* Object was marked because it is finalizable. */
# define MARKED_FROM_REGISTER (ptr_t)(4)
/* Object was marked from a rgister. Hence the */
/* source of the reference doesn't have an address. */
# if ALIGNMENT == 1
/* Fudge back pointer to be even. */
# define HIDE_BACK_PTR(p) HIDE_POINTER(~1 & (GC_word)(p))
@ -68,7 +85,7 @@ typedef struct {
word oh_dummy;
# endif
# endif
char * oh_string; /* object descriptor string */
GC_CONST char * oh_string; /* object descriptor string */
word oh_int; /* object descriptor integers */
# ifdef NEED_CALLINFO
struct callinfo oh_ci[NFRAMES];
@ -81,13 +98,17 @@ typedef struct {
/* The size of the above structure is assumed not to dealign things, */
/* and to be a multiple of the word length. */
#define DEBUG_BYTES (sizeof (oh) + sizeof (word))
#ifdef SHORT_DBG_HDRS
# define DEBUG_BYTES (sizeof (oh))
#else
/* Add space for END_FLAG, but use any extra space that was already */
/* added to catch off-the-end pointers. */
# define DEBUG_BYTES (sizeof (oh) + sizeof (word) - EXTRA_BYTES)
#endif
#define USR_PTR_FROM_BASE(p) ((ptr_t)(p) + sizeof(oh))
/* There is no reason to ever add a byte at the end explicitly, since we */
/* already add a guard word. */
#undef ROUNDED_UP_WORDS
#define ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1) - 1)
/* Round bytes to words without adding extra byte at end. */
#define SIMPLE_ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1) - 1)
#ifdef SAVE_CALL_CHAIN
# define ADD_CALL_CHAIN(base, ra) GC_save_callers(((oh *)(base)) -> oh_ci)

View File

@ -26,13 +26,11 @@ typedef struct hblkhdr hdr;
* table.
*
* This defines HDR, GET_HDR, and SET_HDR, the main macros used to
* retrieve and set object headers. We also define some variants to
* retrieve 2 unrelated headers in interleaved fashion. This
* slightly improves scheduling.
* retrieve and set object headers.
*
* Since 5.0 alpha 5, we can also take advantage of a header lookup
* cache. This is a locally declared direct mapped cache, used inside
* the marker. The HC_GET_HDR and HC_GET_HDR2 macros use and maintain this
* the marker. The HC_GET_HDR macro uses and maintains this
* cache. Assuming we get reasonable hit rates, this shaves a few
* memory references from each pointer validation.
*/
@ -67,16 +65,13 @@ extern hdr * GC_invalid_header; /* header for an imaginary block */
/* Check whether p and corresponding hhdr point to long or invalid */
/* object. If so, advance them to */
/* object. If so, advance hhdr to */
/* beginning of block, or set hhdr to GC_invalid_header. */
#define ADVANCE(p, hhdr, source) \
if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) { \
p = GC_FIND_START(p, hhdr, (word)source); \
if (p == 0) { \
hhdr = GC_invalid_header; \
} else { \
hhdr = GC_find_header(p); \
} \
{ \
hdr * new_hdr = GC_invalid_header; \
p = GC_FIND_START(p, hhdr, &new_hdr, (word)source); \
hhdr = new_hdr; \
}
#ifdef USE_HDR_CACHE
@ -124,35 +119,12 @@ extern hdr * GC_invalid_header; /* header for an imaginary block */
} else { \
HC_MISS(); \
GET_HDR(p, hhdr); \
ADVANCE(p, hhdr, source); \
hce -> block_addr = (word)(p) >> LOG_HBLKSIZE; \
hce -> hce_hdr = hhdr; \
} \
}
# define HC_GET_HDR2(p1, hhdr1, source1, p2, hhdr2, source2) \
{ \
hdr_cache_entry * hce1 = HCE(p1); \
hdr_cache_entry * hce2 = HCE(p2); \
if (HCE_VALID_FOR(hce1, p1)) { \
HC_HIT(); \
hhdr1 = hce1 -> hce_hdr; \
} else { \
HC_MISS(); \
GET_HDR(p1, hhdr1); \
ADVANCE(p1, hhdr1, source1); \
hce1 -> block_addr = (word)(p1) >> LOG_HBLKSIZE; \
hce1 -> hce_hdr = hhdr1; \
} \
if (HCE_VALID_FOR(hce2, p2)) { \
HC_HIT(); \
hhdr2 = hce2 -> hce_hdr; \
} else { \
HC_MISS(); \
GET_HDR(p2, hhdr2); \
ADVANCE(p2, hhdr2, source2); \
hce2 -> block_addr = (word)(p2) >> LOG_HBLKSIZE; \
hce2 -> hce_hdr = hhdr2; \
if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) { \
ADVANCE(p, hhdr, source); \
} else { \
hce -> block_addr = (word)(p) >> LOG_HBLKSIZE; \
hce -> hce_hdr = hhdr; \
} \
} \
}
@ -165,16 +137,10 @@ extern hdr * GC_invalid_header; /* header for an imaginary block */
# define HC_GET_HDR(p, hhdr, source) \
{ \
GET_HDR(p, hhdr); \
ADVANCE(p, hhdr, source); \
if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) { \
ADVANCE(p, hhdr, source); \
} \
}
# define HC_GET_HDR2(p1, hhdr1, source1, p2, hhdr2, source2) \
{ \
GET_HDR2(p1, hhdr1, p2, hhdr2); \
ADVANCE(p1, hhdr1, source1); \
ADVANCE(p2, hhdr2, source2); \
}
#endif
typedef struct bi {
@ -229,8 +195,6 @@ typedef struct bi {
# define GET_HDR(p, hhdr) (hhdr) = HDR(p)
# define SET_HDR(p, hhdr) HDR_INNER(p) = (hhdr)
# define GET_HDR_ADDR(p, ha) (ha) = &(HDR_INNER(p))
# define GET_HDR2(p1, hhdr1, p2, hhdr2) \
{ GET_HDR(p1, hhdr1); GET_HDR(p2, hhdr2); }
# else /* hash */
/* Hash function for tree top level */
# define TL_HASH(hi) ((hi) & (TOP_SZ - 1))
@ -257,40 +221,6 @@ typedef struct bi {
# define SET_HDR(p, hhdr) { register hdr ** _ha; GET_HDR_ADDR(p, _ha); \
*_ha = (hhdr); }
# define HDR(p) GC_find_header((ptr_t)(p))
/* And some interleaved versions for two pointers at once. */
/* This hopefully helps scheduling on processors like IA64. */
# define GET_BI2(p1, bottom_indx1, p2, bottom_indx2) \
{ \
register word hi1 = \
(word)(p1) >> (LOG_BOTTOM_SZ + LOG_HBLKSIZE); \
register word hi2 = \
(word)(p2) >> (LOG_BOTTOM_SZ + LOG_HBLKSIZE); \
register bottom_index * _bi1 = GC_top_index[TL_HASH(hi1)]; \
register bottom_index * _bi2 = GC_top_index[TL_HASH(hi2)]; \
\
while (_bi1 -> key != hi1 && _bi1 != GC_all_nils) \
_bi1 = _bi1 -> hash_link; \
while (_bi2 -> key != hi2 && _bi2 != GC_all_nils) \
_bi2 = _bi2 -> hash_link; \
(bottom_indx1) = _bi1; \
(bottom_indx2) = _bi2; \
}
# define GET_HDR_ADDR2(p1, ha1, p2, ha2) \
{ \
register bottom_index * bi1; \
register bottom_index * bi2; \
\
GET_BI2(p1, bi1, p2, bi2); \
(ha1) = &(HDR_FROM_BI(bi1, p1)); \
(ha2) = &(HDR_FROM_BI(bi2, p2)); \
}
# define GET_HDR2(p1, hhdr1, p2, hhdr2) \
{ register hdr ** _ha1; \
register hdr ** _ha2; \
GET_HDR_ADDR2(p1, _ha1, p2, _ha2); \
(hhdr1) = *_ha1; \
(hhdr2) = *_ha2; \
}
# endif
/* Is the result a forwarding address to someplace closer to the */

View File

@ -43,6 +43,7 @@
*
*/
# ifdef THREADS
void GC_noop1 GC_PROTO((word));
# ifdef PCR_OBSOLETE /* Faster, but broken with multiple lwp's */
# include "th/PCR_Th.h"
# include "th/PCR_ThCrSec.h"
@ -236,7 +237,7 @@
/* "set" means 0 and "clear" means 1 here. */
# define GC_test_and_set(addr) !GC_test_and_clear(addr);
# define GC_TEST_AND_SET_DEFINED
# define GC_clear(addr) GC_noop1(addr); *(volatile unsigned int *)addr = 1;
# define GC_clear(addr) GC_noop1((word)(addr)); *(volatile unsigned int *)addr = 1;
/* The above needs a memory barrier! */
# define GC_CLEAR_DEFINED
# endif

View File

@ -25,7 +25,7 @@
#ifndef GC_PMARK_H
# define GC_PMARK_H
# ifdef KEEP_BACK_PTRS
# if defined(KEEP_BACK_PTRS) || defined(PRINT_BLACK_LIST)
# include "dbg_mlc.h"
# endif
# ifndef GC_MARK_H
@ -132,12 +132,17 @@ extern mse * GC_mark_stack;
*/
#endif /* PARALLEL_MARK */
/* Return a pointer to within 1st page of object. */
/* Set *new_hdr_p to corr. hdr. */
#ifdef __STDC__
# ifdef PRINT_BLACK_LIST
ptr_t GC_find_start(ptr_t current, hdr *hhdr, word source);
ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p, word source);
# else
ptr_t GC_find_start(ptr_t current, hdr *hhdr);
# define source 0
ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p);
# endif
#else
ptr_t GC_find_start();
#endif
mse *GC_signal_mark_stack_overflow(mse *msp);
@ -169,11 +174,11 @@ mse *GC_signal_mark_stack_overflow(mse *msp);
}
#ifdef PRINT_BLACK_LIST
# define GC_FIND_START(current, hhdr, source) \
GC_find_start(current, hhdr, source)
# define GC_FIND_START(current, hhdr, new_hdr_p, source) \
GC_find_start(current, hhdr, new_hdr_p, source)
#else
# define GC_FIND_START(current, hhdr, source) \
GC_find_start(current, hhdr)
# define GC_FIND_START(current, hhdr, new_hdr_p, source) \
GC_find_start(current, hhdr, new_hdr_p)
#endif
/* Push the contents of current onto the mark stack if it is a valid */
@ -188,9 +193,10 @@ mse *GC_signal_mark_stack_overflow(mse *msp);
\
GET_HDR(my_current, my_hhdr); \
if (IS_FORWARDING_ADDR_OR_NIL(my_hhdr)) { \
my_current = GC_FIND_START(my_current, my_hhdr, (word)source); \
if (my_current == 0) goto exit_label; \
my_hhdr = GC_find_header(my_current); \
hdr * new_hdr = GC_invalid_header; \
my_current = GC_FIND_START(my_current, my_hhdr, \
&new_hdr, (word)source); \
my_hhdr = new_hdr; \
} \
PUSH_CONTENTS_HDR(my_current, mark_stack_top, mark_stack_limit, \
source, exit_label, my_hhdr); \
@ -210,27 +216,6 @@ exit_label: ; \
exit_label: ; \
}
/* As above, but deal with two pointers in interleaved fashion. */
# define HC_PUSH_CONTENTS2(current1, current2, mark_stack_top, \
mark_stack_limit, \
source1, source2, exit_label1, exit_label2) \
{ \
hdr * hhdr1; \
ptr_t my_current1 = current1; \
hdr * hhdr2; \
ptr_t my_current2 = current2; \
\
HC_GET_HDR2(my_current1, hhdr1, source1, my_current2, hhdr2, source2); \
PUSH_CONTENTS_HDR(my_current1, mark_stack_top, mark_stack_limit, \
source1, exit_label1, hhdr1); \
exit_label1: ; \
if (0 != hhdr2) { \
PUSH_CONTENTS_HDR(my_current2, mark_stack_top, mark_stack_limit, \
source2, exit_label2, hhdr2); \
} \
exit_label2: ; \
}
/* Set mark bit, exit if it was already set. */
# ifdef USE_MARK_BYTES
@ -257,10 +242,12 @@ exit_label2: ; \
# endif /* USE_MARK_BYTES */
/* If the mark bit corresponding to current is not set, set it, and */
/* push the contents of the object on the mark stack. Since we */
/* already have the header, we only look at the low order bits of */
/* current. (The value of current doesn't matter if hhdr = */
/* GC_invalid_header.) */
/* push the contents of the object on the mark stack. For a small */
/* object we assume that current is the (possibly interior) pointer */
/* to the object. For large objects we assume that current points */
/* to somewhere inside the first page of the object. If */
/* GC_all_interior_pointers is set, it may have been previously */
/* adjusted to make that true. */
# define PUSH_CONTENTS_HDR(current, mark_stack_top, mark_stack_limit, \
source, exit_label, hhdr) \
{ \
@ -346,7 +333,7 @@ mse * GC_mark_from GC_PROTO((mse * top, mse * bottom, mse *limit));
while (!GC_mark_stack_empty()) MARK_FROM_MARK_STACK(); \
if (GC_mark_state != MS_NONE) { \
GC_set_mark_bit(real_ptr); \
while (!GC_mark_some((ptr_t)0)); \
while (!GC_mark_some((ptr_t)0)) {} \
} \
}

View File

@ -634,7 +634,7 @@ extern GC_warn_proc GC_current_warn_proc;
# else
# define ALIGNED_WORDS(n) ROUNDED_UP_WORDS(n)
# endif
# define SMALL_OBJ(bytes) ((bytes) < (MAXOBJBYTES -EXTRA_BYTES))
# define SMALL_OBJ(bytes) ((bytes) < (MAXOBJBYTES - EXTRA_BYTES))
# define ADD_SLOP(bytes) ((bytes) + EXTRA_BYTES)
# ifndef MIN_WORDS
/* MIN_WORDS is the size of the smallest allocated object. */
@ -1456,6 +1456,9 @@ void GC_clear_hdr_marks GC_PROTO((hdr * hhdr));
/* Clear the mark bits in a header */
void GC_set_hdr_marks GC_PROTO((hdr * hhdr));
/* Set the mark bits in a header */
void GC_set_fl_marks GC_PROTO((ptr_t p));
/* Set all mark bits associated with */
/* a free list. */
void GC_add_roots_inner GC_PROTO((char * b, char * e, GC_bool tmp));
GC_bool GC_is_static_root GC_PROTO((ptr_t p));
/* Is the address p in one of the registered static */
@ -1484,9 +1487,9 @@ void GC_bl_init GC_PROTO((void));
/* reference from the heap or static data */
# define GC_ADD_TO_BLACK_LIST_NORMAL(bits, source) \
if (GC_all_interior_pointers) { \
GC_add_to_black_list_stack(bits, source); \
GC_add_to_black_list_stack(bits, (ptr_t)(source)); \
} else { \
GC_add_to_black_list_normal(bits, source); \
GC_add_to_black_list_normal(bits, (ptr_t)(source)); \
}
# else
void GC_add_to_black_list_normal GC_PROTO((word p));
@ -1796,12 +1799,16 @@ void GC_dump GC_PROTO((void));
/* Make arguments appear live to compiler */
# ifdef __WATCOMC__
void GC_noop(void*, ...);
void GC_noop(void*, ...);
# else
GC_API void GC_noop();
# ifdef __DMC__
GC_API void GC_noop(...);
# else
GC_API void GC_noop();
# endif
# endif
void GC_noop1 GC_PROTO((word arg));
void GC_noop1 GC_PROTO((word));
/* Logging and diagnostic output: */
GC_API void GC_printf GC_PROTO((GC_CONST char * format, long, long, long, long, long, long));
@ -1859,7 +1866,7 @@ void GC_err_puts GC_PROTO((GC_CONST char *s));
# define GC_ASSERT(expr)
# endif
# ifdef PARALLEL_MARK
# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
/* We need additional synchronization facilities from the thread */
/* support. We believe these are less performance critical */
/* than the main garbage collector lock; standard pthreads-based */
@ -1878,13 +1885,15 @@ void GC_err_puts GC_PROTO((GC_CONST char *s));
extern void GC_acquire_mark_lock();
extern void GC_release_mark_lock();
extern void GC_notify_all_marker();
extern void GC_notify_all_builder();
extern void GC_wait_marker();
/* extern void GC_wait_builder(); */
extern void GC_wait_for_reclaim();
extern word GC_fl_builder_count; /* Protected by mark lock. */
# endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */
# ifdef PARALLEL_MARK
extern void GC_notify_all_marker();
extern void GC_wait_marker();
extern word GC_mark_no; /* Protected by mark lock. */
extern void GC_help_marker(word my_mark_no);
@ -1894,4 +1903,29 @@ void GC_err_puts GC_PROTO((GC_CONST char *s));
/* some other reason. */
# endif /* PARALLEL_MARK */
# if defined(LINUX_THREADS) || defined(IRIX_THREADS) \
|| defined(HPUX_THREADS) || defined(OSF1_THREADS)
/* We define the thread suspension signal here, so that we can refer */
/* to it in the dirty bit implementation, if necessary. Ideally we */
/* would allocate a (real-time ?) signal using the standard mechanism.*/
/* unfortunately, there is no standard mechanism. (There is one */
/* in Linux glibc, but it's not exported.) Thus we continue to use */
/* the same hard-coded signals we've always used. */
# if !defined(SIG_SUSPEND)
# if defined(LINUX_THREADS)
# if defined(SPARC) && !defined(SIGPWR)
/* SPARC/Linux doesn't properly define SIGPWR in <signal.h>.
* It is aliased to SIGLOST in asm/signal.h, though. */
# define SIG_SUSPEND SIGLOST
# else
/* Linuxthreads uses SIGUSR1 and SIGUSR2. */
# define SIG_SUSPEND SIGPWR
# endif
# else /* !LINUX_THREADS */
# define SIG_SUSPEND _SIGRTMIN + 6
# endif
# endif /* !SIG_SUSPEND */
# endif
# endif /* GC_PRIVATE_H */

View File

@ -174,7 +174,7 @@
# define IA64
# define mach_type_known
# endif
# if defined(LINUX) && defined(powerpc)
# if defined(LINUX) && (defined(powerpc) || defined(__powerpc__))
# define POWERPC
# define mach_type_known
# endif
@ -350,6 +350,14 @@
# define S370
# define mach_type_known
# endif
# if defined(__GNU__)
# if defined(__i386__)
/* The Debian Hurd running on generic PC */
# define HURD
# define I386
# define mach_type_known
# endif
# endif
/* Feel free to add more clauses here */
@ -497,6 +505,14 @@
* word stores of 0 are used instead.
*/
/* If we are using a recent version of gcc, we can use __builtin_unwind_init()
* to push the relevant registers onto the stack. This generally makes
* USE_GENERIC_PUSH_REGS the preferred approach for marking from registers.
*/
# if defined(__GNUC__) && ((__GNUC__ >= 3) || \
(__GNUC__ == 2 && __GNUC_MINOR__ >= 8))
# define HAVE_BUILTIN_UNWIND_INIT
# endif
# define STACK_GRAN 0x1000000
# ifdef M68K
@ -804,6 +820,9 @@
# define ALIGN_DOUBLE /* Not strictly necessary, but may give speed */
/* improvement on Pentiums. */
# endif
# ifdef HAVE_BUILTIN_UNWIND_INIT
# define USE_GENERIC_PUSH_REGS
# endif
# ifdef SEQUENT
# define OS_TYPE "SEQUENT"
extern int etext;
@ -1023,6 +1042,17 @@
# define DATASTART ((ptr_t) &__nullarea)
# define DATAEND ((ptr_t) &_end)
# endif
# ifdef HURD
# define OS_TYPE "HURD"
# define STACK_GROWS_DOWN
# define HEURISTIC2
extern int __data_start;
# define DATASTART ( (ptr_t) (&__data_start))
extern int _end;
# define DATAEND ( (ptr_t) (&_end))
/* # define MPROTECT_VDB Not quite working yet? */
# define DYNAMIC_LOADING
# endif
# endif
# ifdef NS32K
@ -1039,7 +1069,6 @@
# ifdef MIPS
# define MACH_TYPE "MIPS"
/* # define STACKBOTTOM ((ptr_t)0x7fff8000) sometimes also works. */
# ifdef LINUX
/* This was developed for a linuxce style platform. Probably */
/* needs to be tweaked for workstation class machines. */
@ -1047,8 +1076,9 @@
extern int __data_start;
# define DATASTART ((ptr_t)(&__data_start))
# define ALIGNMENT 4
# define USE_GENERIC_PUSH_REGS 1
# define STACKBOTTOM 0x80000000
# define USE_GENERIC_PUSH_REGS
# define STACKBOTTOM ((ptr_t)0x7fff8000)
/* Older toolchains may need 0x80000000. */
/* In many cases, this should probably use LINUX_STACKBOTTOM */
/* instead. But some kernel versions seem to give the wrong */
/* value from /proc. */
@ -1106,7 +1136,7 @@
# define ALIGNMENT 4
# define OS_TYPE "NETBSD"
# define HEURISTIC2
# define USE_GENERIC_PUSH_REGS 1
# define USE_GENERIC_PUSH_REGS
# ifdef __ELF__
extern int etext;
# define DATASTART GC_data_start
@ -1587,6 +1617,12 @@
# if defined(HPUX_THREADS) && !defined(HPUX)
--> inconsistent configuration
# endif
# if defined(WIN32_THREADS) && !defined(MSWIN32)
/* Ideally CYGWIN32 should work, in addition to MSWIN32. I suspect the necessary code */
/* is mostly there, but nobody has actually made sure the right combination of pieces is */
/* compiled in, etc. */
--> inconsistent configuration
# endif
# if defined(PCR) || defined(SRC_M3) || \
defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || \
defined(IRIX_THREADS) || defined(LINUX_THREADS) || \

View File

@ -100,8 +100,8 @@ GC_thread GC_lookup_thread(pthread_t id);
* The only way to suspend threads given the pthread interface is to send
* signals. Unfortunately, this means we have to reserve
* a signal, and intercept client calls to change the signal mask.
* We use SIG_SUSPEND, defined in gc_priv.h.
*/
# define SIG_SUSPEND (SIGRTMIN + 6)
pthread_mutex_t GC_suspend_lock = PTHREAD_MUTEX_INITIALIZER;
/* Number of threads stopped so far */

View File

@ -55,6 +55,12 @@
|| defined(GC_OSF1_THREADS) || defined(OSF1_THREADS) \
# include "private/gc_priv.h"
# if defined(HPUX_THREADS) && !defined(USE_PTHREAD_SPECIFIC) \
&& !defined(USE_HPUX_TLS)
# define USE_HPUX_TLS
# endif
# ifdef THREAD_LOCAL_ALLOC
# if !defined(USE_PTHREAD_SPECIFIC) && !defined(USE_HPUX_TLS)
# include "private/specific.h"
@ -161,15 +167,16 @@ typedef struct GC_Thread_Rep {
# ifdef THREAD_LOCAL_ALLOC
# if CPP_WORDSZ == 64 && defined(ALIGN_DOUBLE)
# define GRANULARITY 16
# define NFREELISTS 48
# define NFREELISTS 49
# else
# define GRANULARITY 8
# define NFREELISTS 64
# define NFREELISTS 65
# endif
/* The ith free list corresponds to size (i+1)*GRANULARITY */
# define INDEX_FROM_BYTES(n) (ADD_SLOP(n) - 1)/GRANULARITY
# define BYTES_FROM_INDEX(i) (((i) + 1) * GRANULARITY - EXTRA_BYTES)
# define SMALL_ENOUGH(bytes) (ADD_SLOP(bytes) <= NFREELISTS*GRANULARITY)
/* The ith free list corresponds to size i*GRANULARITY */
# define INDEX_FROM_BYTES(n) ((ADD_SLOP(n) + GRANULARITY - 1)/GRANULARITY)
# define BYTES_FROM_INDEX(i) ((i) * GRANULARITY - EXTRA_BYTES)
# define SMALL_ENOUGH(bytes) (ADD_SLOP(bytes) <= \
(NFREELISTS-1)*GRANULARITY)
ptr_t ptrfree_freelists[NFREELISTS];
ptr_t normal_freelists[NFREELISTS];
# ifdef GC_GCJ_SUPPORT
@ -194,12 +201,12 @@ typedef struct GC_Thread_Rep {
GC_thread GC_lookup_thread(pthread_t id);
static GC_bool fully_initialized = FALSE;
static GC_bool parallel_initialized = FALSE;
# if defined(__GNUC__)
void GC_full_init() __attribute__ ((constructor));
void GC_init_parallel() __attribute__ ((constructor));
# else
void GC_full_init();
void GC_init_parallel();
# endif
# if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL)
@ -223,8 +230,8 @@ static void return_freelists(ptr_t *fl, ptr_t *gfl)
ptr_t q, *qptr;
size_t nwords;
for (i = 0; i < NFREELISTS; ++i) {
nwords = (i + 1) * (GRANULARITY/sizeof(word));
for (i = 1; i < NFREELISTS; ++i) {
nwords = i * (GRANULARITY/sizeof(word));
qptr = fl + i;
q = *qptr;
if ((word)q < HBLKSIZE) continue;
@ -243,6 +250,12 @@ static void return_freelists(ptr_t *fl, ptr_t *gfl)
}
}
/* We statically allocate a single "size 0" object. It is linked to */
/* itself, and is thus repeatedly reused for all size 0 allocation */
/* requests. (Size 0 gcj allocation requests are incorrect, and */
/* we arrange for those to fault asap.) */
static ptr_t size_zero_object = (ptr_t)(&size_zero_object);
/* Each thread structure must be initialized. */
/* This call must be made from the new thread. */
/* Caller holds allocation lock. */
@ -259,13 +272,19 @@ void GC_init_thread_local(GC_thread p)
if (0 != GC_setspecific(GC_thread_key, p)) {
ABORT("Failed to set thread specific allocation pointers");
}
for (i = 0; i < NFREELISTS; ++i) {
for (i = 1; i < NFREELISTS; ++i) {
p -> ptrfree_freelists[i] = (ptr_t)1;
p -> normal_freelists[i] = (ptr_t)1;
# ifdef GC_GCJ_SUPPORT
p -> gcj_freelists[i] = (ptr_t)1;
# endif
}
/* Set up the size 0 free lists. */
p -> ptrfree_freelists[0] = (ptr_t)(&size_zero_object);
p -> normal_freelists[0] = (ptr_t)(&size_zero_object);
# ifdef GC_GCJ_SUPPORT
p -> gcj_freelists[0] = (ptr_t)(-1);
# endif
}
#ifdef GC_GCJ_SUPPORT
@ -303,7 +322,7 @@ GC_PTR GC_local_malloc(size_t bytes)
/* This can happen if we get called when the world is */
/* being initialized. Whether we can actually complete */
/* the initialization then is unclear. */
GC_full_init();
GC_init_parallel();
k = GC_thread_key;
}
# endif
@ -326,10 +345,8 @@ GC_PTR GC_local_malloc(size_t bytes)
*my_fl = my_entry + index + 1;
return GC_malloc(bytes);
} else {
my_entry = GC_generic_malloc_many(BYTES_FROM_INDEX(index),
NORMAL);
*my_fl = my_entry;
if (my_entry == 0) return GC_oom_fn(bytes);
GC_generic_malloc_many(BYTES_FROM_INDEX(index), NORMAL, my_fl);
if (*my_fl == 0) return GC_oom_fn(bytes);
return GC_local_malloc(bytes);
}
}
@ -352,10 +369,11 @@ GC_PTR GC_local_malloc_atomic(size_t bytes)
*my_fl = my_entry + index + 1;
return GC_malloc_atomic(bytes);
} else {
my_entry = GC_generic_malloc_many(BYTES_FROM_INDEX(index),
PTRFREE);
*my_fl = my_entry;
if (my_entry == 0) return GC_oom_fn(bytes);
GC_generic_malloc_many(BYTES_FROM_INDEX(index), PTRFREE, my_fl);
/* *my_fl is updated while the collector is excluded; */
/* the free list is always visible to the collector as */
/* such. */
if (*my_fl == 0) return GC_oom_fn(bytes);
return GC_local_malloc_atomic(bytes);
}
}
@ -390,18 +408,22 @@ GC_PTR GC_local_gcj_malloc(size_t bytes,
/* allocation of the next object, but to see this object */
/* still containing a free list pointer. Otherwise the */
/* marker might find a random "mark descriptor". */
*my_fl = obj_link(my_entry);
*(void **)result = ptr_to_struct_containing_descr;
*(volatile ptr_t *)my_fl = obj_link(my_entry);
/* We must update the freelist before we store the pointer. */
/* Otherwise a GC at this point would see a corrupted */
/* free list. */
/* A memory barrier is probably never needed, since the */
/* action of stopping this thread will cause prior writes */
/* to complete. */
*(void * volatile *)result = ptr_to_struct_containing_descr;
return result;
} else if ((word)my_entry - 1 < DIRECT_GRANULES) {
*my_fl = my_entry + index + 1;
return GC_gcj_malloc(bytes, ptr_to_struct_containing_descr);
} else {
my_entry = GC_generic_malloc_many(BYTES_FROM_INDEX(index),
GC_gcj_kind);
*my_fl = my_entry;
if (my_entry == 0) return GC_oom_fn(bytes);
return GC_gcj_malloc(bytes, ptr_to_struct_containing_descr);
GC_generic_malloc_many(BYTES_FROM_INDEX(index), GC_gcj_kind, my_fl);
if (*my_fl == 0) return GC_oom_fn(bytes);
return GC_local_gcj_malloc(bytes, ptr_to_struct_containing_descr);
}
}
}
@ -415,22 +437,16 @@ GC_PTR GC_local_gcj_malloc(size_t bytes,
# endif /* !THREAD_LOCAL_ALLOC */
/*
* The only way to suspend threads given the pthread interface is to send
* signals. We can't use SIGSTOP directly, because we need to get the
* thread to save its stack pointer in the GC thread table before
* suspending. So we have to reserve a signal of our own for this.
* This means we have to intercept client calls to change the signal mask.
* The linuxthreads package already uses SIGUSR1 and SIGUSR2,
* so we need to reuse something else. I chose SIGPWR.
* (Perhaps SIGUNUSED would be a better choice.)
* We use signals to stop threads during GC.
*
* Suspended threads wait in signal handler for SIG_THR_RESTART.
* That's more portable than semaphores or condition variables.
* (We do use sem_post from a signal handler, but that should be portable.)
*
* The thread suspension signal SIG_SUSPEND is now defined in gc_priv.h.
* Note that we can't just stop a thread; we need it to save its stack
* pointer(s) and acknowledge.
*/
#ifndef SIG_SUSPEND
# if defined(HPUX_THREADS) || defined(GC_OSF1_THREADS)
# define SIG_SUSPEND _SIGRTMIN + 6
# else
# define SIG_SUSPEND SIGPWR
# endif
#endif
#ifndef SIG_THR_RESTART
# if defined(HPUX_THREADS) || defined(GC_OSF1_THREADS)
@ -440,12 +456,6 @@ GC_PTR GC_local_gcj_malloc(size_t bytes,
# endif
#endif
/* SPARC/Linux doesn't properly define SIGPWR in <signal.h>.
* It is aliased to SIGLOST in asm/signal.h, though. */
#if defined(SPARC) && !defined(SIGPWR)
# define SIGPWR SIGLOST
#endif
sem_t GC_suspend_ack_sem;
#if !defined(HPUX_THREADS) && !defined(GC_OSF1_THREADS)
@ -654,6 +664,34 @@ void GC_push_thread_structures GC_PROTO((void))
GC_push_all((ptr_t)(GC_threads), (ptr_t)(GC_threads)+sizeof(GC_threads));
}
#ifdef THREAD_LOCAL_ALLOC
/* We must explicitly mark ptrfree and gcj free lists, since the free */
/* list links wouldn't otherwise be found. We also set them in the */
/* normal free lists, since that involves touching less memory than if */
/* we scanned them normally. */
void GC_mark_thread_local_free_lists(void)
{
int i, j;
GC_thread p;
ptr_t q;
for (i = 0; i < THREAD_TABLE_SZ; ++i) {
for (p = GC_threads[i]; 0 != p; p = p -> next) {
for (j = 1; j < NFREELISTS; ++j) {
q = p -> ptrfree_freelists[j];
if ((word)q > HBLKSIZE) GC_set_fl_marks(q);
q = p -> normal_freelists[j];
if ((word)q > HBLKSIZE) GC_set_fl_marks(q);
# ifdef GC_GCJ_SUPPORT
q = p -> gcj_freelists[j];
if ((word)q > HBLKSIZE) GC_set_fl_marks(q);
# endif /* GC_GCJ_SUPPORT */
}
}
}
}
#endif /* THREAD_LOCAL_ALLOC */
/* Add a thread to GC_threads. We assume it wasn't already there. */
/* Caller holds allocation lock. */
GC_thread GC_new_thread(pthread_t id)
@ -752,7 +790,6 @@ void GC_stop_world()
GC_stopping_thread = my_thread; /* debugging only. */
GC_stopping_pid = getpid(); /* debugging only. */
/* Make sure all free list construction has stopped before we start. */
/* No new construction can start, since free list construction is */
/* required to acquire and release the GC lock before it starts, */
@ -795,6 +832,7 @@ void GC_stop_world()
#if DEBUG_THREADS
GC_printf1("World stopped 0x%x\n", pthread_self());
#endif
GC_stopping_thread = 0; /* debugging only */
}
/* Caller holds allocation lock, and has held it continuously since */
@ -1072,9 +1110,12 @@ void GC_thr_init()
/* may require allocation. */
/* Called as constructor without allocation lock. */
/* Must be called before a second thread is created. */
void GC_full_init()
/* Called without allocation lock. */
void GC_init_parallel()
{
if (fully_initialized) return;
if (parallel_initialized) return;
parallel_initialized = TRUE;
/* GC_init() calls us back, so set flag first. */
if (!GC_is_initialized) GC_init();
/* If we are using a parallel marker, start the helper threads. */
# ifdef PARALLEL_MARK
@ -1086,7 +1127,6 @@ void GC_full_init()
GC_init_thread_local(GC_lookup_thread(pthread_self()));
UNLOCK();
# endif
fully_initialized = TRUE;
}
@ -1327,7 +1367,7 @@ WRAP_FUNC(pthread_create)(pthread_t *new_thread,
LOCK();
si = (struct start_info *)GC_INTERNAL_MALLOC(sizeof(struct start_info), NORMAL);
UNLOCK();
if (!fully_initialized) GC_full_init();
if (!parallel_initialized) GC_init_parallel();
if (0 == si) return(ENOMEM);
sem_init(&(si -> registered), 0, 0);
si -> start_routine = start_routine;
@ -1539,7 +1579,7 @@ void GC_lock()
#endif /* !USE_SPINLOCK */
#ifdef PARALLEL_MARK
#if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
#ifdef GC_ASSERTIONS
pthread_t GC_mark_lock_holder = NO_THREAD;
@ -1559,8 +1599,6 @@ void GC_lock()
static pthread_mutex_t mark_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
static pthread_cond_t mark_cv = PTHREAD_COND_INITIALIZER;
static pthread_cond_t builder_cv = PTHREAD_COND_INITIALIZER;
void GC_acquire_mark_lock()
@ -1587,21 +1625,11 @@ void GC_release_mark_lock()
}
}
void GC_wait_marker()
{
GC_ASSERT(GC_mark_lock_holder == pthread_self());
# ifdef GC_ASSERTIONS
GC_mark_lock_holder = NO_THREAD;
# endif
if (pthread_cond_wait(&mark_cv, &mark_mutex) != 0) {
ABORT("pthread_cond_wait failed");
}
GC_ASSERT(GC_mark_lock_holder == NO_THREAD);
# ifdef GC_ASSERTIONS
GC_mark_lock_holder = pthread_self();
# endif
}
/* Collector must wait for a freelist builders for 2 reasons: */
/* 1) Mark bits may still be getting examined without lock. */
/* 2) Partial free lists referenced only by locals may not be scanned */
/* correctly, e.g. if they contain "pointer-free" objects, since the */
/* free-list link may be ignored. */
void GC_wait_builder()
{
GC_ASSERT(GC_mark_lock_holder == pthread_self());
@ -1617,11 +1645,13 @@ void GC_wait_builder()
# endif
}
void GC_notify_all_marker()
void GC_wait_for_reclaim()
{
if (pthread_cond_broadcast(&mark_cv) != 0) {
ABORT("pthread_cond_broadcast failed");
GC_acquire_mark_lock();
while (GC_fl_builder_count > 0) {
GC_wait_builder();
}
GC_release_mark_lock();
}
void GC_notify_all_builder()
@ -1632,14 +1662,34 @@ void GC_notify_all_builder()
}
}
void GC_wait_for_reclaim()
#endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */
#ifdef PARALLEL_MARK
static pthread_cond_t mark_cv = PTHREAD_COND_INITIALIZER;
void GC_wait_marker()
{
GC_acquire_mark_lock();
while (GC_fl_builder_count > 0) {
GC_wait_builder();
GC_ASSERT(GC_mark_lock_holder == pthread_self());
# ifdef GC_ASSERTIONS
GC_mark_lock_holder = NO_THREAD;
# endif
if (pthread_cond_wait(&mark_cv, &mark_mutex) != 0) {
ABORT("pthread_cond_wait failed");
}
GC_release_mark_lock();
GC_ASSERT(GC_mark_lock_holder == NO_THREAD);
# ifdef GC_ASSERTIONS
GC_mark_lock_holder = pthread_self();
# endif
}
void GC_notify_all_marker()
{
if (pthread_cond_broadcast(&mark_cv) != 0) {
ABORT("pthread_cond_broadcast failed");
}
}
#endif /* PARALLEL_MARK */
# endif /* LINUX_THREADS */

View File

@ -228,7 +228,7 @@ void GC_push_regs()
&& !(defined(NETBSD) && defined(__ELF__)) \
&& !(defined(OPENBSD) && defined(__ELF__)) \
&& !(defined(BEOS) && defined(__ELF__)) \
&& !defined(DOS4GW)
&& !defined(DOS4GW) && !defined(HURD)
/* I386 code, generic code does not appear to work */
/* It does appear to work under OS2, and asms dont */
/* This is used for some 38g UNIX variants and for CYGWIN32 */
@ -244,7 +244,8 @@ void GC_push_regs()
# if ( defined(I386) && defined(LINUX) && defined(__ELF__) ) \
|| ( defined(I386) && defined(FREEBSD) && defined(__ELF__) ) \
|| ( defined(I386) && defined(NETBSD) && defined(__ELF__) ) \
|| ( defined(I386) && defined(OPENBSD) && defined(__ELF__) )
|| ( defined(I386) && defined(OPENBSD) && defined(__ELF__) ) \
|| ( defined(I386) && defined(HURD) && defined(__ELF__) )
/* This is modified for Linux with ELF (Note: _ELF_ only) */
/* This section handles FreeBSD with ELF. */
@ -391,8 +392,8 @@ void GC_push_regs()
# endif
/* other machines... */
# if !(defined M68K) && !(defined VAX) && !(defined RT)
# if !(defined SPARC) && !(defined I386) && !(defined NS32K)
# if !defined(M68K) && !defined(VAX) && !defined(RT)
# if !defined(SPARC) && !defined(I386) && !defined(NS32K)
# if !defined(POWERPC) && !defined(UTS4)
# if !defined(PJ) && !(defined(MIPS) && defined(LINUX))
--> bad news <--
@ -407,27 +408,35 @@ void GC_push_regs()
void GC_generic_push_regs(cold_gc_frame)
ptr_t cold_gc_frame;
{
/* Generic code */
/* The idea is due to Parag Patel at HP. */
/* We're not sure whether he would like */
/* to be he acknowledged for it or not. */
{
static jmp_buf regs;
register word * i = (word *) regs;
register ptr_t lim = (ptr_t)(regs) + (sizeof regs);
# ifdef HAVE_BUILTIN_UNWIND_INIT
/* This was suggested by Richard Henderson as the way to */
/* force callee-save registers and register windows onto */
/* the stack. */
__builtin_unwind_init();
# else /* !HAVE_BUILTIN_UNWIND_INIT */
/* Generic code */
/* The idea is due to Parag Patel at HP. */
/* We're not sure whether he would like */
/* to be he acknowledged for it or not. */
jmp_buf regs;
register word * i = (word *) regs;
register ptr_t lim = (ptr_t)(regs) + (sizeof regs);
/* Setjmp on Sun 3s doesn't clear all of the buffer. */
/* That tends to preserve garbage. Clear it. */
/* Setjmp doesn't always clear all of the buffer. */
/* That tends to preserve garbage. Clear it. */
for (; (char *)i < lim; i++) {
*i = 0;
}
# if defined(POWERPC) || defined(MSWIN32) || defined(MSWINCE) \
|| defined(UTS4) || defined(LINUX)
(void) setjmp(regs);
# else
(void) _setjmp(regs);
# endif
# if defined(SPARC) || defined(IA64)
# if defined(POWERPC) || defined(MSWIN32) || defined(MSWINCE) \
|| defined(UTS4) || defined(LINUX)
(void) setjmp(regs);
# else
(void) _setjmp(regs);
# endif
# endif /* !HAVE_BUILTIN_UNWIND_INIT */
# if (defined(SPARC) && !defined(HAVE_BUILTIN_UNWIND_INIT)) \
|| defined(IA64)
/* On a register window machine, we need to save register */
/* contents on the stack for this to work. The setjmp */
/* is probably not needed on SPARC, since pointers are */
@ -438,6 +447,10 @@ ptr_t cold_gc_frame;
word GC_save_regs_in_stack();
GC_save_regs_ret_val = GC_save_regs_in_stack();
/* On IA64 gcc, could use __builtin_ia64_flushrs() and */
/* __builtin_ia64_flushrs(). The latter will be done */
/* implicitly by __builtin_unwind_init() for gcc3.0.1 */
/* and later. */
}
# endif
GC_push_current_stack(cold_gc_frame);
@ -511,7 +524,7 @@ ptr_t cold_gc_frame;
/* returns arg. Stack clearing is crucial on SPARC, so we supply */
/* an assembly version that's more careful. Assumes limit is hotter */
/* than sp, and limit is 8 byte aligned. */
#if defined(ASM_CLEAR_CODE) && !defined(THREADS)
#if defined(ASM_CLEAR_CODE)
#ifndef SPARC
--> fix it
#endif

View File

@ -323,10 +323,15 @@ extern ptr_t GC_reclaim_generic();
/* GC_malloc_many or friends to replenish it. (We do not round up */
/* object sizes, since a call indicates the intention to consume many */
/* objects of exactly this size.) */
/* We return the free-list by assigning it to *result, since it is */
/* not safe to return, e.g. a linked list of pointer-free objects, */
/* since the collector would not retain the entire list if it were */
/* invoked just as we were returning. */
/* Note that the client should usually clear the link field. */
ptr_t GC_generic_malloc_many(lb, k)
void GC_generic_malloc_many(lb, k, result)
register word lb;
register int k;
ptr_t *result;
{
ptr_t op;
ptr_t p;
@ -345,13 +350,20 @@ DCL_LOCK_STATE;
if (!SMALL_OBJ(lb)) {
op = GC_generic_malloc(lb, k);
if(0 != op) obj_link(op) = 0;
return(op);
*result = op;
return;
}
lw = ALIGNED_WORDS(lb);
GC_INVOKE_FINALIZERS();
DISABLE_SIGNALS();
LOCK();
if (!GC_is_initialized) GC_init_inner();
/* Do our share of marking work */
if (GC_incremental && !GC_dont_gc) {
ENTER_GC();
GC_collect_a_little_inner(1);
EXIT_GC();
}
/* First see if we can reclaim a page of objects waiting to be */
/* reclaimed. */
{
@ -403,6 +415,7 @@ DCL_LOCK_STATE;
GC_mem_found += my_words_allocd;
# endif
# ifdef PARALLEL_MARK
*result = op;
(void)GC_atomic_add(
(volatile GC_word *)(&GC_words_allocd_tmp),
(GC_word)(my_words_allocd));
@ -410,7 +423,8 @@ DCL_LOCK_STATE;
-- GC_fl_builder_count;
if (GC_fl_builder_count == 0) GC_notify_all_builder();
GC_release_mark_lock();
return GC_clear_stack(op);
(void) GC_clear_stack(0);
return;
# else
GC_words_allocd += my_words_allocd;
goto out;
@ -464,11 +478,13 @@ DCL_LOCK_STATE;
op = GC_build_fl(h, lw, ok -> ok_init, 0);
# ifdef PARALLEL_MARK
*result = op;
GC_acquire_mark_lock();
-- GC_fl_builder_count;
if (GC_fl_builder_count == 0) GC_notify_all_builder();
GC_release_mark_lock();
return GC_clear_stack(op);
(void) GC_clear_stack(0);
return;
# else
goto out;
# endif
@ -481,14 +497,17 @@ DCL_LOCK_STATE;
if (0 != op) obj_link(op) = 0;
out:
*result = op;
UNLOCK();
ENABLE_SIGNALS();
return(GC_clear_stack(op));
(void) GC_clear_stack(0);
}
GC_PTR GC_malloc_many(size_t lb)
{
return(GC_generic_malloc_many(lb, NORMAL));
ptr_t result;
GC_generic_malloc_many(lb, NORMAL, &result);
return result;
}
/* Note that the "atomic" version of this would be unsafe, since the */

View File

@ -427,21 +427,22 @@ GC_bool GC_mark_stack_empty()
#endif
/* Given a pointer to someplace other than a small object page or the */
/* first page of a large object, return a pointer either to the */
/* start of the large object or NIL. */
/* In the latter case black list the address current. */
/* Returns NIL without black listing if current points to a block */
/* with IGNORE_OFF_PAGE set. */
/* first page of a large object, either: */
/* - return a pointer to somewhere in the first page of the large */
/* object, if current points to a large object. */
/* In this case *hhdr is replaced with a pointer to the header */
/* for the large object. */
/* - just return current if it does not point to a large object. */
/*ARGSUSED*/
# ifdef PRINT_BLACK_LIST
ptr_t GC_find_start(current, hhdr, source)
word source;
ptr_t GC_find_start(current, hhdr, new_hdr_p, source)
ptr_t source;
# else
ptr_t GC_find_start(current, hhdr)
ptr_t GC_find_start(current, hhdr, new_hdr_p)
# define source 0
# endif
register ptr_t current;
register hdr * hhdr;
register hdr *hhdr, **new_hdr_p;
{
if (GC_all_interior_pointers) {
if (hhdr != 0) {
@ -457,17 +458,15 @@ register hdr * hhdr;
if ((word *)orig - (word *)current
>= (ptrdiff_t)(hhdr->hb_sz)) {
/* Pointer past the end of the block */
GC_ADD_TO_BLACK_LIST_NORMAL((word)orig, source);
return(0);
return(orig);
}
*new_hdr_p = hhdr;
return(current);
} else {
GC_ADD_TO_BLACK_LIST_NORMAL((word)current, source);
return(0);
return(current);
}
} else {
GC_ADD_TO_BLACK_LIST_NORMAL((word)current, source);
return(0);
return(current);
}
# undef source
}

View File

@ -471,8 +471,9 @@ ptr_t cold_gc_frame;
cold_gc_bs_pointer = bsp - 2048;
if (cold_gc_bs_pointer < BACKING_STORE_BASE) {
cold_gc_bs_pointer = BACKING_STORE_BASE;
} else {
GC_push_all_stack(BACKING_STORE_BASE, cold_gc_bs_pointer);
}
GC_push_all_stack(BACKING_STORE_BASE, cold_gc_bs_pointer);
} else {
cold_gc_bs_pointer = BACKING_STORE_BASE;
}
@ -501,6 +502,10 @@ void GC_push_gc_structures GC_PROTO((void))
# endif
}
#ifdef THREAD_LOCAL_ALLOC
void GC_mark_thread_local_free_lists();
#endif
/*
* Call the mark routines (GC_tl_push for a single pointer, GC_push_conditional
* on groups of pointers) on every top level accessible pointer.
@ -552,6 +557,12 @@ ptr_t cold_gc_frame;
GC_push_gc_structures();
}
/* Mark thread local free lists, even if their mark */
/* descriptor excludes the link field. */
# ifdef THREAD_LOCAL_ALLOC
GC_mark_thread_local_free_lists();
# endif
/*
* Now traverse stacks.
*/

View File

@ -45,7 +45,7 @@
mutex_t GC_allocate_ml; /* Implicitly initialized. */
# else
# ifdef WIN32_THREADS
# if defined(_DLL) || defined(GC_DLL)
# if !defined(GC_NOT_DLL) && (defined(_DLL) || defined(GC_DLL))
__declspec(dllexport) CRITICAL_SECTION GC_allocate_ml;
# else
CRITICAL_SECTION GC_allocate_ml;
@ -301,6 +301,8 @@ ptr_t arg;
if (++random_no % 13 == 0) {
limit = sp;
MAKE_HOTTER(limit, BIG_CLEAR_SIZE*sizeof(word));
limit &= ~0xf; /* Make it sufficiently aligned for assembly */
/* implementations of GC_clear_stack_inner. */
return GC_clear_stack_inner(arg, limit);
} else {
BZERO(dummy, SMALL_CLEAR_SIZE*sizeof(word));
@ -441,6 +443,15 @@ void GC_init()
UNLOCK();
ENABLE_SIGNALS();
# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
/* Make sure marker threads and started and thread local */
/* allocation is initialized, in case we didn't get */
/* called from GC_init_parallel(); */
{
extern void GC_init_parallel(void);
GC_init_parallel();
}
# endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */
}
#if defined(MSWIN32) || defined(MSWINCE)
@ -682,7 +693,7 @@ out:
}
int GC_write(buf, len)
char * buf;
GC_CONST char * buf;
size_t len;
{
BOOL tmp;
@ -735,7 +746,7 @@ int GC_tmp; /* Should really be local ... */
#if !defined(MSWIN32) && !defined(MSWINCE) && !defined(OS2) && !defined(MACOS)
int GC_write(fd, buf, len)
int fd;
char *buf;
GC_CONST char *buf;
size_t len;
{
register int bytes_written = 0;
@ -867,7 +878,7 @@ GC_CONST char * msg;
/* It's arguably nicer to sleep, but that makes it harder */
/* to look at the thread if the debugger doesn't know much */
/* about threads. */
for(;;);
for(;;) {}
}
# ifdef MSWIN32
DebugBreak();

View File

@ -63,7 +63,11 @@
/* Blatantly OS dependent routines, except for those that are related */
/* to dynamic loading. */
# if !defined(THREADS) && !defined(STACKBOTTOM) && defined(HEURISTIC2)
# if defined(HEURISTIC2) || defined(SEARCH_FOR_DATA_START)
# define NEED_FIND_LIMIT
# endif
# if !defined(STACKBOTTOM) && defined(HEURISTIC2)
# define NEED_FIND_LIMIT
# endif
@ -75,13 +79,8 @@
# define NEED_FIND_LIMIT
# endif
# if (defined(SVR4) || defined(AUX) || defined(DGUX)) && !defined(PCR)
# define NEED_FIND_LIMIT
# endif
# if defined(LINUX) && \
(defined(POWERPC) || defined(SPARC) || defined(ALPHA) || defined(IA64) \
|| defined(MIPS))
# if (defined(SVR4) || defined(AUX) || defined(DGUX) \
|| (defined(LINUX) && defined(SPARC))) && !defined(PCR)
# define NEED_FIND_LIMIT
# endif
@ -123,8 +122,10 @@
# include <fcntl.h>
#endif
#ifdef SUNOS5SIGS
# include <sys/siginfo.h>
#if defined(SUNOS5SIGS) || defined (HURD) || defined(LINUX)
# ifdef SUNOS5SIGS
# include <sys/siginfo.h>
# endif
# undef setjmp
# undef longjmp
# define setjmp(env) sigsetjmp(env, 1)
@ -338,7 +339,7 @@ void GC_enable_signals(void)
&& !defined(MSWINCE) \
&& !defined(MACOS) && !defined(DJGPP) && !defined(DOS4GW)
# if defined(sigmask) && !defined(UTS4)
# if defined(sigmask) && !defined(UTS4) && !defined(HURD)
/* Use the traditional BSD interface */
# define SIGSET_T int
# define SIG_DEL(set, signal) (set) &= ~(sigmask(signal))
@ -519,7 +520,7 @@ ptr_t GC_get_stack_base()
# undef GC_AMIGA_SB
# endif /* AMIGA */
# if defined(NEED_FIND_LIMIT) || defined(UNIX_LIKE)
# if defined(NEED_FIND_LIMIT) || (defined(UNIX_LIKE) && !defined(ECOS))
# ifdef __STDC__
typedef void (*handler)(int);
@ -527,9 +528,9 @@ ptr_t GC_get_stack_base()
typedef void (*handler)();
# endif
# if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1)
# if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1) || defined(HURD)
static struct sigaction old_segv_act;
# if defined(_sigargs) || defined(HPUX) /* !Irix6.x */
# if defined(_sigargs) /* !Irix6.x */ || defined(HPUX) || defined(HURD)
static struct sigaction old_bus_act;
# endif
# else
@ -544,11 +545,16 @@ ptr_t GC_get_stack_base()
# endif
{
# ifndef ECOS
# if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1)
# if defined(SUNOS5SIGS) || defined(IRIX5) \
|| defined(OSF1) || defined(HURD)
struct sigaction act;
act.sa_handler = h;
act.sa_flags = SA_RESTART | SA_NODEFER;
# ifdef SUNOS5SIGS
act.sa_flags = SA_RESTART | SA_NODEFER;
# else
act.sa_flags = SA_RESTART;
# endif
/* The presence of SA_NODEFER represents yet another gross */
/* hack. Under Solaris 2.3, siglongjmp doesn't appear to */
/* interact correctly with -lthread. We hide the confusion */
@ -564,7 +570,7 @@ ptr_t GC_get_stack_base()
# else
(void) sigaction(SIGSEGV, &act, &old_segv_act);
# if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
|| defined(HPUX)
|| defined(HPUX) || defined(HURD)
/* Under Irix 5.x or HP/UX, we may get SIGBUS. */
/* Pthreads doesn't exist under Irix 5.x, so we */
/* don't have to worry in the threads case. */
@ -601,10 +607,11 @@ ptr_t GC_get_stack_base()
void GC_reset_fault_handler()
{
# ifndef ECOS
# if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1)
# if defined(SUNOS5SIGS) || defined(IRIX5) \
|| defined(OSF1) || defined(HURD)
(void) sigaction(SIGSEGV, &old_segv_act, 0);
# if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \
|| defined(HPUX)
|| defined(HPUX) || defined(HURD)
(void) sigaction(SIGBUS, &old_bus_act, 0);
# endif
# else
@ -753,7 +760,7 @@ ptr_t GC_get_stack_base()
#endif /* FREEBSD_STACKBOTTOM */
#if !defined(BEOS) && !defined(AMIGA) && !defined(MSWIN32) \
&& !defined(MSWINCE) && !defined(OS2)
&& !defined(MSWINCE) && !defined(OS2) && !defined(ECOS)
ptr_t GC_get_stack_base()
{
@ -1808,7 +1815,8 @@ struct hblk *h;
#if defined(SUNOS4) || defined(FREEBSD)
typedef void (* SIG_PF)();
#endif
#if defined(SUNOS5SIGS) || defined(OSF1) || defined(LINUX) || defined(MACOSX)
#if defined(SUNOS5SIGS) || defined(OSF1) || defined(LINUX) \
|| defined(MACOSX) || defined(HURD)
# ifdef __STDC__
typedef void (* SIG_PF)(int);
# else
@ -1826,7 +1834,7 @@ struct hblk *h;
# define SIG_DFL (SIG_PF) (-1)
#endif
#if defined(IRIX5) || defined(OSF1)
#if defined(IRIX5) || defined(OSF1) || defined(HURD)
typedef void (* REAL_SIG_PF)(int, int, struct sigcontext *);
#endif
#if defined(SUNOS5SIGS)
@ -2013,7 +2021,7 @@ SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */
#ifdef GC_TEST_AND_SET_DEFINED
static VOLATILE unsigned int fault_handler_lock = 0;
void async_set_pht_entry_from_index(VOLATILE page_hash_table db, int index) {
while (GC_test_and_set(&fault_handler_lock));
while (GC_test_and_set(&fault_handler_lock)) {}
/* Could also revert to set_pht_entry_from_index_safe if initial */
/* GC_test_and_set fails. */
set_pht_entry_from_index(db, index);
@ -2067,16 +2075,21 @@ SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */
# define CODE_OK (code == BUS_PAGE_FAULT)
# endif
# endif
# if defined(IRIX5) || defined(OSF1)
# if defined(IRIX5) || defined(OSF1) || defined(HURD)
# include <errno.h>
void GC_write_fault_handler(int sig, int code, struct sigcontext *scp)
# define SIG_OK (sig == SIGSEGV)
# ifdef OSF1
# define SIG_OK (sig == SIGSEGV)
# define CODE_OK (code == 2 /* experimentally determined */)
# endif
# ifdef IRIX5
# define SIG_OK (sig == SIGSEGV)
# define CODE_OK (code == EACCES)
# endif
# ifdef HURD
# define SIG_OK (sig == SIGBUS || sig == SIGSEGV)
# define CODE_OK TRUE
# endif
# endif
# if defined(LINUX)
# if defined(ALPHA) || defined(M68K)
@ -2131,6 +2144,9 @@ SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */
# endif
{
register unsigned i;
# if defined(HURD)
char *addr = (char *) code;
# endif
# ifdef IRIX5
char * addr = (char *) (size_t) (scp -> sc_badvaddr);
# endif
@ -2254,7 +2270,7 @@ SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */
# endif
return;
# endif
# if defined (IRIX5) || defined(OSF1)
# if defined (IRIX5) || defined(OSF1) || defined(HURD)
(*(REAL_SIG_PF)old_handler) (sig, code, scp);
return;
# endif
@ -2266,13 +2282,24 @@ SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */
# endif
}
}
UNPROTECT(h, GC_page_size);
/* We need to make sure that no collection occurs between */
/* the UNPROTECT and the setting of the dirty bit. Otherwise */
/* a write by a third thread might go unnoticed. Reversing */
/* the order is just as bad, since we would end up unprotecting */
/* a page in a GC cycle during which it's not marked. */
/* Currently we do this by disabling the thread stopping */
/* signals while this handler is running. An alternative might */
/* be to record the fact that we're about to unprotect, or */
/* have just unprotected a page in the GC's thread structure, */
/* and then to have the thread stopping code set the dirty */
/* flag, if necessary. */
for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
register int index = PHT_HASH(h+i);
async_set_pht_entry_from_index(GC_dirty_pages, index);
}
UNPROTECT(h, GC_page_size);
# if defined(OSF1) || defined(LINUX)
# if defined(OSF1)
/* These reset the signal handler each time by default. */
signal(SIGSEGV, (SIG_PF) GC_write_fault_handler);
# endif
@ -2321,16 +2348,25 @@ struct hblk *h;
void GC_dirty_init()
{
# if defined(SUNOS5SIGS) || defined(IRIX5) /* || defined(OSF1) */
# if defined(SUNOS5SIGS) || defined(IRIX5) || defined(LINUX) || \
defined(OSF1) || defined(HURD)
struct sigaction act, oldact;
# ifdef IRIX5
/* We should probably specify SA_SIGINFO for Linux, and handle */
/* the different architectures more uniformly. */
# if defined(IRIX5) || defined(LINUX) || defined(OSF1) || defined(HURD)
act.sa_flags = SA_RESTART;
act.sa_handler = GC_write_fault_handler;
act.sa_handler = (SIG_PF)GC_write_fault_handler;
# else
act.sa_flags = SA_RESTART | SA_SIGINFO;
act.sa_sigaction = GC_write_fault_handler;
# endif
(void)sigemptyset(&act.sa_mask);
# ifdef SIG_SUSPEND
/* Arrange to postpone SIG_SUSPEND while we're in a write fault */
/* handler. This effectively makes the handler atomic w.r.t. */
/* stopping the world for GC. */
(void)sigaddset(&act.sa_mask, SIG_SUSPEND);
# endif /* SIG_SUSPEND */
# endif
# if defined(MACOSX)
struct sigaction act, oldact;
@ -2359,7 +2395,7 @@ void GC_dirty_init()
# endif
}
# endif
# if defined(OSF1) || defined(SUNOS4) || defined(LINUX)
# if defined(SUNOS4)
GC_old_segv_handler = signal(SIGSEGV, (SIG_PF)GC_write_fault_handler);
if (GC_old_segv_handler == SIG_IGN) {
GC_err_printf0("Previously ignored segmentation violation!?");
@ -2371,18 +2407,20 @@ void GC_dirty_init()
# endif
}
# endif
# if defined(SUNOS5SIGS) || defined(IRIX5)
# if defined(SUNOS5SIGS) || defined(IRIX5) || defined(LINUX) \
|| defined(OSF1) || defined(HURD)
/* SUNOS5SIGS includes HPUX */
# if defined(IRIX_THREADS)
sigaction(SIGSEGV, 0, &oldact);
sigaction(SIGSEGV, &act, 0);
# else
sigaction(SIGSEGV, &act, &oldact);
# endif
# if defined(_sigargs)
# if defined(_sigargs) || defined(HURD)
/* This is Irix 5.x, not 6.x. Irix 5.x does not have */
/* sa_sigaction. */
GC_old_segv_handler = oldact.sa_handler;
# else /* Irix 6.x or SUNOS5SIGS */
# else /* Irix 6.x or SUNOS5SIGS or LINUX */
if (oldact.sa_flags & SA_SIGINFO) {
GC_old_segv_handler = (SIG_PF)(oldact.sa_sigaction);
} else {
@ -2399,7 +2437,7 @@ void GC_dirty_init()
# endif
}
# endif
# if defined(MACOSX) || defined(HPUX)
# if defined(MACOSX) || defined(HPUX) || defined(LINUX) || defined(HURD)
sigaction(SIGBUS, &act, &oldact);
GC_old_bus_handler = oldact.sa_handler;
if (GC_old_bus_handler == SIG_IGN) {
@ -2411,7 +2449,7 @@ void GC_dirty_init()
GC_err_printf0("Replaced other SIGBUS handler\n");
# endif
}
# endif /* MACOS || HPUX */
# endif /* MACOS || HPUX || LINUX */
# if defined(MSWIN32)
GC_old_segv_handler = SetUnhandledExceptionFilter(GC_write_fault_handler);
if (GC_old_segv_handler != NULL) {
@ -2548,10 +2586,14 @@ word len;
result = readv(fd, &iov, 1);
}
# else
# if defined(HURD)
result = __read(fd, buf, nbyte);
# else
/* The two zero args at the end of this list are because one
IA-64 syscall() implementation actually requires six args
to be passed, even though they aren't always used. */
result = syscall(SYS_read, fd, buf, nbyte, 0, 0);
# endif /* !HURD */
# endif
GC_end_syscall();
return(result);
@ -3005,9 +3047,11 @@ struct callinfo info[NFRAMES];
register int i;
info[nframes].ci_pc = fp->FR_SAVPC;
for (i = 0; i < NARGS; i++) {
info[nframes].ci_arg[i] = ~(fp->fr_arg[i]);
}
# if NARGS > 0
for (i = 0; i < NARGS; i++) {
info[nframes].ci_arg[i] = ~(fp->fr_arg[i]);
}
# endif /* NARGS > 0 */
}
if (nframes < NFRAMES) info[nframes].ci_pc = 0;
}

View File

@ -1,4 +1,5 @@
.text
.text
.set linkageArea,24
.set params,4
@ -15,52 +16,80 @@ _GC_push_regs:
stw r0,8(r1) ; save return address
stwu r1,-spaceToSave(r1) ; skip over caller save area
;
mr r3,r2 ; mark from r2. Well I'm not really sure
mr r3,r2 ; mark from r2. Well Im not really sure
; that this is necessary or even the right
; thing to do - at least it doesn't harm...
; According to Apple's docs it points to
; thing to do - at least it doesnt harm...
; According to Apples docs it points to
; the direct data area, whatever that is...
bl _GC_push_one
bl L_GC_push_one$stub
mr r3,r13 ; mark from r13-r31
bl _GC_push_one
bl L_GC_push_one$stub
mr r3,r14
bl _GC_push_one
bl L_GC_push_one$stub
mr r3,r15
bl _GC_push_one
bl L_GC_push_one$stub
mr r3,r16
bl _GC_push_one
bl L_GC_push_one$stub
mr r3,r17
bl _GC_push_one
bl L_GC_push_one$stub
mr r3,r18
bl _GC_push_one
bl L_GC_push_one$stub
mr r3,r19
bl _GC_push_one
bl L_GC_push_one$stub
mr r3,r20
bl _GC_push_one
bl L_GC_push_one$stub
mr r3,r21
bl _GC_push_one
bl L_GC_push_one$stub
mr r3,r22
bl _GC_push_one
bl L_GC_push_one$stub
mr r3,r23
bl _GC_push_one
bl L_GC_push_one$stub
mr r3,r24
bl _GC_push_one
bl L_GC_push_one$stub
mr r3,r25
bl _GC_push_one
bl L_GC_push_one$stub
mr r3,r26
bl _GC_push_one
bl L_GC_push_one$stub
mr r3,r27
bl _GC_push_one
bl L_GC_push_one$stub
mr r3,r28
bl _GC_push_one
bl L_GC_push_one$stub
mr r3,r29
bl _GC_push_one
bl L_GC_push_one$stub
mr r3,r30
bl _GC_push_one
bl L_GC_push_one$stub
mr r3,r31
bl _GC_push_one
bl L_GC_push_one$stub
; EPILOG
lwz r0,spaceToSave8(r1) ; get return address back
mtlr r0 ; reset link register
addic r1,r1,spaceToSave ; restore stack pointer
blr
.data
.picsymbol_stub
L_GC_push_one$stub:
.indirect_symbol _GC_push_one
mflr r0
bcl 20,31,L0$_GC_push_one
L0$_GC_push_one:
mflr r11
addis r11,r11,ha16(L_GC_push_one$lazy_ptr-L0$_GC_push_one)
mtlr r0
lwz r12,lo16(L_GC_push_one$lazy_ptr-L0$_GC_push_one)(r11)
mtctr r12
addi r11,r11,lo16(L_GC_push_one$lazy_ptr-L0$_GC_push_one)
bctr
.data
.lazy_symbol_pointer
L_GC_push_one$lazy_ptr:
.indirect_symbol _GC_push_one
.long dyld_stub_binding_helper
.non_lazy_symbol_pointer
L_GC_push_one$non_lazy_ptr:
.indirect_symbol _GC_push_one
.long 0

View File

@ -20,7 +20,7 @@
signed_word GC_mem_found = 0;
/* Number of words of memory reclaimed */
#ifdef PARALLEL_MARK
#if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
word GC_fl_builder_count = 0;
/* Number of threads currently building free lists without */
/* holding GC lock. It is not safe to collect if this is */
@ -866,6 +866,9 @@ int report_if_found; /* Abort if a GC_reclaimable object is found */
{
int kind;
# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
GC_ASSERT(0 == GC_fl_builder_count);
# endif
/* Clear reclaim- and free-lists */
for (kind = 0; kind < GC_n_kinds; kind++) {
register ptr_t *fop;
@ -902,6 +905,9 @@ int report_if_found; /* Abort if a GC_reclaimable object is found */
/* so that you can convince yourself that it really is very stupid. */
GC_reclaim_all((GC_stop_func)0, FALSE);
# endif
# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
GC_ASSERT(0 == GC_fl_builder_count);
# endif
}

View File

@ -14,6 +14,9 @@
*/
/* An incomplete test for the garbage collector. */
/* Some more obscure entry points are not tested at all. */
/* This must be compiled with the same flags used to build the */
/* GC. It uses GC internals to allow more precise results */
/* checking for some of the tests. */
# undef GC_BUILD
@ -238,8 +241,8 @@ sexpr y;
#ifdef GC_GCJ_SUPPORT
#include "private/dbg_mlc.h"
#include "private/gc_pmark.h"
#include "gc_mark.h"
#include "private/dbg_mlc.h" /* For USR_PTR_FROM_BASE */
#include "gc_gcj.h"
/* The following struct emulates the vtable in gcj. */
@ -267,16 +270,12 @@ struct GC_ms_entry * fake_gcj_mark_proc(word * addr,
addr = (word *)USR_PTR_FROM_BASE(addr);
}
x = (sexpr)(addr + 1); /* Skip the vtable pointer. */
/* We could just call PUSH_CONTENTS directly here. But any real */
/* real client would try to filter out the obvious misses. */
if (0 != x -> sexpr_cdr) {
PUSH_CONTENTS((ptr_t)(x -> sexpr_cdr), mark_stack_ptr,
mark_stack_limit, &(x -> sexpr_cdr), exit1);
}
if ((ptr_t)(x -> sexpr_car) > (ptr_t) GC_least_plausible_heap_addr) {
PUSH_CONTENTS((ptr_t)(x -> sexpr_car), mark_stack_ptr,
mark_stack_limit, &(x -> sexpr_car), exit2);
}
mark_stack_ptr = GC_MARK_AND_PUSH(
(GC_PTR)(x -> sexpr_cdr), mark_stack_ptr,
mark_stack_limit, (GC_PTR *)&(x -> sexpr_cdr));
mark_stack_ptr = GC_MARK_AND_PUSH(
(GC_PTR)(x -> sexpr_car), mark_stack_ptr,
mark_stack_limit, (GC_PTR *)&(x -> sexpr_car));
return(mark_stack_ptr);
}
@ -703,6 +702,13 @@ int n;
# endif
collectable_count++;
# ifdef THREAD_LOCAL_ALLOC
/* Minimally exercise thread local allocation */
{
char * result = (char *)GC_LOCAL_MALLOC_ATOMIC(17);
memset(result, 'a', 17);
}
# endif /* THREAD_LOCAL_ALLOC */
# if defined(MACOS)
/* get around static data limitations. */
if (!live_indicators)

View File

@ -1,6 +1,6 @@
#define GC_VERSION_MAJOR 6
#define GC_VERSION_MINOR 0
#define GC_ALPHA_VERSION 7
#define GC_ALPHA_VERSION GC_NOT_ALPHA
# define GC_NOT_ALPHA 0xff