Initial revision
From-SVN: r44969
This commit is contained in:
parent
b38a75e57d
commit
61f38a77a0
15 changed files with 11927 additions and 0 deletions
597
boehm-gc/Makefile.direct
Normal file
597
boehm-gc/Makefile.direct
Normal 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
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
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
90
boehm-gc/digimars.mak
Normal 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
|
59
boehm-gc/doc/README.autoconf
Normal file
59
boehm-gc/doc/README.autoconf
Normal 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.
|
||||
|
||||
|
78
boehm-gc/doc/README.macros
Normal file
78
boehm-gc/doc/README.macros
Normal 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
289
boehm-gc/doc/debugging.html
Normal 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
|
||||
(<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 > 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 > 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
438
boehm-gc/doc/gcdescr.html
Normal 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
198
boehm-gc/doc/tree.html
Normal 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
13
boehm-gc/gcname.c
Normal 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
251
boehm-gc/install-sh
Executable 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
435
boehm-gc/libtool.m4
vendored
Normal 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
3078
boehm-gc/ltconfig
Executable file
File diff suppressed because it is too large
Load diff
4012
boehm-gc/ltmain.sh
Normal file
4012
boehm-gc/ltmain.sh
Normal file
File diff suppressed because it is too large
Load diff
36
boehm-gc/mkinstalldirs
Executable file
36
boehm-gc/mkinstalldirs
Executable 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
|
Loading…
Add table
Reference in a new issue