Commit 79f777fd by Bryce McKinlay Committed by Bryce McKinlay

Imported GC 6.1 Alpha 3. Finally.

From-SVN: r49698
parent 00532602
2002-02-12 Bryce McKinlay <bryce@waitaki.otago.ac.nz>
Imported GC 6.1 Alpha 3.
2001-02-11 Adam Megacz <adam@xwt.org
* gcc/boehm-gc/configure.in: support for win32, saner
* gcc/boehm-gc/configure.in: support for win32, saner
cross-compile options
2001-02-08 Anthony Green <green@redhat.com>
......@@ -16,13 +20,13 @@
2002-02-06 Adam Megacz <adam@xwt.org>
* boehm-gc/include/gc.h: (GC_CreateThread) This function is
now exposed on all Win32 platforms.
* boehm-gc/win32_threads.c: (GC_CreateThread) This now
compiles on Win32; it invokes CreateThread() if GC is built
as a DLL; otherwise it registers the thread.
* boehm-gc/misc.c (GC_init): Initialize GC_allocate_ml in case
libgcjgc was not built as a DLL.
* boehm-gc/include/gc.h: (GC_CreateThread) This function is
now exposed on all Win32 platforms.
* boehm-gc/win32_threads.c: (GC_CreateThread) This now
compiles on Win32; it invokes CreateThread() if GC is built
as a DLL; otherwise it registers the thread.
* boehm-gc/misc.c (GC_init): Initialize GC_allocate_ml in case
libgcjgc was not built as a DLL.
2002-02-01 Adam Megacz <adam@xwt.org>
......
......@@ -6,8 +6,6 @@
AUTOMAKE_OPTIONS = cygnus
SUBDIRS = include
# Multilib support variables.
MULTISRCTOP =
MULTIBUILDTOP =
......@@ -31,7 +29,8 @@ libgcjgc_la_SOURCES = allchblk.c alloc.c blacklst.c checksums.c dbg_mlc.c \
dyn_load.c finalize.c gc_dlopen.c gcj_mlc.c headers.c irix_threads.c \
linux_threads.c malloc.c mallocx.c mark.c mark_rts.c misc.c new_hblk.c \
obj_map.c os_dep.c pcr_interface.c ptr_chck.c real_malloc.c reclaim.c \
solaris_pthreads.c solaris_threads.c specific.c stubborn.c typd_mlc.c
solaris_pthreads.c solaris_threads.c specific.c stubborn.c typd_mlc.c \
backgraph.c
# Include THREADLIBS here to ensure that the correct versions of
# linuxthread semaphore functions get linked:
......
......@@ -10,20 +10,13 @@
# c++ interface to gc.a
# cord/de - builds dumb editor based on cords.
ABI_FLAG=
# ABI_FLAG should be the cc flag that specifies the ABI. On most
# platforms this will be the empty string. Possible values:
# +DD64 for 64-bit executable on HP/UX.
# -n32, -n64, -o32 for SGI/MIPS ABIs.
AS_ABI_FLAG=$(ABI_FLAG)
# ABI flag for assembler. On HP/UX this is +A64 for 64 bit
# executables.
CC=cc $(ABI_FLAG)
CXX=g++ $(ABI_FLAG)
AS=as $(AS_ABI_FLAG)
AS=as $(ABI_FLAG)
# The above doesn't work with gas, which doesn't run cpp.
# Define AS as `gcc -c -x assembler-with-cpp' instead.
# Under Irix 6, you will have to specify the ABI (-o32, -n32, or -64)
# if you use something other than the default ABI on your machine.
# Redefining srcdir allows object code for the nonPCR version of the collector
# to be generated in different directories.
......@@ -61,15 +54,12 @@ HOSTCFLAGS=$(CFLAGS)
# gc.h before performing thr_ or dl* or GC_ operations.)
# Must also define -D_REENTRANT.
# -DGC_SOLARIS_PTHREADS enables support for Solaris pthreads.
# (Internally this define GC_SOLARIS_THREADS as well.)
# Define SOLARIS_THREADS as well.
# -DGC_IRIX_THREADS enables support for Irix pthreads. See README.irix.
# -DGC_HPUX_THREADS enables support for HP/UX 11 pthreads.
# Also requires -D_REENTRANT or -D_POSIX_C_SOURCE=199506L. See README.hp.
# -DGC_LINUX_THREADS enables support for Xavier Leroy's Linux threads.
# see README.linux. -D_REENTRANT may also be required.
# -DGC_OSF1_THREADS enables support for Tru64 pthreads. Untested.
# -DGC_FREEBSD_THREADS enables support for FreeBSD pthreads. Untested.
# Appeared to run into some underlying thread problems.
# -DALL_INTERIOR_POINTERS allows all pointers to the interior
# of objects to be recognized. (See gc_priv.h for consequences.)
# Alternatively, GC_all_interior_pointers can be set at process
......@@ -207,8 +197,8 @@ HOSTCFLAGS=$(CFLAGS)
# 15% or so.
# -DUSE_3DNOW_PREFETCH causes the collector to issue AMD 3DNow style
# prefetch instructions. Same restrictions as USE_I686_PREFETCH.
# Minimally tested. Didn't appear to be an obvious win on a K6-2/500.
# -DGC_USE_LD_WRAP in combination with the old flags listed in README.linux
# UNTESTED!!
# -DGC_USE_LD_WRAP in combination with the gld flags listed in README.linux
# causes the collector some system and pthread calls in a more transparent
# fashion than the usual macro-based approach. Requires GNU ld, and
# currently probably works only with Linux.
......@@ -266,8 +256,7 @@ SRCS= $(CSRCS) mips_sgi_mach_dep.s rs6000_mach_dep.s alpha_mach_dep.s \
include/gc_local_alloc.h include/private/dbg_mlc.h \
include/private/specific.h powerpc_macosx_mach_dep.s \
include/leak_detector.h include/gc_amiga_redirects.h \
include/gc_pthread_redirects.h ia64_save_regs_in_stack.s \
$(CORD_SRCS)
include/gc_pthread_redirects.h $(CORD_SRCS)
DOC_FILES= README.QUICK doc/README.Mac doc/README.MacOSX doc/README.OS2 \
doc/README.amiga doc/README.cords doc/debugging.html \
......
......@@ -86,7 +86,6 @@ word blocks_needed;
}
# define HBLK_IS_FREE(hdr) ((hdr) -> hb_map == GC_invalid_map)
# define PHDR(hhdr) HDR(hhdr -> hb_prev)
# define NHDR(hhdr) HDR(hhdr -> hb_next)
......@@ -719,9 +718,6 @@ int n;
if (0 == hbp) return 0;
/* Notify virtual dirty bit implementation that we are about to write. */
GC_write_hint(hbp);
/* Add it to map of valid blocks */
if (!GC_install_counts(hbp, (word)size_needed)) return(0);
/* This leaks memory under very rare conditions. */
......@@ -731,6 +727,11 @@ int n;
GC_remove_counts(hbp, (word)size_needed);
return(0); /* ditto */
}
/* Notify virtual dirty bit implementation that we are about to write. */
/* Ensure that pointerfree objects are not protected if it's avoidable. */
GC_remove_protection(hbp, divHBLKSZ(size_needed),
(hhdr -> hb_descr == 0) /* pointer-free */);
/* We just successfully allocated a block. Restart count of */
/* consecutive failures. */
......
......@@ -78,7 +78,7 @@ char * GC_copyright[] =
{"Copyright 1988,1989 Hans-J. Boehm and Alan J. Demers ",
"Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved. ",
"Copyright (c) 1996-1998 by Silicon Graphics. All rights reserved. ",
"Copyright (c) 1999-2000 by Hewlett-Packard Company. All rights reserved. ",
"Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved. ",
"THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY",
" EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.",
"See source code for details." };
......@@ -97,13 +97,17 @@ word GC_free_space_divisor = 3;
extern GC_bool GC_collection_in_progress();
/* Collection is in progress, or was abandoned. */
extern GC_bool GC_print_back_height;
int GC_never_stop_func GC_PROTO((void)) { return(0); }
unsigned long GC_time_limit = TIME_LIMIT;
CLOCK_TYPE GC_start_time; /* Time at which we stopped world. */
/* used only in GC_timeout_stop_func. */
int GC_n_attempts = 0; /* Number of attempts at finishing */
/* collection within TIME_LIMIT */
/* collection within GC_time_limit. */
#if defined(SMALL_CONFIG) || defined(NO_CLOCK)
# define GC_timeout_stop_func GC_never_stop_func
......@@ -118,7 +122,7 @@ int GC_n_attempts = 0; /* Number of attempts at finishing */
#ifndef NO_CLOCK
GET_TIME(current_time);
time_diff = MS_TIME_DIFF(current_time,GC_start_time);
if (time_diff >= TIME_LIMIT) {
if (time_diff >= GC_time_limit) {
# ifdef CONDPRINT
if (GC_print_stats) {
GC_printf0("Abandoning stopped marking after ");
......@@ -277,9 +281,10 @@ void GC_maybe_gc()
/* If we run out of time, this turns into */
/* incremental marking. */
# ifndef NO_CLOCK
GET_TIME(GC_start_time);
if (GC_time_limit != GC_TIME_UNLIMITED) { GET_TIME(GC_start_time); }
# endif
if (GC_stopped_mark(GC_timeout_stop_func)) {
if (GC_stopped_mark(GC_time_limit == GC_TIME_UNLIMITED?
GC_never_stop_func : GC_timeout_stop_func)) {
# ifdef SAVE_CALL_CHAIN
GC_save_callers(GC_last_stack);
# endif
......@@ -391,7 +396,8 @@ int n;
# ifdef PARALLEL_MARK
GC_wait_for_reclaim();
# endif
if (GC_n_attempts < MAX_PRIOR_ATTEMPTS) {
if (GC_n_attempts < MAX_PRIOR_ATTEMPTS
&& GC_time_limit != GC_TIME_UNLIMITED) {
GET_TIME(GC_start_time);
if (!GC_stopped_mark(GC_timeout_stop_func)) {
GC_n_attempts++;
......@@ -436,7 +442,7 @@ GC_stop_func stop_func;
{
register int i;
int dummy;
# ifdef PRINTTIMES
# if defined(PRINTTIMES) || defined(CONDPRINT)
CLOCK_TYPE start_time, current_time;
# endif
......@@ -444,6 +450,9 @@ GC_stop_func stop_func;
# ifdef PRINTTIMES
GET_TIME(start_time);
# endif
# if defined(CONDPRINT) && !defined(PRINTTIMES)
if (GC_print_stats) GET_TIME(start_time);
# endif
# ifdef CONDPRINT
if (GC_print_stats) {
GC_printf1("--> Marking for collection %lu ",
......@@ -453,6 +462,11 @@ GC_stop_func stop_func;
(unsigned long) WORDS_TO_BYTES(GC_words_wasted));
}
# endif
# ifdef MAKE_BACK_GRAPH
if (GC_print_back_height) {
GC_build_back_graph();
}
# endif
/* Mark from all roots. */
/* Minimize junk left in my registers and on the stack */
......@@ -506,6 +520,14 @@ GC_stop_func stop_func;
GET_TIME(current_time);
GC_printf1("World-stopped marking took %lu msecs\n",
MS_TIME_DIFF(current_time,start_time));
# else
# ifdef CONDPRINT
if (GC_print_stats) {
GET_TIME(current_time);
GC_printf1("World-stopped marking took %lu msecs\n",
MS_TIME_DIFF(current_time,start_time));
}
# endif
# endif
START_WORLD();
return(TRUE);
......@@ -612,6 +634,17 @@ void GC_finish_collection()
GET_TIME(finalize_time);
# endif
if (GC_print_back_height) {
# ifdef MAKE_BACK_GRAPH
GC_traverse_back_graph();
# else
# ifndef SMALL_CONFIG
GC_err_printf0("Back height not available: "
"Rebuild collector with -DMAKE_BACK_GRAPH\n");
# endif
# endif
}
/* Clear free list mark bits, in case they got accidentally marked */
/* (or GC_find_leak is set and they were intentionally marked). */
/* Also subtract memory remaining from GC_mem_found count. */
......
#! /bin/sh
# Attempt to guess a canonical system name.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
# Free Software Foundation, Inc.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002 Free Software Foundation, Inc.
timestamp='2001-10-05'
timestamp='2002-01-10'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
......@@ -24,7 +24,7 @@ timestamp='2001-10-05'
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Per Bothner <bothner@cygnus.com>.
# Originally written by Per Bothner <per@bothner.com>.
# Please send patches to <config-patches@gnu.org>. Submit a context
# diff and a properly formatted ChangeLog entry.
#
......@@ -135,23 +135,21 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# object file format. This provides both forward
# compatibility and a consistent mechanism for selecting the
# object file format.
# Determine the machine/vendor (is the vendor relevant).
case "${UNAME_MACHINE}" in
amiga) machine=m68k-unknown ;;
arm32) machine=arm-unknown ;;
atari*) machine=m68k-atari ;;
sun3*) machine=m68k-sun ;;
mac68k) machine=m68k-apple ;;
macppc) machine=powerpc-apple ;;
hp3[0-9][05]) machine=m68k-hp ;;
ibmrt|romp-ibm) machine=romp-ibm ;;
sparc*) machine=`uname -p`-unknown ;;
*) machine=${UNAME_MACHINE}-unknown ;;
#
# Note: NetBSD doesn't particularly care about the vendor
# portion of the name. We always set it to "unknown".
UNAME_MACHINE_ARCH=`(uname -p) 2>/dev/null` || \
UNAME_MACHINE_ARCH=unknown
case "${UNAME_MACHINE_ARCH}" in
arm*) machine=arm-unknown ;;
sh3el) machine=shl-unknown ;;
sh3eb) machine=sh-unknown ;;
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;
esac
# The Operating System including object format, if it has switched
# to ELF recently, or will in the future.
case "${UNAME_MACHINE}" in
i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k)
case "${UNAME_MACHINE_ARCH}" in
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
eval $set_cc_for_build
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep __ELF__ >/dev/null
......@@ -291,6 +289,9 @@ EOF
*:[Aa]miga[Oo][Ss]:*:*)
echo ${UNAME_MACHINE}-unknown-amigaos
exit 0 ;;
*:[Mm]orph[Oo][Ss]:*:*)
echo ${UNAME_MACHINE}-unknown-morphos
exit 0 ;;
*:OS/390:*:*)
echo i370-ibm-openedition
exit 0 ;;
......@@ -736,6 +737,9 @@ EOF
i*:PW*:*)
echo ${UNAME_MACHINE}-pc-pw32
exit 0 ;;
x86:Interix*:3*)
echo i386-pc-interix3
exit 0 ;;
i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
......@@ -767,10 +771,24 @@ EOF
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit 0 ;;
mips:Linux:*:*)
case `sed -n '/^byte/s/^.*: \(.*\) endian/\1/p' < /proc/cpuinfo` in
big) echo mips-unknown-linux-gnu && exit 0 ;;
little) echo mipsel-unknown-linux-gnu && exit 0 ;;
esac
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#undef CPU
#undef mips
#undef mipsel
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
CPU=mipsel
#else
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
CPU=mips
#else
CPU=
#endif
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
rm -f $dummy.c
test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0
;;
ppc:Linux:*:*)
echo powerpc-unknown-linux-gnu
......@@ -843,32 +861,25 @@ EOF
esac
# Determine whether the default compiler is a.out or elf
eval $set_cc_for_build
cat >$dummy.c <<EOF
#include <features.h>
#ifdef __cplusplus
#include <stdio.h> /* for printf() prototype */
int main (int argc, char *argv[]) {
#else
int main (argc, argv) int argc; char *argv[]; {
#endif
#ifdef __ELF__
# ifdef __GLIBC__
# if __GLIBC__ >= 2
printf ("%s-pc-linux-gnu\n", argv[1]);
# else
printf ("%s-pc-linux-gnulibc1\n", argv[1]);
# endif
# else
printf ("%s-pc-linux-gnulibc1\n", argv[1]);
# endif
#else
printf ("%s-pc-linux-gnuaout\n", argv[1]);
#endif
return 0;
}
sed 's/^ //' << EOF >$dummy.c
#include <features.h>
#ifdef __ELF__
# ifdef __GLIBC__
# if __GLIBC__ >= 2
LIBC=gnu
# else
LIBC=gnulibc1
# endif
# else
LIBC=gnulibc1
# endif
#else
LIBC=gnuaout
#endif
EOF
$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0
rm -f $dummy.c $dummy
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
rm -f $dummy.c
test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
;;
i*86:DYNIX/ptx:4*:*)
......@@ -947,7 +958,7 @@ EOF
exit 0 ;;
M68*:*:R3V[567]*:*)
test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0)
3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0)
OS_REL=''
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
......@@ -1056,7 +1067,7 @@ EOF
*:QNX:*:4*)
echo i386-pc-qnx
exit 0 ;;
NSR-[KW]:NONSTOP_KERNEL:*:*)
NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*)
echo nsr-tandem-nsk${UNAME_RELEASE}
exit 0 ;;
*:NonStop-UX:*:*)
......
......@@ -2693,8 +2693,7 @@ EOF
THREADLIBS="-lpthread -lrt"
;;
*-*-freebsd*)
echo "configure: warning: "Threaded GC is prone to deadlock before FreeBSD 4.5."" 1>&2
echo "configure: warning: "Related symptom is pthread_join returns spurious EINTR."" 1>&2
echo "configure: warning: "FreeBSD does not yet fully support threads with Boehm GC."" 1>&2
cat >> confdefs.h <<\EOF
#define GC_FREEBSD_THREADS 1
EOF
......@@ -2739,7 +2738,7 @@ esac
echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
echo "configure:2743: checking for dlopen in -ldl" >&5
echo "configure:2742: 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
......@@ -2747,7 +2746,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-ldl $LIBS"
cat > conftest.$ac_ext <<EOF
#line 2751 "configure"
#line 2750 "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
......@@ -2758,7 +2757,7 @@ int main() {
dlopen()
; return 0; }
EOF
if { (eval echo configure:2762: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:2761: \"$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
......@@ -2814,8 +2813,16 @@ esac
machdep=
case "$host" in
alpha*-*-*)
machdep="alpha_mach_dep.lo"
# alpha_mach_dep.s assumes that pointers are not saved in fp registers.
# Gcc on a 21264 can spill pointers to fp registers. Oops.
# alpha*-*-*)
# machdep="alpha_mach_dep.lo"
# ;;
i?86-*-solaris2.[89]*)
cat >> confdefs.h <<\EOF
#define SOLARIS25_PROC_VDB_BUG_FIXED 1
EOF
;;
alpha-*-openbsd*)
if test x"${ac_cv_lib_dl_dlopen}" != xyes ; then
......@@ -2845,12 +2852,6 @@ fi
fi
;;
i?86-*-solaris2.[89]*)
cat >> confdefs.h <<\EOF
#define SOLARIS25_PROC_VDB_BUG_FIXED 1
EOF
;;
mipstx39-*-elf*)
machdep="mips_ultrix_mach_dep.lo"
cat >> confdefs.h <<\EOF
......@@ -2873,12 +2874,16 @@ EOF
;;
sparc-sun-solaris2.3*)
machdep="sparc_mach_dep.lo"
cat >> confdefs.h <<\EOF
#define SUNOS53_SHARED_LIB 1
EOF
;;
ia64-*-hpux*)
sparc-sun-solaris2.*)
machdep="sparc_mach_dep.lo"
;;
ia64-*-*)
machdep="mach_dep.lo ia64_save_regs_in_stack.lo"
;;
esac
......@@ -2964,7 +2969,17 @@ EOF
EOF
case $host in
ia64-*-linux* )
cat >> confdefs.h <<\EOF
#define MAKE_BACK_GRAPH 1
EOF
;;
x86-*-linux* | i586-*-linux* | i686-*-linux* )
cat >> confdefs.h <<\EOF
#define MAKE_BACK_GRAPH 1
EOF
echo "configure: warning: "Client must not use -fomit-frame-pointer."" 1>&2
cat >> confdefs.h <<\EOF
#define SAVE_CALL_COUNT 8
......
......@@ -90,8 +90,7 @@ case "$THREADS" in
THREADLIBS="-lpthread -lrt"
;;
*-*-freebsd*)
AC_MSG_WARN("Threaded GC is prone to deadlock before FreeBSD 4.5.")
AC_MSG_WARN("Related symptom is pthread_join returns spurious EINTR.")
AC_MSG_WARN("FreeBSD does not yet fully support threads with Boehm GC.")
AC_DEFINE(GC_FREEBSD_THREADS)
INCLUDES="$INCLUDES -pthread"
THREADLIBS=-pthread
......@@ -155,8 +154,13 @@ AC_SUBST(CXXINCLUDES)
machdep=
case "$host" in
alpha*-*-*)
machdep="alpha_mach_dep.lo"
# alpha_mach_dep.s assumes that pointers are not saved in fp registers.
# Gcc on a 21264 can spill pointers to fp registers. Oops.
# alpha*-*-*)
# machdep="alpha_mach_dep.lo"
# ;;
i?86-*-solaris2.[[89]]*)
AC_DEFINE(SOLARIS25_PROC_VDB_BUG_FIXED)
;;
alpha-*-openbsd*)
if test x"${ac_cv_lib_dl_dlopen}" != xyes ; then
......@@ -164,9 +168,6 @@ case "$host" in
AM_DISABLE_SHARED
fi
;;
i?86-*-solaris2.[[89]]*)
AC_DEFINE(SOLARIS25_PROC_VDB_BUG_FIXED)
;;
mipstx39-*-elf*)
machdep="mips_ultrix_mach_dep.lo"
AC_DEFINE(STACKBASE, __stackbase)
......@@ -180,9 +181,13 @@ case "$host" in
AC_DEFINE(NO_EXECUTE_PERMISSION)
;;
sparc-sun-solaris2.3*)
machdep="sparc_mach_dep.lo"
AC_DEFINE(SUNOS53_SHARED_LIB)
;;
ia64-*-hpux*)
sparc-sun-solaris2.*)
machdep="sparc_mach_dep.lo"
;;
ia64-*-*)
machdep="mach_dep.lo ia64_save_regs_in_stack.lo"
;;
esac
......@@ -243,7 +248,11 @@ AC_ARG_ENABLE(full-debug,
AC_DEFINE(KEEP_BACK_PTRS)
AC_DEFINE(DBG_HDRS_ALL)
case $host in
ia64-*-linux* )
AC_DEFINE(MAKE_BACK_GRAPH)
;;
x86-*-linux* | i586-*-linux* | i686-*-linux* )
AC_DEFINE(MAKE_BACK_GRAPH)
AC_MSG_WARN("Client must not use -fomit-frame-pointer.")
AC_DEFINE(SAVE_CALL_COUNT, 8)
;;
......
......@@ -246,6 +246,9 @@ word integer;
# ifdef KEEP_BACK_PTRS
((oh *)p) -> oh_back_ptr = HIDE_BACK_PTR(NOT_MARKED);
# endif
# ifdef MAKE_BACK_GRAPH
((oh *)p) -> oh_bg_ptr = HIDE_BACK_PTR((ptr_t)0);
# endif
((oh *)p) -> oh_string = string;
((oh *)p) -> oh_int = integer;
# ifndef SHORT_DBG_HDRS
......@@ -275,6 +278,9 @@ word integer;
# ifdef KEEP_BACK_PTRS
((oh *)p) -> oh_back_ptr = HIDE_BACK_PTR(NOT_MARKED);
# endif
# ifdef MAKE_BACK_GRAPH
((oh *)p) -> oh_bg_ptr = HIDE_BACK_PTR((ptr_t)0);
# endif
((oh *)p) -> oh_string = string;
((oh *)p) -> oh_int = integer;
# ifndef SHORT_DBG_HDRS
......
......@@ -27,7 +27,7 @@ are GPL'ed, but with an exception that should cover all uses in the
collector. (If you are concerned about such things, I recommend you look
at the notice in config.guess or ltmain.sh.)
This is version 6.1alpha1 of a conservative garbage collector for C and C++.
This is version 6.1alpha3 of a conservative garbage collector for C and C++.
You might find a more recent version of this at
......
......@@ -1413,6 +1413,61 @@ Since 6.0:
less common thread implementations, since some of the original code
didn't stand up to close scrutiny. Support for the next pthreads
implementation should be easier to add.
Since 6.1alpha1:
- No longer wrap read by default in multithreaded applications. It was
pointed out on the libgcj list that this holds the allocation lock for
way too long if the read blocks. For now, reads into the heap are
broken with incremental collection. It's possible to turn this back on
if you make sure that read calls don't block (e.g. by calling select
first).
- Fix ifdef in Solaris_threads.h to refer to GC_SOLARIS_THREADS.
- Added check for environment variable GC_IGNORE_GCJ_INFO.
- Added printing of stop-the-world GC times if GC_PRINT_STATS environment
variable is set.
- The calloc definition in leak_detector.h was missing parentheses, and
realloc was missing a second argument to GC_REALLOC.
(Thanks to Elrond (elrond<at>samba-tng.org).)
- Added GC_PRINT_BACK_HEIGHT environment variable and associated
code, mostly in the new file backgraph.c. See doc/README.environment.
- Added -DUSE_GLOBAL_ALLOC to work around a Windows NT issue. (Thanks to
Jonathan Clark.)
- Integrated port to NEC EWS4800 (MIPS-based workstation, with somewhat
different address-space layout). This may help for other machines with
holes in the data segment. (Thanks to Hironori Sakamoto.)
- Changed the order in which GC_push_roots and friends push things onto
the mark stack. GC_push_all calls need to come first, since we can't
necessarily recovere if those overflow the mark stack. (Thanks to
Matthew Flatt for tracking down the problem.)
- Some minor cleanups to mostly support the Intel compiler on Linux/IA64.
Since 6.1 alpha2:
- Minor cleanup on the gcconfig.h section for SPARC.
- Minor fix to support Intel compiler for I386/Linux. (Thanks to Sven
Hartrumpf.)
- Added SPARC V9 (64-bit) support. (Thanks to Jeff Sturm.)
- Restructured the way in which we determine whether or not to keep
call stacks for debug allocation. By default SAVE_CALL_COUNT is
now zero on all platforms. Added SAVE_CALL_NARGS parameters.
If possible, use execinfo.h to capture call stack. (This should
add support for a number of new platforms, though often at
considerable runtime expense.)
- Try to print symbolic information for call stacks. On Linux, we
do this with a combination of execinfo.h and running addr2line in
a separate process. This is both much more expensive and much more
useful. Amazingly, it seems to be fast enough for most purposes.
- Redefined strdup if -DREDIRECT_MALLOC is given.
- Changed incremental collector and MPROTECT_VDB implementation so that,
under favorable conditions, pointerfree objects are not protected.
Added GC_incremental_protection_needs() to determine ahead of time whether
pointerfree objects may be protected. Replaced GC_write_hint() with
GC_remove_protection().
- Added test for GC_ENABLE_INCREMENTAL environment variable.
- Made GC_time_limit runtime configurable. Added GC_PAUSE_TIME_TARGET
environment variable.
- Eliminated GC_page_sz, a duplicate of GC_page_size.
- Caused the Solaris and Irix thread creation primitives to call
GC_init_inner().
To do:
......
The garbage collector looks at a number of environment variables which are
the used to affect its operation. These are examined only on Un*x-like
then used to affect its operation. These are examined only on Un*x-like
platforms.
GC_INITIAL_HEAP_SIZE=<bytes> - Initial heap size in bytes. May speed up
......@@ -32,6 +32,47 @@ GC_NPROCS=<n> - Linux w/threads only. Explicitly sets the number of processors
GC_NO_BLACKLIST_WARNING - Prevents the collector from issuing
"Needed to allocate blacklisted block at ..." warnings.
GC_IGNORE_GCJ_INFO - Ignore the type descriptors implicitly supplied by
GC_gcj_malloc and friends. This is useful for debugging
descriptor generation problems, and possibly for
temporarily working around such problems. It forces a
fully conservative scan of all heap objects except
those known to be pointerfree, and may thus have other
adverse effects.
GC_PRINT_BACK_HEIGHT - Print max length of chain through unreachable objects
ending in a reachable one. If this number remains
bounded, then the program is "GC robust". This ensures
that a fixed number of misidentified pointers can only
result in a bounded space leak. This currently only
works if debugging allocation is used throughout.
It increases GC space and time requirements appreciably.
This feature is still somewhat experimental, and requires
that the collector have been built with MAKE_BACK_GRAPH
defined. For details, see Boehm, "Bounding Space Usage
of Conservative Garbage Collectors", POPL 2001, or
http://lib.hpl.hp.com/techpubs/2001/HPL-2001-251.html .
GC_ENABLE_INCREMENTAL - Turn on incremental collection at startup. Note that,
depending on platform and collector configuration, this
may involve write protecting pieces of the heap to
track modifications. These pieces may include pointerfree
objects or not. Although this is intended to be
transparent, it may cause unintended system call failures.
Use with caution.
GC_PAUSE_TIME_TARGET - Set the desired garbage collector pause time in msecs.
This only has an effect if incremental collection is enabled.
If a collection requires appreciably more time than this,
the client will be restarted, and the collector will need
to do additional work to compensate. The special value
"999999" indicates that pause time is unlimited, and the
incremental collector will behave completely like a
simple generational collector. If the collector is
configured for parallel marking, and run on a multiprocessor,
incremental collection should only be used with unlimited
pause time.
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:
......
The collector has at various times been compiled under Windows 95 & NT,
with the original Microsoft SDK, with Visual C++ 2.0, 4.0, and 6, with
the GNU win32 environment, with Borland 4.5, and recently with
Watcom C. It is likely that some of these have been broken in the
meantime. Patches are appreciated.
the GNU win32 environment, with Borland 4.5, with Watcom C, and recently
with the Digital Mars compiler. It is likely that some of these have been
broken in the meantime. Patches are appreciated.
It runs under both win32s and win32, but with different semantics.
Under win32, all writable pages outside of the heaps and stack are
......@@ -45,6 +45,13 @@ window colors.)
In general -DREDIRECT_MALLOC is unlikely to work unless the
application is completely statically linked.
The collector normally allocates memory from the OS with VirtualAlloc.
This appears to cause problems under Windows NT and Windows 2000 (but
not Windows 95/98) if the memory is later passed to CreateDIBitmap.
To work around this problem, build the collector with -DUSE_GLOBAL_ALLOC.
This is currently incompatible with -DUSE_MUNMAP. (Thanks to Jonathan
Clark for tracking this down.)
For Microsoft development tools, rename NT_MAKEFILE as
MAKEFILE. (Make sure that the CPU environment variable is defined
to be i386.) In order to use the gc_cpp.h C++ interface, all
......
......@@ -79,6 +79,14 @@
# define l_name lm_name
#endif
#if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \
(defined(FREEBSD) && defined(__ELF__)) || \
(defined(NETBSD) && defined(__ELF__)) || defined(HURD)
# include <stddef.h>
# include <elf.h>
# include <link.h>
#endif
/* Newer versions of GNU/Linux define this macro. We
* define it similarly for any ELF systems that don't. */
# ifndef ElfW
......@@ -438,10 +446,6 @@ static char *parse_map_entry(char *buf_ptr, word *start, word *end,
/* For glibc 2.2.4+. Unfortunately, it doesn't work for older */
/* versions. Thanks to Jakub Jelinek for most of the code. */
#include <stddef.h>
#include <elf.h>
#include <link.h>
# if defined(LINUX) /* Are others OK here, too? */ \
&& (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \
|| (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG)))
......
......@@ -838,3 +838,4 @@ void GC_notify_or_invoke_finalizers GC_PROTO((void))
# endif
return(result);
}
......@@ -54,6 +54,7 @@ ptr_t * GC_gcjdebugobjfreelist;
void GC_init_gcj_malloc(int mp_index, void * /* really GC_mark_proc */mp)
{
register int i;
GC_bool ignore_gcj_info;
DCL_LOCK_STATE;
GC_init(); /* In case it's not already done. */
......@@ -65,6 +66,12 @@ void GC_init_gcj_malloc(int mp_index, void * /* really GC_mark_proc */mp)
return;
}
GC_gcj_malloc_initialized = TRUE;
ignore_gcj_info = (0 != GETENV("GC_IGNORE_GCJ_INFO"));
# ifdef CONDPRINT
if (GC_print_stats && ignore_gcj_info) {
GC_printf0("Gcj-style type information is disabled!\n");
}
# endif
GC_mark_procs[mp_index] = (GC_mark_proc)mp;
if (mp_index >= GC_n_mark_procs) ABORT("GC_init_gcj_malloc: bad index");
/* Set up object kind gcj-style indirect descriptor. */
......@@ -75,9 +82,17 @@ void GC_init_gcj_malloc(int mp_index, void * /* really GC_mark_proc */mp)
GC_gcj_kind = GC_n_kinds++;
GC_obj_kinds[GC_gcj_kind].ok_freelist = GC_gcjobjfreelist;
GC_obj_kinds[GC_gcj_kind].ok_reclaim_list = 0;
GC_obj_kinds[GC_gcj_kind].ok_descriptor =
(((word)(-MARK_DESCR_OFFSET - GC_INDIR_PER_OBJ_BIAS)) | GC_DS_PER_OBJECT);
GC_obj_kinds[GC_gcj_kind].ok_relocate_descr = FALSE;
if (ignore_gcj_info) {
/* Use a simple length-based descriptor, thus forcing a fully */
/* conservative scan. */
GC_obj_kinds[GC_gcj_kind].ok_descriptor = (0 | GC_DS_LENGTH);
GC_obj_kinds[GC_gcj_kind].ok_relocate_descr = TRUE;
} else {
GC_obj_kinds[GC_gcj_kind].ok_descriptor =
(((word)(-MARK_DESCR_OFFSET - GC_INDIR_PER_OBJ_BIAS))
| GC_DS_PER_OBJECT);
GC_obj_kinds[GC_gcj_kind].ok_relocate_descr = FALSE;
}
GC_obj_kinds[GC_gcj_kind].ok_init = TRUE;
/* Set up object kind for objects that require mark proc call. */
GC_gcjdebugobjfreelist = (ptr_t *)
......@@ -88,9 +103,14 @@ void GC_init_gcj_malloc(int mp_index, void * /* really GC_mark_proc */mp)
GC_gcj_debug_kind = GC_n_kinds++;
GC_obj_kinds[GC_gcj_debug_kind].ok_freelist = GC_gcjdebugobjfreelist;
GC_obj_kinds[GC_gcj_debug_kind].ok_reclaim_list = 0;
GC_obj_kinds[GC_gcj_debug_kind].ok_descriptor =
GC_MAKE_PROC(mp_index, 1 /* allocated with debug info */);
GC_obj_kinds[GC_gcj_debug_kind].ok_relocate_descr = FALSE;
if (ignore_gcj_info) {
GC_obj_kinds[GC_gcj_kind].ok_descriptor = (0 | GC_DS_LENGTH);
GC_obj_kinds[GC_gcj_kind].ok_relocate_descr = TRUE;
} else {
GC_obj_kinds[GC_gcj_debug_kind].ok_descriptor =
GC_MAKE_PROC(mp_index, 1 /* allocated with debug info */);
GC_obj_kinds[GC_gcj_debug_kind].ok_relocate_descr = FALSE;
}
GC_obj_kinds[GC_gcj_debug_kind].ok_init = TRUE;
UNLOCK();
ENABLE_SIGNALS();
......
# Makefile.in generated automatically by automake 1.4-p1 from Makefile.am
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
......@@ -96,7 +96,8 @@ target_all = @target_all@
AUTOMAKE_OPTIONS = foreign
include_HEADERS = gc.h gc_backptr.h gc_local_alloc.h gc_pthread_redirects.h gc_cpp.h
include_HEADERS = gc.h gc_backptr.h gc_local_alloc.h \
gc_pthread_redirects.h gc_cpp.h
CONFIG_CLEAN_FILES =
HEADERS = $(include_HEADERS)
......
......@@ -305,6 +305,20 @@ GC_API int GC_dont_precollect; /* Don't collect as part of */
*/
GC_API void GC_init GC_PROTO((void));
GC_API unsigned long GC_time_limit;
/* If incremental collection is enabled, */
/* We try to terminate collections */
/* after this many milliseconds. Not a */
/* hard time bound. Setting this to */
/* GC_TIME_UNLIMITED will essentially */
/* disable incremental collection while */
/* leaving generational collection */
/* enabled. */
# define GC_TIME_UNLIMITED 999999
/* Setting GC_time_limit to this value */
/* will disable the "pause time exceeded */
/* tests. */
/*
* general purpose allocation routines, with roughly malloc calling conv.
* The atomic versions promise that no relevant pointers are contained
......@@ -463,6 +477,16 @@ GC_API size_t GC_get_total_bytes GC_PROTO((void));
/* functional if GC_parallel is TRUE. */
GC_API void GC_enable_incremental GC_PROTO((void));
/* Does incremental mode write-protect pages? Returns zero or */
/* more of the following, or'ed together: */
#define GC_PROTECTS_POINTER_HEAP 1 /* May protect non-atomic objs. */
#define GC_PROTECTS_PTRFREE_HEAP 2
#define GC_PROTECTS_STATIC_DATA 4 /* Curently never. */
#define GC_PROTECTS_STACK 8 /* Probably impractical. */
#define GC_PROTECTS_NONE 0
GC_API int GC_incremental_protection_needs GC_PROTO((void));
/* Perform some garbage collection work, if appropriate. */
/* Return 0 if there is no more work to be done. */
/* Typically performs an amount of work corresponding roughly */
......
#define GC_DEBUG
#include "gc.h"
#define malloc(n) GC_MALLOC(n)
#define calloc(m,n) GC_MALLOC(m*n)
#define calloc(m,n) GC_MALLOC((m)*(n))
#define free(p) GC_FREE(p)
#define realloc(p,n) GC_REALLOC(n)
#define realloc(p,n) GC_REALLOC((p),(n))
#define CHECK_LEAKS() GC_gcollect()
......@@ -46,7 +46,8 @@
/* 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)
# if defined(KEEP_BACK_PTRS) || defined(PRINT_BLACK_LIST) \
|| defined(MAKE_BACK_GRAPH)
/* Pointer "source"s that aren't real locations. */
/* Used in oh_back_ptr fields and as "source" */
/* argument to some marking functions. */
......@@ -60,28 +61,42 @@
/* Object header */
typedef struct {
# ifdef KEEP_BACK_PTRS
GC_hidden_pointer oh_back_ptr;
/* We make sure that we only store even valued */
/* pointers here, so that the hidden version has */
/* the least significant bit set. We never */
/* 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. */
# if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)
/* We potentially keep two different kinds of back */
/* pointers. KEEP_BACK_PTRS stores a single back */
/* pointer in each reachable object to allow reporting */
/* of why an object was retained. MAKE_BACK_GRAPH */
/* builds a graph containing the inverse of all */
/* "points-to" edges including those involving */
/* objects that have just become unreachable. This */
/* allows detection of growing chains of unreachable */
/* objects. It may be possible to eventually combine */
/* both, but for now we keep them separate. Both */
/* kinds of back pointers are hidden using the */
/* following macros. In both cases, the plain version */
/* is constrained to have an least significant bit of 1,*/
/* to allow it to be distinguished from a free list */
/* link. This means the plain version must have an */
/* lsb of 0. */
/* Note that blocks dropped by black-listing will */
/* also have the lsb clear once debugging has */
/* started. */
/* We're careful never to overwrite a value with lsb 0. */
# if ALIGNMENT == 1
/* Fudge back pointer to be even. */
# define HIDE_BACK_PTR(p) HIDE_POINTER(~1 & (GC_word)(p))
# else
# define HIDE_BACK_PTR(p) HIDE_POINTER(p)
# endif
# ifdef ALIGN_DOUBLE
# ifdef KEEP_BACK_PTRS
GC_hidden_pointer oh_back_ptr;
# endif
# ifdef MAKE_BACK_GRAPH
GC_hidden_pointer oh_bg_ptr;
# endif
# if defined(ALIGN_DOUBLE) && \
(defined(KEEP_BACK_PTRS) != defined(MAKE_BACK_GRAPH))
word oh_dummy;
# endif
# endif
......@@ -139,9 +154,9 @@ typedef struct {
GC_bool GC_has_other_debug_info(/* p */);
#endif
#ifdef KEEP_BACK_PTRS
#if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)
# define GC_HAS_DEBUG_INFO(p) \
((((oh *)p)->oh_back_ptr & 1) && GC_has_other_debug_info(p))
((*((word *)p) & 1) && GC_has_other_debug_info(p))
#else
# define GC_HAS_DEBUG_INFO(p) GC_has_other_debug_info(p)
#endif
......
......@@ -136,7 +136,8 @@ extern mse * GC_mark_stack;
/* Set *new_hdr_p to corr. hdr. */
#ifdef __STDC__
# ifdef PRINT_BLACK_LIST
ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p, word source);
ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p,
ptr_t source);
# else
ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p);
# endif
......
......@@ -249,20 +249,6 @@ typedef char * ptr_t; /* A generic pointer to which we can add */
#ifdef SAVE_CALL_CHAIN
/*
* Number of frames and arguments to save in objects allocated by
* debugging allocator.
*/
# ifndef SAVE_CALL_COUNT
# define NFRAMES 6 /* Number of frames to save. Even for */
/* alignment reasons. */
# else
# define NFRAMES ((SAVE_CALL_COUNT + 1) & ~1)
# endif
# define NARGS 2 /* Mumber of arguments to save for each call. */
# define NEED_CALLINFO
/* Fill in the pc and argument information for up to NFRAMES of my */
/* callers. Ignore my frame and my callers frame. */
struct callinfo;
......@@ -270,14 +256,6 @@ void GC_save_callers GC_PROTO((struct callinfo info[NFRAMES]));
void GC_print_callers GC_PROTO((struct callinfo info[NFRAMES]));
#else
# ifdef GC_ADD_CALLER
# define NFRAMES 1
# define NARGS 0
# define NEED_CALLINFO
# endif
#endif
#ifdef NEED_CALLINFO
......@@ -396,7 +374,8 @@ struct hblk; /* See below. */
+ GC_page_size-1)
# else
# if defined(NEXT) || defined(MACOSX) || defined(DOS4GW) || \
(defined(AMIGA) && !defined(GC_AMIGA_FASTALLOC))
(defined(AMIGA) && !defined(GC_AMIGA_FASTALLOC)) || \
(defined(SUNOS5) && !defined(USE_MMAP))
# define GET_MEM(bytes) HBLKPTR((size_t) \
calloc(1, (size_t)bytes + GC_page_size) \
+ GC_page_size-1)
......@@ -787,12 +766,11 @@ struct hblkhdr {
# define BODY_SZ (HBLKSIZE/sizeof(word))
struct hblk {
# if 0 /* DISCARDWORDS no longer supported */
word garbage[DISCARD_WORDS];
# endif
word hb_body[BODY_SZ];
};
# define HBLK_IS_FREE(hdr) ((hdr) -> hb_map == GC_invalid_map)
# define OBJ_SZ_TO_BLOCKS(sz) \
divHBLKSZ(WORDS_TO_BYTES(sz) + HBLKSIZE-1)
/* Size of block (in units of HBLKSIZE) needed to hold objects of */
......@@ -1765,8 +1743,12 @@ GC_bool GC_page_was_ever_dirty GC_PROTO((struct hblk *h));
void GC_is_fresh GC_PROTO((struct hblk *h, word n));
/* Assert the region currently contains no */
/* valid pointers. */
void GC_write_hint GC_PROTO((struct hblk *h));
/* h is about to be written. */
void GC_remove_protection GC_PROTO((struct hblk *h, word nblocks,
GC_bool pointerfree));
/* h is about to be writteni or allocated. Ensure */
/* that it's not write protected by the virtual */
/* dirty bit implementation. */
void GC_dirty_init GC_PROTO((void));
/* Slow/general mark bit manipulation: */
......
......@@ -85,9 +85,12 @@
# endif
# define mach_type_known
# endif
# if defined(mips) || defined(__mips)
# if defined(mips) || defined(__mips) || defined(_mips)
# define MIPS
# if !defined(LINUX)
# if defined(nec_ews) || defined(_nec_ews)
# define EWS4800
# endif
# if !defined(LINUX) && !defined(EWS4800)
# if defined(ultrix) || defined(__ultrix) || defined(__NetBSD__)
# define ULTRIX
# else
......@@ -726,6 +729,7 @@
# define ELF_CLASS ELFCLASS64
# else
# define ALIGNMENT 4 /* Required by hardware */
# define CPP_WORDSZ 32
# endif
# define ALIGN_DOUBLE
# ifdef SUNOS5
......@@ -735,8 +739,12 @@
extern char * GC_SysVGetDataStart();
# define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, &_etext)
# define DATAEND (&_end)
# ifndef USE_MMAP
# if !defined(USE_MMAP) && defined(REDIRECT_MALLOC)
# define USE_MMAP
/* Otherwise we now use calloc. Mmap may result in the */
/* heap interleaved with thread stacks, which can result in */
/* excessive blacklisting. Sbrk is unusable since it */
/* doesn't interact correctly with the system malloc. */
# endif
# ifdef USE_MMAP
# define HEAP_START (ptr_t)0x40000000
......@@ -760,7 +768,9 @@
# define GETPAGESIZE() sysconf(_SC_PAGESIZE)
/* getpagesize() appeared to be missing from at least one */
/* Solaris 5.4 installation. Weird. */
# define DYNAMIC_LOADING
# if CPP_WORDSZ == 32
# define DYNAMIC_LOADING
# endif
# endif
# ifdef SUNOS4
# define OS_TYPE "SUNOS4"
......@@ -782,7 +792,6 @@
# define DYNAMIC_LOADING
# endif
# ifdef DRSNX
# define CPP_WORDSZ 32
# define OS_TYPE "DRSNX"
extern char * GC_SysVGetDataStart();
extern int etext;
......@@ -805,7 +814,6 @@
# ifdef __arch64__
# define STACKBOTTOM ((ptr_t) 0x80000000000ULL)
# define DATASTART (ptr_t)GC_SysVGetDataStart(0x100000, &_etext)
# define CPP_WORDSZ 64
# else
# define STACKBOTTOM ((ptr_t) 0xf0000000)
# define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, &_etext)
......@@ -858,7 +866,7 @@
# endif
# ifdef SUNOS5
# define OS_TYPE "SUNOS5"
extern int _etext, _end;
extern int _etext, _end;
extern char * GC_SysVGetDataStart();
# define DATASTART GC_SysVGetDataStart(0x1000, &_etext)
# define DATAEND (&_end)
......@@ -867,15 +875,20 @@
/* base is a property of the executable, so this should not break */
/* old executables. */
/* HEURISTIC2 probably works, but this appears to be preferable. */
# include <sys/vmparam.h>
# include <sys/vm.h>
# define STACKBOTTOM USRSTACK
/** At least in Solaris 2.5, PROC_VDB gives wrong values for dirty bits. */
/* At least in Solaris 2.5, PROC_VDB gives wrong values for dirty bits. */
/* It appears to be fixed in 2.8 and 2.9. */
# ifdef SOLARIS25_PROC_VDB_BUG_FIXED
# define PROC_VDB
# endif
# define DYNAMIC_LOADING
# ifndef USE_MMAP
# if !defined(USE_MMAP) && defined(REDIRECT_MALLOC)
# define USE_MMAP
/* Otherwise we now use calloc. Mmap may result in the */
/* heap interleaved with thread stacks, which can result in */
/* excessive blacklisting. Sbrk is unusable since it */
/* doesn't interact correctly with the system malloc. */
# endif
# ifdef USE_MMAP
# define HEAP_START (ptr_t)0x40000000
......@@ -900,6 +913,10 @@
# define ELF_CLASS ELFCLASS32
# endif
# ifdef LINUX
# ifndef __GNUC__
/* The Intel compiler doesn't like inline assembly */
# define USE_GENERIC_PUSH_REGS
# endif
# define OS_TYPE "LINUX"
# define LINUX_STACKBOTTOM
# if 0
......@@ -1035,6 +1052,8 @@
# ifdef __ELF__
# define DYNAMIC_LOADING
# endif
extern char etext;
# define DATASTART ((ptr_t)(&etext))
# endif
# ifdef NETBSD
# define OS_TYPE "NETBSD"
......@@ -1045,7 +1064,7 @@
# ifdef BSDI
# define OS_TYPE "BSDI"
# endif
# if defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD) \
# if defined(OPENBSD) || defined(NETBSD) \
|| defined(THREE86BSD) || defined(BSDI)
# define HEURISTIC2
extern char etext;
......@@ -1113,6 +1132,29 @@
/* instead. But some kernel versions seem to give the wrong */
/* value from /proc. */
# endif /* Linux */
# ifdef EWS4800
# define HEURISTIC2
# if defined(_MIPS_SZPTR) && (_MIPS_SZPTR == 64)
extern int _fdata[], _end[];
# define DATASTART ((ptr_t)_fdata)
# define DATAEND ((ptr_t)_end)
# define CPP_WORDSZ _MIPS_SZPTR
# define ALIGNMENT (_MIPS_SZPTR/8)
# else
extern int etext, edata, end;
extern int _DYNAMIC_LINKING, _gp;
# define DATASTART ((ptr_t)((((word)&etext + 0x3ffff) & ~0x3ffff) \
+ ((word)&etext & 0xffff)))
# define DATAEND (&edata)
# define DATASTART2 (&_DYNAMIC_LINKING \
? (ptr_t)(((word)&_gp + 0x8000 + 0x3ffff) & ~0x3ffff) \
: (ptr_t)&edata)
# define DATAEND2 (&end)
# define ALIGNMENT 4
# endif
# define OS_TYPE "EWS4800"
# define USE_GENERIC_PUSH_REGS 1
# endif
# ifdef ULTRIX
# define HEURISTIC2
# define DATASTART (ptr_t)0x10000000
......@@ -1394,7 +1436,13 @@
# define BACKING_STORE_BASE ((ptr_t)GC_register_stackbottom)
# define SEARCH_FOR_DATA_START
# define DATASTART GC_data_start
# define DYNAMIC_LOADING
# ifdef __GNUC__
# define DYNAMIC_LOADING
# else
/* In the Intel compiler environment, we seem to end up with */
/* statically linked executables and an undefined reference */
/* to _DYNAMIC */
# endif
# define MPROTECT_VDB
/* Requires Linux 2.3.47 or later. */
extern int _end;
......@@ -1707,17 +1755,68 @@
/* descriptions. */
# define USE_GENERIC_PUSH_REGS
# endif
# if defined(I386) && defined(LINUX)
# if defined(SPARC)
# define ASM_CLEAR_CODE /* Stack clearing is crucial, and we */
/* include assembly code to do it well. */
# endif
/* Can we save call chain in objects for debugging? */
/* SET NFRAMES (# of saved frames) and NARGS (#of args for each frame) */
/* to reasonable values for the platform. */
/* Set SAVE_CALL_CHAIN if we can. SAVE_CALL_COUNT can be specified at */
/* build time, though we feel free to adjust it slightly. */
/* Define NEED_CALLINFO if we either save the call stack or */
/* GC_ADD_CALLER is defined. */
#ifdef LINUX
# include <features.h>
# if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 || __GLIBC__ > 2
# define HAVE_BUILTIN_BACKTRACE
# endif
#endif
#if defined(SPARC)
# define CAN_SAVE_CALL_STACKS
# define CAN_SAVE_CALL_ARGS
#endif
#if defined(I386) && defined(LINUX)
/* SAVE_CALL_CHAIN is supported if the code is compiled to save */
/* frame pointers by default, i.e. no -fomit-frame-pointer flag. */
# ifdef SAVE_CALL_COUNT
# define CAN_SAVE_CALL_STACKS
# define CAN_SAVE_CALL_ARGS
#endif
#if defined(HAVE_BUILTIN_BACKTRACE) && !defined(CAN_SAVE_CALL_STACKS)
# define CAN_SAVE_CALL_STACKS
#endif
# if defined(SAVE_CALL_COUNT) && !defined(GC_ADD_CALLER) \
&& defined(CAN_SAVE_CALL_STACKS)
# define SAVE_CALL_CHAIN
# endif
# ifdef SAVE_CALL_CHAIN
# if defined(SAVE_CALL_NARGS) && defined(CAN_SAVE_CALL_ARGS)
# define NARGS SAVE_CALL_NARGS
# else
# define NARGS 0 /* Number of arguments to save for each call. */
# endif
# endif
# if defined(SPARC)
# define SAVE_CALL_CHAIN
# define ASM_CLEAR_CODE /* Stack clearing is crucial, and we */
/* include assembly code to do it well. */
# ifdef SAVE_CALL_CHAIN
# ifndef SAVE_CALL_COUNT
# define NFRAMES 6 /* Number of frames to save. Even for */
/* alignment reasons. */
# else
# define NFRAMES ((SAVE_CALL_COUNT + 1) & ~1)
# endif
# define NEED_CALLINFO
# endif /* SAVE_CALL_CHAIN */
# ifdef GC_ADD_CALLER
# define NFRAMES 1
# define NARGS 0
# define NEED_CALLINFO
# endif
# if defined(MAKE_BACK_GRAPH) && !defined(DBG_HDRS_ALL)
# define DBG_HDRS_ALL
# endif
# endif /* GCCONFIG_H */
......@@ -141,8 +141,6 @@ GC_bool GC_thr_initialized = FALSE;
size_t GC_min_stack_sz;
size_t GC_page_sz;
# define N_FREE_LISTS 25
ptr_t GC_stack_free_lists[N_FREE_LISTS] = { 0 };
/* GC_stack_free_lists[i] is free list for stacks of */
......@@ -171,14 +169,14 @@ ptr_t GC_stack_alloc(size_t * stack_size)
if (result != 0) {
GC_stack_free_lists[index] = *(ptr_t *)result;
} else {
result = (ptr_t) GC_scratch_alloc(search_sz + 2*GC_page_sz);
result = (ptr_t)(((word)result + GC_page_sz) & ~(GC_page_sz - 1));
result = (ptr_t) GC_scratch_alloc(search_sz + 2*GC_page_size);
result = (ptr_t)(((word)result + GC_page_size) & ~(GC_page_size - 1));
/* Protect hottest page to detect overflow. */
# ifdef STACK_GROWS_UP
/* mprotect(result + search_sz, GC_page_sz, PROT_NONE); */
/* mprotect(result + search_sz, GC_page_size, PROT_NONE); */
# else
/* mprotect(result, GC_page_sz, PROT_NONE); */
result += GC_page_sz;
/* mprotect(result, GC_page_size, PROT_NONE); */
result += GC_page_size;
# endif
}
*stack_size = search_sz;
......@@ -438,7 +436,6 @@ void GC_thr_init()
if (GC_thr_initialized) return;
GC_thr_initialized = TRUE;
GC_min_stack_sz = HBLKSIZE;
GC_page_sz = sysconf(_SC_PAGESIZE);
(void) sigaction(SIG_SUSPEND, 0, &act);
if (act.sa_handler != SIG_DFL)
ABORT("Previously installed SIG_SUSPEND handler");
......@@ -602,7 +599,7 @@ GC_pthread_create(pthread_t *new_thread,
si -> start_routine = start_routine;
si -> arg = arg;
LOCK();
if (!GC_thr_initialized) GC_thr_init();
if (!GC_initialized) GC_init();
if (NULL == attr) {
stack = 0;
(void) pthread_attr_init(&new_attr);
......
......@@ -1268,6 +1268,17 @@ int WRAP_FUNC(pthread_join)(pthread_t thread, void **retval)
/* cant have been recycled by pthreads. */
UNLOCK();
result = REAL_FUNC(pthread_join)(thread, retval);
# if defined (GC_FREEBSD_THREADS)
/* On FreeBSD, the wrapped pthread_join() sometimes returns (what
appears to be) a spurious EINTR which caused the test and real code
to gratuitously fail. Having looked at system pthread library source
code, I see how this return code may be generated. In one path of
code, pthread_join() just returns the errno setting of the thread
being joined. This does not match the POSIX specification or the
local man pages thus I have taken the liberty to catch this one
spurious return value properly conditionalized on GC_FREEBSD_THREADS. */
if (result == EINTR) result = 0;
# endif
if (result == 0) {
LOCK();
/* Here the pthread thread id may have been recycled. */
......
......@@ -429,7 +429,7 @@ ptr_t cold_gc_frame;
*i = 0;
}
# if defined(POWERPC) || defined(MSWIN32) || defined(MSWINCE) \
|| defined(UTS4) || defined(LINUX)
|| defined(UTS4) || defined(LINUX) || defined(EWS4800)
(void) setjmp(regs);
# else
(void) _setjmp(regs);
......@@ -492,8 +492,10 @@ ptr_t cold_gc_frame;
/* On IA64, we also need to flush register windows. But they end */
/* up on the other side of the stack segment. */
/* Returns the backing store pointer for the register stack. */
/* We implement this as a separate file in HP/UX. */
# ifdef IA64
/* We now implement this as a separate assembly file, since inline */
/* assembly code here doesn't work with either the Intel or HP */
/* compilers. */
# if 0
# ifdef LINUX
asm(" .text");
asm(" .psr abi64");
......
......@@ -337,6 +337,20 @@ DCL_LOCK_STATE;
{
return((GC_PTR)REDIRECT_MALLOC(n*lb));
}
# include <string.h>
# ifdef __STDC__
char *strdup(const char *s)
# else
char *strdup(s)
char *s;
# endif
{
size_t len = strlen + 1;
char * result = ((char *)REDIRECT_MALLOC(len+1));
BCOPY(s, result, len+1);
return result;
}
# endif /* REDIRECT_MALLOC */
/* Explicitly deallocate an object p. */
......
......@@ -838,7 +838,7 @@ long GC_markers = 2; /* Normally changed by thread-library- */
/* -specific code. */
/* Mark using the local mark stack until the global mark stack is empty */
/* and ther are no active workers. Update GC_first_nonempty to reflect */
/* and there are no active workers. Update GC_first_nonempty to reflect */
/* progress. */
/* Caller does not hold mark lock. */
/* Caller has already incremented GC_helper_count. We decrement it, */
......@@ -918,7 +918,7 @@ void GC_mark_local(mse *local_mark_stack, int id)
return;
}
/* else there's something on the stack again, or */
/* another help may push something. */
/* another helper may push something. */
GC_active_count++;
GC_ASSERT(GC_active_count > 0);
GC_release_mark_lock();
......@@ -950,8 +950,10 @@ void GC_do_parallel_mark()
GC_acquire_mark_lock();
GC_ASSERT(I_HOLD_LOCK());
GC_ASSERT(!GC_help_wanted);
GC_ASSERT(GC_active_count == 0);
/* This could be a GC_ASSERT, but it seems safer to keep it on */
/* all the time, especially since it's cheap. */
if (GC_help_wanted || GC_active_count != 0 || GC_helper_count != 0)
ABORT("Tried to start parallel mark in bad state");
# ifdef PRINTSTATS
GC_printf1("Starting marking for mark phase number %lu\n",
(unsigned long)GC_mark_no);
......@@ -1374,11 +1376,11 @@ ptr_t cold_gc_frame;
return;
}
# ifdef STACK_GROWS_DOWN
GC_push_all_eager(bottom, cold_gc_frame);
GC_push_all(cold_gc_frame - sizeof(ptr_t), top);
GC_push_all_eager(bottom, cold_gc_frame);
# else /* STACK_GROWS_UP */
GC_push_all_eager(cold_gc_frame, top);
GC_push_all(bottom, cold_gc_frame + sizeof(ptr_t));
GC_push_all_eager(cold_gc_frame, top);
# endif /* STACK_GROWS_UP */
} else {
GC_push_all_eager(bottom, top);
......
......@@ -252,7 +252,7 @@ GC_bool tmp;
n_root_sets++;
}
static roots_were_cleared = FALSE;
static GC_bool roots_were_cleared = FALSE;
void GC_clear_roots GC_PROTO((void))
{
......@@ -522,16 +522,6 @@ ptr_t cold_gc_frame;
register int i;
/*
* push registers - i.e., call GC_push_one(r) for each
* register contents r.
*/
# ifdef USE_GENERIC_PUSH_REGS
GC_generic_push_regs(cold_gc_frame);
# else
GC_push_regs(); /* usually defined in machine_dep.c */
# endif
/*
* Next push static data. This must happen early on, since it's
* not robust against mark stack overflow.
*/
......@@ -564,19 +554,30 @@ ptr_t cold_gc_frame;
# endif
/*
* Now traverse stacks.
* Now traverse stacks, and mark from register contents.
* These must be done last, since they can legitimately overflow
* the mark stack.
*/
# if !defined(USE_GENERIC_PUSH_REGS)
# ifdef USE_GENERIC_PUSH_REGS
GC_generic_push_regs(cold_gc_frame);
/* Also pushes stack, so that we catch callee-save registers */
/* saved inside the GC_push_regs frame. */
# else
/*
* push registers - i.e., call GC_push_one(r) for each
* register contents r.
*/
GC_push_regs(); /* usually defined in machine_dep.c */
GC_push_current_stack(cold_gc_frame);
/* In the threads case, this only pushes collector frames. */
/* In the USE_GENERIC_PUSH_REGS case, this is done inside */
/* GC_push_regs, so that we catch callee-save registers saved */
/* inside the GC_push_regs frame. */
/* In the case of linux threads on IA64, the hot section of */
/* the main stack is marked here, but the register stack */
/* backing store is handled in the threads-specific code. */
# endif
if (GC_push_other_roots != 0) (*GC_push_other_roots)();
/* In the threads case, this also pushes thread stacks. */
/* Note that without interior pointer recognition lots */
/* of stuff may have been pushed already, and this */
/* should be careful about mark stack overflows. */
}
/*
* Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
* Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
* Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved.
*
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
......@@ -97,6 +98,8 @@ GC_bool GC_quiet = 0;
GC_bool GC_print_stats = 0;
GC_bool GC_print_back_height = 0;
#ifdef FIND_LEAK
int GC_find_leak = 1;
#else
......@@ -479,6 +482,12 @@ int sig;
}
#endif
#ifdef MSWIN32
extern GC_bool GC_is_win32s();
#else
# define GC_is_win32s() FALSE
#endif
void GC_init_inner()
{
# if !defined(THREADS) && defined(GC_ASSERTIONS)
......@@ -502,6 +511,22 @@ void GC_init_inner()
if (0 != GETENV("GC_DONT_GC")) {
GC_dont_gc = 1;
}
if (0 != GETENV("GC_PRINT_BACK_HEIGHT")) {
GC_print_back_height = 1;
}
{
char * time_limit_string = GETENV("GC_PAUSE_TIME_TARGET");
if (0 != time_limit_string) {
long time_limit;
if (time_limit_string != 0) time_limit = atol(time_limit_string);
if (time_limit < 5) {
WARN("GC_PAUSE_TIME_TARGET environment variable value too small "
"or bad syntax: Ignoring\n", 0);
} else {
GC_time_limit = time_limit;
}
}
}
# ifdef UNIX_LIKE
if (0 != GETENV("GC_LOOP_ON_ABORT")) {
GC_set_and_save_fault_handler(looping_handler);
......@@ -611,8 +636,19 @@ void GC_init_inner()
PCR_IL_Unlock();
GC_pcr_install();
# endif
/* Get black list set up */
if (!GC_dont_precollect) GC_gcollect_inner();
# if !defined(SMALL_CONFIG)
if (!GC_is_win32s() && 0 != GETENV("GC_ENABLE_INCREMENTAL")) {
GC_ASSERT(!GC_incremental);
GC_setpagesize();
# ifndef GC_SOLARIS_THREADS
GC_dirty_init();
# endif
GC_ASSERT(GC_words_allocd == 0)
GC_incremental = TRUE;
}
# endif /* !SMALL_CONFIG */
/* Get black list set up and/or incrmental GC started */
if (!GC_dont_precollect || GC_incremental) GC_gcollect_inner();
GC_is_initialized = TRUE;
# ifdef STUBBORN_ALLOC
GC_stubborn_init();
......@@ -645,20 +681,14 @@ void GC_enable_incremental GC_PROTO(())
LOCK();
if (GC_incremental) goto out;
GC_setpagesize();
# ifdef MSWIN32
{
extern GC_bool GC_is_win32s();
/* VirtualProtect is not functional under win32s. */
if (GC_is_win32s()) goto out;
}
# endif /* MSWIN32 */
if (GC_is_win32s()) goto out;
# ifndef GC_SOLARIS_THREADS
GC_dirty_init();
# endif
if (!GC_is_initialized) {
GC_init_inner();
}
if (GC_incremental) goto out;
if (GC_dont_gc) {
/* Can't easily do it. */
UNLOCK();
......@@ -900,6 +930,13 @@ GC_CONST char * msg;
#ifdef NEED_CALLINFO
#ifdef HAVE_BUILTIN_BACKTRACE
# include <execinfo.h>
# ifdef LINUX
# include <unistd.h>
# endif
#endif
void GC_print_callers (info)
struct callinfo info[NFRAMES];
{
......@@ -925,7 +962,73 @@ struct callinfo info[NFRAMES];
GC_err_printf0("\n");
}
# endif
GC_err_printf1("\t\t##PC##= 0x%X\n", info[i].ci_pc);
# if defined(HAVE_BUILTIN_BACKTRACE) && !defined(REDIRECT_MALLOC)
/* Unfortunately backtrace_symbols calls malloc, which makes */
/* it dangersous if that has been redirected. */
{
char **sym_name =
backtrace_symbols((void **)(&(info[i].ci_pc)), 1);
char *name = sym_name[0];
GC_bool found_it = (strchr(name, '(') != 0);
FILE *pipe;
# ifdef LINUX
if (!found_it) {
# define EXE_SZ 100
static char exe_name[EXE_SZ];
# define CMD_SZ 200
char cmd_buf[CMD_SZ];
# define RESULT_SZ 200
static char result_buf[RESULT_SZ];
size_t result_len;
static GC_bool found_exe_name = FALSE;
static GC_bool will_fail = FALSE;
int ret_code;
/* Unfortunately, this is the common case for the */
/* main executable. */
/* Try to get it via a hairy and expensive scheme. */
/* First we get the name of the executable: */
if (will_fail) goto out;
if (!found_exe_name) {
ret_code = readlink("/proc/self/exe", exe_name, EXE_SZ);
if (ret_code < 0 || ret_code >= EXE_SZ || exe_name[0] != '/') {
will_fail = TRUE; /* Dont try again. */
goto out;
}
exe_name[ret_code] = '\0';
found_exe_name = TRUE;
}
/* Then we use popen to start addr2line -e <exe> <addr> */
/* There are faster ways to do this, but hopefully this */
/* isn't time critical. */
sprintf(cmd_buf, "/usr/bin/addr2line -e %s 0x%lx", exe_name,
(unsigned long)info[i].ci_pc);
pipe = popen(cmd_buf, "r");
if (pipe < 0 || fgets(result_buf, RESULT_SZ, pipe) == 0) {
will_fail = TRUE;
goto out;
}
result_len = strlen(result_buf);
if (result_buf[result_len - 1] == '\n') --result_len;
if (result_buf[0] == '?'
|| result_buf[result_len-2] == ':'
&& result_buf[result_len-1] == '0')
goto out;
if (result_len < RESULT_SZ - 25) {
/* Add in hex address */
sprintf(result_buf + result_len, " [0x%lx]",
(unsigned long)info[i].ci_pc);
}
name = result_buf;
pclose(pipe);
out:
}
# endif
GC_err_printf1("\t\t%s\n", name);
free(sym_name);
}
# else
GC_err_printf1("\t\t##PC##= 0x%lx\n", info[i].ci_pc);
# endif
}
}
......
......@@ -631,47 +631,41 @@ COUNT_DECL
ptr_t result = list;
GC_ASSERT(GC_find_header((ptr_t)hbp) == hhdr);
GC_remove_protection(hbp, 1, (hhdr)->hb_descr == 0 /* Pointer-free? */);
if (init) {
switch(sz) {
# if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
case 1:
/* We now issue the hint even if GC_nearly_full returned */
/* DONT_KNOW. */
GC_write_hint(hbp);
result = GC_reclaim1(hbp, hhdr, list COUNT_ARG);
break;
case 2:
GC_write_hint(hbp);
result = GC_reclaim_clear2(hbp, hhdr, list COUNT_ARG);
break;
case 4:
GC_write_hint(hbp);
result = GC_reclaim_clear4(hbp, hhdr, list COUNT_ARG);
break;
# endif /* !SMALL_CONFIG && !USE_MARK_BYTES */
default:
GC_write_hint(hbp);
result = GC_reclaim_clear(hbp, hhdr, sz, list COUNT_ARG);
break;
}
} else {
GC_ASSERT((hhdr)->hb_descr == 0 /* Pointer-free block */);
switch(sz) {
# if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES)
case 1:
GC_write_hint(hbp);
result = GC_reclaim1(hbp, hhdr, list COUNT_ARG);
break;
case 2:
GC_write_hint(hbp);
result = GC_reclaim_uninit2(hbp, hhdr, list COUNT_ARG);
break;
case 4:
GC_write_hint(hbp);
result = GC_reclaim_uninit4(hbp, hhdr, list COUNT_ARG);
break;
# endif /* !SMALL_CONFIG && !USE_MARK_BYTES */
default:
GC_write_hint(hbp);
result = GC_reclaim_uninit(hbp, hhdr, sz, list COUNT_ARG);
break;
}
......
......@@ -88,8 +88,8 @@ GC_pthread_create(pthread_t *new_thread,
}
LOCK();
if (!GC_thr_initialized) {
GC_thr_init();
if (!GC_is_initialized) {
GC_init_inner();
}
GC_multithreaded++;
......
......@@ -16,7 +16,7 @@
*/
/* Boehm, September 14, 1994 4:44 pm PDT */
# if defined(GC_SOLARIS_THREADS)
# if defined(GC_SOLARIS_THREADS) || defined(GC_SOLARIS_PTHREADS)
# include "private/gc_priv.h"
# include "private/solaris_threads.h"
......@@ -414,7 +414,6 @@ GC_bool GC_thr_initialized = FALSE;
size_t GC_min_stack_sz;
size_t GC_page_sz;
/*
* stack_head is stored at the top of free stacks
......@@ -456,7 +455,7 @@ ptr_t GC_stack_alloc(size_t * stack_size)
GC_stack_free_lists[index] = GC_stack_free_lists[index]->next;
} else {
#ifdef MMAP_STACKS
base = (ptr_t)mmap(0, search_sz + GC_page_sz,
base = (ptr_t)mmap(0, search_sz + GC_page_size,
PROT_READ|PROT_WRITE, MAP_PRIVATE |MAP_NORESERVE,
GC_zfd, 0);
if (base == (ptr_t)-1)
......@@ -465,27 +464,27 @@ ptr_t GC_stack_alloc(size_t * stack_size)
return NULL;
}
mprotect(base, GC_page_sz, PROT_NONE);
/* Should this use divHBLKSZ(search_sz + GC_page_sz) ? -- cf */
mprotect(base, GC_page_size, PROT_NONE);
/* Should this use divHBLKSZ(search_sz + GC_page_size) ? -- cf */
GC_is_fresh((struct hblk *)base, divHBLKSZ(search_sz));
base += GC_page_sz;
base += GC_page_size;
#else
base = (ptr_t) GC_scratch_alloc(search_sz + 2*GC_page_sz);
base = (ptr_t) GC_scratch_alloc(search_sz + 2*GC_page_size);
if (base == NULL)
{
*stack_size = 0;
return NULL;
}
base = (ptr_t)(((word)base + GC_page_sz) & ~(GC_page_sz - 1));
base = (ptr_t)(((word)base + GC_page_size) & ~(GC_page_size - 1));
/* Protect hottest page to detect overflow. */
# ifdef SOLARIS23_MPROTECT_BUG_FIXED
mprotect(base, GC_page_sz, PROT_NONE);
mprotect(base, GC_page_size, PROT_NONE);
# endif
GC_is_fresh((struct hblk *)base, divHBLKSZ(search_sz));
base += GC_page_sz;
base += GC_page_size;
#endif
}
*stack_size = search_sz;
......@@ -665,8 +664,8 @@ void GC_my_stack_limits()
/* original thread */
/* Empirically, what should be the stack page with lowest */
/* address is actually inaccessible. */
stack_size = GC_get_orig_stack_size() - GC_page_sz;
stack = GC_stackbottom - stack_size + GC_page_sz;
stack_size = GC_get_orig_stack_size() - GC_page_size;
stack = GC_stackbottom - stack_size + GC_page_size;
} else {
stack = me -> stack;
}
......@@ -704,7 +703,7 @@ void GC_push_all_stacks()
top = p -> stack + p -> stack_size;
} else {
/* The original stack. */
bottom = GC_stackbottom - GC_get_orig_stack_size() + GC_page_sz;
bottom = GC_stackbottom - GC_get_orig_stack_size() + GC_page_size;
top = GC_stackbottom;
}
if ((word)sp > (word)bottom && (word)sp < (word)top) bottom = sp;
......@@ -789,7 +788,6 @@ void GC_thr_init(void)
GC_thr_initialized = TRUE;
GC_min_stack_sz = ((thr_min_stack() + 32*1024 + HBLKSIZE-1)
& ~(HBLKSIZE - 1));
GC_page_sz = sysconf(_SC_PAGESIZE);
#ifdef MMAP_STACKS
GC_zfd = open("/dev/zero", O_RDONLY);
if (GC_zfd == -1)
......@@ -911,10 +909,7 @@ GC_thr_create(void *stack_base, size_t stack_size,
void * stack = stack_base;
LOCK();
if (!GC_thr_initialized)
{
GC_thr_init();
}
if (!GC_is_initialized) GC_init_inner();
GC_multithreaded++;
if (stack == 0) {
if (stack_size == 0) stack_size = 1024*1024;
......
......@@ -9,13 +9,38 @@
.globl GC_push_regs
GC_save_regs_in_stack:
GC_push_regs:
#if defined(__arch64__) || defined(__sparcv9)
save %sp,-128,%sp
flushw
ret
restore %sp,2047+128,%o0
#else /* 32 bit SPARC */
ta 0x3 ! ST_FLUSH_WINDOWS
mov %sp,%o0
retl
nop
#endif /* 32 bit SPARC */
.GC_save_regs_in_stack_end:
.size GC_save_regs_in_stack,.GC_save_regs_in_stack_end-GC_save_regs_in_stack
.globl GC_clear_stack_inner
GC_clear_stack_inner:
#if defined(__arch64__) || defined(__sparcv9)
mov %sp,%o2 ! Save sp
add %sp,2047-8,%o3 ! p = sp+bias-8
add %o1,-2047-192,%sp ! Move sp out of the way,
! so that traps still work.
! Includes some extra words
! so we can be sloppy below.
loop:
stx %g0,[%o3] ! *(long *)p = 0
cmp %o3,%o1
bgu,pt %xcc, loop ! if (p > limit) goto loop
asm("add %o3,-8,%o3 ! p -= 8 (delay slot)
retl
mov %o2,%sp ! Restore sp., delay slot
#else /* 32 bit SPARC */
mov %sp,%o2 ! Save sp
add %sp,-8,%o3 ! p = sp-8
clr %g1 ! [g0,g1] = 0
......@@ -30,6 +55,10 @@ loop:
add %o3,-8,%o3 ! p -= 8 (delay slot)
retl
mov %o2,%sp ! Restore sp., delay slot
#endif /* 32 bit SPARC */
.GC_clear_stack_inner_end:
.size GC_clear_stack_inner,.GC_clear_stack_inner_end-GC_clear_stack_inner
......
......@@ -20,7 +20,7 @@
# undef GC_BUILD
#ifdef DBG_HDRS_ALL
#if defined(DBG_HDRS_ALL) || defined(MAKE_BACK_GRAPH)
# define GC_DEBUG
#endif
......@@ -1340,7 +1340,7 @@ void SetMinimumStack(long minSize)
# endif
GC_INIT(); /* Only needed if gc is dynamic library. */
(void) GC_set_warn_proc(warn_proc);
# if defined(MPROTECT_VDB) || defined(PROC_VDB)
# if (defined(MPROTECT_VDB) || defined(PROC_VDB)) && !defined(MAKE_BACK_GRAPH)
GC_enable_incremental();
(void) GC_printf0("Switched to incremental mode\n");
# if defined(MPROTECT_VDB)
......@@ -1571,7 +1571,9 @@ main()
n_tests = 0;
GC_INIT(); /* Only needed if gc is dynamic library. */
GC_enable_incremental();
# ifndef MAKE_BACK_GRAPH
GC_enable_incremental();
# endif
(void) GC_set_warn_proc(warn_proc);
if (thr_keycreate(&fl_key, GC_free) != 0) {
(void)GC_printf1("Key creation failed %lu\n", (unsigned long)code);
......@@ -1628,7 +1630,7 @@ main()
pthread_attr_setstacksize(&attr, 1000000);
# endif
n_tests = 0;
# if defined(MPROTECT_VDB) && !defined(PARALLEL_MARK) &&!defined(REDIRECT_MALLOC)
# if defined(MPROTECT_VDB) && !defined(PARALLEL_MARK) &&!defined(REDIRECT_MALLOC) && !defined(MAKE_BACK_GRAPH)
GC_enable_incremental();
(void) GC_printf0("Switched to incremental mode\n");
(void) GC_printf0("Emulating dirty bits with mprotect/signals\n");
......
......@@ -10,13 +10,13 @@ int main()
"-Wl,--wrap -Wl,pthread_sigmask -Wl,--wrap -Wl,sleep\n");
# endif
# if defined(GC_LINUX_THREADS) || defined(GC_IRIX_THREADS) \
|| defined(GC_FREEBSD_THREADS)
|| defined(GC_FREEBSD_THREADS) || defined(GC_SOLARIS_PTHREADS)
printf("-lpthread\n");
# endif
# if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS)
printf("-lpthread -lrt\n");
# endif
# if defined(GC_SOLARIS_THREADS)
# if defined(GC_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS)
printf("-lthread -ldl\n");
# endif
return 0;
......
#define GC_VERSION_MAJOR 6
#define GC_VERSION_MINOR 1
#define GC_ALPHA_VERSION 1
#define GC_ALPHA_VERSION 3
# define GC_NOT_ALPHA 0xff
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment