Commit 54f28c21 by Bryce McKinlay Committed by Bryce McKinlay

Import Boehm GC version 6.6.

From-SVN: r110204
parent ac42ec79
2006-01-24 Bryce McKinlay <mckinlay@redhat.com>
Import Boehm GC version 6.6.
2006-01-24 David Ayers <d.ayers@inode.at>
PR libobjc/13946
......
......@@ -17,28 +17,27 @@ else
asm_libgc_sources =
endif
GC_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 aix_irix_threads.c \
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 \
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 \
backgraph.c win32_threads.c \
pthread_support.c pthread_stop_world.c darwin_stop_world.c \
$(asm_libgc_sources)
$(asm_libgcjgc_sources)
libgcjgc_convenience_la_SOURCES = $(libgcjgc_la_SOURCES)
EXTRA_DIST = alpha_mach_dep.S \
mips_sgi_mach_dep.s mips_ultrix_mach_dep.s powerpc_darwin_mach_dep.s \
rs6000_mach_dep.s sparc_mach_dep.S sparc_netbsd_mach_dep.s \
sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s
libgcjgc_la_SOURCES = $(GC_SOURCES)
libgcjgc_convenience_la_SOURCES = $(GC_SOURCES)
# Include THREADLIBS here to ensure that the correct versions of
# linuxthread semaphore functions get linked:
libgcjgc_la_LIBADD = @addobjs@ $(THREADLIBS)
libgcjgc_la_LIBADD = @addobjs@ $(THREADLIBS) $(UNWINDLIBS)
libgcjgc_la_DEPENDENCIES = @addobjs@
libgcjgc_la_LDFLAGS = -version-info 1:1:0 -rpath $(toolexeclibdir)
libgcjgc_la_LDFLAGS = -version-info 1:2:0 -rpath $(toolexeclibdir)
libgcjgc_convenience_la_LIBADD = @addobjs@
libgcjgc_convenience_la_DEPENDENCIES = @addobjs@
......@@ -48,7 +47,7 @@ AM_CFLAGS = @GC_CFLAGS@
check_PROGRAMS = gctest
gctest_SOURCES = tests/test.c
gctest_LDADD = ./libgcjgc.la $(THREADLIBS) $(EXTRA_TEST_LIBS)
gctest_LDADD = ./libgcjgc.la $(THREADDLLIBS) $(UNWINDLIBS) $(EXTRA_TEST_LIBS)
gctest_LDFLAGS = -shared-libgcc
TESTS_ENVIRONMENT = LD_LIBRARY_PATH=../../$(MULTIBUILDTOP)gcc
TESTS = gctest
......
......@@ -36,7 +36,7 @@ CFLAGS= -O -I$(srcdir)/include -DATOMIC_UNCOLLECTABLE -DNO_SIGNALS -DNO_EXECUTE_
# -DGC_LINUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC
# To build the parallel collector in a static library on HP/UX,
# add to the above:
# -DGC_HPUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC -D_POSIX_C_SOURCE=199506L
# -DGC_HPUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC -D_POSIX_C_SOURCE=199506L -mt
# To build the thread-safe collector on Tru64, add to the above:
# -pthread -DGC_OSF1_THREADS
......@@ -70,10 +70,11 @@ HOSTCFLAGS=$(CFLAGS)
# 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.
# -DGC_OSF1_THREADS enables support for Tru64 pthreads.
# -DGC_FREEBSD_THREADS enables support for FreeBSD pthreads.
# Appeared to run into some underlying thread problems.
# -DGC_DARWIN_THREADS enables support for Mac OS X pthreads. Untested.
# -DGC_DARWIN_THREADS enables support for Mac OS X pthreads.
# -DGC_AIX_THREADS enables support for IBM AIX threads.
# -DGC_DGUX386_THREADS enables support for DB/UX on I386 threads.
# See README.DGUX386.
# -DGC_WIN32_THREADS enables support for win32 threads. That makes sense
......@@ -233,8 +234,8 @@ HOSTCFLAGS=$(CFLAGS)
# -DTHREAD_LOCAL_ALLOC defines GC_local_malloc(), GC_local_malloc_atomic()
# and GC_local_gcj_malloc(). Needed for gc_gcj.h interface. These allocate
# in a way that usually does not involve acquisition of a global lock.
# Currently requires -DGC_LINUX_THREADS, but should be easy to port to
# other pthreads environments. Recommended for multiprocessors.
# Currently works only on platforms such as Linux which use pthread_support.c.
# Recommended for multiprocessors.
# -DUSE_COMPILER_TLS causes thread local allocation to use compiler-supported
# "__thread" thread-local variables. This is the default in HP/UX. It
# may help performance on recent Linux installations. (It failed for
......@@ -276,6 +277,10 @@ HOSTCFLAGS=$(CFLAGS)
# -DPOINTER_SHIFT=n causes the collector to left shift candidate pointers
# by the indicated amount before trying to interpret them. Applied
# after POINTER_MASK. EXPERIMENTAL. See also the preceding macro.
# -DDARWIN_DONT_PARSE_STACK Causes the Darwin port to discover thread
# stack bounds in the same way as other pthread ports, without trying to
# walk the frames onthe stack. This is recommended only as a fallback
# for applications that don't support proper stack unwinding.
#
CXXFLAGS= $(CFLAGS)
......@@ -283,9 +288,9 @@ AR= ar
RANLIB= ranlib
OBJS= alloc.o reclaim.o allchblk.o misc.o mach_dep.o os_dep.o mark_rts.o headers.o mark.o obj_map.o blacklst.o finalize.o new_hblk.o dbg_mlc.o malloc.o stubborn.o checksums.o solaris_threads.o aix_irix_threads.o pthread_support.o pthread_stop_world.o darwin_stop_world.o typd_mlc.o ptr_chck.o mallocx.o solaris_pthreads.o gcj_mlc.o specific.o gc_dlopen.o backgraph.o win32_threads.o
OBJS= alloc.o reclaim.o allchblk.o misc.o mach_dep.o os_dep.o mark_rts.o headers.o mark.o obj_map.o blacklst.o finalize.o new_hblk.o dbg_mlc.o malloc.o stubborn.o checksums.o solaris_threads.o pthread_support.o pthread_stop_world.o darwin_stop_world.o typd_mlc.o ptr_chck.o mallocx.o solaris_pthreads.o gcj_mlc.o specific.o gc_dlopen.o backgraph.o win32_threads.o
CSRCS= reclaim.c allchblk.c misc.c alloc.c mach_dep.c os_dep.c mark_rts.c headers.c mark.c obj_map.c pcr_interface.c blacklst.c finalize.c new_hblk.c real_malloc.c dyn_load.c dbg_mlc.c malloc.c stubborn.c checksums.c solaris_threads.c aix_irix_threads.c pthread_support.c pthread_stop_world.c darwin_stop_world.c typd_mlc.c ptr_chck.c mallocx.c solaris_pthreads.c gcj_mlc.c specific.c gc_dlopen.c backgraph.c win32_threads.c
CSRCS= reclaim.c allchblk.c misc.c alloc.c mach_dep.c os_dep.c mark_rts.c headers.c mark.c obj_map.c pcr_interface.c blacklst.c finalize.c new_hblk.c real_malloc.c dyn_load.c dbg_mlc.c malloc.c stubborn.c checksums.c solaris_threads.c pthread_support.c pthread_stop_world.c darwin_stop_world.c typd_mlc.c ptr_chck.c mallocx.c solaris_pthreads.c gcj_mlc.c specific.c gc_dlopen.c backgraph.c win32_threads.c
CORD_SRCS= cord/cordbscs.c cord/cordxtra.c cord/cordprnt.c cord/de.c cord/cordtest.c include/cord.h include/ec.h include/private/cord_pos.h cord/de_win.c cord/de_win.h cord/de_cmds.h cord/de_win.ICO cord/de_win.RC
......
......@@ -65,12 +65,13 @@ DIST_COMMON = $(srcdir)/../config.guess $(srcdir)/../config.sub \
$(srcdir)/../compile $(srcdir)/../compile $(srcdir)/../compile \
$(srcdir)/../compile $(srcdir)/../compile $(srcdir)/../compile \
$(srcdir)/../compile $(srcdir)/../compile $(srcdir)/../compile \
$(srcdir)/../compile $(srcdir)/../compile $(srcdir)/../compile \
$(srcdir)/../ltmain.sh $(srcdir)/../config.guess \
$(srcdir)/../config.sub
$(srcdir)/../compile $(srcdir)/../ltmain.sh \
$(srcdir)/../config.guess $(srcdir)/../config.sub
subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
$(top_srcdir)/../config/depstand.m4 \
$(top_srcdir)/../config/lead-dot.m4 \
$(top_srcdir)/../config/no-executables.m4 \
$(top_srcdir)/../libtool.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
......@@ -82,34 +83,36 @@ CONFIG_HEADER = $(top_builddir)/include/gc_config.h \
CONFIG_CLEAN_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
am__DEPENDENCIES_1 =
@POWERPC_DARWIN_TRUE@am__objects_1 = powerpc_darwin_mach_dep.lo
am__objects_2 = allchblk.lo alloc.lo blacklst.lo checksums.lo \
am_libgcjgc_la_OBJECTS = allchblk.lo alloc.lo blacklst.lo checksums.lo \
dbg_mlc.lo dyn_load.lo finalize.lo gc_dlopen.lo gcj_mlc.lo \
headers.lo aix_irix_threads.lo malloc.lo mallocx.lo mark.lo \
mark_rts.lo misc.lo new_hblk.lo obj_map.lo os_dep.lo \
pcr_interface.lo ptr_chck.lo real_malloc.lo reclaim.lo \
solaris_pthreads.lo solaris_threads.lo specific.lo stubborn.lo \
typd_mlc.lo backgraph.lo win32_threads.lo pthread_support.lo \
pthread_stop_world.lo darwin_stop_world.lo $(am__objects_1)
am_libgcjgc_la_OBJECTS = $(am__objects_2)
headers.lo malloc.lo mallocx.lo mark.lo mark_rts.lo misc.lo \
new_hblk.lo obj_map.lo os_dep.lo pcr_interface.lo ptr_chck.lo \
real_malloc.lo reclaim.lo solaris_pthreads.lo \
solaris_threads.lo specific.lo stubborn.lo typd_mlc.lo \
backgraph.lo win32_threads.lo pthread_support.lo \
pthread_stop_world.lo darwin_stop_world.lo
libgcjgc_la_OBJECTS = $(am_libgcjgc_la_OBJECTS)
am_libgcjgc_convenience_la_OBJECTS = $(am__objects_2)
am__objects_1 = allchblk.lo alloc.lo blacklst.lo checksums.lo \
dbg_mlc.lo dyn_load.lo finalize.lo gc_dlopen.lo gcj_mlc.lo \
headers.lo malloc.lo mallocx.lo mark.lo mark_rts.lo misc.lo \
new_hblk.lo obj_map.lo os_dep.lo pcr_interface.lo ptr_chck.lo \
real_malloc.lo reclaim.lo solaris_pthreads.lo \
solaris_threads.lo specific.lo stubborn.lo typd_mlc.lo \
backgraph.lo win32_threads.lo pthread_support.lo \
pthread_stop_world.lo darwin_stop_world.lo
am_libgcjgc_convenience_la_OBJECTS = $(am__objects_1)
libgcjgc_convenience_la_OBJECTS = \
$(am_libgcjgc_convenience_la_OBJECTS)
am__dirstamp = $(am__leading_dot)dirstamp
am_gctest_OBJECTS = tests/test.$(OBJEXT)
gctest_OBJECTS = $(am_gctest_OBJECTS)
gctest_DEPENDENCIES = ./libgcjgc.la $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1)
gctest_DEPENDENCIES = ./libgcjgc.la $(am__DEPENDENCIES_1)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_builddir)/include
depcomp =
am__depfiles_maybe =
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
CCASCOMPILE = $(CCAS) $(AM_CCASFLAGS) $(CCASFLAGS)
LTCCASCOMPILE = $(LIBTOOL) --mode=compile $(CCAS) $(AM_CCASFLAGS) \
$(CCASFLAGS)
SOURCES = $(libgcjgc_la_SOURCES) $(libgcjgc_convenience_la_SOURCES) \
$(gctest_SOURCES)
MULTISRCTOP =
......@@ -254,34 +257,33 @@ SUBDIRS = include
noinst_LTLIBRARIES = libgcjgc.la libgcjgc_convenience.la
@POWERPC_DARWIN_FALSE@asm_libgc_sources =
@POWERPC_DARWIN_TRUE@asm_libgc_sources = powerpc_darwin_mach_dep.s
GC_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 aix_irix_threads.c \
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 \
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 \
backgraph.c win32_threads.c \
pthread_support.c pthread_stop_world.c darwin_stop_world.c \
$(asm_libgc_sources)
$(asm_libgcjgc_sources)
libgcjgc_convenience_la_SOURCES = $(libgcjgc_la_SOURCES)
EXTRA_DIST = alpha_mach_dep.S \
mips_sgi_mach_dep.s mips_ultrix_mach_dep.s powerpc_darwin_mach_dep.s \
rs6000_mach_dep.s sparc_mach_dep.S sparc_netbsd_mach_dep.s \
sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s
libgcjgc_la_SOURCES = $(GC_SOURCES)
libgcjgc_convenience_la_SOURCES = $(GC_SOURCES)
# Include THREADLIBS here to ensure that the correct versions of
# linuxthread semaphore functions get linked:
libgcjgc_la_LIBADD = @addobjs@ $(THREADLIBS)
libgcjgc_la_LIBADD = @addobjs@ $(THREADLIBS) $(UNWINDLIBS)
libgcjgc_la_DEPENDENCIES = @addobjs@
libgcjgc_la_LDFLAGS = -version-info 1:1:0 -rpath $(toolexeclibdir)
libgcjgc_la_LDFLAGS = -version-info 1:2:0 -rpath $(toolexeclibdir)
libgcjgc_convenience_la_LIBADD = @addobjs@
libgcjgc_convenience_la_DEPENDENCIES = @addobjs@
AM_CXXFLAGS = @GC_CFLAGS@
AM_CFLAGS = @GC_CFLAGS@
gctest_SOURCES = tests/test.c
gctest_LDADD = ./libgcjgc.la $(THREADLIBS) $(EXTRA_TEST_LIBS)
gctest_LDADD = ./libgcjgc.la $(THREADDLLIBS) $(UNWINDLIBS) $(EXTRA_TEST_LIBS)
gctest_LDFLAGS = -shared-libgcc
TESTS_ENVIRONMENT = LD_LIBRARY_PATH=../../$(MULTIBUILDTOP)gcc
TESTS = gctest
......@@ -414,12 +416,6 @@ distclean-compile:
.c.lo:
$(LTCOMPILE) -c -o $@ $<
.s.o:
$(CCASCOMPILE) -c $<
.s.obj:
$(CCASCOMPILE) -c `$(CYGPATH_W) '$<'`
mostlyclean-libtool:
-rm -f *.lo
......
......@@ -547,39 +547,6 @@ AC_DEFUN([AM_PROG_INSTALL_SH],
install_sh=${install_sh-"$am_aux_dir/install-sh"}
AC_SUBST(install_sh)])
# -*- Autoconf -*-
# Copyright (C) 2003 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# serial 1
# Check whether the underlying file-system supports filenames
# with a leading dot. For instance MS-DOS doesn't.
AC_DEFUN([AM_SET_LEADING_DOT],
[rm -rf .tst 2>/dev/null
mkdir .tst 2>/dev/null
if test -d .tst; then
am__leading_dot=.
else
am__leading_dot=_
fi
rmdir .tst 2>/dev/null
AC_SUBST([am__leading_dot])])
# Add --enable-maintainer-mode option to configure.
# From Jim Meyering
......@@ -1168,5 +1135,7 @@ AC_SUBST([am__untar])
]) # _AM_PROG_TAR
m4_include([../config/acx.m4])
m4_include([../config/depstand.m4])
m4_include([../config/lead-dot.m4])
m4_include([../config/no-executables.m4])
m4_include([../libtool.m4])
......@@ -285,8 +285,8 @@ int n;
GET_HDR(hhdr -> hb_prev, phdr);
phdr -> hb_next = hhdr -> hb_next;
}
FREE_ASSERT(GC_free_bytes[index] >= hhdr -> hb_sz);
INCR_FREE_BYTES(index, - (signed_word)(hhdr -> hb_sz));
FREE_ASSERT(GC_free_bytes[index] >= 0);
if (0 != hhdr -> hb_next) {
hdr * nhdr;
GC_ASSERT(!IS_FORWARDING_ADDR_OR_NIL(NHDR(hhdr)));
......
......@@ -92,6 +92,16 @@ char * GC_copyright[] =
# include "version.h"
#if defined(SAVE_CALL_CHAIN) && \
!(defined(REDIRECT_MALLOC) && defined(GC_HAVE_BUILTIN_BACKTRACE))
# define SAVE_CALL_CHAIN_IN_GC
/* This is only safe if the call chain save mechanism won't end up */
/* calling GC_malloc. The GNU C library documentation suggests */
/* that backtrace doesn't use malloc, but at least the initial */
/* call in some versions does seem to invoke the dynamic linker, */
/* which uses malloc. */
#endif
/* some more variables */
extern signed_word GC_mem_found; /* Number of reclaimed longwords */
......@@ -196,7 +206,8 @@ word GC_adj_words_allocd()
/* had been reallocated this round. Finalization is user */
/* visible progress. And if we don't count this, we have */
/* stability problems for programs that finalize all objects. */
result += GC_words_wasted;
if ((GC_words_wasted >> 3) < result)
result += GC_words_wasted;
/* This doesn't reflect useful work. But if there is lots of */
/* new fragmentation, the same is probably true of the heap, */
/* and the collection will be correspondingly cheaper. */
......@@ -221,6 +232,8 @@ void GC_clear_a_few_frames()
{
# define NWORDS 64
word frames[NWORDS];
/* Some compilers will warn that frames was set but never used. */
/* That's the whole idea ... */
register int i;
for (i = 0; i < NWORDS; i++) frames[i] = 0;
......@@ -293,7 +306,7 @@ void GC_maybe_gc()
# endif
if (GC_stopped_mark(GC_time_limit == GC_TIME_UNLIMITED?
GC_never_stop_func : GC_timeout_stop_func)) {
# ifdef SAVE_CALL_CHAIN
# ifdef SAVE_CALL_CHAIN_IN_GC
GC_save_callers(GC_last_stack);
# endif
GC_finish_collection();
......@@ -358,7 +371,7 @@ GC_stop_func stop_func;
}
GC_invalidate_mark_state(); /* Flush mark stack. */
GC_clear_marks();
# ifdef SAVE_CALL_CHAIN
# ifdef SAVE_CALL_CHAIN_IN_GC
GC_save_callers(GC_last_stack);
# endif
GC_is_full_gc = TRUE;
......@@ -413,7 +426,7 @@ int n;
for (i = GC_deficit; i < GC_RATE*n; i++) {
if (GC_mark_some((ptr_t)0)) {
/* Need to finish a collection */
# ifdef SAVE_CALL_CHAIN
# ifdef SAVE_CALL_CHAIN_IN_GC
GC_save_callers(GC_last_stack);
# endif
# ifdef PARALLEL_MARK
......@@ -929,7 +942,7 @@ word n;
# endif
expansion_slop = WORDS_TO_BYTES(min_words_allocd()) + 4*MAXHINCR*HBLKSIZE;
if (GC_last_heap_addr == 0 && !((word)space & SIGNB)
|| GC_last_heap_addr != 0 && GC_last_heap_addr < (ptr_t)space) {
|| (GC_last_heap_addr != 0 && GC_last_heap_addr < (ptr_t)space)) {
/* Assume the heap is growing up */
GC_greatest_plausible_heap_addr =
(GC_PTR)GC_max((ptr_t)GC_greatest_plausible_heap_addr,
......@@ -992,7 +1005,7 @@ word needed_blocks;
GC_bool ignore_off_page;
{
if (!GC_incremental && !GC_dont_gc &&
(GC_dont_expand && GC_words_allocd > 0 || GC_should_collect())) {
((GC_dont_expand && GC_words_allocd > 0) || GC_should_collect())) {
GC_gcollect_inner();
} else {
word blocks_to_get = GC_heapsize/(HBLKSIZE*GC_free_space_divisor)
......@@ -1001,6 +1014,9 @@ GC_bool ignore_off_page;
if (blocks_to_get > MAXHINCR) {
word slop;
/* Get the minimum required to make it likely that we */
/* can satisfy the current request in the presence of black- */
/* listing. This will probably be more than MAXHINCR. */
if (ignore_off_page) {
slop = 4;
} else {
......
# $Id: alpha_mach_dep.s,v 1.2 1993/01/18 22:54:51 dosser Exp $
.arch ev6
.text
......@@ -12,13 +11,13 @@ GC_push_regs:
.mask 0x04000000, 0
.frame $sp, 16, $26, 0
# $0 integer result
# $1-$8 temp regs - not preserved cross calls
# $9-$15 call saved regs
# $16-$21 argument regs - not preserved cross calls
# $22-$28 temp regs - not preserved cross calls
# $29 global pointer - not preserved cross calls
# $30 stack pointer
/* $0 integer result */
/* $1-$8 temp regs - not preserved cross calls */
/* $9-$15 call saved regs */
/* $16-$21 argument regs - not preserved cross calls */
/* $22-$28 temp regs - not preserved cross calls */
/* $29 global pointer - not preserved cross calls */
/* $30 stack pointer */
# define call_push(x) \
mov x, $16; \
......@@ -33,12 +32,12 @@ GC_push_regs:
call_push($14)
call_push($15)
# $f0-$f1 floating point results
# $f2-$f9 call saved regs
# $f10-$f30 temp regs - not preserved cross calls
/* $f0-$f1 floating point results */
/* $f2-$f9 call saved regs */
/* $f10-$f30 temp regs - not preserved cross calls */
# Use the most efficient transfer method for this hardware.
# Bit 1 detects the FIX extension, which includes ftoit.
/* Use the most efficient transfer method for this hardware. */
/* Bit 1 detects the FIX extension, which includes ftoit. */
amask 2, $0
bne $0, $use_stack
......
......@@ -1767,7 +1767,7 @@ fi
# Define the identity of the package.
PACKAGE=gc
VERSION=6.3
VERSION=6.6
# Some tools Automake needs.
......
......@@ -36,7 +36,7 @@ ACX_NONCANONICAL_TARGET
mkinstalldirs="`cd $ac_aux_dir && ${PWDCMD-pwd}`/mkinstalldirs"
AC_SUBST(mkinstalldirs)
AM_INIT_AUTOMAKE(gc, 6.3, no-define)
AM_INIT_AUTOMAKE(gc, 6.6, no-define)
# The autoconf 2.5x version of the no-executables hack.
GCC_NO_EXECUTABLES
......
......@@ -59,7 +59,7 @@ static int extract_conv_spec(CORD_pos source, char *buf,
register int result = 0;
register int current_number = 0;
register int saw_period = 0;
register int saw_number;
register int saw_number = 0;
register int chars_so_far = 0;
register char current;
......@@ -243,7 +243,7 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args)
char * str = va_arg(args, char *);
register char c;
while (c = *str++) {
while ((c = *str++)) {
CORD_ec_append(result, c);
}
goto done;
......@@ -320,7 +320,7 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args)
if (buf != result[0].ec_bufptr) {
register char c;
while (c = *buf++) {
while ((c = *buf++)) {
CORD_ec_append(result, c);
}
} else {
......
......@@ -221,7 +221,7 @@ void test_printf()
if (CORD_cmp(result, result2) != 0)ABORT("CORD_sprintf goofed 5");
}
main()
int main()
{
# ifdef THINK_C
printf("cordtest:\n");
......
File mode changed from 100644 to 100755
......@@ -14,7 +14,13 @@
Page 50: "If a leaf procedure's red zone usage would exceed 224 bytes, then
it must set up a stack frame just like routines that call other routines."
*/
#define PPC_RED_ZONE_SIZE 224
#ifdef POWERPC
# if CPP_WORDSZ == 32
# define PPC_RED_ZONE_SIZE 224
# elif CPP_WORDSZ == 64
# define PPC_RED_ZONE_SIZE 320
# endif
#endif
typedef struct StackFrame {
unsigned long savedSP;
......@@ -24,12 +30,17 @@ typedef struct StackFrame {
unsigned long savedRTOC;
} StackFrame;
unsigned int FindTopOfStack(unsigned int stack_start) {
unsigned long FindTopOfStack(unsigned int stack_start) {
StackFrame *frame;
if (stack_start == 0) {
__asm__ volatile("lwz %0,0(r1)" : "=r" (frame));
# ifdef POWERPC
# if CPP_WORDSZ == 32
__asm__ volatile("lwz %0,0(r1)" : "=r" (frame));
# else
__asm__ volatile("ldz %0,0(r1)" : "=r" (frame));
# endif
# endif
} else {
frame = (StackFrame *)stack_start;
}
......@@ -38,7 +49,7 @@ unsigned int FindTopOfStack(unsigned int stack_start) {
/* GC_printf1("FindTopOfStack start at sp = %p\n", frame); */
# endif
do {
if (frame->savedSP == NULL) break;
if (frame->savedSP == 0) break;
/* if there are no more stack frames, stop */
frame = (StackFrame*)frame->savedSP;
......@@ -54,9 +65,88 @@ unsigned int FindTopOfStack(unsigned int stack_start) {
/* GC_printf1("FindTopOfStack finish at sp = %p\n", frame); */
# endif
return (unsigned int)frame;
return (unsigned long)frame;
}
#ifdef DARWIN_DONT_PARSE_STACK
void GC_push_all_stacks() {
int i;
kern_return_t r;
GC_thread p;
pthread_t me;
ptr_t lo, hi;
ppc_thread_state_t state;
mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
me = pthread_self();
if (!GC_thr_initialized) GC_thr_init();
for(i=0;i<THREAD_TABLE_SZ;i++) {
for(p=GC_threads[i];p!=0;p=p->next) {
if(p -> flags & FINISHED) continue;
if(pthread_equal(p->id,me)) {
lo = GC_approx_sp();
} else {
/* Get the thread state (registers, etc) */
r = thread_get_state(
p->stop_info.mach_thread,
MACHINE_THREAD_STATE,
(natural_t*)&state,
&thread_state_count);
if(r != KERN_SUCCESS) ABORT("thread_get_state failed");
lo = (void*)(state.r1 - PPC_RED_ZONE_SIZE);
GC_push_one(state.r0);
GC_push_one(state.r2);
GC_push_one(state.r3);
GC_push_one(state.r4);
GC_push_one(state.r5);
GC_push_one(state.r6);
GC_push_one(state.r7);
GC_push_one(state.r8);
GC_push_one(state.r9);
GC_push_one(state.r10);
GC_push_one(state.r11);
GC_push_one(state.r12);
GC_push_one(state.r13);
GC_push_one(state.r14);
GC_push_one(state.r15);
GC_push_one(state.r16);
GC_push_one(state.r17);
GC_push_one(state.r18);
GC_push_one(state.r19);
GC_push_one(state.r20);
GC_push_one(state.r21);
GC_push_one(state.r22);
GC_push_one(state.r23);
GC_push_one(state.r24);
GC_push_one(state.r25);
GC_push_one(state.r26);
GC_push_one(state.r27);
GC_push_one(state.r28);
GC_push_one(state.r29);
GC_push_one(state.r30);
GC_push_one(state.r31);
} /* p != me */
if(p->flags & MAIN_THREAD)
hi = GC_stackbottom;
else
hi = p->stack_end;
#if DEBUG_THREADS
GC_printf3("Darwin: Stack for thread 0x%lx = [%lx,%lx)\n",
(unsigned long) p -> id,
(unsigned long) lo,
(unsigned long) hi
);
#endif
GC_push_all_stack(lo,hi);
} /* for(p=GC_threads[i]...) */
} /* for(i=0;i<THREAD_TABLE_SZ...) */
}
#else /* !DARWIN_DONT_PARSE_STACK; Use FindTopOfStack() */
void GC_push_all_stacks() {
int i;
kern_return_t r;
......@@ -76,8 +166,12 @@ void GC_push_all_stacks() {
lo = GC_approx_sp();
hi = (ptr_t)FindTopOfStack(0);
} else {
# ifdef POWERPC
# if defined(POWERPC)
# if CPP_WORDSZ == 32
ppc_thread_state_t info;
# else
ppc_thread_state64_t info;
# endif
mach_msg_type_number_t outCount = THREAD_STATE_MAX;
r = thread_get_state(thread, MACHINE_THREAD_STATE,
(natural_t *)&info, &outCount);
......@@ -156,6 +250,7 @@ void GC_push_all_stacks() {
GC_push_all_stack(lo, hi);
} /* for(p=GC_threads[i]...) */
}
#endif /* !DARWIN_DONT_PARSE_STACK */
static mach_port_t GC_mach_handler_thread;
static int GC_use_mach_handler_thread = 0;
......@@ -325,6 +420,8 @@ void GC_start_world()
kern_return_t kern_result;
thread_act_array_t act_list;
mach_msg_type_number_t listcount;
struct thread_basic_info info;
mach_msg_type_number_t outCount = THREAD_INFO_MAX;
# if DEBUG_THREADS
GC_printf0("World starting\n");
......@@ -351,8 +448,6 @@ void GC_start_world()
# endif
continue;
}
struct thread_basic_info info;
mach_msg_type_number_t outCount = THREAD_INFO_MAX;
kern_result = thread_info(thread, THREAD_BASIC_INFO,
(thread_info_t)&info, &outCount);
if(kern_result != KERN_SUCCESS) ABORT("thread_info failed");
......
......@@ -28,7 +28,7 @@ are GPL'ed, but with an exception that should cover all uses in the
collector. (If you are concerned about such things, I recommend you look
at the notice in config.guess or ltmain.sh.)
This is version 6.3 of a conservative garbage collector for C and C++.
This is version 6.6 of a conservative garbage collector for C and C++.
You might find a more recent version of this at
......
......@@ -2100,7 +2100,151 @@ Since gc6.3alpha6:
to Andrew Begel.)
- Fix GC_task_self declaration in os_dep.c. (Thanks to Andrew Pinski.)
- Increase INITIAL_BUF_SZ in os_dep.c for Solaris /proc reads.
Since 6.3:
- Merge gcconfig.h changes from gcc tree.
- Unconditionally include gc_priv.h in solaris_pthreads.c, win32_threads.h,
aix_irix_threads.c, and solaris_threads.c to get thread definitions.
- Start marker threads in GC_thr_init, so that they get started even
if no other threads are ever started. (Oddly enough, the parallel
collector worked correctly, though not well, with no helper threads.)
- Go ahead and split large blocks in GC_allochblk_nth if GC_dont_gc
is set. (Thanks to Alexander Petrossian.)
- GC_PRINT_BACK_HEIGHT would deadlock with thread support.
- Let in_progress_space in backgraph.s grow dynamically.
- Fix README.solaris2. The GC_thr_init() hack doesn't work anymore.
- Convert GC_finalizer_mem_freed to bytes in allchblk.c.
- Add missing declaration for GC_generic_malloc_words_small_inner.
Without it, s390x breaks. (Thanks to Ulrich Weigand.)
- Applied several MacOSX patches to support older tool chains.
(Thanks to Stefan Ring.)
- Bug fix for NetBSD/amd64. (Thanks to Marc Recht.) Add NetBSD/sh3
support. (Thanks to Uchiyama Yasushi.)
- Fixed an uninitialized variable in cordprnt.c. (Thanks to gcc for
providing the warning.)
- Eliminated some, but not all, gcc -Wall warnings.
- Changed some old style casts to reinterpret_cast in new_gc_alloc.h.
(Thanks to Dan Grayson.)
- GC_extend_size_map shouldn't adjust for GC_all_interior_pointers if
GC_DONT_ADD_BYTE_AT_END is set.
- Changed some (long) casts to (word) in preparation for win64.
(Thanks to Peter Colson.)
- Changed "int stack_size" declaration in pthread_support.c to use
size_t. (Only mattered with GC_ASSERTIONS enabled.)
- Added CRIS (etrax) support. (Thanks to Simon Posnjak and
Hans-Peter Nilsson.)
- Removed GC_IGNORE_FB frame buffer recognition, and replaced
it with a check that the mapping type is MEM_IMAGE.
In theory, this should work much better, but it is a high
risk change for win32. (Thanks to Ashley Bone for the crucial
experimental data behind this, and to Rutger Ovidus for
some further experiments.)
- Fixed print_block_list to print the correct kind number for
STUBBORN. (Thanks to Rutger Ovidus.)
- GC_allochblk_nth incremented GC_words_wasted by bytes rather than
words.
- Consider GC_words_wasted in GC_adj_words_allocd only if it is within
reason. (A hack to avoid some extremely unlikely scenarios in which
we manage to allocate only "wasted" space. 7.0 has a better fix.)
- Changed PowerPC GC_clear implementation to use lwsync instead of
eieio, since the documentation recommends against eieio, and
it seems to be incorrect if the preceding memory op is a load.
- Fixed print_block_list to print the correct kind number for
STUBBORN. (Thanks to Rutger Ovidus.)
- Have configure.in generate an error if it is asked to support
pthreads, but doesn't know how to.
- Added Kazuhiro Inaoka's patch for Renesas M32R support.
- Have the GNU build mechanism link with -ldl. Rename THREADLIBS
to THREADDLLIBS to reflect this. (Thanks to Sven Verdoolaege.)
- Added Hannes Mehnert's patch for FreeBSD/SPARC support.
- Merged some FreeBSD specific patches to threadlibs.c and dyn_load.c.
(Thanks tp John Merryweather Cooper.)
- Define MPROTECT_VDB on MACOSX only if threads are being used, since the
dirty page tracking mechanism uses threads. (This avoids an undefined
reference to _GC_darwin_register_mach_handler_thread.)
- By popular demand, use __libc symbols only if we are built with
USE_LIBC_PRIVATES, which is off by default, and not otherwise documented.
- Ignore GC_enable_incremental() requests when KEEP_BACK_PTRS is set.
The GC itself will dirty lots of pages in this cases, probably making
it counterproductive on all platforms. And the DARWIN port crashes.
Since GC6.4:
- Integrated Paolo Molaro's patch to deal with EINTR in sem_wait.
- Make GC_approx_sp() write to dummy location to ensure that stack
is grown here, when sp looks reasonable, rather than later, when
it might look like a bad memory reference. (Problem was never
observed that I know of. But on rereading the code it seemed
dubious.)
- Separate out GC_with_callee_saves_pushed and sometimes call
it from GC_suspend_handler in pthread_stop_world.c. Callee-save
register values sometimes failed to get traced under HP/UX on
PA-RISC. Linux/IA64 had the same problem, though non-stacked
callee-save registers seem to be so rarely used there that nobody
ever noticed.
- Integrated an ancient Darwin powerpc_darwin_machine_dep.s patch
from Andreas Tobler, which I had lost.
- Fix compare_and_exchange implementation for gcc/IA64 to deal with
pickier compiler versions.
- Fixed Itanium 32-bit ABI support (HP/UX). In particular, the
compare_and_exchange implementation didn't consider that possibility.
- Undefine GC_pthread_detach in win32_threads.c. (Thanks to
Tagliapietra Tommaso.)
- Fixed inclusion of frame.h for NETBSD in os_dep.c.
- Applied Dan Bonachea's patch to use mmap on AIX.
- Several fixes to resurrect the Irix port on recent OS versions.
- Change ALPHA to use LINUX_STACKBOTTOM.
- Change SPARC64/LINUX to also use LINUX_STACKBOTTOM. Deal with potential
bad values of __libc_stack_end on that platform. (Thanks to David Miller.)
- Relax gctest to allow larger heap if ALIGN_DOUBLE isn't set.
(Unnecessary in 7.0)
- Force a define of __STDC__=0 for the IBM compiler on AIX, so that
we get prototypes. (Unnecessary in 7.0)
- GC_INIT definition for AIX and CYGWIN referred to DATASTART and DATAEND
which are only defined in private include files.
- Integrated some small gcconfig.h patches from Dan Bonachea. Also
relaxed assertion about FreeBSD stack size in pthread_support.c.
- Integrated Andrew Begel's darwin_stop_world.c patch for 64-bit
support. This may need additional work.
- Avoided potentially infinite recursion in GC_save_callers if
the system backtrace calls malloc. The workaround currently requires
__thread support if this code is used with threads.
- Avoided another similar infinite recursion by conditionally
invoking GC_save_callers in alloc.c. (Thanks to Matthias Andree
for helping to track down both of these.)
- Removed all traces of aix_irix_threads.c. AIX and Irix now use
pthread_support.c and pthread_stop_world.c. The old code appeared
to be unreliable for AIX, and was not regularly maintained.
- On Irix, ignore segments with MA_FETCHOP or MA_NOTCACHED attributed;
they're not always safe to read.
- Fixed a previously vacuous assertion (diagnosed by the SGI compiler)
in GC_remove_from_fl.
- Fix stack_size assertion in GC_pthread_create.
- Fix assertion in GC_steal_mark_stack.
Since 6.5
- Fix CPU count detection for Irix and FreeBSD. (Thanks to Dan Bonachea.)
- Integrate Dan Bonachea's patch for the IBM XLC compiler on Darwin.
- Integrated Andreas Tobler's FreeBSD/PowerPC patch.
- Don't access the GC thread structure from the restart handler. It's
unsafe, since the handler may run too late. (Thanks to Ben Maurer for
tracking this down.)
- Applied Christian Thalinger's patch to change comment syntax in
alpha_mach_dep.S.
- Added test for GC_no_dls in GC_dyld_image_add for DARWIN. (Thanks to
Juan Jose Garcia Ripoli).
- Use LINUX_STACKBOTTOM for Linux/SH and LINUX/ARM. (Thanks to Sugioka
Toshinobu and Christian Thalinger.)
- Rewrote GC_parse_map_entry. This assumed a fixed column layout of
/proc/self/maps on Linux. This ceased to be true about 2 years ago.
The old code is probably quite problemetic with -DREDIRECT_MALLOC. It
is also used by default for IA64, though I haven't seen actual failures
there.
- More consistently define HBLKSIZE to 4096 on 64 bit architectures with
4K pages. (Thanks to Andrew Haley.)
- With win32 threads, GC_stop_world needs to acquire GC_write_cs. (Thanks
to Ben Hutchings for the observation and patch.)
- Move up struct callinfo declaration to make gcc 4.0.2. happy.
To do:
- The USE_MUNMAP code should really use a separate data structure
indexed by physical page to keep track of time since last use of
......
6.5 update:
I disabled incremental GC on Darwin in this version, since I couldn't
get gctest to pass when the GC was built as a dynamic library. Building
with -DMPROTECT_VDB (and threads) on the command line should get you
back to the old state. - HB
./configure --enable-cplusplus results in a "make check" failure, probably
because the ::delete override ends up in a separate dl, and Darwin dynamic
loader semantics appear to be such that this is not really visible to the
main program, unlike on ELF systems. Someone who understands dynamic
loading needs to lookat this. For now, gc_cpp.o needs to be linked
statically, if needed. - HB
Darwin/MacOSX Support - December 16, 2003
=========================================
......
......@@ -115,6 +115,7 @@ GC_IGNORE_FB[=<n>] - (Win32 only.) Try to avoid treating a mapped
are never honored, eliminating this risk for most,
but not all, applications. This feature is likely to disappear
if/when we find a less disgusting "solution".
IN VERSION 6.4 AND LATER, THIS SHOULD BE UNNECESSARY.
The following turn on runtime flags that are also program settable. Checked
only during initialization. We expect that they will usually be set through
......
......@@ -19,10 +19,10 @@ Linux threads. These should not be touched by the client program.
To use threads, you need to abide by the following requirements:
1) You need to use LinuxThreads (which are included in libc6).
1) You need to use LinuxThreads or NPTL (which are included in libc6).
The collector relies on some implementation details of the LinuxThreads
package. It is unlikely that this code will work on other
package. This code may not work on other
pthread implementations (in particular it will *not* work with
MIT pthreads).
......
......@@ -43,9 +43,7 @@ can result in unpleasant heap growth. But it seems better than the
race/deadlock issues we had before.
If solaris_threads are used on an X86 processor with malloc redirected to
GC_malloc, it is necessary to call GC_thr_init explicitly before forking the
first thread. (This avoids a deadlock arising from calling GC_thr_init
with the allocation lock held.)
GC_malloc a deadlock is likely to result.
It appears that there is a problem in using gc_cpp.h in conjunction with
Solaris threads and Sun's C++ runtime. Apparently the overloaded new operator
......
......@@ -96,17 +96,25 @@
/* Newer versions of GNU/Linux define this macro. We
* define it similarly for any ELF systems that don't. */
# ifndef ElfW
# ifdef __NetBSD__
# if ELFSIZE == 32
# if defined(FREEBSD)
# if __ELF_WORD_SIZE == 32
# define ElfW(type) Elf32_##type
# else
# define ElfW(type) Elf64_##type
# endif
# else
# if !defined(ELF_CLASS) || ELF_CLASS == ELFCLASS32
# define ElfW(type) Elf32_##type
# ifdef NETBSD
# if ELFSIZE == 32
# define ElfW(type) Elf32_##type
# else
# define ElfW(type) Elf64_##type
# endif
# else
# define ElfW(type) Elf64_##type
# if !defined(ELF_CLASS) || ELF_CLASS == ELFCLASS32
# define ElfW(type) Elf32_##type
# else
# define ElfW(type) Elf64_##type
# endif
# endif
# endif
# endif
......@@ -485,7 +493,6 @@ static struct link_map *
GC_FirstDLOpenedLinkMap()
{
ElfW(Dyn) *dp;
struct r_debug *r;
static struct link_map *cachedResult = 0;
if( _DYNAMIC == 0) {
......@@ -494,6 +501,12 @@ GC_FirstDLOpenedLinkMap()
if( cachedResult == 0 ) {
int tag;
for( dp = _DYNAMIC; (tag = dp->d_tag) != 0; dp++ ) {
/* FIXME: The DT_DEBUG header is not mandated by the */
/* ELF spec. This code appears to be dependent on */
/* idiosynchracies of older GNU tool chains. If this code */
/* fails for you, the real problem is probably that it is */
/* being used at all. You should be getting the */
/* dl_iterate_phdr version. */
if( tag == DT_DEBUG ) {
struct link_map *lm
= ((struct r_debug *)(dp->d_un.d_ptr))->r_map;
......@@ -618,7 +631,8 @@ void GC_register_dynamic_libraries()
}
for (i = 0; i < needed_sz; i++) {
flags = addr_map[i].pr_mflags;
if ((flags & (MA_BREAK | MA_STACK | MA_PHYS)) != 0) goto irrelevant;
if ((flags & (MA_BREAK | MA_STACK | MA_PHYS
| MA_FETCHOP | MA_NOTCACHED)) != 0) goto irrelevant;
if ((flags & (MA_READ | MA_WRITE)) != (MA_READ | MA_WRITE))
goto irrelevant;
/* The latter test is empirically useless in very old Irix */
......@@ -758,25 +772,27 @@ void GC_register_dynamic_libraries()
/* Should [start, start+len) be treated as a frame buffer */
/* and ignored? */
/* Unfortunately, we currently have no real way to tell */
/* automatically, and rely largely on user input. */
/* FIXME: If we had more data on this phenomenon (e.g. */
/* is start aligned to a MB multiple?) we should be able to */
/* do better. */
/* Unfortunately, we currently are not quite sure how to tell */
/* this automatically, and rely largely on user input. */
/* We expect that any mapping with type MEM_MAPPED (which */
/* apparently excludes library data sections) can be safely */
/* ignored. But we're too chicken to do that in this */
/* version. */
/* Based on a very limited sample, it appears that: */
/* - Frame buffer mappings appear as mappings of length */
/* 2**n MB - 192K. (We guess the 192K can vary a bit.) */
/* - Have a stating address at best 64K aligned. */
/* I'd love more information about the mapping, since I */
/* can't reproduce the problem. */
static GC_bool is_frame_buffer(ptr_t start, size_t len)
/* - Frame buffer mappings appear as mappings of large */
/* length, usually a bit less than a power of two. */
/* - The definition of "a bit less" in the above cannot */
/* be made more precise. */
/* - Have a starting address at best 64K aligned. */
/* - Have type == MEM_MAPPED. */
static GC_bool is_frame_buffer(ptr_t start, size_t len, DWORD tp)
{
static GC_bool initialized = FALSE;
# define MB (1024*1024)
# define DEFAULT_FB_MB 15
# define MIN_FB_MB 3
if (GC_disallow_ignore_fb) return FALSE;
if (GC_disallow_ignore_fb || tp != MEM_MAPPED) return FALSE;
if (!initialized) {
char * ignore_fb_string = GETENV("GC_IGNORE_FB");
......@@ -869,7 +885,7 @@ void GC_register_dynamic_libraries()
* !is_frame_buffer(p, buf.RegionSize, buf.Type)
* instead of just checking for MEM_IMAGE.
* If something breaks, change it back. */
&& buf.Type == MEM_IMAGE) {
&& buf.Type == MEM_IMAGE) {
# ifdef DEBUG_VIRTUALQUERY
GC_dump_meminfo(&buf);
# endif
......@@ -1125,21 +1141,22 @@ static const char *GC_dyld_name_for_hdr(struct mach_header *hdr) {
static void GC_dyld_image_add(struct mach_header* hdr, unsigned long slide) {
unsigned long start,end,i;
const struct section *sec;
if (GC_no_dls) return;
for(i=0;i<sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]);i++) {
sec = getsectbynamefromheader(
hdr,GC_dyld_sections[i].seg,GC_dyld_sections[i].sect);
if(sec == NULL || sec->size == 0) continue;
start = slide + sec->addr;
end = start + sec->size;
# ifdef DARWIN_DEBUG
GC_printf4("Adding section at %p-%p (%lu bytes) from image %s\n",
if(sec == NULL || sec->size == 0) continue;
start = slide + sec->addr;
end = start + sec->size;
# ifdef DARWIN_DEBUG
GC_printf4("Adding section at %p-%p (%lu bytes) from image %s\n",
start,end,sec->size,GC_dyld_name_for_hdr(hdr));
# endif
# endif
GC_add_roots((char*)start,(char*)end);
}
# ifdef DARWIN_DEBUG
GC_print_static_roots();
# endif
}
# ifdef DARWIN_DEBUG
GC_print_static_roots();
# endif
}
/* This should never be called by a thread holding the lock */
......@@ -1152,15 +1169,15 @@ static void GC_dyld_image_remove(struct mach_header* hdr, unsigned long slide) {
if(sec == NULL || sec->size == 0) continue;
start = slide + sec->addr;
end = start + sec->size;
# ifdef DARWIN_DEBUG
# ifdef DARWIN_DEBUG
GC_printf4("Removing section at %p-%p (%lu bytes) from image %s\n",
start,end,sec->size,GC_dyld_name_for_hdr(hdr));
# endif
GC_remove_roots((char*)start,(char*)end);
}
# ifdef DARWIN_DEBUG
GC_print_static_roots();
# endif
# ifdef DARWIN_DEBUG
GC_print_static_roots();
# endif
}
void GC_register_dynamic_libraries() {
......
......@@ -43,6 +43,8 @@ DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
$(srcdir)/gc_ext_config.h.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
$(top_srcdir)/../config/depstand.m4 \
$(top_srcdir)/../config/lead-dot.m4 \
$(top_srcdir)/../config/no-executables.m4 \
$(top_srcdir)/../libtool.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
......
......@@ -55,7 +55,7 @@
# include <gc_config.h>
# include "gc_config_macros.h"
# if defined(__STDC__) || defined(__cplusplus)
# if defined(__STDC__) || defined(__cplusplus) || defined(_AIX)
# define GC_PROTO(args) args
typedef void * GC_PTR;
# define GC_CONST const
......@@ -214,7 +214,7 @@ GC_API GC_word GC_free_space_divisor;
/* least N/GC_free_space_divisor bytes between */
/* collections, where N is the heap size plus */
/* a rough estimate of the root set size. */
/* Initially, GC_free_space_divisor = 4. */
/* Initially, GC_free_space_divisor = 3. */
/* Increasing its value will use less space */
/* but more collection time. Decreasing it */
/* will appreciably decrease collection time */
......@@ -340,6 +340,9 @@ GC_API void GC_end_stubborn_change GC_PROTO((GC_PTR));
/* the base of the user object. */
/* Return 0 if displaced_pointer doesn't point to within a valid */
/* object. */
/* Note that a deallocated object in the garbage collected heap */
/* may be considered valid, even if it has been deallocated with */
/* GC_free. */
GC_API GC_PTR GC_base GC_PROTO((GC_PTR displaced_pointer));
/* Given a pointer to the base of an object, return its size in bytes. */
......@@ -877,7 +880,7 @@ GC_API GC_PTR GC_is_valid_displacement GC_PROTO((GC_PTR p));
/* Safer assignment of a pointer to a nonstack location. */
#ifdef GC_DEBUG
# ifdef __STDC__
# if defined(__STDC__) || defined(_AIX)
# define GC_PTR_STORE(p, q) \
(*(void **)GC_is_visible(p) = GC_is_valid_displacement(q))
# else
......@@ -972,12 +975,32 @@ extern void GC_thr_init GC_PROTO((void));/* Needed for Solaris/X86 */
# define GC_INIT() { extern end, etext; \
GC_noop(&end, &etext); }
#else
# if defined(__CYGWIN32__) && defined(GC_DLL) || defined (_AIX)
# if defined(__CYGWIN32__) || defined (_AIX)
/*
* Similarly gnu-win32 DLLs need explicit initialization from
* the main program, as does AIX.
*/
# define GC_INIT() { GC_add_roots(DATASTART, DATAEND); }
# ifdef __CYGWIN32__
extern int _data_start__[];
extern int _data_end__[];
extern int _bss_start__[];
extern int _bss_end__[];
# define GC_MAX(x,y) ((x) > (y) ? (x) : (y))
# define GC_MIN(x,y) ((x) < (y) ? (x) : (y))
# define GC_DATASTART ((GC_PTR) GC_MIN(_data_start__, _bss_start__))
# define GC_DATAEND ((GC_PTR) GC_MAX(_data_end__, _bss_end__))
# ifdef GC_DLL
# define GC_INIT() { GC_add_roots(GC_DATASTART, GC_DATAEND); }
# else
# define GC_INIT()
# endif
# endif
# if defined(_AIX)
extern int _data[], _end[];
# define GC_DATASTART ((GC_PTR)((ulong)_data))
# define GC_DATAEND ((GC_PTR)((ulong)_end))
# define GC_INIT() { GC_add_roots(GC_DATASTART, GC_DATAEND); }
# endif
# else
# if defined(__APPLE__) && defined(__MACH__) || defined(GC_WIN32_THREADS)
# define GC_INIT() { GC_init(); }
......
......@@ -59,6 +59,10 @@
# define GC_DGUX386_THREADS
# define GC_PTHREADS
# endif
# if defined(_AIX)
# define GC_AIX_THREADS
# define GC_PTHREADS
# endif
#endif /* GC_THREADS */
#if defined(GC_THREADS) && !defined(GC_PTHREADS) && \
......
......@@ -74,7 +74,7 @@ cycle, then that's considered a storage leak, and neither will be
collectable. See the interface gc.h for low-level facilities for
handling such cycles of objects with clean-up.
The collector cannot guarrantee that it will find all inaccessible
The collector cannot guarantee that it will find all inaccessible
objects. In practice, it finds almost all of them.
......
......@@ -109,7 +109,7 @@ enum { GC_byte_alignment = 8 };
enum { GC_word_alignment = GC_byte_alignment/GC_bytes_per_word };
inline void * &GC_obj_link(void * p)
{ return *(void **)p; }
{ return *reinterpret_cast<void **>(p); }
// Compute a number of words >= n+1 bytes.
// The +1 allows for pointers one past the end.
......@@ -228,7 +228,7 @@ class single_client_gc_alloc_template {
} else {
flh = GC_objfreelist_ptr + nwords;
GC_obj_link(p) = *flh;
memset((char *)p + GC_bytes_per_word, 0,
memset(reinterpret_cast<char *>(p) + GC_bytes_per_word, 0,
GC_bytes_per_word * (nwords - 1));
*flh = p;
GC_aux::GC_mem_recently_freed += nwords;
......@@ -352,9 +352,9 @@ class simple_alloc<T, alloc> { \
public: \
static T *allocate(size_t n) \
{ return 0 == n? 0 : \
(T*) alloc::ptr_free_allocate(n * sizeof (T)); } \
reinterpret_cast<T*>(alloc::ptr_free_allocate(n * sizeof (T))); } \
static T *allocate(void) \
{ return (T*) alloc::ptr_free_allocate(sizeof (T)); } \
{ return reinterpret_cast<T*>(alloc::ptr_free_allocate(sizeof (T))); } \
static void deallocate(T *p, size_t n) \
{ if (0 != n) alloc::ptr_free_deallocate(p, n * sizeof (T)); } \
static void deallocate(T *p) \
......
......@@ -108,7 +108,7 @@ extern hdr * GC_invalid_header; /* header for an imaginary block */
/* Analogous to GET_HDR, except that in the case of large objects, it */
/* Returns the header for the object beginning, and updates p. */
/* Returns &GC_bad_header instead of 0. All of this saves a branch */
/* Returns GC_invalid_header instead of 0. All of this saves a branch */
/* in the fast path. */
# define HC_GET_HDR(p, hhdr, source) \
{ \
......
......@@ -139,6 +139,25 @@
# define GC_TEST_AND_SET_DEFINED
# endif
# if defined(POWERPC)
# if CPP_WORDSZ == 64
inline static int GC_test_and_set(volatile unsigned int *addr) {
unsigned long oldval;
unsigned long temp = 1; /* locked value */
__asm__ __volatile__(
"1:\tldarx %0,0,%3\n" /* load and reserve */
"\tcmpdi %0, 0\n" /* if load is */
"\tbne 2f\n" /* non-zero, return already set */
"\tstdcx. %2,0,%1\n" /* else store conditional */
"\tbne- 1b\n" /* retry if lost reservation */
"\tsync\n" /* import barrier */
"2:\t\n" /* oldval is zero if we set */
: "=&r"(oldval), "=p"(addr)
: "r"(temp), "1"(addr)
: "cr0","memory");
return (int)oldval;
}
# else
inline static int GC_test_and_set(volatile unsigned int *addr) {
int oldval;
int temp = 1; /* locked value */
......@@ -156,12 +175,13 @@
: "cr0","memory");
return oldval;
}
# define GC_TEST_AND_SET_DEFINED
inline static void GC_clear(volatile unsigned int *addr) {
__asm__ __volatile__("eieio" : : : "memory");
*(addr) = 0;
}
# define GC_CLEAR_DEFINED
# endif
# define GC_TEST_AND_SET_DEFINED
inline static void GC_clear(volatile unsigned int *addr) {
__asm__ __volatile__("lwsync" : : : "memory");
*(addr) = 0;
}
# define GC_CLEAR_DEFINED
# endif
# if defined(ALPHA)
inline static int GC_test_and_set(volatile unsigned int * addr)
......@@ -282,6 +302,8 @@
# define GC_test_and_set(addr) test_and_set((void *)addr,1)
# endif
# else
# include <sgidefs.h>
# include <mutex.h>
# define GC_test_and_set(addr) __test_and_set32((void *)addr,1)
# define GC_clear(addr) __lock_release(addr);
# define GC_CLEAR_DEFINED
......@@ -354,7 +376,7 @@
# endif
# if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
&& !defined(GC_IRIX_THREADS) && !defined(GC_WIN32_THREADS)
&& !defined(GC_WIN32_THREADS)
# define NO_THREAD (pthread_t)(-1)
# include <pthread.h>
# if defined(PARALLEL_MARK)
......@@ -401,6 +423,29 @@
# if defined(POWERPC)
# if !defined(GENERIC_COMPARE_AND_SWAP)
# if CPP_WORDSZ == 64
/* Returns TRUE if the comparison succeeded. */
inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr,
GC_word old, GC_word new_val)
{
unsigned long result, dummy;
__asm__ __volatile__(
"1:\tldarx %0,0,%5\n"
"\tcmpd %0,%4\n"
"\tbne 2f\n"
"\tstdcx. %3,0,%2\n"
"\tbne- 1b\n"
"\tsync\n"
"\tli %1, 1\n"
"\tb 3f\n"
"2:\tli %1, 0\n"
"3:\t\n"
: "=&r" (dummy), "=r" (result), "=p" (addr)
: "r" (new_val), "r" (old), "2"(addr)
: "cr0","memory");
return (GC_bool) result;
}
# else
/* Returns TRUE if the comparison succeeded. */
inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr,
GC_word old, GC_word new_val)
......@@ -422,6 +467,7 @@
: "cr0","memory");
return (GC_bool) result;
}
# endif
# endif /* !GENERIC_COMPARE_AND_SWAP */
inline static void GC_memory_barrier()
{
......@@ -598,33 +644,6 @@
extern pthread_t GC_mark_lock_holder;
# endif
# endif /* GC_PTHREADS with linux_threads.c implementation */
# if defined(GC_IRIX_THREADS)
# include <pthread.h>
/* This probably should never be included, but I can't test */
/* on Irix anymore. */
# include <mutex.h>
extern volatile unsigned int GC_allocate_lock;
/* This is not a mutex because mutexes that obey the (optional) */
/* POSIX scheduling rules are subject to convoys in high contention */
/* applications. This is basically a spin lock. */
extern pthread_t GC_lock_holder;
extern void GC_lock(void);
/* Allocation lock holder. Only set if acquired by client through */
/* GC_call_with_alloc_lock. */
# define SET_LOCK_HOLDER() GC_lock_holder = pthread_self()
# define NO_THREAD (pthread_t)(-1)
# define UNSET_LOCK_HOLDER() GC_lock_holder = NO_THREAD
# define I_HOLD_LOCK() (pthread_equal(GC_lock_holder, pthread_self()))
# define LOCK() { if (GC_test_and_set(&GC_allocate_lock)) GC_lock(); }
# define UNLOCK() GC_clear(&GC_allocate_lock);
extern VOLATILE GC_bool GC_collecting;
# define ENTER_GC() \
{ \
GC_collecting = 1; \
}
# define EXIT_GC() GC_collecting = 0;
# endif /* GC_IRIX_THREADS */
# if defined(GC_WIN32_THREADS)
# if defined(GC_PTHREADS)
# include <pthread.h>
......
......@@ -262,17 +262,6 @@ typedef char * ptr_t; /* A generic pointer to which we can add */
/* */
/*********************************/
#ifdef SAVE_CALL_CHAIN
/* Fill in the pc and argument information for up to NFRAMES of my */
/* callers. Ignore my frame and my callers frame. */
struct callinfo;
void GC_save_callers GC_PROTO((struct callinfo info[NFRAMES]));
void GC_print_callers GC_PROTO((struct callinfo info[NFRAMES]));
#endif
#ifdef NEED_CALLINFO
struct callinfo {
word ci_pc; /* Caller, not callee, pc */
......@@ -286,6 +275,16 @@ void GC_print_callers GC_PROTO((struct callinfo info[NFRAMES]));
};
#endif
#ifdef SAVE_CALL_CHAIN
/* Fill in the pc and argument information for up to NFRAMES of my */
/* callers. Ignore my frame and my callers frame. */
void GC_save_callers GC_PROTO((struct callinfo info[NFRAMES]));
void GC_print_callers GC_PROTO((struct callinfo info[NFRAMES]));
#endif
/*********************************/
/* */
......
......@@ -55,7 +55,7 @@
# endif
/* And one for FreeBSD: */
# if defined(__FreeBSD__)
# if defined(__FreeBSD__) && !defined(FREEBSD)
# define FREEBSD
# endif
......@@ -97,6 +97,10 @@
# define ARM32
# define mach_type_known
# endif
# if defined(NETBSD) && defined(__sh__)
# define SH
# define mach_type_known
# endif
# if defined(vax)
# define VAX
# ifdef ultrix
......@@ -167,7 +171,7 @@
# define mach_type_known
# endif
# if defined(sparc) && defined(unix) && !defined(sun) && !defined(linux) \
&& !defined(__OpenBSD__) && !(__NetBSD__)
&& !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__FreeBSD__)
# define SPARC
# define DRSNX
# define mach_type_known
......@@ -198,14 +202,16 @@
# if defined(_PA_RISC1_0) || defined(_PA_RISC1_1) || defined(_PA_RISC2_0) \
|| defined(hppa) || defined(__hppa__)
# define HP_PA
# ifndef LINUX
# if !defined(LINUX) && !defined(HPUX)
# define HPUX
# endif
# define mach_type_known
# endif
# if defined(__ia64) && defined(_HPUX_SOURCE)
# define IA64
# define HPUX
# ifndef HPUX
# define HPUX
# endif
# define mach_type_known
# endif
# if defined(__BEOS__) && defined(_X86_)
......@@ -235,7 +241,8 @@
# endif
# define mach_type_known
# endif
# if defined(LINUX) && (defined(powerpc) || defined(__powerpc__) || defined(powerpc64) || defined(__powerpc64__))
# if defined(LINUX) && (defined(powerpc) || defined(__powerpc__) || \
defined(powerpc64) || defined(__powerpc64__))
# define POWERPC
# define mach_type_known
# endif
......@@ -293,11 +300,11 @@
# define DARWIN
# define POWERPC
# define mach_type_known
# endif
# if defined(__APPLE__) && defined(__MACH__) && defined(__i386__)
# define DARWIN
# define I386
# else
# if defined(__i386__)
# define I386
--> Not really supported, but at least we recognize it.
# endif
# endif
# if defined(NeXT) && defined(mc68000)
# define M68K
......@@ -326,6 +333,10 @@
# define X86_64
# define mach_type_known
# endif
# if defined(FREEBSD) && defined(__sparc__)
# define SPARC
# define mach_type_known
#endif
# if defined(bsdi) && (defined(i386) || defined(__i386__))
# define I386
# define BSDI
......@@ -486,6 +497,9 @@
/* POWERPC ==> IBM/Apple PowerPC */
/* (MACOS(<=9),DARWIN(incl.MACOSX),*/
/* LINUX, NETBSD, NOSYS variants) */
/* Handles 32 and 64-bit variants. */
/* AIX should be handled here, but */
/* that's called an RS6000. */
/* CRIS ==> Axis Etrax */
/* M32R ==> Renesas M32R */
......@@ -493,12 +507,12 @@
/*
* For each architecture and OS, the following need to be defined:
*
* CPP_WORD_SZ is a simple integer constant representing the word size.
* CPP_WORDSZ is a simple integer constant representing the word size.
* in bits. We assume byte addressibility, where a byte has 8 bits.
* We also assume CPP_WORD_SZ is either 32 or 64.
* We also assume CPP_WORDSZ is either 32 or 64.
* (We care about the length of pointers, not hardware
* bus widths. Thus a 64 bit processor with a C compiler that uses
* 32 bit pointers should use CPP_WORD_SZ of 32, not 64. Default is 32.)
* 32 bit pointers should use CPP_WORDSZ of 32, not 64. Default is 32.)
*
* MACH_TYPE is a string representation of the machine type.
* OS_TYPE is analogous for the OS.
......@@ -615,7 +629,8 @@
*/
# if defined(__GNUC__) && ((__GNUC__ >= 3) || \
(__GNUC__ == 2 && __GNUC_MINOR__ >= 8)) \
&& !defined(__INTEL_COMPILER)
&& !defined(__INTEL_COMPILER) \
&& !defined(__PATHCC__)
# define HAVE_BUILTIN_UNWIND_INIT
# endif
......@@ -740,7 +755,7 @@
# endif
# endif
# ifdef POWERPC
# if defined(POWERPC)
# define MACH_TYPE "POWERPC"
# ifdef MACOS
# define ALIGNMENT 2 /* Still necessary? Could it be 4? */
......@@ -753,10 +768,12 @@
# define DATAEND /* not needed */
# endif
# ifdef LINUX
# if (defined (powerpc64) || defined(__powerpc64__))
# if defined(__powerpc64__)
# define ALIGNMENT 8
# define CPP_WORDSZ 64
# define HBLKSIZE 4096
# ifndef HBLKSIZE
# define HBLKSIZE 4096
# endif
# else
# define ALIGNMENT 4
# endif
......@@ -770,7 +787,7 @@
# define DATAEND (_end)
# endif
# ifdef DARWIN
# if (defined (__ppc64__))
# ifdef __ppc64__
# define ALIGNMENT 8
# define CPP_WORDSZ 64
# else
......@@ -787,8 +804,10 @@
# define USE_MMAP_ANON
# define USE_ASM_PUSH_REGS
/* This is potentially buggy. It needs more testing. See the comments in
os_dep.c */
# define MPROTECT_VDB
os_dep.c. It relies on threads to track writes. */
# ifdef GC_DARWIN_THREADS
/* # define MPROTECT_VDB -- diabled for now. May work for some apps. */
# endif
# include <unistd.h>
# define GETPAGESIZE() getpagesize()
# if defined(USE_PPC_PREFETCH) && defined(__GNUC__)
......@@ -975,6 +994,23 @@
# define DATASTART ((ptr_t)(etext))
# endif
# endif
# ifdef FREEBSD
# define OS_TYPE "FREEBSD"
# define SIG_SUSPEND SIGUSR1
# define SIG_THR_RESTART SIGUSR2
# define FREEBSD_STACKBOTTOM
# ifdef __ELF__
# define DYNAMIC_LOADING
# endif
extern char etext[];
extern char edata[];
extern char end[];
# define NEED_FIND_LIMIT
# define DATASTART ((ptr_t)(&etext))
# define DATAEND (GC_find_limit (DATASTART, TRUE))
# define DATASTART2 ((ptr_t)(&edata))
# define DATAEND2 ((ptr_t)(&end))
# endif
# endif
# ifdef I386
......@@ -1158,26 +1194,8 @@
# endif
# ifdef CYGWIN32
# define OS_TYPE "CYGWIN32"
extern int _data_start__[];
extern int _data_end__[];
extern int _bss_start__[];
extern int _bss_end__[];
/* For binutils 2.9.1, we have */
/* DATASTART = _data_start__ */
/* DATAEND = _bss_end__ */
/* whereas for some earlier versions it was */
/* DATASTART = _bss_start__ */
/* DATAEND = _data_end__ */
/* To get it right for both, we take the */
/* minumum/maximum of the two. */
# ifndef MAX
# define MAX(x,y) ((x) > (y) ? (x) : (y))
# endif
# ifndef MIN
# define MIN(x,y) ((x) < (y) ? (x) : (y))
# endif
# define DATASTART ((ptr_t) MIN(_data_start__, _bss_start__))
# define DATAEND ((ptr_t) MAX(_data_end__, _bss_end__))
# define DATASTART ((ptr_t)GC_DATASTART) /* From gc.h */
# define DATAEND ((ptr_t)GC_DATAEND)
# undef STACK_GRAN
# define STACK_GRAN 0x10000
# define HEURISTIC1
......@@ -1421,6 +1439,8 @@
# define CPP_WORDSZ 32
# define STACKBOTTOM ((ptr_t)((ulong)&errno))
# endif
# define USE_MMAP
# define USE_MMAP_ANON
/* From AIX linker man page:
_text Specifies the first location of the program.
_etext Specifies the first location after the program.
......@@ -1728,7 +1748,7 @@
# define USE_GENERIC_PUSH_REGS
# ifdef UTS4
# define OS_TYPE "UTS4"
extern int etext[];
extern int etext[];
extern int _etext[];
extern int _end[];
extern ptr_t GC_SysVGetDataStart();
......@@ -1742,18 +1762,20 @@
# define MACH_TYPE "S390"
# define USE_GENERIC_PUSH_REGS
# ifndef __s390x__
# define ALIGNMENT 4
# define CPP_WORDSZ 32
# define ALIGNMENT 4
# define CPP_WORDSZ 32
# else
# define ALIGNMENT 8
# define CPP_WORDSZ 64
# define HBLKSIZE 4096
# define ALIGNMENT 8
# define CPP_WORDSZ 64
# endif
# ifndef HBLKSIZE
# define HBLKSIZE 4096
# endif
# ifdef LINUX
# define OS_TYPE "LINUX"
# define LINUX_STACKBOTTOM
# define DYNAMIC_LOADING
extern int __data_start[];
extern int __data_start[];
# define DATASTART ((ptr_t)(__data_start))
extern int _end[];
# define DATAEND (_end)
......@@ -1859,6 +1881,13 @@
extern int _end[];
# define DATAEND (_end)
# endif
# ifdef NETBSD
# define OS_TYPE "NETBSD"
# define HEURISTIC2
# define DATASTART GC_data_start
# define USE_GENERIC_PUSH_REGS
# define DYNAMIC_LOADING
# endif
# endif
# ifdef SH4
......@@ -2107,7 +2136,8 @@
# define THREADS
# endif
# if defined(HP_PA) || defined(M88K) || defined(POWERPC) && !defined(DARWIN) \
# if defined(HP_PA) || defined(M88K) \
|| defined(POWERPC) && !defined(DARWIN) \
|| defined(LINT) || defined(MSWINCE) || defined(ARM32) || defined(CRIS) \
|| (defined(I386) && defined(__LCC__))
/* Use setjmp based hack to mark from callee-save registers. */
......@@ -2249,7 +2279,7 @@
# else
# if defined(AMIGA) && defined(GC_AMIGA_FASTALLOC)
extern void *GC_amiga_get_mem(size_t size);
# define GET_MEM(bytes) HBLKPTR((size_t) \
# define GET_MEM(bytes) HBLKPTR((size_t) \
GC_amiga_get_mem((size_t)bytes + GC_page_size) \
+ GC_page_size-1)
# else
......@@ -2265,4 +2295,10 @@
#endif /* GC_PRIVATE_H */
#if defined(_AIX) && !defined(__GNUC__) && !defined(__STDC__)
/* IBMs xlc compiler doesn't appear to follow the convention of */
/* defining __STDC__ to be zero in extended mode. */
# define __STDC__ 0
#endif
# endif /* GCCONFIG_H */
......@@ -2,7 +2,6 @@
#define GC_PTHREAD_STOP_WORLD_H
struct thread_stop_info {
int signal;
word last_stop_count; /* GC_last_stop_count value when thread */
/* last successfully handled a suspend */
/* signal. */
......
......@@ -4,7 +4,7 @@
# include "private/gc_priv.h"
# if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
&& !defined(GC_IRIX_THREADS) && !defined(GC_WIN32_THREADS)
&& !defined(GC_WIN32_THREADS)
#if defined(GC_DARWIN_THREADS)
# include "private/darwin_stop_world.h"
......
......@@ -27,6 +27,10 @@
# endif
# endif
#if defined(RS6000) || defined(POWERPC)
# include <ucontext.h>
#endif
#if defined(__MWERKS__) && !defined(POWERPC)
asm static void PushMacRegisters()
......@@ -413,6 +417,13 @@ ptr_t arg;
/* the stack. */
__builtin_unwind_init();
# else /* !HAVE_BUILTIN_UNWIND_INIT */
# if defined(RS6000) || defined(POWERPC)
/* FIXME: RS6000 means AIX. */
/* This should probably be used in all Posix/non-gcc */
/* settings. We defer that change to minimize risk. */
ucontext_t ctxt;
getcontext(&ctxt);
# else
/* Generic code */
/* The idea is due to Parag Patel at HP. */
/* We're not sure whether he would like */
......@@ -426,7 +437,7 @@ ptr_t arg;
for (; (char *)i < lim; i++) {
*i = 0;
}
# if defined(POWERPC) || defined(MSWIN32) || defined(MSWINCE) \
# if defined(MSWIN32) || defined(MSWINCE) \
|| defined(UTS4) || defined(LINUX) || defined(EWS4800)
(void) setjmp(regs);
# else
......@@ -435,15 +446,16 @@ ptr_t arg;
/* SUSV3, setjmp() may or may not save signal mask. */
/* _setjmp won't, but is less portable. */
# endif
# endif /* !AIX ... */
# endif /* !HAVE_BUILTIN_UNWIND_INIT */
# elif defined(PTHREADS) && !defined(MSWIN32) /* !USE_GENERIC_PUSH_REGS */
/* We may still need this to save thread contexts. */
/* This should probably be used in all Posix/non-gcc */
/* settings. We defer that change to minimize risk. */
ucontext_t ctxt;
getcontext(&ctxt);
# else /* Shouldn't be needed */
ABORT("Unexpected call to GC_with_callee_saves_pushed");
# else
# if defined(PTHREADS) && !defined(MSWIN32) /* !USE_GENERIC_PUSH_REGS */
/* We may still need this to save thread contexts. */
ucontext_t ctxt;
getcontext(&ctxt);
# else /* Shouldn't be needed */
ABORT("Unexpected call to GC_with_callee_saves_pushed");
# endif
# endif
# if (defined(SPARC) && !defined(HAVE_BUILTIN_UNWIND_INIT)) \
|| defined(IA64)
......@@ -480,7 +492,7 @@ ptr_t cold_gc_frame;
/* the stack. Return sp. */
# ifdef SPARC
asm(" .seg \"text\"");
# if defined(SVR4) || defined(NETBSD)
# if defined(SVR4) || defined(NETBSD) || defined(FREEBSD)
asm(" .globl GC_save_regs_in_stack");
asm("GC_save_regs_in_stack:");
asm(" .type GC_save_regs_in_stack,#function");
......
......@@ -172,7 +172,8 @@ int obj_kind;
# endif /* REDIRECT_REALLOC */
/* The same thing, except caller does not hold allocation lock. */
/* Allocate memory such that only pointers to near the */
/* beginning of the object are considered. */
/* We avoid holding allocation lock while we clear memory. */
ptr_t GC_generic_malloc_ignore_off_page(lb, k)
register size_t lb;
......
......@@ -858,9 +858,9 @@ mse * GC_steal_mark_stack(mse * low, mse * high, mse * local,
++top;
top -> mse_descr = descr;
top -> mse_start = p -> mse_start;
GC_ASSERT( top -> mse_descr & GC_DS_TAGS != GC_DS_LENGTH ||
top -> mse_descr < GC_greatest_plausible_heap_addr
- GC_least_plausible_heap_addr);
GC_ASSERT( (top -> mse_descr & GC_DS_TAGS) != GC_DS_LENGTH ||
top -> mse_descr < (ptr_t)GC_greatest_plausible_heap_addr
- (ptr_t)GC_least_plausible_heap_addr);
/* If this is a big object, count it as */
/* size/256 + 1 objects. */
++i;
......@@ -1450,8 +1450,8 @@ void GC_push_all_eager(bottom, top)
ptr_t bottom;
ptr_t top;
{
word * b = (word *)(((long) bottom + ALIGNMENT-1) & ~(ALIGNMENT-1));
word * t = (word *)(((long) top) & ~(ALIGNMENT-1));
word * b = (word *)(((word) bottom + ALIGNMENT-1) & ~(ALIGNMENT-1));
word * t = (word *)(((word) top) & ~(ALIGNMENT-1));
register word *p;
register word q;
register word *lim;
......
......@@ -246,7 +246,7 @@ void *arg2;
byte_sz = WORDS_TO_BYTES(word_sz);
if (GC_all_interior_pointers) {
/* We need one extra byte; don't fill in GC_size_map[byte_sz] */
byte_sz--;
byte_sz -= EXTRA_BYTES;
}
for (j = low_limit; j <= byte_sz; j++) GC_size_map[j] = word_sz;
......@@ -805,7 +805,10 @@ void GC_init_inner()
void GC_enable_incremental GC_PROTO(())
{
# if !defined(SMALL_CONFIG)
# if !defined(SMALL_CONFIG) && !defined(KEEP_BACK_PTRS)
/* If we are keeping back pointers, the GC itself dirties all */
/* pages on which objects have been marked, making */
/* incremental GC pointless. */
if (!GC_find_leak) {
DCL_LOCK_STATE;
......
......@@ -12,7 +12,7 @@
; GC_push_regs function. Under some optimization levels GCC will clobber
; some of the non-volatile registers before we get a chance to save them
; therefore, this can't be inline asm.
; therefore, this cannot be inline asm.
.text
.align LOG2_GPR_BYTES
......
#include "private/pthread_support.h"
#if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
&& !defined(GC_IRIX_THREADS) && !defined(GC_WIN32_THREADS) \
&& !defined(GC_DARWIN_THREADS) && !defined(GC_AIX_THREADS)
&& !defined(GC_WIN32_THREADS) && !defined(GC_DARWIN_THREADS)
#include <signal.h>
#include <semaphore.h>
#include <errno.h>
#include <unistd.h>
#include <sys/time.h>
#ifndef HPUX
# include <sys/select.h>
/* Doesn't exist on HP/UX 11.11. */
#endif
#if DEBUG_THREADS
......@@ -67,7 +71,22 @@ void GC_remove_allowed_signals(sigset_t *set)
static sigset_t suspend_handler_mask;
word GC_stop_count; /* Incremented at the beginning of GC_stop_world. */
volatile sig_atomic_t GC_stop_count;
/* Incremented at the beginning of GC_stop_world. */
volatile sig_atomic_t GC_world_is_stopped = FALSE;
/* FALSE ==> it is safe for threads to restart, i.e. */
/* they will see another suspend signal before they */
/* are expected to stop (unless they have voluntarily */
/* stopped). */
void GC_brief_async_signal_safe_sleep()
{
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 1000 * TIME_LIMIT / 2;
select(0, 0, 0, 0, &tv);
}
#ifdef GC_OSF1_THREADS
GC_bool GC_retry_signals = TRUE;
......@@ -108,7 +127,9 @@ extern void GC_with_callee_saves_pushed();
void GC_suspend_handler(int sig)
{
int old_errno = errno;
GC_with_callee_saves_pushed(GC_suspend_handler_inner, (ptr_t)(word)sig);
errno = old_errno;
}
#else
......@@ -116,7 +137,9 @@ void GC_suspend_handler(int sig)
/* in the signal handler frame. */
void GC_suspend_handler(int sig)
{
int old_errno = errno;
GC_suspend_handler_inner((ptr_t)(word)sig);
errno = old_errno;
}
#endif
......@@ -172,16 +195,26 @@ void GC_suspend_handler_inner(ptr_t sig_arg)
/* this thread a SIG_THR_RESTART signal. */
/* SIG_THR_RESTART should be masked at this point. Thus there */
/* is no race. */
do {
me->stop_info.signal = 0;
sigsuspend(&suspend_handler_mask); /* Wait for signal */
} while (me->stop_info.signal != SIG_THR_RESTART);
/* We do not continue until we receive a SIG_THR_RESTART, */
/* but we do not take that as authoritative. (We may be */
/* accidentally restarted by one of the user signals we */
/* don't block.) After we receive the signal, we use a */
/* primitive and expensive mechanism to wait until it's */
/* really safe to proceed. Under normal circumstances, */
/* this code should not be executed. */
sigsuspend(&suspend_handler_mask); /* Wait for signal */
while (GC_world_is_stopped && GC_stop_count == my_stop_count) {
GC_brief_async_signal_safe_sleep();
# if DEBUG_THREADS
GC_err_printf0("Sleeping in signal handler");
# endif
}
/* If the RESTART signal gets lost, we can still lose. That should be */
/* less likely than losing the SUSPEND signal, since we don't do much */
/* between the sem_post and sigsuspend. */
/* We'd need more handshaking to work around that, since we don't want */
/* to accidentally leave a RESTART signal pending, thus causing us to */
/* continue prematurely in a future round. */
/* We'd need more handshaking to work around that. */
/* Simply dropping the sigsuspend call should be safe, but is unlikely */
/* to be efficient. */
#if DEBUG_THREADS
GC_printf1("Continuing 0x%lx\n", my_thread);
......@@ -191,20 +224,11 @@ void GC_suspend_handler_inner(ptr_t sig_arg)
void GC_restart_handler(int sig)
{
pthread_t my_thread = pthread_self();
GC_thread me;
if (sig != SIG_THR_RESTART) ABORT("Bad signal in suspend_handler");
/* Let the GC_suspend_handler() know that we got a SIG_THR_RESTART. */
/* The lookup here is safe, since I'm doing this on behalf */
/* of a thread which holds the allocation lock in order */
/* to stop the world. Thus concurrent modification of the */
/* data structure is impossible. */
me = GC_lookup_thread(my_thread);
me->stop_info.signal = SIG_THR_RESTART;
/*
** Note: even if we didn't do anything useful here,
** Note: even if we don't do anything useful here,
** it would still be necessary to have a signal handler,
** rather than ignoring the signals, otherwise
** the signals will not be delivered at all, and
......@@ -357,6 +381,7 @@ void GC_stop_world()
/* We should have previously waited for it to become zero. */
# endif /* PARALLEL_MARK */
++GC_stop_count;
GC_world_is_stopped = TRUE;
n_live_threads = GC_suspend_all();
if (GC_retry_signals) {
......@@ -390,10 +415,10 @@ void GC_stop_world()
}
for (i = 0; i < n_live_threads; i++) {
while (0 != (code = sem_wait(&GC_suspend_ack_sem))) {
if (errno != EINTR) {
GC_err_printf1("Sem_wait returned %ld\n", (unsigned long)code);
ABORT("sem_wait for handler failed");
}
if (errno != EINTR) {
GC_err_printf1("Sem_wait returned %ld\n", (unsigned long)code);
ABORT("sem_wait for handler failed");
}
}
}
# ifdef PARALLEL_MARK
......@@ -419,6 +444,7 @@ void GC_start_world()
GC_printf0("World starting\n");
# endif
GC_world_is_stopped = FALSE;
for (i = 0; i < THREAD_TABLE_SZ; i++) {
for (p = GC_threads[i]; p != 0; p = p -> next) {
if (p -> id != my_thread) {
......@@ -428,8 +454,7 @@ void GC_start_world()
#if DEBUG_THREADS
GC_printf1("Sending restart signal to 0x%lx\n", p -> id);
#endif
result = pthread_kill(p -> id, SIG_THR_RESTART);
result = pthread_kill(p -> id, SIG_THR_RESTART);
switch(result) {
case ESRCH:
/* Not really there anymore. Possible? */
......
......@@ -2,7 +2,7 @@
* Copyright (c) 1994 by Xerox Corporation. All rights reserved.
* Copyright (c) 1996 by Silicon Graphics. All rights reserved.
* Copyright (c) 1998 by Fergus Henderson. All rights reserved.
* Copyright (c) 2000-2001 by Hewlett-Packard Company. All rights reserved.
* Copyright (c) 2000-2004 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.
......@@ -51,8 +51,7 @@
# include "private/pthread_support.h"
# if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
&& !defined(GC_IRIX_THREADS) && !defined(GC_WIN32_THREADS) \
&& !defined(GC_AIX_THREADS)
&& !defined(GC_WIN32_THREADS)
# if defined(GC_HPUX_THREADS) && !defined(USE_PTHREAD_SPECIFIC) \
&& !defined(USE_COMPILER_TLS)
......@@ -69,7 +68,8 @@
# endif
# if (defined(GC_DGUX386_THREADS) || defined(GC_OSF1_THREADS) || \
defined(GC_DARWIN_THREADS)) && !defined(USE_PTHREAD_SPECIFIC)
defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS)) \
&& !defined(USE_PTHREAD_SPECIFIC)
# define USE_PTHREAD_SPECIFIC
# endif
......@@ -117,7 +117,7 @@
# include <semaphore.h>
#endif /* !GC_DARWIN_THREADS */
#if defined(GC_DARWIN_THREADS)
#if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS)
# include <sys/sysctl.h>
#endif /* GC_DARWIN_THREADS */
......@@ -840,9 +840,9 @@ int GC_get_nprocs()
/* We hold the allocation lock. */
void GC_thr_init()
{
# ifndef GC_DARWIN_THREADS
int dummy;
# endif
# ifndef GC_DARWIN_THREADS
int dummy;
# endif
GC_thread t;
if (GC_thr_initialized) return;
......@@ -874,14 +874,15 @@ void GC_thr_init()
# if defined(GC_HPUX_THREADS)
GC_nprocs = pthread_num_processors_np();
# endif
# if defined(GC_OSF1_THREADS)
# if defined(GC_OSF1_THREADS) || defined(GC_AIX_THREADS)
GC_nprocs = sysconf(_SC_NPROCESSORS_ONLN);
if (GC_nprocs <= 0) GC_nprocs = 1;
# endif
# if defined(GC_FREEBSD_THREADS)
GC_nprocs = 1;
# if defined(GC_IRIX_THREADS)
GC_nprocs = sysconf(_SC_NPROC_ONLN);
if (GC_nprocs <= 0) GC_nprocs = 1;
# endif
# if defined(GC_DARWIN_THREADS)
# if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS)
int ncpus = 1;
size_t len = sizeof(ncpus);
sysctl((int[2]) {CTL_HW, HW_NCPU}, 2, &ncpus, &len, NULL, 0);
......@@ -928,6 +929,8 @@ void GC_thr_init()
/* Disable true incremental collection, but generational is OK. */
GC_time_limit = GC_TIME_UNLIMITED;
}
/* If we are using a parallel marker, actually start helper threads. */
if (GC_parallel) start_mark_threads();
# endif
}
......@@ -944,10 +947,6 @@ void GC_init_parallel()
/* 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
if (GC_parallel) start_mark_threads();
# endif
/* Initialize thread local free lists if used. */
# if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL)
LOCK();
......@@ -1223,7 +1222,7 @@ WRAP_FUNC(pthread_create)(pthread_t *new_thread,
if (!GC_thr_initialized) GC_thr_init();
# ifdef GC_ASSERTIONS
{
int stack_size;
size_t stack_size;
if (NULL == attr) {
pthread_attr_t my_attr;
pthread_attr_init(&my_attr);
......@@ -1231,7 +1230,13 @@ WRAP_FUNC(pthread_create)(pthread_t *new_thread,
} else {
pthread_attr_getstacksize(attr, &stack_size);
}
GC_ASSERT(stack_size >= (8*HBLKSIZE*sizeof(word)));
# ifdef PARALLEL_MARK
GC_ASSERT(stack_size >= (8*HBLKSIZE*sizeof(word)));
# else
/* FreeBSD-5.3/Alpha: default pthread stack is 64K, */
/* HBLKSIZE=8192, sizeof(word)=8 */
GC_ASSERT(stack_size >= 65536);
# endif
/* Our threads may need to do some work for the GC. */
/* Ridiculously small threads won't work, and they */
/* probably wouldn't work anyway. */
......
......@@ -888,7 +888,7 @@ void GC_print_block_list()
{
struct Print_stats pstats;
GC_printf0("(kind(0=ptrfree,1=normal,2=unc.,3=stubborn):size_in_bytes, #_marks_set)\n");
GC_printf1("(kind(0=ptrfree,1=normal,2=unc.,%lu=stubborn):size_in_bytes, #_marks_set)\n", STUBBORN);
pstats.number_of_blocks = 0;
pstats.total_bytes = 0;
GC_apply_to_all_blocks(GC_print_block_descr, (word)&pstats);
......
......@@ -16,7 +16,7 @@
* Modified by Peter C. for Solaris Posix Threads.
*/
#include "private/gc_priv.h"
# include "private/gc_priv.h"
# if defined(GC_SOLARIS_PTHREADS)
# include <pthread.h>
......
......@@ -16,7 +16,7 @@
*/
/* Boehm, September 14, 1994 4:44 pm PDT */
#include "private/gc_priv.h"
# include "private/gc_priv.h"
# if defined(GC_SOLARIS_THREADS) || defined(GC_SOLARIS_PTHREADS)
# include "private/solaris_threads.h"
......@@ -248,8 +248,8 @@ static void stop_all_lwps()
for (i = 0; i < max_lwps; i++)
last_ids[i] = 0;
for (;;) {
if (syscall(SYS_ioctl, GC_main_proc_fd, PIOCSTATUS, &status) < 0)
ABORT("Main PIOCSTATUS failed");
if (syscall(SYS_ioctl, GC_main_proc_fd, PIOCSTATUS, &status) < 0)
ABORT("Main PIOCSTATUS failed");
if (status.pr_nlwp < 1)
ABORT("Invalid number of lwps returned by PIOCSTATUS");
if (status.pr_nlwp >= max_lwps) {
......@@ -262,7 +262,7 @@ static void stop_all_lwps()
for (i = 0; i < max_lwps; i++)
last_ids[i] = 0;
continue;
}
}
if (syscall(SYS_ioctl, GC_main_proc_fd, PIOCLWPIDS, GC_current_ids) < 0)
ABORT("PIOCLWPIDS failed");
changed = FALSE;
......
......@@ -1367,6 +1367,10 @@ void check_heap_stats()
max_heap_sz = 11000000;
}
# endif
# ifndef ALIGN_DOUBLE
/* We end up needing more small object pages. */
max_heap_sz += 2000000;
# endif
# ifdef GC_DEBUG
max_heap_sz *= 2;
# ifdef SAVE_CALL_CHAIN
......
......@@ -11,10 +11,17 @@ 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_SOLARIS_PTHREADS) \
|| defined(GC_SOLARIS_PTHREADS) \
|| defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS)
printf("-lpthread\n");
# endif
# if defined(GC_FREEBSD_THREADS)
# if (__FREEBSD_version >= 500000)
printf("-lpthread\n");
# else
printf("-pthread\n");
# endif
# endif
# if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS)
printf("-lpthread -lrt\n");
# endif
......
......@@ -2,7 +2,7 @@
/* Eventually this one may become unnecessary. For now we need */
/* it to keep the old-style build process working. */
#define GC_TMP_VERSION_MAJOR 6
#define GC_TMP_VERSION_MINOR 3
#define GC_TMP_VERSION_MINOR 6
#define GC_TMP_ALPHA_VERSION GC_NOT_ALPHA
#ifndef GC_NOT_ALPHA
......
......@@ -11,6 +11,7 @@
# undef pthread_create
# undef pthread_sigmask
# undef pthread_join
# undef pthread_detach
# undef dlopen
# define DEBUG_CYGWIN_THREADS 0
......@@ -185,7 +186,7 @@ static void GC_delete_thread(DWORD thread_id) {
/* Must still be in_use, since nobody else can store our thread_id. */
i++) {}
if (i > my_max) {
WARN("Removing nonexisiting thread %ld\n", (GC_word)thread_id);
WARN("Removing nonexistent thread %ld\n", (GC_word)thread_id);
} else {
GC_delete_gc_thread(thread_table+i);
}
......@@ -232,6 +233,9 @@ void GC_push_thread_structures GC_PROTO((void))
# endif
}
/* Defined in misc.c */
extern CRITICAL_SECTION GC_write_cs;
void GC_stop_world()
{
DWORD thread_id = GetCurrentThreadId();
......@@ -240,6 +244,9 @@ void GC_stop_world()
if (!GC_thr_initialized) ABORT("GC_stop_world() called before GC_thr_init()");
GC_please_stop = TRUE;
# ifndef CYGWIN32
EnterCriticalSection(&GC_write_cs);
# endif /* !CYGWIN32 */
for (i = 0; i <= GC_get_max_thread_index(); i++)
if (thread_table[i].stack_base != 0
&& thread_table[i].id != thread_id) {
......@@ -270,6 +277,9 @@ void GC_stop_world()
# endif
thread_table[i].suspended = TRUE;
}
# ifndef CYGWIN32
LeaveCriticalSection(&GC_write_cs);
# endif /* !CYGWIN32 */
}
void GC_start_world()
......
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