Initial revision

From-SVN: r44969
This commit is contained in:
Tom Tromey 2001-08-17 18:39:15 +00:00
parent b38a75e57d
commit 61f38a77a0
15 changed files with 11927 additions and 0 deletions

597
boehm-gc/Makefile.direct Normal file
View File

@ -0,0 +1,597 @@
# This is the original manually generated Makefile. It may still be used
# to build the collector.
#
# Primary targets:
# gc.a - builds basic library
# c++ - adds C++ interface to library
# cords - adds cords (heavyweight strings) to library
# test - prints porting information, then builds basic version of gc.a,
# and runs some tests of collector and cords. Does not add cords or
# c++ interface to gc.a
# cord/de - builds dumb editor based on cords.
ABI_FLAG=
CC=cc $(ABI_FLAG)
CXX=g++ $(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.
srcdir= .
VPATH= $(srcdir)
CFLAGS= -O -I$(srcdir)/include -DATOMIC_UNCOLLECTABLE -DNO_SIGNALS -DNO_EXECUTE_PERMISSION -DSILENT -DALL_INTERIOR_POINTERS
# To build the parallel collector on Linux, add to the above:
# -DGC_LINUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC
# To build the parallel collector n a static library on HP/UX, add to the above:
# -DGC_HPUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC -DUSE_HPUX_TLS -D_POSIX_C_SOURCE=199506L
# HOSTCC and HOSTCFLAGS are used to build executables that will be run as
# part of the build process, i.e. on the build machine. These will usually
# be the same as CC and CFLAGS, except in a cross-compilation environment.
# Note that HOSTCFLAGS should include any -D flags that affect thread support.
HOSTCC=$(CC)
HOSTCFLAGS=$(CFLAGS)
# For dynamic library builds, it may be necessary to add flags to generate
# PIC code, e.g. -fPIC on Linux.
# Setjmp_test may yield overly optimistic results when compiled
# without optimization.
# These define arguments influence the collector configuration:
# -DSILENT disables statistics printing, and improves performance.
# -DFIND_LEAK causes GC_find_leak to be initially set.
# This causes the collector to assume that all inaccessible
# objects should have been explicitly deallocated, and reports exceptions.
# Finalization and the test program are not usable in this mode.
# -DGC_SOLARIS_THREADS enables support for Solaris (thr_) threads.
# (Clients should also define GC_SOLARIS_THREADS and then include
# gc.h before performing thr_ or dl* or GC_ operations.)
# Must also define -D_REENTRANT.
# -DGC_SOLARIS_PTHREADS enables support for Solaris pthreads.
# 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.
# -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
# initialization time.
# -DSMALL_CONFIG tries to tune the collector for small heap sizes,
# usually causing it to use less space in such situations.
# Incremental collection no longer works in this case.
# -DLARGE_CONFIG tunes the collector for unusually large heaps.
# Necessary for heaps larger than about 500 MB on most machines.
# Recommended for heaps larger than about 64 MB.
# -DDONT_ADD_BYTE_AT_END is meaningful only with -DALL_INTERIOR_POINTERS or
# GC_all_interior_pointers = 1. Normally -DALL_INTERIOR_POINTERS
# causes all objects to be padded so that pointers just past the end of
# an object can be recognized. This can be expensive. (The padding
# is normally more than one byte due to alignment constraints.)
# -DDONT_ADD_BYTE_AT_END disables the padding.
# -DNO_SIGNALS does not disable signals during critical parts of
# the GC process. This is no less correct than many malloc
# implementations, and it sometimes has a significant performance
# impact. However, it is dangerous for many not-quite-ANSI C
# programs that call things like printf in asynchronous signal handlers.
# This is on by default. Turning it off has not been extensively tested with
# compilers that reorder stores. It should have been.
# -DNO_EXECUTE_PERMISSION may cause some or all of the heap to not
# have execute permission, i.e. it may be impossible to execute
# code from the heap. Currently this only affects the incremental
# collector on UNIX machines. It may greatly improve its performance,
# since this may avoid some expensive cache synchronization.
# -DGC_NO_OPERATOR_NEW_ARRAY declares that the C++ compiler does not support
# the new syntax "operator new[]" for allocating and deleting arrays.
# See gc_cpp.h for details. No effect on the C part of the collector.
# This is defined implicitly in a few environments. Must also be defined
# by clients that use gc_cpp.h.
# -DREDIRECT_MALLOC=X causes malloc, realloc, and free to be defined
# as aliases for X, GC_realloc, and GC_free, respectively.
# Calloc is redefined in terms of the new malloc. X should
# be either GC_malloc or GC_malloc_uncollectable, or
# GC_debug_malloc_replacement. (The latter invokes GC_debug_malloc
# with dummy source location information, but still results in
# properly remembered call stacks on Linux/X86 and Solaris/SPARC.)
# The former is occasionally useful for working around leaks in code
# you don't want to (or can't) look at. It may not work for
# existing code, but it often does. Neither works on all platforms,
# since some ports use malloc or calloc to obtain system memory.
# (Probably works for UNIX, and win32.)
# -DREDIRECT_REALLOC=X causes GC_realloc to be redirected to X.
# The canonical use is -DREDIRECT_REALLOC=GC_debug_realloc_replacement,
# together with -DREDIRECT_MALLOC=GC_debug_malloc_replacement to
# generate leak reports with call stacks for both malloc and realloc.
# -DIGNORE_FREE turns calls to free into a noop. Only useful with
# -DREDIRECT_MALLOC.
# -DNO_DEBUGGING removes GC_dump and the debugging routines it calls.
# Reduces code size slightly at the expense of debuggability.
# -DJAVA_FINALIZATION makes it somewhat safer to finalize objects out of
# order by specifying a nonstandard finalization mark procedure (see
# finalize.c). Objects reachable from finalizable objects will be marked
# in a sepearte postpass, and hence their memory won't be reclaimed.
# Not recommended unless you are implementing a language that specifies
# these semantics. Since 5.0, determines only only the initial value
# of GC_java_finalization variable.
# -DFINALIZE_ON_DEMAND causes finalizers to be run only in response
# to explicit GC_invoke_finalizers() calls.
# In 5.0 this became runtime adjustable, and this only determines the
# initial value of GC_finalize_on_demand.
# -DATOMIC_UNCOLLECTABLE includes code for GC_malloc_atomic_uncollectable.
# This is useful if either the vendor malloc implementation is poor,
# or if REDIRECT_MALLOC is used.
# -DHBLKSIZE=ddd, where ddd is a power of 2 between 512 and 16384, explicitly
# sets the heap block size. Each heap block is devoted to a single size and
# kind of object. For the incremental collector it makes sense to match
# the most likely page size. Otherwise large values result in more
# fragmentation, but generally better performance for large heaps.
# -DUSE_MMAP use MMAP instead of sbrk to get new memory.
# Works for Solaris and Irix.
# -DUSE_MUNMAP causes memory to be returned to the OS under the right
# circumstances. This currently disables VM-based incremental collection.
# This is currently experimental, and works only under some Unix and
# Linux versions.
# -DMMAP_STACKS (for Solaris threads) Use mmap from /dev/zero rather than
# GC_scratch_alloc() to get stack memory.
# -DPRINT_BLACK_LIST Whenever a black list entry is added, i.e. whenever
# the garbage collector detects a value that looks almost, but not quite,
# like a pointer, print both the address containing the value, and the
# value of the near-bogus-pointer. Can be used to identifiy regions of
# memory that are likely to contribute misidentified pointers.
# -DKEEP_BACK_PTRS Add code to save back pointers in debugging headers
# for objects allocated with the debugging allocator. If all objects
# through GC_MALLOC with GC_DEBUG defined, this allows the client
# to determine how particular or randomly chosen objects are reachable
# for debugging/profiling purposes. The gc_backptr.h interface is
# implemented only if this is defined.
# -DGC_ASSERTIONS Enable some internal GC assertion checking. Currently
# this facility is only used in a few places. It is intended primarily
# for debugging of the garbage collector itself, but could also
# -DDBG_HDRS_ALL Make sure that all objects have debug headers. Increases
# the reliability (from 99.9999% to 100%) of some of the debugging
# code (especially KEEP_BACK_PTRS). Makes -DSHORT_DBG_HDRS possible.
# Assumes that all client allocation is done through debugging
# allocators.
# -DSHORT_DBG_HDRS Assume that all objects have debug headers. Shorten
# the headers to minimize object size, at the expense of checking for
# writes past the end of an object. This is intended for environments
# in which most client code is written in a "safe" language, such as
# Scheme or Java. Assumes that all client allocation is done using
# the GC_debug_ functions, or through the macros that expand to these,
# or by redirecting malloc to GC_debug_malloc_replacement.
# (Also eliminates the field for the requested object size.)
# occasionally be useful for debugging of client code. Slows down the
# collector somewhat, but not drastically.
# -DSAVE_CALL_COUNT=<n> Set the number of call frames saved with objects
# allocated through the debugging interface. Affects the amount of
# information generated in leak reports. Only matters on platforms
# on which we can quickly generate call stacks, currently Linux/(X86 & SPARC)
# and Solaris/SPARC. Turns on call chain saving on X86. On X86, client
# code should NOT be compiled with -fomit-frame-pointer.
# -DCHECKSUMS reports on erroneously clear dirty bits, and unexpectedly
# altered stubborn objects, at substantial performance cost.
# Use only for debugging of the incremental collector.
# -DGC_GCJ_SUPPORT includes support for gcj (and possibly other systems
# that include a pointer to a type descriptor in each allocated object).
# Building this way requires an ANSI C compiler.
# -DUSE_I686_PREFETCH causes the collector to issue Pentium III style
# prefetch instructions. No effect except on X86 Linux platforms.
# Assumes a very recent gcc-compatible compiler and assembler.
# (Gas prefetcht0 support was added around May 1999.)
# Empirically the code appears to still run correctly on Pentium II
# processors, though with no performance benefit. May not run on other
# X86 processors? In some cases this improves performance by
# 15% or so.
# -DUSE_3DNOW_PREFETCH causes the collector to issue AMD 3DNow style
# prefetch instructions. Same restrictions as USE_I686_PREFETCH.
# 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.
# -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.
# -DPARALLEL_MARK allows the marker to run in multiple threads. Recommended
# for multiprocessors. Currently requires Linux on X86 or IA64, though
# support for other Posix platforms should be fairly easy to add,
# if the thread implementation is otherwise supported.
# -DNO_GETENV prevents the collector from looking at environment variables.
# These may otherwise alter its configuration, or turn off GC altogether.
# I don't know of a reason to disable this, except possibly if the
# resulting process runs as a privileged user?
# -DSTUBBORN_ALLOC allows allocation of "hard to change" objects, and thus
# makes incremental collection easier. Was enabled by default until 6.0.
# Rarely used, to my knowledge.
#
CXXFLAGS= $(CFLAGS)
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 irix_threads.o linux_threads.o typd_mlc.o ptr_chck.o mallocx.o solaris_pthreads.o gcj_mlc.o specific.o gc_dlopen.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 irix_threads.c linux_threads.c typd_mlc.c ptr_chck.c mallocx.c solaris_pthreads.c gcj_mlc.c specific.c gc_dlopen.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
CORD_OBJS= cord/cordbscs.o cord/cordxtra.o cord/cordprnt.o
SRCS= $(CSRCS) mips_sgi_mach_dep.s rs6000_mach_dep.s alpha_mach_dep.s \
sparc_mach_dep.s include/gc.h include/gc_typed.h \
include/private/gc_hdrs.h include/private/gc_priv.h \
include/private/gcconfig.h include/private/gc_pmark.h \
include/gc_inl.h include/gc_inline.h include/gc_mark.h \
threadlibs.c if_mach.c if_not_there.c gc_cpp.cc include/gc_cpp.h \
gcname.c include/weakpointer.h include/private/gc_locks.h \
gcc_support.c mips_ultrix_mach_dep.s include/gc_alloc.h \
include/new_gc_alloc.h include/javaxfc.h sparc_sunos4_mach_dep.s \
sparc_netbsd_mach_dep.s \
include/private/solaris_threads.h include/gc_backptr.h \
hpux_test_and_clear.s include/gc_gcj.h \
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 $(CORD_SRCS)
DOC_FILES= README.QUICK doc/README.Mac doc/README.MacOSX doc/README.OS2 \
doc/README.amiga doc/README.cords doc/debugging.html \
doc/README.dj doc/README.hp doc/README.linux doc/README.rs6000 \
doc/README.sgi doc/README.solaris2 doc/README.uts \
doc/README.win32 doc/barrett_diagram doc/README \
doc/README.contributors doc/README.changes doc/gc.man \
doc/README.environment doc/tree.html doc/gcdescr.html \
doc/README.autoconf doc/README.macros
TESTS= tests/test.c tests/test_cpp.cc tests/trace_test.c \
tests/leak_test.c tests/thread_leak_test.c
GNU_BUILD_FILES= configure.in Makefile.am configure acinclude.m4 \
libtool.m4 install-sh configure.host Makefile.in \
aclocal.m4 config.sub config.guess ltconfig \
ltmain.sh mkinstalldirs
OTHER_MAKEFILES= OS2_MAKEFILE NT_MAKEFILE NT_THREADS_MAKEFILE gc.mak \
BCC_MAKEFILE EMX_MAKEFILE WCC_MAKEFILE Makefile.dj \
PCR-Makefile SMakefile.amiga Makefile.DLLs \
digimars.mak Makefile.direct
# Makefile and Makefile.direct are copies of each other.
OTHER_FILES= Makefile setjmp_t.c callprocs pc_excludes \
MacProjects.sit.hqx MacOS.c \
Mac_files/datastart.c Mac_files/dataend.c \
Mac_files/MacOS_config.h Mac_files/MacOS_Test_config.h \
add_gc_prefix.c gc_cpp.cpp win32_threads.c \
version.h AmigaOS.c \
$(TESTS) $(GNU_BUILD_FILES) $(OTHER_MAKEFILES)
CORD_INCLUDE_FILES= $(srcdir)/include/gc.h $(srcdir)/include/cord.h \
$(srcdir)/include/ec.h $(srcdir)/include/private/cord_pos.h
UTILS= if_mach if_not_there threadlibs
# Libraries needed for curses applications. Only needed for de.
CURSES= -lcurses -ltermlib
# The following is irrelevant on most systems. But a few
# versions of make otherwise fork the shell specified in
# the SHELL environment variable.
SHELL= /bin/sh
SPECIALCFLAGS = -I$(srcdir)/include
# Alternative flags to the C compiler for mach_dep.c.
# Mach_dep.c often doesn't like optimization, and it's
# not time-critical anyway.
# Set SPECIALCFLAGS to -q nodirect_code on Encore.
all: gc.a gctest
BSD-pkg-all: bsd-libgc.a
bsd-libgc.a:
$(MAKE) CFLAGS="$(CFLAGS)" clean c++-t
mv gc.a bsd-libgc.a
BSD-pkg-install: BSD-pkg-all
${CP} bsd-libgc.a libgc.a
${INSTALL_DATA} libgc.a ${PREFIX}/lib
${INSTALL_DATA} gc.h gc_cpp.h ${PREFIX}/include
pcr: PCR-Makefile include/private/gc_private.h include/private/gc_hdrs.h \
include/private/gc_locks.h include/gc.h include/private/gcconfig.h \
mach_dep.o $(SRCS)
$(MAKE) -f PCR-Makefile depend
$(MAKE) -f PCR-Makefile
$(OBJS) tests/test.o dyn_load.o dyn_load_sunos53.o: \
$(srcdir)/include/private/gc_priv.h \
$(srcdir)/include/private/gc_hdrs.h $(srcdir)/include/private/gc_locks.h \
$(srcdir)/include/gc.h \
$(srcdir)/include/private/gcconfig.h $(srcdir)/include/gc_typed.h \
Makefile
# The dependency on Makefile is needed. Changing
# options such as -DSILENT affects the size of GC_arrays,
# invalidating all .o files that rely on gc_priv.h
mark.o typd_mlc.o finalize.o ptr_chck.o: $(srcdir)/include/gc_mark.h $(srcdir)/include/private/gc_pmark.h
specific.o linux_threads.o: $(srcdir)/include/private/specific.h
solaris_threads.o solaris_pthreads.o: $(srcdir)/include/private/solaris_threads.h
dbg_mlc.o gcj_mlc.o: $(srcdir)/include/private/dbg_mlc.h
tests/test.o: tests $(srcdir)/tests/test.c
$(CC) $(CFLAGS) -c $(srcdir)/tests/test.c
mv test.o tests/test.o
tests:
mkdir tests
base_lib gc.a: $(OBJS) dyn_load.o $(UTILS)
echo > base_lib
rm -f dont_ar_1
./if_mach SPARC SUNOS5 touch dont_ar_1
./if_mach SPARC SUNOS5 $(AR) rus gc.a $(OBJS) dyn_load.o
./if_mach M68K AMIGA touch dont_ar_1
./if_mach M68K AMIGA $(AR) -vrus gc.a $(OBJS) dyn_load.o
./if_not_there dont_ar_1 $(AR) ru gc.a $(OBJS) dyn_load.o
./if_not_there dont_ar_1 $(RANLIB) gc.a || cat /dev/null
# ignore ranlib failure; that usually means it doesn't exist, and isn't needed
cords: $(CORD_OBJS) cord/cordtest $(UTILS)
rm -f dont_ar_3
./if_mach SPARC SUNOS5 touch dont_ar_3
./if_mach SPARC SUNOS5 $(AR) rus gc.a $(CORD_OBJS)
./if_mach M68K AMIGA touch dont_ar_3
./if_mach M68K AMIGA $(AR) -vrus gc.a $(CORD_OBJS)
./if_not_there dont_ar_3 $(AR) ru gc.a $(CORD_OBJS)
./if_not_there dont_ar_3 $(RANLIB) gc.a || cat /dev/null
gc_cpp.o: $(srcdir)/gc_cpp.cc $(srcdir)/include/gc_cpp.h $(srcdir)/include/gc.h Makefile
$(CXX) -c $(CXXFLAGS) $(srcdir)/gc_cpp.cc
test_cpp: $(srcdir)/tests/test_cpp.cc $(srcdir)/include/gc_cpp.h gc_cpp.o $(srcdir)/include/gc.h \
base_lib $(UTILS)
rm -f test_cpp
./if_mach HP_PA HPUX $(CXX) $(CXXFLAGS) -o test_cpp $(srcdir)/tests/test_cpp.cc gc_cpp.o gc.a -ldld `./threadlibs`
./if_not_there test_cpp $(CXX) $(CXXFLAGS) -o test_cpp $(srcdir)/tests/test_cpp.cc gc_cpp.o gc.a `./threadlibs`
c++-t: c++
./test_cpp 1
c++-nt: c++
@echo "Use ./test_cpp 1 to test the leak library"
c++: gc_cpp.o $(srcdir)/include/gc_cpp.h test_cpp
rm -f dont_ar_4
./if_mach SPARC SUNOS5 touch dont_ar_4
./if_mach SPARC SUNOS5 $(AR) rus gc.a gc_cpp.o
./if_mach M68K AMIGA touch dont_ar_4
./if_mach M68K AMIGA $(AR) -vrus gc.a gc_cpp.o
./if_not_there dont_ar_4 $(AR) ru gc.a gc_cpp.o
./if_not_there dont_ar_4 $(RANLIB) gc.a || cat /dev/null
./test_cpp 1
echo > c++
dyn_load_sunos53.o: dyn_load.c
$(CC) $(CFLAGS) -DSUNOS53_SHARED_LIB -c $(srcdir)/dyn_load.c -o $@
# SunOS5 shared library version of the collector
sunos5gc.so: $(OBJS) dyn_load_sunos53.o
$(CC) -G -o sunos5gc.so $(OBJS) dyn_load_sunos53.o -ldl
ln sunos5gc.so libgc.so
# Alpha/OSF shared library version of the collector
libalphagc.so: $(OBJS)
ld -shared -o libalphagc.so $(OBJS) dyn_load.o -lc
ln libalphagc.so libgc.so
# IRIX shared library version of the collector
libirixgc.so: $(OBJS) dyn_load.o
ld -shared $(ABI_FLAG) -o libirixgc.so $(OBJS) dyn_load.o -lc
ln libirixgc.so libgc.so
# Linux shared library version of the collector
liblinuxgc.so: $(OBJS) dyn_load.o
gcc -shared -o liblinuxgc.so $(OBJS) dyn_load.o
ln liblinuxgc.so libgc.so
# Alternative Linux rule. This is preferable, but is likely to break the
# Makefile for some non-linux platforms.
# LIBOBJS= $(patsubst %.o, %.lo, $(OBJS))
#
#.SUFFIXES: .lo $(SUFFIXES)
#
#.c.lo:
# $(CC) $(CFLAGS) $(CPPFLAGS) -fPIC -c $< -o $@
#
# liblinuxgc.so: $(LIBOBJS) dyn_load.lo
# gcc -shared -Wl,-soname=libgc.so.0 -o libgc.so.0 $(LIBOBJS) dyn_load.lo
# touch liblinuxgc.so
mach_dep.o: $(srcdir)/mach_dep.c $(srcdir)/mips_sgi_mach_dep.s $(srcdir)/mips_ultrix_mach_dep.s \
$(srcdir)/rs6000_mach_dep.s $(srcdir)/powerpc_macosx_mach_dep.s $(UTILS)
rm -f mach_dep.o
./if_mach MIPS IRIX5 $(AS) -o mach_dep.o $(srcdir)/mips_sgi_mach_dep.s
./if_mach MIPS RISCOS $(AS) -o mach_dep.o $(srcdir)/mips_ultrix_mach_dep.s
./if_mach MIPS ULTRIX $(AS) -o mach_dep.o $(srcdir)/mips_ultrix_mach_dep.s
./if_mach RS6000 "" $(AS) -o mach_dep.o $(srcdir)/rs6000_mach_dep.s
./if_mach POWERPC MACOSX $(AS) -o mach_dep.o $(srcdir)/powerpc_macosx_mach_dep.s
# ./if_mach ALPHA "" $(AS) -o mach_dep.o $(srcdir)/alpha_mach_dep.s
# alpha_mach_dep.s assumes that pointers are not saved in fp registers.
# Gcc on a 21264 can spill pointers to fp registers. Oops.
./if_mach SPARC SUNOS5 $(AS) -o mach_dep.o $(srcdir)/sparc_mach_dep.s
./if_mach SPARC SUNOS4 $(AS) -o mach_dep.o $(srcdir)/sparc_sunos4_mach_dep.s
./if_mach SPARC OPENBSD $(AS) -o mach_dep.o $(srcdir)/sparc_sunos4_mach_dep.s
./if_mach SPARC NETBSD $(AS) -o mach_dep.o $(srcdir)/sparc_netbsd_mach_dep.s
./if_not_there mach_dep.o $(CC) -c $(SPECIALCFLAGS) $(srcdir)/mach_dep.c
mark_rts.o: $(srcdir)/mark_rts.c $(UTILS)
rm -f mark_rts.o
-./if_mach ALPHA OSF1 $(CC) -c $(CFLAGS) -Wo,-notail $(srcdir)/mark_rts.c
./if_not_there mark_rts.o $(CC) -c $(CFLAGS) $(srcdir)/mark_rts.c
# Work-around for DEC optimizer tail recursion elimination bug.
# The ALPHA-specific line should be removed if gcc is used.
alloc.o: version.h
cord:
mkdir cord
cord/cordbscs.o: cord $(srcdir)/cord/cordbscs.c $(CORD_INCLUDE_FILES)
$(CC) $(CFLAGS) -c -I$(srcdir) $(srcdir)/cord/cordbscs.c
mv cordbscs.o cord/cordbscs.o
# not all compilers understand -o filename
cord/cordxtra.o: cord $(srcdir)/cord/cordxtra.c $(CORD_INCLUDE_FILES)
$(CC) $(CFLAGS) -c -I$(srcdir) $(srcdir)/cord/cordxtra.c
mv cordxtra.o cord/cordxtra.o
cord/cordprnt.o: cord $(srcdir)/cord/cordprnt.c $(CORD_INCLUDE_FILES)
$(CC) $(CFLAGS) -c -I$(srcdir) $(srcdir)/cord/cordprnt.c
mv cordprnt.o cord/cordprnt.o
cord/cordtest: $(srcdir)/cord/cordtest.c $(CORD_OBJS) gc.a $(UTILS)
rm -f cord/cordtest
./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o cord/cordtest $(srcdir)/cord/cordtest.c $(CORD_OBJS) gc.a -lucb
./if_mach HP_PA HPUX $(CC) $(CFLAGS) -o cord/cordtest $(srcdir)/cord/cordtest.c $(CORD_OBJS) gc.a -ldld `./threadlibs`
./if_mach M68K AMIGA $(CC) $(CFLAGS) -UGC_AMIGA_MAKINGLIB -o cord/cordtest $(srcdir)/cord/cordtest.c $(CORD_OBJS) gc.a `./threadlibs`
./if_not_there cord/cordtest $(CC) $(CFLAGS) -o cord/cordtest $(srcdir)/cord/cordtest.c $(CORD_OBJS) gc.a `./threadlibs`
cord/de: $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a $(UTILS)
rm -f cord/de
./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a $(CURSES) -lucb `./threadlibs`
./if_mach HP_PA HPUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a $(CURSES) -ldld `./threadlibs`
./if_mach RS6000 "" $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses
./if_mach POWERPC MACOSX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a
./if_mach I386 LINUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses `./threadlibs`
./if_mach ALPHA LINUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses `./threadlibs`
./if_mach IA64 LINUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses `./threadlibs`
./if_mach M68K AMIGA $(CC) $(CFLAGS) -UGC_AMIGA_MAKINGLIB -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses
./if_not_there cord/de $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a $(CURSES) `./threadlibs`
if_mach: $(srcdir)/if_mach.c $(srcdir)/include/private/gcconfig.h
$(HOSTCC) $(HOSTCFLAGS) -o if_mach $(srcdir)/if_mach.c
threadlibs: $(srcdir)/threadlibs.c $(srcdir)/include/private/gcconfig.h Makefile
$(HOSTCC) $(HOSTCFLAGS) -o threadlibs $(srcdir)/threadlibs.c
if_not_there: $(srcdir)/if_not_there.c
$(HOSTCC) $(HOSTCFLAGS) -o if_not_there $(srcdir)/if_not_there.c
clean:
rm -f gc.a *.o *.exe tests/*.o gctest gctest_dyn_link test_cpp \
setjmp_test mon.out gmon.out a.out core if_not_there if_mach \
threadlibs $(CORD_OBJS) cord/cordtest cord/de
-rm -f *~
gctest: tests/test.o gc.a $(UTILS)
rm -f gctest
./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o gctest tests/test.o gc.a -lucb
./if_mach HP_PA HPUX $(CC) $(CFLAGS) -o gctest tests/test.o gc.a -ldld `./threadlibs`
./if_mach M68K AMIGA $(CC) $(CFLAGS) -UGC_AMIGA_MAKINGLIB -o gctest tests/test.o gc.a `./threadlibs`
./if_not_there gctest $(CC) $(CFLAGS) -o gctest tests/test.o gc.a `./threadlibs`
# If an optimized setjmp_test generates a segmentation fault,
# odds are your compiler is broken. Gctest may still work.
# Try compiling setjmp_t.c unoptimized.
setjmp_test: $(srcdir)/setjmp_t.c $(srcdir)/include/gc.h $(UTILS)
$(CC) $(CFLAGS) -o setjmp_test $(srcdir)/setjmp_t.c
test: KandRtest cord/cordtest
cord/cordtest
# Those tests that work even with a K&R C compiler:
KandRtest: setjmp_test gctest
./setjmp_test
./gctest
add_gc_prefix: $(srcdir)/add_gc_prefix.c $(srcdir)/version.h
$(CC) -o add_gc_prefix $(srcdir)/add_gc_prefix.c
gcname: $(srcdir)/gcname.c $(srcdir)/version.h
$(CC) -o gcname $(srcdir)/gcname.c
gc.tar: $(SRCS) $(DOC_FILES) $(OTHER_FILES) add_gc_prefix gcname
cp Makefile Makefile.old
cp Makefile.direct Makefile
rm -f `./gcname`
ln -s . `./gcname`
./add_gc_prefix $(SRCS) $(DOC_FILES) $(OTHER_FILES) > /tmp/gc.tar-files
tar cvfh gc.tar `cat /tmp/gc.tar-files`
cp gc.tar `./gcname`.tar
gzip `./gcname`.tar
rm `./gcname`
pc_gc.tar: $(SRCS) $(OTHER_FILES)
tar cvfX pc_gc.tar pc_excludes $(SRCS) $(OTHER_FILES)
floppy: pc_gc.tar
-mmd a:/cord
-mmd a:/cord/private
-mmd a:/include
-mmd a:/include/private
mkdir /tmp/pc_gc
cat pc_gc.tar | (cd /tmp/pc_gc; tar xvf -)
-mcopy -tmn /tmp/pc_gc/* a:
-mcopy -tmn /tmp/pc_gc/cord/* a:/cord
-mcopy -mn /tmp/pc_gc/cord/de_win.ICO a:/cord
-mcopy -tmn /tmp/pc_gc/cord/private/* a:/cord/private
-mcopy -tmn /tmp/pc_gc/include/* a:/include
-mcopy -tmn /tmp/pc_gc/include/private/* a:/include/private
rm -r /tmp/pc_gc
gc.tar.Z: gc.tar
compress gc.tar
gc.tar.gz: gc.tar
gzip gc.tar
lint: $(CSRCS) tests/test.c
lint -DLINT $(CSRCS) tests/test.c | egrep -v "possible pointer alignment problem|abort|exit|sbrk|mprotect|syscall|change in ANSI|improper alignment"
# BTL: added to test shared library version of collector.
# Currently works only under SunOS5. Requires GC_INIT call from statically
# loaded client code.
ABSDIR = `pwd`
gctest_dyn_link: tests/test.o libgc.so
$(CC) -L$(ABSDIR) -R$(ABSDIR) -o gctest_dyn_link tests/test.o -lgc -ldl -lthread
gctest_irix_dyn_link: tests/test.o libirixgc.so
$(CC) -L$(ABSDIR) -o gctest_irix_dyn_link tests/test.o -lirixgc
# The following appear to be dead, especially since libgc_globals.h
# is apparently lost.
test_dll.o: tests/test.c libgc_globals.h
$(CC) $(CFLAGS) -DGC_USE_DLL -c tests/test.c -o test_dll.o
test_dll: test_dll.o libgc_dll.a libgc.dll
$(CC) test_dll.o -L$(ABSDIR) -lgc_dll -o test_dll
SYM_PREFIX-libgc=GC
# Uncomment the following line to build a GNU win32 DLL
# include Makefile.DLLs
reserved_namespace: $(SRCS)
for file in $(SRCS) tests/test.c tests/test_cpp.cc; do \
sed s/GC_/_GC_/g < $$file > tmp; \
cp tmp $$file; \
done
user_namespace: $(SRCS)
for file in $(SRCS) tests/test.c tests/test_cpp.cc; do \
sed s/_GC_/GC_/g < $$file > tmp; \
cp tmp $$file; \
done

1121
boehm-gc/config.guess vendored Executable file

File diff suppressed because it is too large Load Diff

1232
boehm-gc/config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

90
boehm-gc/digimars.mak Normal file
View File

@ -0,0 +1,90 @@
# Makefile to build Hans Boehm garbage collector using the Digital Mars
# compiler from www.digitalmars.com
# Written by Walter Bright
DEFINES=-DNDEBUG -DSILENT -DGC_BUILD -D_WINDOWS -DGC_DLL -DALL_INTERIOR_POINTERS -D__STDC__ -DWIN32_THREADS
CFLAGS=-Iinclude $(DEFINES) -wx -g
LFLAGS=/ma/implib/co
CC=sc
.c.obj:
$(CC) -c $(CFLAGS) $*
.cpp.obj:
$(CC) -c $(CFLAGS) -Aa $*
OBJS= \
allchblk.obj\
alloc.obj\
blacklst.obj\
checksums.obj\
dbg_mlc.obj\
dyn_load.obj\
finalize.obj\
gc_cpp.obj\
headers.obj\
mach_dep.obj\
malloc.obj\
mallocx.obj\
mark.obj\
mark_rts.obj\
misc.obj\
new_hblk.obj\
obj_map.obj\
os_dep.obj\
ptr_chck.obj\
reclaim.obj\
stubborn.obj\
typd_mlc.obj\
win32_threads.obj
targets: gc.dll gc.lib gctest.exe
gc.dll: $(OBJS) gc.def digimars.mak
sc -ogc.dll $(OBJS) -L$(LFLAGS) gc.def kernel32.lib user32.lib
gc.def: digimars.mak
echo LIBRARY GC >gc.def
echo DESCRIPTION "Hans Boehm Garbage Collector" >>gc.def
echo EXETYPE NT >>gc.def
echo EXPORTS >>gc.def
echo GC_is_visible_print_proc >>gc.def
echo GC_is_valid_displacement_print_proc >>gc.def
clean:
del gc.def
del $(OBJS)
gctest.exe : gc.lib tests\test.obj
sc -ogctest.exe tests\test.obj gc.lib
tests\test.obj : tests\test.c
$(CC) -c -g -DNDEBUG -DSILENT -DGC_BUILD -D_WINDOWS -DGC_DLL \
-DALL_INTERIOR_POINTERS -DWIN32_THREADS \
-Iinclude tests\test.c -otests\test.obj
allchblk.obj: allchblk.c
alloc.obj: alloc.c
blacklst.obj: blacklst.c
checksums.obj: checksums.c
dbg_mlc.obj: dbg_mlc.c
dyn_load.obj: dyn_load.c
finalize.obj: finalize.c
gc_cpp.obj: gc_cpp.cpp
headers.obj: headers.c
mach_dep.obj: mach_dep.c
malloc.obj: malloc.c
mallocx.obj: mallocx.c
mark.obj: mark.c
mark_rts.obj: mark_rts.c
misc.obj: misc.c
new_hblk.obj: new_hblk.c
obj_map.obj: obj_map.c
os_dep.obj: os_dep.c
ptr_chck.obj: ptr_chck.c
reclaim.obj: reclaim.c
stubborn.obj: stubborn.c
typd_mlc.obj: typd_mlc.c
win32_threads.obj: win32_threads.c

View File

@ -0,0 +1,59 @@
As of GC6.0alpha8, we attempt to support GNU-style builds based on automake,
autoconf and libtool. This is based almost entirely on Tom Tromey's work
with gcj.
To build and install libraries use
configure; make; make install
The advantages of this process are:
1) It should eventually do a better job of automatically determining the
right compiler to use, etc. It probably already does in some cases.
2) It tries to automatically set a good set of default GC parameters for
the platform (e.g. thread support). It provides an easier way to configure
some of the others.
3) It integrates better with other projects using a GNU-style build process.
4) It builds both dynamic and static libraries.
The known disadvantages are:
1) The build scripts are much more complex and harder to debug (though largely
standard). I don't understand them all, and there's probably lots of redundant
stuff.
2) It probably doesn't work on all Un*x-like platforms yet. It probably will
never work on the rest.
3) The scripts are not yet complete. Some of the standard GNU targets don't
yet work. (Corrections/additions are very welcome.)
The distribution should contain all files needed to run "configure" and "make",
as well as the sources needed to regenerate the derived files. (If I missed
some, please let me know.)
Note that the distribution comes with a "Makefile" which will be overwritten
by "configure" with one that is not at all equiavelent to the original. The
distribution contains a copy of the original "Makefile" in "Makefile.direct".
Important options to configure:
--prefix=PREFIX install architecture-independent files in PREFIX
[/usr/local]
--exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
[same as prefix]
--enable-threads=TYPE choose threading package
--enable-parallel-mark parallelize marking and free list construction
--enable-full-debug include full support for pointer backtracing etc.
Unless --prefix is set (or --exec-prefix or one of the more obscure options),
make install will install libgc.a and libgc.so in /usr/local/bin, which
would typically require the "make install" to be run as root.
Most commonly --enable-threads=posix or will be needed. --enable-parallel-mark
is recommended for multiprocessors if it is supported on the platform.

View File

@ -0,0 +1,78 @@
The collector uses a large amount of conditional compilation in order to
deal with platform dependencies. This violates a number of known coding
standards. On the other hand, it seems to be the only practical way to
support this many platforms without excessive code duplication.
A few guidelines have mostly been followed in order to keep this manageable:
1) #if and #ifdef directives are properly indented whenever easily possible.
All known C compilers allow whitespace between the "#" and the "if" to make
this possible. ANSI C also allows white space before the "#", though we
avoid that. It has the known disadvantages that it differs from the normal
GNU conventions, and that it makes patches larger than otherwise necessary.
In my opinion, it's still well worth it, for the same reason that we indent
ordinary "if" statements.
2) Whenever possible, tests are performed on the macros defined in gcconfig.h
instead of directly testing patform-specific predefined macros. This makes it
relatively easy to adapt to new compilers with a different set of predefined
macros. Currently these macros generally identify platforms instead of
features. In many cases, this is a mistake.
3) The code currently avoids #elif, eventhough that would make it more
readable. This was done since #elif would need to be understood by ALL
compilers used to build the collector, and that hasn't always been the case.
It makes sense to reconsider this decision at some point, since #elif has been
standardized at least since 1989.
Many of the tested configuration macros are at least somewhat defined in
either include/private/gcconfig.h or in Makefile.direct. Here is an attempt
at defining some of the remainder: (Thanks to Walter Bright for suggesting
this. This is a work in progress)
MACRO EXPLANATION
----- -----------
__DMC__ Always #define'd by the Digital Mars compiler. Expands
to the compiler version number in hex, i.e. 0x810 is
version 8.1b0
_ENABLE_ARRAYNEW
#define'd by the Digital Mars C++ compiler when
operator new[] and delete[] are separately
overloadable. Used in gc_cpp.h.
_MSC_VER Expands to the Visual C++ compiler version. Assumed to
not be defined for other compilers (at least if they behave
appreciably differently).
_DLL Defined by Visual C++ if dynamic libraries are being built
or used. Used to test whether __declspec(dllimport) or
__declspec(dllexport) needs to be added to declarations
to support the case in which the collector is in a dll.
GC_DLL User-settable macro that forces the effect of _DLL.
GC_NOT_DLL User-settable macro that overrides _DLL, e.g. if dynamic
libraries are used, but the collector is in a static library.
__STDC__ Assumed to be defined only by compilers that understand
prototypes and other C89 features. Its value is generally
not used, since we are fine with most nonconforming extensions.
SUNOS5SIGS Solaris-like signal handling. This is probably misnamed,
since it really doesn't guarantee much more than Posix.
Currently set only for Solaris2.X, HPUX, and DRSNX. Should
probably be set for some other platforms.
PCR Set if the collector is being built as part of the Xerox
Portable Common Runtime.
SRC_M3 Set if the collector is being built as a replacement of the
one in the DEC/Compaq SRC Modula-3 runtime. I suspect this
was last used around 1994, and no doubt broke a long time ago.
It's there primarily incase someone wants to port to a similar
system.

289
boehm-gc/doc/debugging.html Normal file
View File

@ -0,0 +1,289 @@
<HTML>
<HEAD>
<TITLE>Debugging Garbage Collector Related Problems</title>
</head>
<BODY>
<H1>Debugging Garbage Collector Related Problems</h1>
This page contains some hints on
debugging issues specific to
the Boehm-Demers-Weiser conservative garbage collector.
It applies both to debugging issues in client code that manifest themselves
as collector misbehavior, and to debugging the collector itself.
<P>
If you suspect a bug in the collector itself, it is strongly recommended
that you try the latest collector release, even if it is labelled as "alpha",
before proceeding.
<H2>Bus Errors and Segmentation Violations</h2>
<P>
If the fault occurred in GC_find_limit, or with incremental collection enabled,
this is probably normal. The collector installs handlers to take care of
these. You will not see these unless you are using a debugger.
Your debugger <I>should</i> allow you to continue.
It's often preferable to tell the debugger to ignore SIGBUS and SIGSEGV
("<TT>handle SIGSEGV SIGBUS nostop noprint</tt>" in gdb,
"<TT>ignore SIGSEGV SIGBUS</tt>" in most versions of dbx)
and set a breakpoint in <TT>abort</tt>.
The collector will call abort if the signal had another cause,
and there was not other handler previously installed.
<P>
We recommend debugging without incremental collection if possible.
(This applies directly to UNIX systems.
Debugging with incremental collection under win32 is worse. See README.win32.)
<P>
If the application generates an unhandled SIGSEGV or equivalent, it may
often be easiest to set the environment variable GC_LOOP_ON_ABORT. On many
platforms, this will cause the collector to loop in a handler when the
SIGSEGV is encountered (or when the collector aborts for some other reason),
and a debugger can then be attached to the looping
process. This sidesteps common operating system problems related
to incomplete core files for multithreaded applications, etc.
<H2>Other Signals</h2>
On most platforms, the multithreaded version of the collector needs one or
two other signals for internal use by the collector in stopping threads.
It is normally wise to tell the debugger to ignore these. On Linux,
the collector currently uses SIGPWR and SIGXCPU by default.
<H2>Warning Messages About Needing to Allocate Blacklisted Blocks</h2>
The garbage collector generates warning messages of the form
<PRE>
Needed to allocate blacklisted block at 0x...
</pre>
when it needs to allocate a block at a location that it knows to be
referenced by a false pointer. These false pointers can be either permanent
(<I>e.g.</i> a static integer variable that never changes) or temporary.
In the latter case, the warning is largely spurious, and the block will
eventually be reclaimed normally.
In the former case, the program will still run correctly, but the block
will never be reclaimed. Unless the block is intended to be
permanent, the warning indicates a memory leak.
<OL>
<LI>Ignore these warnings while you are using GC_DEBUG. Some of the routines
mentioned below don't have debugging equivalents. (Alternatively, write
the missing routines and send them to me.)
<LI>Replace allocator calls that request large blocks with calls to
<TT>GC_malloc_ignore_off_page</tt> or
<TT>GC_malloc_atomic_ignore_off_page</tt>. You may want to set a
breakpoint in <TT>GC_default_warn_proc</tt> to help you identify such calls.
Make sure that a pointer to somewhere near the beginning of the resulting block
is maintained in a (preferably volatile) variable as long as
the block is needed.
<LI>
If the large blocks are allocated with realloc, we suggest instead allocating
them with something like the following. Note that the realloc size increment
should be fairly large (e.g. a factor of 3/2) for this to exhibit reasonable
performance. But we all know we should do that anyway.
<PRE>
void * big_realloc(void *p, size_t new_size)
{
size_t old_size = GC_size(p);
void * result;
if (new_size <= 10000) return(GC_realloc(p, new_size));
if (new_size <= old_size) return(p);
result = GC_malloc_ignore_off_page(new_size);
if (result == 0) return(0);
memcpy(result,p,old_size);
GC_free(p);
return(result);
}
</pre>
<LI> In the unlikely case that even relatively small object
(&lt;20KB) allocations are triggering these warnings, then your address
space contains lots of "bogus pointers", i.e. values that appear to
be pointers but aren't. Usually this can be solved by using GC_malloc_atomic
or the routines in gc_typed.h to allocate large pointer-free regions of bitmaps, etc. Sometimes the problem can be solved with trivial changes of encoding
in certain values. It is possible, to identify the source of the bogus
pointers by building the collector with <TT>-DPRINT_BLACK_LIST</tt>,
which will cause it to print the "bogus pointers", along with their location.
<LI> If you get only a fixed number of these warnings, you are probably only
introducing a bounded leak by ignoring them. If the data structures being
allocated are intended to be permanent, then it is also safe to ignore them.
The warnings can be turned off by calling GC_set_warn_proc with a procedure
that ignores these warnings (e.g. by doing absolutely nothing).
</ol>
<H2>The Collector References a Bad Address in <TT>GC_malloc</tt></h2>
This typically happens while the collector is trying to remove an entry from
its free list, and the free list pointer is bad because the free list link
in the last allocated object was bad.
<P>
With &gt; 99% probability, you wrote past the end of an allocated object.
Try setting <TT>GC_DEBUG</tt> before including <TT>gc.h</tt> and
allocating with <TT>GC_MALLOC</tt>. This will try to detect such
overwrite errors.
<H2>Unexpectedly Large Heap</h2>
Unexpected heap growth can be due to one of the following:
<OL>
<LI> Data structures that are being unintentionally retained. This
is commonly caused by data structures that are no longer being used,
but were not cleared, or by caches growing without bounds.
<LI> Pointer misidentification. The garbage collector is interpreting
integers or other data as pointers and retaining the "referenced"
objects.
<LI> Heap fragmentation. This should never result in unbounded growth,
but it may account for larger heaps. This is most commonly caused
by allocation of large objects. On some platforms it can be reduced
by building with -DUSE_MUNMAP, which will cause the collector to unmap
memory corresponding to pages that have not been recently used.
<LI> Per object overhead. This is usually a relatively minor effect, but
it may be worth considering. If the collector recognizes interior
pointers, object sizes are increased, so that one-past-the-end pointers
are correctly recognized. The collector can be configured not to do this
(<TT>-DDONT_ADD_BYTE_AT_END</tt>).
<P>
The collector rounds up object sizes so the result fits well into the
chunk size (<TT>HBLKSIZE</tt>, normally 4K on 32 bit machines, 8K
on 64 bit machines) used by the collector. Thus it may be worth avoiding
objects of size 2K + 1 (or 2K if a byte is being added at the end.)
</ol>
The last two cases can often be identified by looking at the output
of a call to <TT>GC_dump()</tt>. Among other things, it will print the
list of free heap blocks, and a very brief description of all chunks in
the heap, the object sizes they correspond to, and how many live objects
were found in the chunk at the last collection.
<P>
Growing data structures can usually be identified by
<OL>
<LI> Building the collector with <TT>-DKEEP_BACK_PTRS</tt>,
<LI> Preferably using debugging allocation (defining <TT>GC_DEBUG</tt>
before including <TT>gc.h</tt> and allocating with <TT>GC_MALLOC</tt>),
so that objects will be identified by their allocation site,
<LI> Running the application long enough so
that most of the heap is composed of "leaked" memory, and
<LI> Then calling <TT>GC_generate_random_backtrace()</tt> from backptr.h
a few times to determine why some randomly sampled objects in the heap are
being retained.
</ol>
<P>
The same technique can often be used to identify problems with false
pointers, by noting whether the reference chains printed by
<TT>GC_generate_random_backtrace()</tt> involve any misidentified pointers.
An alternate technique is to build the collector with
<TT>-DPRINT_BLACK_LIST</tt> which will cause it to report values that
are almost, but not quite, look like heap pointers. It is very likely that
actual false pointers will come from similar sources.
<P>
In the unlikely case that false pointers are an issue, it can usually
be resolved using one or more of the following techniques:
<OL>
<LI> Use <TT>GC_malloc_atomic</tt> for objects containing no pointers.
This is especially important for large arrays containing compressed data,
pseudo-random numbers, and the like. It is also likely to improve GC
performance, perhaps drastically so if the application is paging.
<LI> If you allocate large objects containing only
one or two pointers at the beginning, either try the typed allocation
primitives is <TT>gc_typed.h</tt>, or separate out the pointerfree component.
<LI> Consider using <TT>GC_malloc_ignore_off_page()</tt>
to allocate large objects. (See <TT>gc.h</tt> and above for details.
Large means &gt; 100K in most environments.)
</ol>
<H2>Prematurely Reclaimed Objects</h2>
The usual symptom of this is a segmentation fault, or an obviously overwritten
value in a heap object. This should, of course, be impossible. In practice,
it may happen for reasons like the following:
<OL>
<LI> The collector did not intercept the creation of threads correctly in
a multithreaded application, <I>e.g.</i> because the client called
<TT>pthread_create</tt> without including <TT>gc.h</tt>, which redefines it.
<LI> The last pointer to an object in the garbage collected heap was stored
somewhere were the collector couldn't see it, <I>e.g.</i> in an
object allocated with system <TT>malloc</tt>, in certain types of
<TT>mmap</tt>ed files,
or in some data structure visible only to the OS. (On some platforms,
thread-local storage is one of these.)
<LI> The last pointer to an object was somehow disguised, <I>e.g.</i> by
XORing it with another pointer.
<LI> Incorrect use of <TT>GC_malloc_atomic</tt> or typed allocation.
<LI> An incorrect <TT>GC_free</tt> call.
<LI> The client program overwrote an internal garbage collector data structure.
<LI> A garbage collector bug.
<LI> (Empirically less likely than any of the above.) A compiler optimization
that disguised the last pointer.
</ol>
The following relatively simple techniques should be tried first to narrow
down the problem:
<OL>
<LI> If you are using the incremental collector try turning it off for
debugging.
<LI> Try to reproduce the problem with fully debuggable unoptimized code.
This will eliminate the last possibility, as well as making debugging easier.
<LI> Try replacing any suspect typed allocation and <TT>GC_malloc_atomic</tt>
calls with calls to <TT>GC_malloc</tt>.
<LI> Try removing any GC_free calls (<I>e.g.</i> with a suitable
<TT>#define</tt>).
<LI> Rebuild the collector with <TT>-DGC_ASSERTIONS</tt>.
<LI> If the following works on your platform (i.e. if gctest still works
if you do this), try building the collector with
<TT>-DREDIRECT_MALLOC=GC_malloc_uncollectable</tt>. This will cause
the collector to scan memory allocated with malloc.
</ol>
If all else fails, you will have to attack this with a debugger.
Suggested steps:
<OL>
<LI> Call <TT>GC_dump()</tt> from the debugger around the time of the failure. Verify
that the collectors idea of the root set (i.e. static data regions which
it should scan for pointers) looks plausible. If not, i.e. if it doesn't
include some static variables, report this as
a collector bug. Be sure to describe your platform precisely, since this sort
of problem is nearly always very platform dependent.
<LI> Especially if the failure is not deterministic, try to isolate it to
a relatively small test case.
<LI> Set a break point in <TT>GC_finish_collection</tt>. This is a good
point to examine what has been marked, i.e. found reachable, by the
collector.
<LI> If the failure is deterministic, run the process
up to the last collection before the failure.
Note that the variable <TT>GC_gc_no</tt> counts collections and can be used
to set a conditional breakpoint in the right one. It is incremented just
before the call to GC_finish_collection.
If object <TT>p</tt> was prematurely recycled, it may be helpful to
look at <TT>*GC_find_header(p)</tt> at the failure point.
The <TT>hb_last_reclaimed</tt> field will identify the collection number
during which its block was last swept.
<LI> Verify that the offending object still has its correct contents at
this point.
The call <TT>GC_is_marked(p)</tt> from the debugger to verify that the
object has not been marked, and is about to be reclaimed.
<LI> Determine a path from a root, i.e. static variable, stack, or
register variable,
to the reclaimed object. Call <TT>GC_is_marked(q)</tt> for each object
<TT>q</tt> along the path, trying to locate the first unmarked object, say
<TT>r</tt>.
<LI> If <TT>r</tt> is pointed to by a static root,
verify that the location
pointing to it is part of the root set printed by <TT>GC_dump()</tt>. If it
is on the stack in the main (or only) thread, verify that
<TT>GC_stackbottom</tt> is set correctly to the base of the stack. If it is
in another thread stack, check the collector's thread data structure
(<TT>GC_thread[]</tt> on several platforms) to make sure that stack bounds
are set correctly.
<LI> If <TT>r</tt> is pointed to by heap object <TT>s</tt>, check that the
collector's layout description for <TT>s</tt> is such that the pointer field
will be scanned. Call <TT>*GC_find_header(s)</tt> to look at the descriptor
for the heap chunk. The <TT>hb_descr</tt> field specifies the layout
of objects in that chunk. See gc_mark.h for the meaning of the descriptor.
(If it's low order 2 bits are zero, then it is just the length of the
object prefix to be scanned. This form is always used for objects allocated
with <TT>GC_malloc</tt> or <TT>GC_malloc_atomic</tt>.)
<LI> If the failure is not deterministic, you may still be able to apply some
of the above technique at the point of failure. But remember that objects
allocated since the last collection will not have been marked, even if the
collector is functioning properly. On some platforms, the collector
can be configured to save call chains in objects for debugging.
Enabling this feature will also cause it to save the call stack at the
point of the last GC in GC_arrays._last_stack.
<LI> When looking at GC internal data structures remember that a number
of <TT>GC_</tt><I>xxx</i> variables are really macro defined to
<TT>GC_arrays._</tt><I>xxx</i>, so that
the collector can avoid scanning them.
</ol>
</body>
</html>

438
boehm-gc/doc/gcdescr.html Normal file
View File

@ -0,0 +1,438 @@
<HTML>
<HEAD>
<TITLE> Conservative GC Algorithmic Overview </TITLE>
<AUTHOR> Hans-J. Boehm, Silicon Graphics</author>
</HEAD>
<BODY>
<H1> <I>This is under construction</i> </h1>
<H1> Conservative GC Algorithmic Overview </h1>
<P>
This is a description of the algorithms and data structures used in our
conservative garbage collector. I expect the level of detail to increase
with time. For a survey of GC algorithms, see for example
<A HREF="ftp://ftp.cs.utexas.edu/pub/garbage/gcsurvey.ps"> Paul Wilson's
excellent paper</a>. For an overview of the collector interface,
see <A HREF="gcinterface.html">here</a>.
<P>
This description is targeted primarily at someone trying to understand the
source code. It specifically refers to variable and function names.
It may also be useful for understanding the algorithms at a higher level.
<P>
The description here assumes that the collector is used in default mode.
In particular, we assume that it used as a garbage collector, and not just
a leak detector. We initially assume that it is used in stop-the-world,
non-incremental mode, though the presence of the incremental collector
will be apparent in the design.
We assume the default finalization model, but the code affected by that
is very localized.
<H2> Introduction </h2>
The garbage collector uses a modified mark-sweep algorithm. Conceptually
it operates roughly in four phases:
<OL>
<LI>
<I>Preparation</i> Clear all mark bits, indicating that all objects
are potentially unreachable.
<LI>
<I>Mark phase</i> Marks all objects that can be reachable via chains of
pointers from variables. Normally the collector has no real information
about the location of pointer variables in the heap, so it
views all static data areas, stacks and registers as potentially containing
containing pointers. Any bit patterns that represent addresses inside
heap objects managed by the collector are viewed as pointers.
Unless the client program has made heap object layout information
available to the collector, any heap objects found to be reachable from
variables are again scanned similarly.
<LI>
<I>Sweep phase</i> Scans the heap for inaccessible, and hence unmarked,
objects, and returns them to an appropriate free list for reuse. This is
not really a separate phase; even in non incremental mode this is operation
is usually performed on demand during an allocation that discovers an empty
free list. Thus the sweep phase is very unlikely to touch a page that
would not have been touched shortly thereafter anyway.
<LI>
<I>Finalization phase</i> Unreachable objects which had been registered
for finalization are enqueued for finalization outside the collector.
</ol>
<P>
The remaining sections describe the memory allocation data structures,
and then the last 3 collection phases in more detail. We conclude by
outlining some of the additional features implemented in the collector.
<H2>Allocation</h2>
The collector includes its own memory allocator. The allocator obtains
memory from the system in a platform-dependent way. Under UNIX, it
uses either <TT>malloc</tt>, <TT>sbrk</tt>, or <TT>mmap</tt>.
<P>
Most static data used by the allocator, as well as that needed by the
rest of the garbage collector is stored inside the
<TT>_GC_arrays</tt> structure.
This allows the garbage collector to easily ignore the collectors own
data structures when it searches for root pointers. Other allocator
and collector internal data structures are allocated dynamically
with <TT>GC_scratch_alloc</tt>. <TT>GC_scratch_alloc</tt> does not
allow for deallocation, and is therefore used only for permanent data
structures.
<P>
The allocator allocates objects of different <I>kinds</i>.
Different kinds are handled somewhat differently by certain parts
of the garbage collector. Certain kinds are scanned for pointers,
others are not. Some may have per-object type descriptors that
determine pointer locations. Or a specific kind may correspond
to one specific object layout. Two built-in kinds are uncollectable.
One (<TT>STUBBORN</tt>) is immutable without special precautions.
In spite of that, it is very likely that most applications currently
use at most two kinds: <TT>NORMAL</tt> and <TT>PTRFREE</tt> objects.
<P>
The collector uses a two level allocator. A large block is defined to
be one larger than half of <TT>HBLKSIZE</tt>, which is a power of 2,
typically on the order of the page size.
<P>
Large block sizes are rounded up to
the next multiple of <TT>HBLKSIZE</tt> and then allocated by
<TT>GC_allochblk</tt>. This uses roughly what Paul Wilson has termed
a "next fit" algorithm, i.e. first-fit with a rotating pointer.
The implementation does check for a better fitting immediately
adjacent block, which gives it somewhat better fragmentation characteristics.
I'm now convinced it should use a best fit algorithm. The actual
implementation of <TT>GC_allochblk</tt>
is significantly complicated by black-listing issues
(see below).
<P>
Small blocks are allocated in blocks of size <TT>HBLKSIZE</tt>.
Each block is
dedicated to only one object size and kind. The allocator maintains
separate free lists for each size and kind of object.
<P>
In order to avoid allocating blocks for too many distinct object sizes,
the collector normally does not directly allocate objects of every possible
request size. Instead request are rounded up to one of a smaller number
of allocated sizes, for which free lists are maintained. The exact
allocated sizes are computed on demand, but subject to the constraint
that they increase roughly in geometric progression. Thus objects
requested early in the execution are likely to be allocated with exactly
the requested size, subject to alignment constraints.
See <TT>GC_init_size_map</tt> for details.
<P>
The actual size rounding operation during small object allocation is
implemented as a table lookup in <TT>GC_size_map</tt>.
<P>
Both collector initialization and computation of allocated sizes are
handled carefully so that they do not slow down the small object fast
allocation path. An attempt to allocate before the collector is initialized,
or before the appropriate <TT>GC_size_map</tt> entry is computed,
will take the same path as an allocation attempt with an empty free list.
This results in a call to the slow path code (<TT>GC_generic_malloc_inner</tt>)
which performs the appropriate initialization checks.
<P>
In non-incremental mode, we make a decision about whether to garbage collect
whenever an allocation would otherwise have failed with the current heap size.
If the total amount of allocation since the last collection is less than
the heap size divided by <TT>GC_free_space_divisor</tt>, we try to
expand the heap. Otherwise, we initiate a garbage collection. This ensures
that the amount of garbage collection work per allocated byte remains
constant.
<P>
The above is in fat an oversimplification of the real heap expansion
heuristic, which adjusts slightly for root size and certain kinds of
fragmentation. In particular, programs with a large root set size and
little live heap memory will expand the heap to amortize the cost of
scanning the roots.
<P>
Versions 5.x of the collector actually collect more frequently in
nonincremental mode. The large block allocator usually refuses to split
large heap blocks once the garbage collection threshold is
reached. This often has the effect of collecting well before the
heap fills up, thus reducing fragmentation and working set size at the
expense of GC time. 6.x will chose an intermediate strategy depending
on how much large object allocation has taken place in the past.
(If the collector is configured to unmap unused pages, versions 6.x
will use the 5.x strategy.)
<P>
(It has been suggested that this should be adjusted so that we favor
expansion if the resulting heap still fits into physical memory.
In many cases, that would no doubt help. But it is tricky to do this
in a way that remains robust if multiple application are contending
for a single pool of physical memory.)
<H2>Mark phase</h2>
The marker maintains an explicit stack of memory regions that are known
to be accessible, but that have not yet been searched for contained pointers.
Each stack entry contains the starting address of the block to be scanned,
as well as a descriptor of the block. If no layout information is
available for the block, then the descriptor is simply a length.
(For other possibilities, see <TT>gc_mark.h</tt>.)
<P>
At the beginning of the mark phase, all root segments are pushed on the
stack by <TT>GC_push_roots</tt>. If <TT>ALL_INTERIOR_PTRS</tt> is not
defined, then stack roots require special treatment. In this case, the
normal marking code ignores interior pointers, but <TT>GC_push_all_stack</tt>
explicitly checks for interior pointers and pushes descriptors for target
objects.
<P>
The marker is structured to allow incremental marking.
Each call to <TT>GC_mark_some</tt> performs a small amount of
work towards marking the heap.
It maintains
explicit state in the form of <TT>GC_mark_state</tt>, which
identifies a particular sub-phase. Some other pieces of state, most
notably the mark stack, identify how much work remains to be done
in each sub-phase. The normal progression of mark states for
a stop-the-world collection is:
<OL>
<LI> <TT>MS_INVALID</tt> indicating that there may be accessible unmarked
objects. In this case <TT>GC_objects_are_marked</tt> will simultaneously
be false, so the mark state is advanced to
<LI> <TT>MS_PUSH_UNCOLLECTABLE</tt> indicating that it suffices to push
uncollectable objects, roots, and then mark everything reachable from them.
<TT>Scan_ptr</tt> is advanced through the heap until all uncollectable
objects are pushed, and objects reachable from them are marked.
At that point, the next call to <TT>GC_mark_some</tt> calls
<TT>GC_push_roots</tt> to push the roots. It the advances the
mark state to
<LI> <TT>MS_ROOTS_PUSHED</tt> asserting that once the mark stack is
empty, all reachable objects are marked. Once in this state, we work
only on emptying the mark stack. Once this is completed, the state
changes to
<LI> <TT>MS_NONE</tt> indicating that reachable objects are marked.
</ol>
The core mark routine <TT>GC_mark_from_mark_stack</tt>, is called
repeatedly by several of the sub-phases when the mark stack starts to fill
up. It is also called repeatedly in <TT>MS_ROOTS_PUSHED</tt> state
to empty the mark stack.
The routine is designed to only perform a limited amount of marking at
each call, so that it can also be used by the incremental collector.
It is fairly carefully tuned, since it usually consumes a large majority
of the garbage collection time.
<P>
The marker correctly handles mark stack overflows. Whenever the mark stack
overflows, the mark state is reset to <TT>MS_INVALID</tt>.
Since there are already marked objects in the heap,
this eventually forces a complete
scan of the heap, searching for pointers, during which any unmarked objects
referenced by marked objects are again pushed on the mark stack. This
process is repeated until the mark phase completes without a stack overflow.
Each time the stack overflows, an attempt is made to grow the mark stack.
All pieces of the collector that push regions onto the mark stack have to be
careful to ensure forward progress, even in case of repeated mark stack
overflows. Every mark attempt results in additional marked objects.
<P>
Each mark stack entry is processed by examining all candidate pointers
in the range described by the entry. If the region has no associated
type information, then this typically requires that each 4-byte aligned
quantity (8-byte aligned with 64-bit pointers) be considered a candidate
pointer.
<P>
We determine whether a candidate pointer is actually the address of
a heap block. This is done in the following steps:
<NL>
<LI> The candidate pointer is checked against rough heap bounds.
These heap bounds are maintained such that all actual heap objects
fall between them. In order to facilitate black-listing (see below)
we also include address regions that the heap is likely to expand into.
Most non-pointers fail this initial test.
<LI> The candidate pointer is divided into two pieces; the most significant
bits identify a <TT>HBLKSIZE</tt>-sized page in the address space, and
the least significant bits specify an offset within that page.
(A hardware page may actually consist of multiple such pages.
HBLKSIZE is usually the page size divided by a small power of two.)
<LI>
The page address part of the candidate pointer is looked up in a
<A HREF="tree.html">table</a>.
Each table entry contains either 0, indicating that the page is not part
of the garbage collected heap, a small integer <I>n</i>, indicating
that the page is part of large object, starting at least <I>n</i> pages
back, or a pointer to a descriptor for the page. In the first case,
the candidate pointer i not a true pointer and can be safely ignored.
In the last two cases, we can obtain a descriptor for the page containing
the beginning of the object.
<LI>
The starting address of the referenced object is computed.
The page descriptor contains the size of the object(s)
in that page, the object kind, and the necessary mark bits for those
objects. The size information can be used to map the candidate pointer
to the object starting address. To accelerate this process, the page header
also contains a pointer to a precomputed map of page offsets to displacements
from the beginning of an object. The use of this map avoids a
potentially slow integer remainder operation in computing the object
start address.
<LI>
The mark bit for the target object is checked and set. If the object
was previously unmarked, the object is pushed on the mark stack.
The descriptor is read from the page descriptor. (This is computed
from information <TT>GC_obj_kinds</tt> when the page is first allocated.)
</nl>
<P>
At the end of the mark phase, mark bits for left-over free lists are cleared,
in case a free list was accidentally marked due to a stray pointer.
<H2>Sweep phase</h2>
At the end of the mark phase, all blocks in the heap are examined.
Unmarked large objects are immediately returned to the large object free list.
Each small object page is checked to see if all mark bits are clear.
If so, the entire page is returned to the large object free list.
Small object pages containing some reachable object are queued for later
sweeping.
<P>
This initial sweep pass touches only block headers, not
the blocks themselves. Thus it does not require significant paging, even
if large sections of the heap are not in physical memory.
<P>
Nonempty small object pages are swept when an allocation attempt
encounters an empty free list for that object size and kind.
Pages for the correct size and kind are repeatedly swept until at
least one empty block is found. Sweeping such a page involves
scanning the mark bit array in the page header, and building a free
list linked through the first words in the objects themselves.
This does involve touching the appropriate data page, but in most cases
it will be touched only just before it is used for allocation.
Hence any paging is essentially unavoidable.
<P>
Except in the case of pointer-free objects, we maintain the invariant
that any object in a small object free list is cleared (except possibly
for the link field). Thus it becomes the burden of the small object
sweep routine to clear objects. This has the advantage that we can
easily recover from accidentally marking a free list, though that could
also be handled by other means. The collector currently spends a fair
amount of time clearing objects, and this approach should probably be
revisited.
<P>
In most configurations, we use specialized sweep routines to handle common
small object sizes. Since we allocate one mark bit per word, it becomes
easier to examine the relevant mark bits if the object size divides
the word length evenly. We also suitably unroll the inner sweep loop
in each case. (It is conceivable that profile-based procedure cloning
in the compiler could make this unnecessary and counterproductive. I
know of no existing compiler to which this applies.)
<P>
The sweeping of small object pages could be avoided completely at the expense
of examining mark bits directly in the allocator. This would probably
be more expensive, since each allocation call would have to reload
a large amount of state (e.g. next object address to be swept, position
in mark bit table) before it could do its work. The current scheme
keeps the allocator simple and allows useful optimizations in the sweeper.
<H2>Finalization</h2>
Both <TT>GC_register_disappearing_link</tt> and
<TT>GC_register_finalizer</tt> add the request to a corresponding hash
table. The hash table is allocated out of collected memory, but
the reference to the finalizable object is hidden from the collector.
Currently finalization requests are processed non-incrementally at the
end of a mark cycle.
<P>
The collector makes an initial pass over the table of finalizable objects,
pushing the contents of unmarked objects onto the mark stack.
After pushing each object, the marker is invoked to mark all objects
reachable from it. The object itself is not explicitly marked.
This assures that objects on which a finalizer depends are neither
collected nor finalized.
<P>
If in the process of marking from an object the
object itself becomes marked, we have uncovered
a cycle involving the object. This usually results in a warning from the
collector. Such objects are not finalized, since it may be
unsafe to do so. See the more detailed
<A HREF="finalization.html"> discussion of finalization semantics</a>.
<P>
Any objects remaining unmarked at the end of this process are added to
a queue of objects whose finalizers can be run. Depending on collector
configuration, finalizers are dequeued and run either implicitly during
allocation calls, or explicitly in response to a user request.
<P>
The collector provides a mechanism for replacing the procedure that is
used to mark through objects. This is used both to provide support for
Java-style unordered finalization, and to ignore certain kinds of cycles,
<I>e.g.</i> those arising from C++ implementations of virtual inheritance.
<H2>Generational Collection and Dirty Bits</h2>
We basically use the parallel and generational GC algorithm described in
<A HREF="papers/pldi91.ps.gz">"Mostly Parallel Garbage Collection"</a>,
by Boehm, Demers, and Shenker.
<P>
The most significant modification is that
the collector always runs in the allocating thread.
There is no separate garbage collector thread.
If an allocation attempt either requests a large object, or encounters
an empty small object free list, and notices that there is a collection
in progress, it immediately performs a small amount of marking work
as described above.
<P>
This change was made both because we wanted to easily accommodate
single-threaded environments, and because a separate GC thread requires
very careful control over the scheduler to prevent the mutator from
out-running the collector, and hence provoking unneeded heap growth.
<P>
In incremental mode, the heap is always expanded when we encounter
insufficient space for an allocation. Garbage collection is triggered
whenever we notice that more than
<TT>GC_heap_size</tt>/2 * <TT>GC_free_space_divisor</tt>
bytes of allocation have taken place.
After <TT>GC_full_freq</tt> minor collections a major collection
is started.
<P>
All collections initially run interrupted until a predetermined
amount of time (50 msecs by default) has expired. If this allows
the collection to complete entirely, we can avoid correcting
for data structure modifications during the collection. If it does
not complete, we return control to the mutator, and perform small
amounts of additional GC work during those later allocations that
cannot be satisfied from small object free lists. When marking completes,
the set of modified pages is retrieved, and we mark once again from
marked objects on those pages, this time with the mutator stopped.
<P>
We keep track of modified pages using one of three distinct mechanisms:
<OL>
<LI>
Through explicit mutator cooperation. Currently this requires
the use of <TT>GC_malloc_stubborn</tt>.
<LI>
By write-protecting physical pages and catching write faults. This is
implemented for many Unix-like systems and for win32. It is not possible
in a few environments.
<LI>
By retrieving dirty bit information from /proc. (Currently only Sun's
Solaris supports this. Though this is considerably cleaner, performance
may actually be better with mprotect and signals.)
</ol>
<H2>Thread support</h2>
We support several different threading models. Unfortunately Pthreads,
the only reasonably well standardized thread model, supports too narrow
an interface for conservative garbage collection. There appears to be
no portable way to allow the collector to coexist with various Pthreads
implementations. Hence we currently support only a few of the more
common Pthreads implementations.
<P>
In particular, it is very difficult for the collector to stop all other
threads in the system and examine the register contents. This is currently
accomplished with very different mechanisms for different Pthreads
implementations. The Solaris implementation temporarily disables much
of the user-level threads implementation by stopping kernel-level threads
("lwp"s). The Irix implementation sends signals to individual Pthreads
and has them wait in the signal handler. The Linux implementation
is similar in spirit to the Irix one.
<P>
The Irix implementation uses
only documented Pthreads calls, but relies on extensions to their semantics,
notably the use of mutexes and condition variables from signal
handlers. The Linux implementation should be far closer to
portable, though impirically it is not completely portable.
<P>
All implementations must
intercept thread creation and a few other thread-specific calls to allow
enumeration of threads and location of thread stacks. This is current
accomplished with <TT># define</tt>'s in <TT>gc.h</tt>, or optionally
by using ld's function call wrapping mechanism under Linux.
<P>
Comments are appreciated. Please send mail to
<A HREF="mailto:boehm@acm.org"><TT>boehm@acm.org</tt></a>
</body>

198
boehm-gc/doc/tree.html Normal file
View File

@ -0,0 +1,198 @@
<HTML>
<HEAD>
<TITLE> Two-Level Tree Structure for Fast Pointer Lookup</TITLE>
<AUTHOR> Hans-J. Boehm, Silicon Graphics</author>
</HEAD>
<BODY>
<H1>Two-Level Tree Structure for Fast Pointer Lookup</h1>
<P>
The conservative garbage collector described
<A HREF="gc.html">here</a> uses a 2-level tree
data structure to aid in fast pointer identification.
This data structure is described in a bit more detail here, since
<OL>
<LI> Variations of the data structure are more generally useful.
<LI> It appears to be hard to understand by reading the code.
<LI> Some other collectors appear to use inferior data structures to
solve the same problem.
<LI> It is central to fast collector operation.
</ol>
A candidate pointer is divided into three sections, the <I>high</i>,
<I>middle</i>, and <I>low</i> bits. The exact division between these
three groups of bits is dependent on the detailed collector configuration.
<P>
The high and middle bits are used to look up an entry in the table described
here. The resulting table entry consists of either a block descriptor
(<TT>struct hblkhdr *</tt> or <TT>hdr *</tt>)
identifying the layout of objects in the block, or an indication that this
address range corresponds to the middle of a large block, together with a
hint for locating the actual block descriptor. Such a hint consist
of a displacement that can be subtracted from the middle bits of the candidate
pointer without leaving the object.
<P>
In either case, the block descriptor (<TT>struct hblkhdr</tt>)
refers to a table of object starting addresses (the <TT>hb_map</tt> field).
The starting address table is indexed by the low bits if the candidate pointer.
The resulting entry contains a displacement to the beginning of the object,
or an indication that this cannot be a valid object pointer.
(If all interior pointer are recognized, pointers into large objects
are handled specially, as appropriate.)
<H2>The Tree</h2>
<P>
The rest of this discussion focuses on the two level data structure
used to map the high and middle bits to the block descriptor.
<P>
The high bits are used as an index into the <TT>GC_top_index</tt> (really
<TT>GC_arrays._top_index</tt>) array. Each entry points to a
<TT>bottom_index</tt> data structure. This structure in turn consists
mostly of an array <TT>index</tt> indexed by the middle bits of
the candidate pointer. The <TT>index</tt> array contains the actual
<TT>hdr</tt> pointers.
<P>
Thus a pointer lookup consists primarily of a handful of memory references,
and can be quite fast:
<OL>
<LI> The appropriate <TT>bottom_index</tt> pointer is looked up in
<TT>GC_top_index</tt>, based on the high bits of the candidate pointer.
<LI> The appropriate <TT>hdr</tt> pointer is looked up in the
<TT>bottom_index</tt> structure, based on the middle bits.
<LI> The block layout map pointer is retrieved from the <TT>hdr</tt>
structure. (This memory reference is necessary since we try to share
block layout maps.)
<LI> The displacement to the beginning of the object is retrieved from the
above map.
</ol>
<P>
In order to conserve space, not all <TT>GC_top_index</tt> entries in fact
point to distinct <TT>bottom_index</tt> structures. If no address with
the corresponding high bits is part of the heap, then the entry points
to <TT>GC_all_nils</tt>, a single <TT>bottom_index</tt> structure consisting
only of NULL <TT>hdr</tt> pointers.
<P>
<TT>Bottom_index</tt> structures contain slightly more information than
just <TT>hdr</tt> pointers. The <TT>asc_link</tt> field is used to link
all <TT>bottom_index</tt> structures in ascending order for fast traversal.
This list is pointed to be <TT>GC_all_bottom_indices</tt>.
It is maintained with the aid of <TT>key</tt> field that contains the
high bits corresponding to the <TT>bottom_index</tt>.
<H2>64 bit addresses</h2>
<P>
In the case of 64 bit addresses, this picture is complicated slightly
by the fact that one of the index structures would have to be huge to
cover the entire address space with a two level tree. We deal with this
by turning <TT>GC_top_index</tt> into a chained hash table, instead of
a simple array. This adds a <TT>hash_link</tt> field to the
<TT>bottom_index</tt> structure.
<P>
The "hash function" consists of dropping the high bits. This is cheap to
compute, and guarantees that there will be no collisions if the heap
is contiguous and not excessively large.
<H2>A picture</h2>
<P>
The following is an ASCII diagram of the data structure.
This was contributed by Dave Barrett several years ago.
<PRE>
Data Structure used by GC_base in gc3.7:
21-Apr-94
63 LOG_TOP_SZ[11] LOG_BOTTOM_SZ[10] LOG_HBLKSIZE[13]
+------------------+----------------+------------------+------------------+
p:| | TL_HASH(hi) | | HBLKDISPL(p) |
+------------------+----------------+------------------+------------------+
\-----------------------HBLKPTR(p)-------------------/
\------------hi-------------------/
\______ ________/ \________ _______/ \________ _______/
V V V
| | |
GC_top_index[] | | |
--- +--------------+ | | |
^ | | | | |
| | | | | |
TOP +--------------+<--+ | |
_SZ +-<| [] | * | |
(items)| +--------------+ if 0 < bi< HBLKSIZE | |
| | | | then large object | |
| | | | starts at the bi'th | |
v | | | HBLK before p. | i |
--- | +--------------+ | (word- |
v | aligned) |
bi= |GET_BI(p){->hash_link}->key==hi | |
v | |
| (bottom_index) \ scratch_alloc'd | |
| ( struct bi ) / by get_index() | |
--- +->+--------------+ | |
^ | | | |
^ | | | |
BOTTOM | | ha=GET_HDR_ADDR(p) | |
_SZ(items)+--------------+<----------------------+ +-------+
| +--<| index[] | |
| | +--------------+ GC_obj_map: v
| | | | from / +-+-+-----+-+-+-+-+ ---
v | | | GC_add < 0| | | | | | | | ^
--- | +--------------+ _map_entry \ +-+-+-----+-+-+-+-+ |
| | asc_link | +-+-+-----+-+-+-+-+ MAXOBJSZ
| +--------------+ +-->| | | j | | | | | +1
| | key | | +-+-+-----+-+-+-+-+ |
| +--------------+ | +-+-+-----+-+-+-+-+ |
| | hash_link | | | | | | | | | | v
| +--------------+ | +-+-+-----+-+-+-+-+ ---
| | |<--MAX_OFFSET--->|
| | (bytes)
HDR(p)| GC_find_header(p) | |<--MAP_ENTRIES-->|
| \ from | =HBLKSIZE/WORDSZ
| (hdr) (struct hblkhdr) / alloc_hdr() | (1024 on Alpha)
+-->+----------------------+ | (8/16 bits each)
GET_HDR(p)| word hb_sz (words) | |
+----------------------+ |
| struct hblk *hb_next | |
+----------------------+ |
|mark_proc hb_mark_proc| |
+----------------------+ |
| char * hb_map |>-------------+
+----------------------+
| ushort hb_obj_kind |
+----------------------+
| hb_last_reclaimed |
--- +----------------------+
^ | |
MARK_BITS| hb_marks[] | *if hdr is free, hb_sz + DISCARD_WORDS
_SZ(words)| | is the size of a heap chunk (struct hblk)
v | | of at least MININCR*HBLKSIZE bytes (below),
--- +----------------------+ otherwise, size of each object in chunk.
Dynamic data structures above are interleaved throughout the heap in blocks of
size MININCR * HBLKSIZE bytes as done by gc_scratch_alloc which cannot be
freed; free lists are used (e.g. alloc_hdr). HBLK's below are collected.
(struct hblk)
--- +----------------------+ < HBLKSIZE --- --- DISCARD_
^ |garbage[DISCARD_WORDS]| aligned ^ ^ HDR_BYTES WORDS
| | | | v (bytes) (words)
| +-----hb_body----------+ < WORDSZ | --- ---
| | | aligned | ^ ^
| | Object 0 | | hb_sz |
| | | i |(word- (words)|
| | | (bytes)|aligned) v |
| + - - - - - - - - - - -+ --- | --- |
| | | ^ | ^ |
n * | | j (words) | hb_sz BODY_SZ
HBLKSIZE | Object 1 | v v | (words)
(bytes) | |--------------- v MAX_OFFSET
| + - - - - - - - - - - -+ --- (bytes)
| | | !All_INTERIOR_PTRS ^ |
| | | sets j only for hb_sz |
| | Object N | valid object offsets. | |
v | | All objects WORDSZ v v
--- +----------------------+ aligned. --- ---
DISCARD_WORDS is normally zero. Indeed the collector has not been tested
with another value in ages.
</pre>
</body>

13
boehm-gc/gcname.c Normal file
View File

@ -0,0 +1,13 @@
#include <stdio.h>
#include "version.h"
int main()
{
if (GC_ALPHA_VERSION == GC_NOT_ALPHA) {
printf("gc%d.%d", GC_VERSION_MAJOR, GC_VERSION_MINOR);
} else {
printf("gc%d.%dalpha%d", GC_VERSION_MAJOR,
GC_VERSION_MINOR, GC_ALPHA_VERSION);
}
return 0;
}

251
boehm-gc/install-sh Executable file
View File

@ -0,0 +1,251 @@
#!/bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5 (mit/util/scripts/install.sh).
#
# Copyright 1991 by the Massachusetts Institute of Technology
#
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in advertising or
# publicity pertaining to distribution of the software without specific,
# written prior permission. M.I.T. makes no representations about the
# suitability of this software for any purpose. It is provided "as is"
# without express or implied warranty.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
true
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
chmodcmd=""
else
instcmd=mkdir
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
then
true
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
true
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
true
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
true
fi
pathcomp="${pathcomp}/"
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
true
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0

435
boehm-gc/libtool.m4 vendored Normal file
View File

@ -0,0 +1,435 @@
## libtool.m4 - Configure libtool for the target system. -*-Shell-script-*-
## Copyright (C) 1996-1999 Free Software Foundation, Inc.
## Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
##
## 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 of the License, 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.
##
## As a special exception to the GNU General Public License, if you
## distribute this file as part of a program that contains a
## configuration script generated by Autoconf, you may include it under
## the same distribution terms that you use for the rest of that program.
# serial 40 AC_PROG_LIBTOOL
AC_DEFUN(AC_PROG_LIBTOOL,
[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
# Save cache, so that ltconfig can load it
AC_CACHE_SAVE
# Actually configure libtool. ac_aux_dir is where install-sh is found.
CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \
LD="$LD" LDFLAGS="$LDFLAGS" LIBS="$LIBS" \
LN_S="$LN_S" NM="$NM" RANLIB="$RANLIB" \
DLLTOOL="$DLLTOOL" AS="$AS" OBJDUMP="$OBJDUMP" \
${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \
$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $lt_target \
|| AC_MSG_ERROR([libtool configure failed])
# Reload cache, that may have been modified by ltconfig
AC_CACHE_LOAD
# This can be used to rebuild libtool when needed
LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh"
# Always use our own libtool.
LIBTOOL='$(SHELL) $(top_builddir)/libtool'
AC_SUBST(LIBTOOL)dnl
# Redirect the config.log output again, so that the ltconfig log is not
# clobbered by the next message.
exec 5>>./config.log
])
AC_DEFUN(AC_LIBTOOL_SETUP,
[AC_PREREQ(2.13)dnl
AC_REQUIRE([AC_ENABLE_SHARED])dnl
AC_REQUIRE([AC_ENABLE_STATIC])dnl
AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl
AC_REQUIRE([AC_CANONICAL_HOST])dnl
AC_REQUIRE([AC_CANONICAL_BUILD])dnl
AC_REQUIRE([AC_PROG_RANLIB])dnl
AC_REQUIRE([AC_PROG_CC])dnl
AC_REQUIRE([AC_PROG_LD])dnl
AC_REQUIRE([AC_PROG_NM])dnl
AC_REQUIRE([AC_PROG_LN_S])dnl
dnl
case "$target" in
NONE) lt_target="$host" ;;
*) lt_target="$target" ;;
esac
# Check for any special flags to pass to ltconfig.
#
# the following will cause an existing older ltconfig to fail, so
# we ignore this at the expense of the cache file... Checking this
# will just take longer ... bummer!
#libtool_flags="--cache-file=$cache_file"
#
test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared"
test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static"
test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install"
test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc"
test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld"
ifdef([AC_PROVIDE_AC_LIBTOOL_DLOPEN],
[libtool_flags="$libtool_flags --enable-dlopen"])
ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL],
[libtool_flags="$libtool_flags --enable-win32-dll"])
AC_ARG_ENABLE(libtool-lock,
[ --disable-libtool-lock avoid locking (might break parallel builds)])
test "x$enable_libtool_lock" = xno && libtool_flags="$libtool_flags --disable-lock"
test x"$silent" = xyes && libtool_flags="$libtool_flags --silent"
# Some flags need to be propagated to the compiler or linker for good
# libtool support.
case "$lt_target" in
*-*-irix6*)
# Find out which ABI we are using.
echo '[#]line __oline__ "configure"' > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile); then
case "`/usr/bin/file conftest.o`" in
*32-bit*)
LD="${LD-ld} -32"
;;
*N32*)
LD="${LD-ld} -n32"
;;
*64-bit*)
LD="${LD-ld} -64"
;;
esac
fi
rm -rf conftest*
;;
*-*-sco3.2v5*)
# On SCO OpenServer 5, we need -belf to get full-featured binaries.
SAVE_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -belf"
AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
[AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])])
if test x"$lt_cv_cc_needs_belf" != x"yes"; then
# this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
CFLAGS="$SAVE_CFLAGS"
fi
;;
ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL],
[*-*-cygwin* | *-*-mingw*)
AC_CHECK_TOOL(DLLTOOL, dlltool, false)
AC_CHECK_TOOL(AS, as, false)
AC_CHECK_TOOL(OBJDUMP, objdump, false)
;;
])
esac
])
# AC_LIBTOOL_DLOPEN - enable checks for dlopen support
AC_DEFUN(AC_LIBTOOL_DLOPEN, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])])
# AC_LIBTOOL_WIN32_DLL - declare package support for building win32 dll's
AC_DEFUN(AC_LIBTOOL_WIN32_DLL, [AC_BEFORE([$0], [AC_LIBTOOL_SETUP])])
# AC_ENABLE_SHARED - implement the --enable-shared flag
# Usage: AC_ENABLE_SHARED[(DEFAULT)]
# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to
# `yes'.
AC_DEFUN(AC_ENABLE_SHARED, [dnl
define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
AC_ARG_ENABLE(shared,
changequote(<<, >>)dnl
<< --enable-shared[=PKGS] build shared libraries [default=>>AC_ENABLE_SHARED_DEFAULT],
changequote([, ])dnl
[p=${PACKAGE-default}
case "$enableval" in
yes) enable_shared=yes ;;
no) enable_shared=no ;;
*)
enable_shared=no
# Look at the argument we got. We use all the common list separators.
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
for pkg in $enableval; do
if test "X$pkg" = "X$p"; then
enable_shared=yes
fi
done
IFS="$ac_save_ifs"
;;
esac],
enable_shared=AC_ENABLE_SHARED_DEFAULT)dnl
])
# AC_DISABLE_SHARED - set the default shared flag to --disable-shared
AC_DEFUN(AC_DISABLE_SHARED, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
AC_ENABLE_SHARED(no)])
# AC_ENABLE_STATIC - implement the --enable-static flag
# Usage: AC_ENABLE_STATIC[(DEFAULT)]
# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to
# `yes'.
AC_DEFUN(AC_ENABLE_STATIC, [dnl
define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
AC_ARG_ENABLE(static,
changequote(<<, >>)dnl
<< --enable-static[=PKGS] build static libraries [default=>>AC_ENABLE_STATIC_DEFAULT],
changequote([, ])dnl
[p=${PACKAGE-default}
case "$enableval" in
yes) enable_static=yes ;;
no) enable_static=no ;;
*)
enable_static=no
# Look at the argument we got. We use all the common list separators.
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
for pkg in $enableval; do
if test "X$pkg" = "X$p"; then
enable_static=yes
fi
done
IFS="$ac_save_ifs"
;;
esac],
enable_static=AC_ENABLE_STATIC_DEFAULT)dnl
])
# AC_DISABLE_STATIC - set the default static flag to --disable-static
AC_DEFUN(AC_DISABLE_STATIC, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
AC_ENABLE_STATIC(no)])
# AC_ENABLE_FAST_INSTALL - implement the --enable-fast-install flag
# Usage: AC_ENABLE_FAST_INSTALL[(DEFAULT)]
# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to
# `yes'.
AC_DEFUN(AC_ENABLE_FAST_INSTALL, [dnl
define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
AC_ARG_ENABLE(fast-install,
changequote(<<, >>)dnl
<< --enable-fast-install[=PKGS] optimize for fast installation [default=>>AC_ENABLE_FAST_INSTALL_DEFAULT],
changequote([, ])dnl
[p=${PACKAGE-default}
case "$enableval" in
yes) enable_fast_install=yes ;;
no) enable_fast_install=no ;;
*)
enable_fast_install=no
# Look at the argument we got. We use all the common list separators.
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
for pkg in $enableval; do
if test "X$pkg" = "X$p"; then
enable_fast_install=yes
fi
done
IFS="$ac_save_ifs"
;;
esac],
enable_fast_install=AC_ENABLE_FAST_INSTALL_DEFAULT)dnl
])
# AC_ENABLE_FAST_INSTALL - set the default to --disable-fast-install
AC_DEFUN(AC_DISABLE_FAST_INSTALL, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
AC_ENABLE_FAST_INSTALL(no)])
# AC_PROG_LD - find the path to the GNU or non-GNU linker
AC_DEFUN(AC_PROG_LD,
[AC_ARG_WITH(gnu-ld,
[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]],
test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
AC_REQUIRE([AC_PROG_CC])dnl
AC_REQUIRE([AC_CANONICAL_HOST])dnl
AC_REQUIRE([AC_CANONICAL_BUILD])dnl
ac_prog=ld
if test "$ac_cv_prog_gcc" = yes; then
# Check if gcc -print-prog-name=ld gives a path.
AC_MSG_CHECKING([for ld used by GCC])
ac_prog=`($CC -print-prog-name=ld) 2>&5`
case "$ac_prog" in
# Accept absolute paths.
changequote(,)dnl
[\\/]* | [A-Za-z]:[\\/]*)
re_direlt='/[^/][^/]*/\.\./'
changequote([,])dnl
# Canonicalize the path of ld
ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
done
test -z "$LD" && LD="$ac_prog"
;;
"")
# If it fails, then pretend we aren't using GCC.
ac_prog=ld
;;
*)
# If it is relative, then search for the first ld in PATH.
with_gnu_ld=unknown
;;
esac
elif test "$with_gnu_ld" = yes; then
AC_MSG_CHECKING([for GNU ld])
else
AC_MSG_CHECKING([for non-GNU ld])
fi
AC_CACHE_VAL(ac_cv_path_LD,
[if test -z "$LD"; then
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
for ac_dir in $PATH; do
test -z "$ac_dir" && ac_dir=.
if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
ac_cv_path_LD="$ac_dir/$ac_prog"
# Check to see if the program is GNU ld. I'd rather use --version,
# but apparently some GNU ld's only accept -v.
# Break only if it was the GNU/non-GNU ld that we prefer.
if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
test "$with_gnu_ld" != no && break
else
test "$with_gnu_ld" != yes && break
fi
fi
done
IFS="$ac_save_ifs"
else
ac_cv_path_LD="$LD" # Let the user override the test with a path.
fi])
LD="$ac_cv_path_LD"
if test -n "$LD"; then
AC_MSG_RESULT($LD)
else
AC_MSG_RESULT(no)
fi
test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
AC_PROG_LD_GNU
])
AC_DEFUN(AC_PROG_LD_GNU,
[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], ac_cv_prog_gnu_ld,
[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
ac_cv_prog_gnu_ld=yes
else
ac_cv_prog_gnu_ld=no
fi])
])
# AC_PROG_NM - find the path to a BSD-compatible name lister
AC_DEFUN(AC_PROG_NM,
[AC_MSG_CHECKING([for BSD-compatible nm])
AC_CACHE_VAL(ac_cv_path_NM,
[if test -n "$NM"; then
# Let the user override the test.
ac_cv_path_NM="$NM"
else
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
test -z "$ac_dir" && ac_dir=.
if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext ; then
# Check to see if the nm accepts a BSD-compat flag.
# Adding the `sed 1q' prevents false positives on HP-UX, which says:
# nm: unknown option "B" ignored
if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
ac_cv_path_NM="$ac_dir/nm -B"
break
elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
ac_cv_path_NM="$ac_dir/nm -p"
break
else
ac_cv_path_NM=${ac_cv_path_NM="$ac_dir/nm"} # keep the first match, but
continue # so that we can try to find one that supports BSD flags
fi
fi
done
IFS="$ac_save_ifs"
test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm
fi])
NM="$ac_cv_path_NM"
AC_MSG_RESULT([$NM])
])
# AC_CHECK_LIBM - check for math library
AC_DEFUN(AC_CHECK_LIBM,
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
LIBM=
case "$lt_target" in
*-*-beos* | *-*-cygwin*)
# These system don't have libm
;;
*-ncr-sysv4.3*)
AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
AC_CHECK_LIB(m, main, LIBM="$LIBM -lm")
;;
*)
AC_CHECK_LIB(m, main, LIBM="-lm")
;;
esac
])
# AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for
# the libltdl convenience library, adds --enable-ltdl-convenience to
# the configure arguments. Note that LIBLTDL is not AC_SUBSTed, nor
# is AC_CONFIG_SUBDIRS called. If DIR is not provided, it is assumed
# to be `${top_builddir}/libltdl'. Make sure you start DIR with
# '${top_builddir}/' (note the single quotes!) if your package is not
# flat, and, if you're not using automake, define top_builddir as
# appropriate in the Makefiles.
AC_DEFUN(AC_LIBLTDL_CONVENIENCE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
case "$enable_ltdl_convenience" in
no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
"") enable_ltdl_convenience=yes
ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
esac
LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdlc.la
INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl'])
])
# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for
# the libltdl installable library, and adds --enable-ltdl-install to
# the configure arguments. Note that LIBLTDL is not AC_SUBSTed, nor
# is AC_CONFIG_SUBDIRS called. If DIR is not provided, it is assumed
# to be `${top_builddir}/libltdl'. Make sure you start DIR with
# '${top_builddir}/' (note the single quotes!) if your package is not
# flat, and, if you're not using automake, define top_builddir as
# appropriate in the Makefiles.
# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
AC_DEFUN(AC_LIBLTDL_INSTALLABLE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
AC_CHECK_LIB(ltdl, main,
[test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no],
[if test x"$enable_ltdl_install" = xno; then
AC_MSG_WARN([libltdl not installed, but installation disabled])
else
enable_ltdl_install=yes
fi
])
if test x"$enable_ltdl_install" = x"yes"; then
ac_configure_args="$ac_configure_args --enable-ltdl-install"
LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdl.la
INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl'])
else
ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
LIBLTDL="-lltdl"
INCLTDL=
fi
])
dnl old names
AC_DEFUN(AM_PROG_LIBTOOL, [indir([AC_PROG_LIBTOOL])])dnl
AC_DEFUN(AM_ENABLE_SHARED, [indir([AC_ENABLE_SHARED], $@)])dnl
AC_DEFUN(AM_ENABLE_STATIC, [indir([AC_ENABLE_STATIC], $@)])dnl
AC_DEFUN(AM_DISABLE_SHARED, [indir([AC_DISABLE_SHARED], $@)])dnl
AC_DEFUN(AM_DISABLE_STATIC, [indir([AC_DISABLE_STATIC], $@)])dnl
AC_DEFUN(AM_PROG_LD, [indir([AC_PROG_LD])])dnl
AC_DEFUN(AM_PROG_NM, [indir([AC_PROG_NM])])dnl
dnl This is just to silence aclocal about the macro not being used
ifelse([AC_DISABLE_FAST_INSTALL])dnl

3078
boehm-gc/ltconfig Executable file

File diff suppressed because it is too large Load Diff

4012
boehm-gc/ltmain.sh Normal file

File diff suppressed because it is too large Load Diff

36
boehm-gc/mkinstalldirs Executable file
View File

@ -0,0 +1,36 @@
#! /bin/sh
# mkinstalldirs --- make directory hierarchy
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
# Created: 1993-05-16
# Last modified: 1994-03-25
# Public domain
errstatus=0
for file in ${1+"$@"} ; do
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
shift
pathcomp=
for d in ${1+"$@"} ; do
pathcomp="$pathcomp$d"
case "$pathcomp" in
-* ) pathcomp=./$pathcomp ;;
esac
if test ! -d "$pathcomp"; then
echo "mkdir $pathcomp" 1>&2
mkdir "$pathcomp" > /dev/null 2>&1 || lasterr=$?
fi
if test ! -d "$pathcomp"; then
errstatus=$lasterr
fi
pathcomp="$pathcomp/"
done
done
exit $errstatus
# mkinstalldirs ends here