Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Unity-Technologies/bdwgc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Boehm <boehm@acm.org>2004-05-06 04:00:00 +0400
committerIvan Maidanski <ivmai@mail.ru>2014-05-17 18:55:00 +0400
commitf3602b41a93efcb0891a1805f8150794cb302feb (patch)
tree9bf1ef1174143c8e3b62d851852d1128b09e6f7c
parent66f2b649d22f423f961301305d40b600a2426ae2 (diff)
gc6.3alpha6 tarball importgc6_3alpha6
-rw-r--r--Makefile14
-rw-r--r--Makefile.direct14
-rw-r--r--Makefile.in2
-rw-r--r--checksums.c34
-rwxr-xr-xconfigure24
-rw-r--r--configure.in4
-rw-r--r--dbg_mlc.c10
-rw-r--r--doc/Makefile.am2
-rw-r--r--doc/Makefile.in2
-rw-r--r--doc/README2
-rw-r--r--doc/README.changes26
-rw-r--r--doc/simple_example.html202
-rw-r--r--dyn_load.c14
-rw-r--r--include/gc.h3
-rw-r--r--include/gc_allocator.h5
-rw-r--r--include/gc_config_macros.h5
-rw-r--r--include/private/gcconfig.h46
-rw-r--r--ltconfig3
-rw-r--r--mark.c8
-rw-r--r--new_hblk.c12
-rw-r--r--os_dep.c62
-rw-r--r--pthread_stop_world.c58
-rw-r--r--tests/test.c4
-rw-r--r--version.h2
24 files changed, 438 insertions, 120 deletions
diff --git a/Makefile b/Makefile
index 74929c18..f2b32246 100644
--- a/Makefile
+++ b/Makefile
@@ -320,14 +320,15 @@ DOC_FILES= README.QUICK doc/README.Mac doc/README.MacOSX doc/README.OS2 \
doc/README.environment doc/tree.html doc/gcdescr.html \
doc/README.autoconf doc/README.macros doc/README.ews4800 \
doc/README.DGUX386 doc/README.arm.cross doc/leak.html \
- doc/scale.html doc/gcinterface.html doc/README.darwin
+ doc/scale.html doc/gcinterface.html doc/README.darwin \
+ doc/simple_example.html
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 \
- ltconfig aclocal.m4 config.sub config.guess \
+ aclocal.m4 config.sub config.guess \
include/Makefile.am include/Makefile.in \
doc/Makefile.am doc/Makefile.in \
ltmain.sh mkinstalldirs depcomp missing
@@ -367,16 +368,23 @@ SPECIALCFLAGS = -I$(srcdir)/include
all: gc.a gctest
-BSD-pkg-all: bsd-libgc.a
+LEAKFLAGS=$(CFLAGS) -DFIND_LEAK
+
+BSD-pkg-all: bsd-libgc.a bsd-libleak.a
bsd-libgc.a:
$(MAKE) CFLAGS="$(CFLAGS)" clean c++-t
mv gc.a bsd-libgc.a
+bsd-libleak.a:
+ $(MAKE) -f Makefile.direct CFLAGS="$(LEAKFLAGS)" clean c++-nt
+ mv gc.a bsd-libleak.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
+ ${INSTALL_MAN} doc/gc.man ${PREFIX}/man/man3/gc.3
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 \
diff --git a/Makefile.direct b/Makefile.direct
index 74929c18..f2b32246 100644
--- a/Makefile.direct
+++ b/Makefile.direct
@@ -320,14 +320,15 @@ DOC_FILES= README.QUICK doc/README.Mac doc/README.MacOSX doc/README.OS2 \
doc/README.environment doc/tree.html doc/gcdescr.html \
doc/README.autoconf doc/README.macros doc/README.ews4800 \
doc/README.DGUX386 doc/README.arm.cross doc/leak.html \
- doc/scale.html doc/gcinterface.html doc/README.darwin
+ doc/scale.html doc/gcinterface.html doc/README.darwin \
+ doc/simple_example.html
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 \
- ltconfig aclocal.m4 config.sub config.guess \
+ aclocal.m4 config.sub config.guess \
include/Makefile.am include/Makefile.in \
doc/Makefile.am doc/Makefile.in \
ltmain.sh mkinstalldirs depcomp missing
@@ -367,16 +368,23 @@ SPECIALCFLAGS = -I$(srcdir)/include
all: gc.a gctest
-BSD-pkg-all: bsd-libgc.a
+LEAKFLAGS=$(CFLAGS) -DFIND_LEAK
+
+BSD-pkg-all: bsd-libgc.a bsd-libleak.a
bsd-libgc.a:
$(MAKE) CFLAGS="$(CFLAGS)" clean c++-t
mv gc.a bsd-libgc.a
+bsd-libleak.a:
+ $(MAKE) -f Makefile.direct CFLAGS="$(LEAKFLAGS)" clean c++-nt
+ mv gc.a bsd-libleak.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
+ ${INSTALL_MAN} doc/gc.man ${PREFIX}/man/man3/gc.3
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 \
diff --git a/Makefile.in b/Makefile.in
index 2c7c1b72..5477b555 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -326,7 +326,7 @@ RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \
DIST_COMMON = $(dist_noinst_HEADERS) $(dist_noinst_SCRIPTS) \
$(include_HEADERS) Makefile.am Makefile.in acinclude.m4 \
aclocal.m4 config.guess config.sub configure configure.in \
- depcomp install-sh ltconfig ltmain.sh missing mkinstalldirs
+ depcomp install-sh ltmain.sh missing mkinstalldirs
DIST_SUBDIRS = $(SUBDIRS)
SOURCES = $(libgc_la_SOURCES) $(EXTRA_libgc_la_SOURCES) $(libgccpp_la_SOURCES) $(gctest_SOURCES) $(test_cpp_SOURCES)
diff --git a/checksums.c b/checksums.c
index 121c36d4..57a6ebc2 100644
--- a/checksums.c
+++ b/checksums.c
@@ -13,14 +13,14 @@
/* Boehm, March 29, 1995 12:51 pm PST */
# ifdef CHECKSUMS
-# include "gc_priv.h"
+# include "private/gc_priv.h"
/* This is debugging code intended to verify the results of dirty bit */
/* computations. Works only in a single threaded environment. */
/* We assume that stubborn objects are changed only when they are */
/* enabled for writing. (Certain kinds of writing are actually */
/* safe under other conditions.) */
-# define NSUMS 2000
+# define NSUMS 10000
# define OFFSET 0x10000
@@ -29,7 +29,7 @@ typedef struct {
word old_sum;
word new_sum;
struct hblk * block; /* Block to which this refers + OFFSET */
- /* to hide it from colector. */
+ /* to hide it from collector. */
} page_entry;
page_entry GC_sums [NSUMS];
@@ -76,12 +76,13 @@ int index;
{
page_entry *pe = GC_sums + index;
register hdr * hhdr = HDR(h);
+ struct hblk *b;
if (pe -> block != 0 && pe -> block != h + OFFSET) ABORT("goofed");
pe -> old_sum = pe -> new_sum;
pe -> new_sum = GC_checksum(h);
# if !defined(MSWIN32) && !defined(MSWINCE)
- if (pe -> new_sum != 0 && !GC_page_was_ever_dirty(h)) {
+ if (pe -> new_sum != 0x80000000 && !GC_page_was_ever_dirty(h)) {
GC_printf1("GC_page_was_ever_dirty(0x%lx) is wrong\n",
(unsigned long)h);
}
@@ -91,13 +92,19 @@ int index;
} else {
GC_n_clean++;
}
- if (pe -> new_valid && pe -> old_sum != pe -> new_sum) {
+ b = h;
+ while (IS_FORWARDING_ADDR_OR_NIL(hhdr) && hhdr != 0) {
+ b -= (word)hhdr;
+ hhdr = HDR(b);
+ }
+ if (pe -> new_valid
+ && hhdr != 0 && hhdr -> hb_descr != 0 /* may contain pointers */
+ && pe -> old_sum != pe -> new_sum) {
if (!GC_page_was_dirty(h) || !GC_page_was_ever_dirty(h)) {
/* Set breakpoint here */GC_n_dirty_errors++;
}
# ifdef STUBBORN_ALLOC
- if (!IS_FORWARDING_ADDR_OR_NIL(hhdr)
- && hhdr -> hb_map != GC_invalid_map
+ if ( hhdr -> hb_map != GC_invalid_map
&& hhdr -> hb_obj_kind == STUBBORN
&& !GC_page_was_changed(h)
&& !GC_on_free_list(h)) {
@@ -120,26 +127,17 @@ word dummy;
register hdr * hhdr = HDR(h);
register bytes = WORDS_TO_BYTES(hhdr -> hb_sz);
- bytes += HDR_BYTES + HBLKSIZE-1;
+ bytes += HBLKSIZE-1;
bytes &= ~(HBLKSIZE-1);
GC_bytes_in_used_blocks += bytes;
}
void GC_check_blocks()
{
- word bytes_in_free_blocks = 0;
- struct hblk * h = GC_hblkfreelist;
- hdr * hhdr = HDR(h);
- word sz;
+ word bytes_in_free_blocks = GC_large_free_bytes;
GC_bytes_in_used_blocks = 0;
GC_apply_to_all_blocks(GC_add_block, (word)0);
- while (h != 0) {
- sz = hhdr -> hb_sz;
- bytes_in_free_blocks += sz;
- h = hhdr -> hb_next;
- hhdr = HDR(h);
- }
GC_printf2("GC_bytes_in_used_blocks = %ld, bytes_in_free_blocks = %ld ",
GC_bytes_in_used_blocks, bytes_in_free_blocks);
GC_printf1("GC_heapsize = %ld\n", GC_heapsize);
diff --git a/configure b/configure
index 3ede246c..84b7f1ca 100755
--- a/configure
+++ b/configure
@@ -1,7 +1,7 @@
#! /bin/sh
# From configure.in Revision: 1.2 .
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.53 for gc 6.3alpha5.
+# Generated by GNU Autoconf 2.53 for gc 6.3alpha6.
#
# Report bugs to <Hans.Boehm@hp.com>.
#
@@ -416,8 +416,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='gc'
PACKAGE_TARNAME='gc'
-PACKAGE_VERSION='6.3alpha5'
-PACKAGE_STRING='gc 6.3alpha5'
+PACKAGE_VERSION='6.3alpha6'
+PACKAGE_STRING='gc 6.3alpha6'
PACKAGE_BUGREPORT='Hans.Boehm@hp.com'
ac_unique_file="gcj_mlc.c"
@@ -930,7 +930,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures gc 6.3alpha5 to adapt to many kinds of systems.
+\`configure' configures gc 6.3alpha6 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -997,7 +997,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of gc 6.3alpha5:";;
+ short | recursive ) echo "Configuration of gc 6.3alpha6:";;
esac
cat <<\_ACEOF
@@ -1106,7 +1106,7 @@ fi
test -n "$ac_init_help" && exit 0
if $ac_init_version; then
cat <<\_ACEOF
-gc configure 6.3alpha5
+gc configure 6.3alpha6
generated by GNU Autoconf 2.53
Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
@@ -1121,7 +1121,7 @@ cat >&5 <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by gc $as_me 6.3alpha5, which was
+It was created by gc $as_me 6.3alpha6, which was
generated by GNU Autoconf 2.53. Invocation command line was
$ $0 $@
@@ -1782,7 +1782,7 @@ fi
# Define the identity of the package.
PACKAGE=gc
- VERSION=6.3alpha5
+ VERSION=6.3alpha6
cat >>confdefs.h <<_ACEOF
@@ -8558,8 +8558,6 @@ LIBTOOL='$(SHELL) $(top_builddir)/libtool'
#
# Check for AViiON Machines running DGUX
#
-echo "$as_me:$LINENO: checking if host is AViiON running DGUX" >&5
-echo $ECHO_N "checking if host is AViiON running DGUX... $ECHO_C" >&6
ac_is_dgux=no
if test "${ac_cv_header_sys_dg_sys_info_h+set}" = set; then
echo "$as_me:$LINENO: checking for sys/dg_sys_info.h" >&5
@@ -8668,8 +8666,6 @@ fi
-echo "$as_me:$LINENO: result: $ac_is_dgux" >&5
-echo "${ECHO_T}$ac_is_dgux" >&6
## :GOTCHA: we do not check anything but sys/dg_sys_info.h
if test $ac_is_dgux = yes; then
if test "$enable_full_debug" = "yes"; then
@@ -9347,7 +9343,7 @@ _ASBOX
} >&5
cat >&5 <<_CSEOF
-This file was extended by gc $as_me 6.3alpha5, which was
+This file was extended by gc $as_me 6.3alpha6, which was
generated by GNU Autoconf 2.53. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -9404,7 +9400,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-gc config.status 6.3alpha5
+gc config.status 6.3alpha6
configured by $0, generated by GNU Autoconf 2.53,
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
diff --git a/configure.in b/configure.in
index 635742cf..3e3aba34 100644
--- a/configure.in
+++ b/configure.in
@@ -17,7 +17,7 @@ dnl Process this file with autoconf to produce configure.
# Initialization
# ==============
-AC_INIT(gc,6.3alpha5,Hans.Boehm@hp.com)
+AC_INIT(gc,6.3alpha6,Hans.Boehm@hp.com)
## version must conform to [0-9]+[.][0-9]+(alpha[0-9]+)?
AC_CONFIG_SRCDIR(gcj_mlc.c)
AC_CANONICAL_TARGET
@@ -308,12 +308,10 @@ AC_PROG_LIBTOOL
#
# Check for AViiON Machines running DGUX
#
-AC_MSG_CHECKING(if host is AViiON running DGUX)
ac_is_dgux=no
AC_CHECK_HEADER(sys/dg_sys_info.h,
[ac_is_dgux=yes;])
-AC_MSG_RESULT($ac_is_dgux)
## :GOTCHA: we do not check anything but sys/dg_sys_info.h
if test $ac_is_dgux = yes; then
if test "$enable_full_debug" = "yes"; then
diff --git a/dbg_mlc.c b/dbg_mlc.c
index 9daa0b0d..aacbb7a1 100644
--- a/dbg_mlc.c
+++ b/dbg_mlc.c
@@ -818,7 +818,15 @@ GC_PTR p;
uncollectable = TRUE;
}
# endif
- if (uncollectable) GC_free(base);
+ if (uncollectable) {
+ GC_free(base);
+ } else {
+ size_t i;
+ size_t obj_sz = hhdr -> hb_sz - BYTES_TO_WORDS(sizeof(oh));
+
+ for (i = 0; i < obj_sz; ++i) ((word *)p)[i] = 0xdeadbeef;
+ GC_ASSERT((word *)p + i == (word *)base + hhdr -> hb_sz);
+ }
} /* !GC_find_leak */
}
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 91446305..9446bcb1 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -23,5 +23,5 @@ dist_pkgdata_DATA = barrett_diagram debugging.html gc.man \
README.MacOSX README.macros README.OS2 README.rs6000 \
README.sgi README.solaris2 README.uts README.win32 \
tree.html leak.html gcinterface.html scale.html \
- README.darwin
+ README.darwin simple_example.html
diff --git a/doc/Makefile.in b/doc/Makefile.in
index 1e9dd929..708fd51b 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -127,7 +127,7 @@ dist_pkgdata_DATA = barrett_diagram debugging.html gc.man \
README.MacOSX README.macros README.OS2 README.rs6000 \
README.sgi README.solaris2 README.uts README.win32 \
tree.html leak.html gcinterface.html scale.html \
- README.darwin
+ README.darwin simple_example.html
subdir = doc
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
diff --git a/doc/README b/doc/README
index 0776e678..ae978c11 100644
--- a/doc/README
+++ b/doc/README
@@ -28,7 +28,7 @@ are GPL'ed, but with an exception that should cover all uses in the
collector. (If you are concerned about such things, I recommend you look
at the notice in config.guess or ltmain.sh.)
-This is version 6.3alpha5 of a conservative garbage collector for C and C++.
+This is version 6.3alpha6 of a conservative garbage collector for C and C++.
You might find a more recent version of this at
diff --git a/doc/README.changes b/doc/README.changes
index 38bde346..129738cf 100644
--- a/doc/README.changes
+++ b/doc/README.changes
@@ -2049,9 +2049,33 @@ Since 6.3alpha4:
- The USE_MUNMAP code could get confused about the age of a block and
prematurely unmap it. GC_unmap_old had a bug related to wrapping of
GC_gc_no. GC_freehblk and GC_merge_unmapped didn't maintain
- hb_last_reclaimed reasonably when blockas were merged. The code was
+ hb_last_reclaimed reasonably when blocks were merged. The code was
fixed to reflect original intent, but that may not always be an
improvement. See todo list item.
+
+Since 6.3alpha5:
+ - Define USE_GENERIC_PUSH_REGS for NetBSD/M68K.
+ - Fixed the X86_64 PREFETCH macros to correctly handle ia32e (which uses
+ different prefetch instructions from AMD64). (Thanks to H.J. Lu.)
+ - GC_config_macros.h did not correctly define GC_WIN32_THREADS from
+ GC_THREADS.
+ - Added simple_example.html.
+ - Merged Andrew Gray's patch to correctly restore signal handlers on
+ FreeBSD.
+ - Merged a patch from Andreas Jaeger to deal with prefetch-related warnings
+ on x86-64. Added some other casts so that the PREFETCH macros
+ always get a ptr_t argument. Removed some casts inthe PREFETCH
+ implementations.
+ - At Jesse Jones suggestion: Added a header guard for gc_allocator.h
+ and changed GC_debug_free to clobber contents of deallocated object.
+ - The signal masking code in pthread_stop_world.c contained some errors.
+ In particular SIGSEGV was masked in the handler, in spite of the fact that
+ it wrote to the heap. This could lead to an uncaught SIGSEGV, which
+ apparently became much more likely in Linux 2.6. Also fixed some
+ typos, and reduced code duplication in the same area.
+ - Remove ltconfig, clean up configure messages for DGUX (thanks to
+ Adrian Bunk for the patches).
+ - Integrated NetBSD/OpenBSD patches from Marc Recht and Matthias Drochner.
To do:
- The USE_MUNMAP code should really use a separate data structure
diff --git a/doc/simple_example.html b/doc/simple_example.html
new file mode 100644
index 00000000..0bc0953e
--- /dev/null
+++ b/doc/simple_example.html
@@ -0,0 +1,202 @@
+<HTML>
+<HEAD>
+<TITLE>Using the Garbage Collector: A simple example</title>
+</head>
+<BODY>
+<H1>Using the Garbage Collector: A simple example</h1>
+The following consists of step-by-step instructions for building and
+using the collector. We'll assume a Linux/gcc platform and
+a single-threaded application. <FONT COLOR=green>The green
+text contains information about other platforms or scenarios.
+It can be skipped, especially on first reading</font>.
+<H2>Building the collector</h2>
+If you haven't already so, unpack the collector and enter
+the newly created directory with
+<PRE>
+tar xvfz gc<version>.tar.gz
+cd gc<version>
+</pre>
+<P>
+You can configure, build, and install the collector in a private
+directory, say /home/xyz/gc, with the following commands:
+<PRE>
+./configure --prefix=/home/xyz/gc --disable-threads
+make
+make check
+make install
+</pre>
+Here the "<TT>make check</tt>" command is optional, but highly recommended.
+It runs a basic correctness test which usually takes well under a minute.
+<FONT COLOR=green>
+<H3>Other platforms</h3>
+On non-Unix, non-Linux platforms, the collector is usually built by copying
+the appropriate makefile (see the platform-specific README in doc/README.xxx
+in the distribution) to the file "Makefile" (overwriting the copy of
+Makefile.direct that was originally there), and then typing "make"
+(or "nmake" or ...). This builds the library in the source tree. You may
+want to move it and the files in the include directory to a more convenient
+place.
+<P>
+If you use a makefile that does not require running a configure script,
+you should first look at the makefile, and adjust any options that are
+documented there.
+<P>
+If your platform provides a "make" utility, that is generally preferred
+to platform- and compiler- dependent "project" files. (At least that is the
+strong preference of the would-be maintainer of those project files.)
+<H3>Threads</h3>
+If you need thread support, configure the collector with
+<PRE>
+--enable-threads=posix --enable-thread-local-alloc --enable-parallel-mark
+</pre>
+instead of
+<TT>--disable-threads</tt>
+If your target is a real old-fashioned uniprocessor (no "hyperthreading",
+etc.) you will want to omit <TT>--enable-parallel-mark</tt>.
+<H3>C++</h3>
+You will need to include the C++ support, which unfortunately tends to
+be among the least portable parts of the collector, since it seems
+to rely on some corner cases of the language. On Linux, it
+suffices to add <TT>--enable-cplusplus</tt> to the configure options.
+</font>
+<H2>Writing the program</h2>
+You will need a
+<PRE>
+#include "gc.h"
+</pre>
+at the beginning of every file that allocates memory through the
+garbage collector. Call <TT>GC_MALLOC</tt> wherever you would
+have call <TT>malloc</tt>. This initializes memory to zero like
+<TT>calloc</tt>; there is no need to explicitly clear the
+result.
+<P>
+If you know that an object will not contain pointers to the
+garbage-collected heap, and you don't need it to be initialized,
+call <TT>GC_MALLOC_ATOMIC</tt> instead.
+<P>
+A function <TT>GC_FREE</tt> is provided but need not be called.
+For very small objects, your program will probably perform better if
+you do not call it, and let the collector do its job.
+<P>
+A <TT>GC_REALLOC</tt> function behaves like the C library <TT>realloc</tt>.
+It allocates uninitialized pointer-free memory if the original
+object was allocated that way.
+<P>
+The following program <TT>loop.c</tt> is a trivial example:
+<PRE>
+#include "gc.h"
+#include &lt;assert.h&gt;
+#include &lt;stdio.h&gt;
+
+int main()
+{
+ int i;
+
+ GC_INIT(); /* Optional on Linux/X86; see below. */
+ for (i = 0; i < 10000000; ++i)
+ {
+ int **p = (int **) GC_MALLOC(sizeof(int *));
+ int *q = (int *) GC_MALLOC_ATOMIC(sizeof(int));
+ assert(*p == 0);
+ *p = (int *) GC_REALLOC(q, 2 * sizeof(int));
+ if (i % 100000 == 0)
+ printf("Heap size = %d\n", GC_get_heap_size());
+ }
+ return 0;
+}
+</pre>
+<FONT COLOR=green>
+<H3>Interaction with the system malloc</h3>
+It is usually best not to mix garbage-collected allocation with the system
+<TT>malloc-free</tt>. If you do, you need to be careful not to store
+pointers to the garbage-collected heap in memory allocated with the system
+<TT>malloc</tt>.
+<H3>Other Platforms</h3>
+On some other platforms it is necessary to call <TT>GC_INIT()</tt> from the main program,
+which is presumed to be part of the main executable, not a dynamic library.
+This can never hurt, and is thus generally good practice.
+
+<H3>Threads</h3>
+For a multithreaded program some more rules apply:
+<UL>
+<LI>
+Files that either allocate through the GC <I>or make thread-related calls</i>
+should first define the macro <TT>GC_THREADS</tt>, and then
+include <TT>"gc.h"</tt>. On some platforms this will redefine some
+threads primitives, e.g. to let the collector keep track of thread creation.
+<LI>
+To take advantage of fast thread-local allocation, use the following instead
+of including <TT>gc.h</tt>:
+<PRE>
+#define GC_REDIRECT_TO_LOCAL
+#include "gc_local_alloc.h"
+</pre>
+This will cause GC_MALLOC and GC_MALLOC_ATOMIC to keep per-thread allocation
+caches, and greatly reduce the number of lock acquisitions during allocation.
+</ul>
+
+<H3>C++</h3>
+In the case of C++, you need to be especially careful not to store pointers
+to the garbage-collected heap in areas that are not traced by the collector.
+The collector includes some <A HREF="gcinterface.html">alternate interfaces</a>
+to make that easier.
+
+<H3>Debugging</h3>
+Additional debug checks can be performed by defining <TT>GC_DEBUG</tt> before
+including <TT>gc.h</tt>. Additional options are available if the collector
+is also built with <TT>--enable-full_debug</tt> and all allocations are
+performed with <TT>GC_DEBUG</tt> defined.
+
+<H3>What if I can't rewrite/recompile my program?</h3>
+You may be able to build the collector with <TT>--enable-redirect-malloc</tt>
+and set the <TT>LD_PRELOAD</tt> environment variable to point to the resulting
+library, thus replacing the standard <TT>malloc</tt> with its garbage-collected
+counterpart. This is rather platform dependent. See the
+<A HREF="leak.html">leak detection documentation</a> for some more details.
+
+</font>
+
+<H2>Compiling and linking</h2>
+
+The above application <TT>loop.c</tt> test program can be compiled and linked
+with
+
+<PRE>
+cc -I/home/xyz/gc/include loop.c /home/xyz/gc/lib/libgc.a -o loop
+</pre>
+
+The <TT>-I</tt> option directs the compiler to the right include
+directory. In this case, we list the static library
+directly on the compile line; the dynamic library could have been
+used instead, provided we arranged for the dynamic loader to find
+it, e.g. by setting <TT>LD_LIBRARY_PATH</tt>.
+
+<FONT COLOR=green>
+
+<H3>Threads</h3>
+
+On pthread platforms, you will of course also have to link with
+<TT>-lpthread</tt>,
+and compile with any thread-safety options required by your compiler.
+On some platforms, you may also need to link with <TT>-ldl</tt>
+or <TT>-lrt</tt>.
+Looking at threadlibs.c in the GC build directory
+should give you the appropriate
+list if a plain <TT>-lpthread</tt> doesn't work.
+
+</font>
+
+<H2>Running the executable</h2>
+
+The executable can of course be run normally, e.g. by typing
+
+<PRE>
+./loop
+</pre>
+
+The operation of the collector is affected by a number of environment variables.
+For example, setting <TT>GC_PRINT_STATS</tt> produces some
+GC statistics on stdout.
+See <TT>README.environment</tt> in the distribution for details.
+</body>
+</html>
diff --git a/dyn_load.c b/dyn_load.c
index 70eb7644..9bd9e060 100644
--- a/dyn_load.c
+++ b/dyn_load.c
@@ -91,10 +91,18 @@
/* Newer versions of GNU/Linux define this macro. We
* define it similarly for any ELF systems that don't. */
# ifndef ElfW
-# if !defined(ELF_CLASS) || ELF_CLASS == ELFCLASS32
-# define ElfW(type) Elf32_##type
+# ifdef __NetBSD__
+# if ELFSIZE == 32
+# define ElfW(type) Elf32_##type
+# else
+# define ElfW(type) Elf64_##type
+# endif
# else
-# define ElfW(type) Elf64_##type
+# if !defined(ELF_CLASS) || ELF_CLASS == ELFCLASS32
+# define ElfW(type) Elf32_##type
+# else
+# define ElfW(type) Elf64_##type
+# endif
# endif
# endif
diff --git a/include/gc.h b/include/gc.h
index 58a2ff54..ae555ae6 100644
--- a/include/gc.h
+++ b/include/gc.h
@@ -778,6 +778,7 @@ GC_API GC_PTR GC_call_with_alloc_lock
/* The following routines are primarily intended for use with a */
/* preprocessor which inserts calls to check C pointer arithmetic. */
+/* They indicate failure by invoking the corresponding _print_proc. */
/* Check that p and q point to the same object. */
/* Fail conspicuously if they don't. */
@@ -855,7 +856,7 @@ GC_API GC_PTR GC_is_valid_displacement GC_PROTO((GC_PTR p));
# define GC_PTR_STORE(p, q) *((p) = (q))
#endif
-/* Fynctions called to report pointer checking errors */
+/* Functions called to report pointer checking errors */
GC_API void (*GC_same_obj_print_proc) GC_PROTO((GC_PTR p, GC_PTR q));
GC_API void (*GC_is_valid_displacement_print_proc)
diff --git a/include/gc_allocator.h b/include/gc_allocator.h
index 87c85099..b0c188cd 100644
--- a/include/gc_allocator.h
+++ b/include/gc_allocator.h
@@ -35,6 +35,10 @@
* library, which itself was derived from the SGI STL implementation.
*/
+#ifndef GC_ALLOCATOR_H
+
+#define GC_ALLOCATOR_H
+
#include "gc.h" // For size_t
/* First some helpers to allow us to dispatch on whether or not a type
@@ -230,3 +234,4 @@ inline bool operator!=(const traceable_allocator<GC_T1>&, const traceable_alloca
return false;
}
+#endif /* GC_ALLOCATOR_H */
diff --git a/include/gc_config_macros.h b/include/gc_config_macros.h
index 4aaca2d3..d8d31141 100644
--- a/include/gc_config_macros.h
+++ b/include/gc_config_macros.h
@@ -97,7 +97,10 @@
# endif
#endif /* GC_THREADS */
-#if defined(GC_THREADS) && !defined(GC_PTHREADS) && defined(MSWIN32)
+#if defined(GC_THREADS) && !defined(GC_PTHREADS) && \
+ (defined(_WIN32) || defined(_MSC_VER) || defined(__CYGWIN__) \
+ || defined(__MINGW32__) || defined(__BORLANDC__) \
+ || defined(_WIN32_WCE))
# define GC_WIN32_THREADS
#endif
diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h
index 734bd855..94b446b6 100644
--- a/include/private/gcconfig.h
+++ b/include/private/gcconfig.h
@@ -310,6 +310,10 @@
# define I386
# define mach_type_known
# endif
+# if defined(__NetBSD__) && defined(__x86_64__)
+# define X86_64
+# define mach_type_known
+# endif
# if defined(bsdi) && (defined(i386) || defined(__i386__))
# define I386
# define BSDI
@@ -605,8 +609,14 @@
# ifdef OPENBSD
# define OS_TYPE "OPENBSD"
# define HEURISTIC2
- extern char etext[];
-# define DATASTART ((ptr_t)(etext))
+# ifdef __ELF__
+# define DATASTART GC_data_start
+# define DYNAMIC_LOADING
+# else
+ extern char etext[];
+# define DATASTART ((ptr_t)(etext))
+# endif
+# define USE_GENERIC_PUSH_REGS
# endif
# ifdef NETBSD
# define OS_TYPE "NETBSD"
@@ -618,6 +628,7 @@
extern char etext[];
# define DATASTART ((ptr_t)(etext))
# endif
+# define USE_GENERIC_PUSH_REGS
# endif
# ifdef LINUX
# define OS_TYPE "LINUX"
@@ -1086,6 +1097,8 @@
# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff))
# endif
# ifdef USE_I686_PREFETCH
+ /* FIXME: Thus should use __builtin_prefetch, but we'll leave that */
+ /* for the next rtelease. */
# define PREFETCH(x) \
__asm__ __volatile__ (" prefetchnta %0": : "m"(*(char *)(x)))
/* Empirically prefetcht0 is much more effective at reducing */
@@ -1624,17 +1637,17 @@
# ifdef __GNUC__
# ifndef __INTEL_COMPILER
# define PREFETCH(x) \
- __asm__ (" lfetch [%0]": : "r"((void *)(x)))
+ __asm__ (" lfetch [%0]": : "r"(x))
# define PREFETCH_FOR_WRITE(x) \
- __asm__ (" lfetch.excl [%0]": : "r"((void *)(x)))
+ __asm__ (" lfetch.excl [%0]": : "r"(x))
# define CLEAR_DOUBLE(x) \
__asm__ (" stf.spill [%0]=f0": : "r"((void *)(x)))
# else
# include <ia64intrin.h>
# define PREFETCH(x) \
- __lfetch(__lfhint_none, (void*)(x))
+ __lfetch(__lfhint_none, (x))
# define PREFETCH_FOR_WRITE(x) \
- __lfetch(__lfhint_nta, (void*)(x))
+ __lfetch(__lfhint_nta, (x))
# define CLEAR_DOUBLE(x) \
__stf_spill((void *)(x), 0)
# endif // __INTEL_COMPILER
@@ -1840,10 +1853,19 @@
extern int etext[];
# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff))
# endif
-# define PREFETCH(x) \
- __asm__ __volatile__ (" prefetch %0": : "m"(*(char *)(x)))
-# define PREFETCH_FOR_WRITE(x) \
- __asm__ __volatile__ (" prefetchw %0": : "m"(*(char *)(x)))
+# if defined(__GNUC__) && __GNUC >= 3
+# define PREFETCH(x) __builtin_prefetch((x), 0, 0)
+# define PREFETCH_FOR_WRITE(x) __builtin_prefetch((x), 1)
+# endif
+# endif
+# ifdef NETBSD
+# define OS_TYPE "NETBSD"
+# ifdef __ELF__
+# define DYNAMIC_LOADING
+# endif
+# define HEURISTIC2
+ extern char etext[];
+# define SEARCH_FOR_DATA_START
# endif
# endif
@@ -1907,6 +1929,10 @@
# define SUNOS5SIGS
# endif
+# if defined(FREEBSD) && (__FreeBSD__ >= 4)
+# define SUNOS5SIGS
+# endif
+
# if defined(SVR4) || defined(LINUX) || defined(IRIX5) || defined(HPUX) \
|| defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD) \
|| defined(DGUX) || defined(BSD) || defined(SUNOS4) \
diff --git a/ltconfig b/ltconfig
deleted file mode 100644
index 962057f0..00000000
--- a/ltconfig
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-# I could find no versions of autoconf that don't invoke ltconfig, but
-# libtool no longer includes an ltconfig. Yuch.
diff --git a/mark.c b/mark.c
index 4b654683..dd1fbd5f 100644
--- a/mark.c
+++ b/mark.c
@@ -684,7 +684,7 @@ mse * mark_stack_limit;
current = *current_p;
FIXUP_POINTER(current);
if ((ptr_t)current >= least_ha && (ptr_t)current < greatest_ha) {
- PREFETCH(current);
+ PREFETCH((ptr_t)current);
HC_PUSH_CONTENTS((ptr_t)current, mark_stack_top,
mark_stack_limit, current_p, exit1);
}
@@ -760,7 +760,7 @@ mse * mark_stack_limit;
FIXUP_POINTER(deferred);
limit = (word *)((char *)limit - ALIGNMENT);
if ((ptr_t)deferred >= least_ha && (ptr_t)deferred < greatest_ha) {
- PREFETCH(deferred);
+ PREFETCH((ptr_t)deferred);
break;
}
if (current_p > limit) goto next_object;
@@ -770,7 +770,7 @@ mse * mark_stack_limit;
FIXUP_POINTER(deferred);
limit = (word *)((char *)limit - ALIGNMENT);
if ((ptr_t)deferred >= least_ha && (ptr_t)deferred < greatest_ha) {
- PREFETCH(deferred);
+ PREFETCH((ptr_t)deferred);
break;
}
if (current_p > limit) goto next_object;
@@ -787,7 +787,7 @@ mse * mark_stack_limit;
if ((ptr_t)current >= least_ha && (ptr_t)current < greatest_ha) {
/* Prefetch the contents of the object we just pushed. It's */
/* likely we will need them soon. */
- PREFETCH(current);
+ PREFETCH((ptr_t)current);
HC_PUSH_CONTENTS((ptr_t)current, mark_stack_top,
mark_stack_limit, current_p, exit2);
}
diff --git a/new_hblk.c b/new_hblk.c
index 1aa2c7a1..e5580e4c 100644
--- a/new_hblk.c
+++ b/new_hblk.c
@@ -104,7 +104,7 @@ ptr_t ofl;
p[3] = 0;
p += 4;
for (; p < lim; p += 4) {
- PREFETCH_FOR_WRITE(p+64);
+ PREFETCH_FOR_WRITE((ptr_t)(p+64));
p[0] = (word)(p-4);
p[1] = 0;
CLEAR_DOUBLE(p+2);
@@ -142,7 +142,7 @@ ptr_t ofl;
p[4] = (word)p;
p += 8;
for (; p < lim; p += 8) {
- PREFETCH_FOR_WRITE(p+64);
+ PREFETCH_FOR_WRITE((ptr_t)(p+64));
p[0] = (word)(p-4);
p[4] = (word)p;
};
@@ -171,10 +171,10 @@ ptr_t list;
/* If we were more serious about it, these should go inside */
/* the loops. But write prefetches usually don't seem to */
/* matter much. */
- PREFETCH_FOR_WRITE((char *)h);
- PREFETCH_FOR_WRITE((char *)h + 128);
- PREFETCH_FOR_WRITE((char *)h + 256);
- PREFETCH_FOR_WRITE((char *)h + 378);
+ PREFETCH_FOR_WRITE((ptr_t)h);
+ PREFETCH_FOR_WRITE((ptr_t)h + 128);
+ PREFETCH_FOR_WRITE((ptr_t)h + 256);
+ PREFETCH_FOR_WRITE((ptr_t)h + 378);
/* Handle small objects sizes more efficiently. For larger objects */
/* the difference is less significant. */
# ifndef SMALL_CONFIG
diff --git a/os_dep.c b/os_dep.c
index cb32bdd0..29eee4ee 100644
--- a/os_dep.c
+++ b/os_dep.c
@@ -129,7 +129,7 @@
#ifdef UNIX_LIKE
# include <fcntl.h>
-# ifdef SUNOS5SIGS
+# if defined(SUNOS5SIGS) && !defined(FREEBSD)
# include <sys/siginfo.h>
# endif
/* Define SETJMP and friends to be the version that restores */
@@ -2225,9 +2225,9 @@ GC_bool is_ptrfree;
# endif /* !DARWIN */
# endif /* MSWIN32 || MSWINCE || DARWIN */
-#if defined(SUNOS4) || defined(FREEBSD)
+#if defined(SUNOS4) || (defined(FREEBSD) && !defined(SUNOS5SIGS))
typedef void (* SIG_PF)();
-#endif /* SUNOS4 || FREEBSD */
+#endif /* SUNOS4 || (FREEBSD && !SUNOS5SIGS) */
#if defined(SUNOS5SIGS) || defined(OSF1) || defined(LINUX) \
|| defined(HURD)
@@ -2254,13 +2254,13 @@ GC_bool is_ptrfree;
#endif /* IRIX5 || OSF1 || HURD */
#if defined(SUNOS5SIGS)
-# ifdef HPUX
-# define SIGINFO __siginfo
+# if defined(HPUX) || defined(FREEBSD)
+# define SIGINFO_T siginfo_t
# else
-# define SIGINFO siginfo
+# define SIGINFO_T struct siginfo
# endif
# ifdef __STDC__
- typedef void (* REAL_SIG_PF)(int, struct SIGINFO *, void *);
+ typedef void (* REAL_SIG_PF)(int, SIGINFO_T *, void *);
# else
typedef void (* REAL_SIG_PF)();
# endif
@@ -2356,7 +2356,7 @@ SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */
/*ARGSUSED*/
#if !defined(DARWIN)
-# if defined (SUNOS4) || defined(FREEBSD)
+# if defined (SUNOS4) || (defined(FREEBSD) && !defined(SUNOS5SIGS))
void GC_write_fault_handler(sig, code, scp, addr)
int sig, code;
struct sigcontext *scp;
@@ -2371,7 +2371,7 @@ SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */
# define SIG_OK (sig == SIGBUS)
# define CODE_OK (code == BUS_PAGE_FAULT)
# endif
-# endif /* SUNOS4 || FREEBSD */
+# endif /* SUNOS4 || (FREEBSD && !SUNOS5SIGS) */
# if defined(IRIX5) || defined(OSF1) || defined(HURD)
# include <errno.h>
@@ -2413,11 +2413,11 @@ SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */
# if defined(SUNOS5SIGS)
# ifdef __STDC__
- void GC_write_fault_handler(int sig, struct SIGINFO *scp, void * context)
+ void GC_write_fault_handler(int sig, SIGINFO_T *scp, void * context)
# else
void GC_write_fault_handler(sig, scp, context)
int sig;
- struct SIGINFO *scp;
+ SIGINFO_T *scp;
void * context;
# endif
# ifdef HPUX
@@ -2428,9 +2428,14 @@ SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */
|| (scp -> si_code == SEGV_UNKNOWN) \
|| (scp -> si_code == BUS_OBJERR)
# else
-# define SIG_OK (sig == SIGSEGV)
-# define CODE_OK (scp -> si_code == SEGV_ACCERR)
-# endif
+# ifdef FREEBSD
+# define SIG_OK (sig == SIGBUS)
+# define CODE_OK (scp -> si_code == BUS_PAGE_FAULT)
+# else
+# define SIG_OK (sig == SIGSEGV)
+# define CODE_OK (scp -> si_code == SEGV_ACCERR)
+# endif
+# endif
# endif /* SUNOS5SIGS */
# if defined(MSWIN32) || defined(MSWINCE)
@@ -2533,6 +2538,10 @@ SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */
in_allocd_block = (HDR(addr) != 0);
# endif
if (!in_allocd_block) {
+ /* FIXME - We should make sure that we invoke the */
+ /* old handler with the appropriate calling */
+ /* sequence, which often depends on SA_SIGINFO. */
+
/* Heap blocks now begin and end on page boundaries */
SIG_PF old_handler;
@@ -2549,11 +2558,17 @@ SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */
return(EXCEPTION_CONTINUE_SEARCH);
# endif
} else {
-# if defined (SUNOS4) || defined(FREEBSD)
+# if defined (SUNOS4) \
+ || (defined(FREEBSD) && !defined(SUNOS5SIGS))
(*old_handler) (sig, code, scp, addr);
return;
# endif
# if defined (SUNOS5SIGS)
+ /*
+ * FIXME: For FreeBSD, this code should check if the
+ * old signal handler used the traditional BSD style and
+ * if so call it using that style.
+ */
(*(REAL_SIG_PF)old_handler) (sig, scp, context);
return;
# endif
@@ -2678,7 +2693,7 @@ void GC_dirty_init()
GC_err_printf0("Page size not multiple of HBLKSIZE\n");
ABORT("Page size not multiple of HBLKSIZE");
}
-# if defined(SUNOS4) || defined(FREEBSD)
+# if defined(SUNOS4) || (defined(FREEBSD) && !defined(SUNOS5SIGS))
GC_old_bus_handler = signal(SIGBUS, GC_write_fault_handler);
if (GC_old_bus_handler == SIG_IGN) {
GC_err_printf0("Previously ignored bus error!?");
@@ -2702,13 +2717,13 @@ void GC_dirty_init()
# endif
}
# endif
-# if defined(SUNOS5SIGS) || defined(IRIX5) || defined(LINUX) \
- || defined(OSF1) || defined(HURD)
+# if (defined(SUNOS5SIGS) && !defined(FREEBSD)) || defined(IRIX5) \
+ || defined(LINUX) || defined(OSF1) || defined(HURD)
/* SUNOS5SIGS includes HPUX */
# if defined(GC_IRIX_THREADS)
sigaction(SIGSEGV, 0, &oldact);
sigaction(SIGSEGV, &act, 0);
-# else
+# else
{
int res = sigaction(SIGSEGV, &act, &oldact);
if (res != 0) ABORT("Sigaction failed");
@@ -2734,8 +2749,9 @@ void GC_dirty_init()
GC_err_printf0("Replaced other SIGSEGV handler\n");
# endif
}
-# endif
-# if defined(HPUX) || defined(LINUX) || defined(HURD)
+# endif /* (SUNOS5SIGS && !FREEBSD) || IRIX5 || LINUX || OSF1 || HURD */
+# if defined(HPUX) || defined(LINUX) || defined(HURD) \
+ || (defined(FREEBSD) && defined(SUNOS5SIGS))
sigaction(SIGBUS, &act, &oldact);
GC_old_bus_handler = oldact.sa_handler;
if (GC_old_bus_handler == SIG_IGN) {
@@ -2747,7 +2763,7 @@ void GC_dirty_init()
GC_err_printf0("Replaced other SIGBUS handler\n");
# endif
}
-# endif /* HPUX || LINUX || HURD */
+# endif /* HPUX || LINUX || HURD || (FREEBSD && SUNOS5SIGS) */
# if defined(MSWIN32)
GC_old_segv_handler = SetUnhandledExceptionFilter(GC_write_fault_handler);
if (GC_old_segv_handler != NULL) {
@@ -3146,7 +3162,7 @@ int dummy;
GC_proc_buf = bufp = new_buf;
GC_proc_buf_size = new_size;
}
- if (syscall(SYS_read, GC_proc_fd, bufp, GC_proc_buf_size) <= 0) {
+ if (READ(GC_proc_fd, bufp, GC_proc_buf_size) <= 0) {
WARN("Insufficient space for /proc read\n", 0);
/* Punt: */
memset(GC_grungy_pages, 0xff, sizeof (page_hash_table));
diff --git a/pthread_stop_world.c b/pthread_stop_world.c
index 1cdda21a..832c49ca 100644
--- a/pthread_stop_world.c
+++ b/pthread_stop_world.c
@@ -39,6 +39,34 @@ void GC_print_sig_mask()
#endif
+/* Remove the signals that we want to allow in thread stopping */
+/* handler from a set. */
+void GC_remove_allowed_signals(sigset_t *set)
+{
+# ifdef NO_SIGNALS
+ if (sigdelset(set, SIGINT) != 0
+ || sigdelset(set, SIGQUIT) != 0
+ || sigdelset(set, SIGABRT) != 0
+ || sigdelset(set, SIGTERM) != 0) {
+ ABORT("sigdelset() failed");
+ }
+# endif
+
+# ifdef MPROTECT_VDB
+ /* Handlers write to the thread structure, which is in the heap, */
+ /* and hence can trigger a protection fault. */
+ if (sigdelset(set, SIGSEGV) != 0
+# ifdef SIGBUS
+ || sigdelset(set, SIGBUS) != 0
+# endif
+ ) {
+ ABORT("sigdelset() failed");
+ }
+# endif
+}
+
+static sigset_t suspend_handler_mask;
+
word GC_stop_count; /* Incremented at the beginning of GC_stop_world. */
#ifdef GC_OSF1_THREADS
@@ -78,7 +106,6 @@ void GC_suspend_handler(int sig)
int dummy;
pthread_t my_thread = pthread_self();
GC_thread me;
- sigset_t mask;
# ifdef PARALLEL_MARK
word my_mark_no = GC_mark_no;
/* Marker can't proceed until we acknowledge. Thus this is */
@@ -125,17 +152,9 @@ void GC_suspend_handler(int sig)
/* this thread a SIG_THR_RESTART signal. */
/* SIG_THR_RESTART should be masked at this point. Thus there */
/* is no race. */
- if (sigfillset(&mask) != 0) ABORT("sigfillset() failed");
- if (sigdelset(&mask, SIG_THR_RESTART) != 0) ABORT("sigdelset() failed");
-# ifdef NO_SIGNALS
- if (sigdelset(&mask, SIGINT) != 0) ABORT("sigdelset() failed");
- if (sigdelset(&mask, SIGQUIT) != 0) ABORT("sigdelset() failed");
- if (sigdelset(&mask, SIGTERM) != 0) ABORT("sigdelset() failed");
- if (sigdelset(&mask, SIGABRT) != 0) ABORT("sigdelset() failed");
-# endif
do {
me->stop_info.signal = 0;
- sigsuspend(&mask); /* Wait for signal */
+ sigsuspend(&suspend_handler_mask); /* Wait for signal */
} while (me->stop_info.signal != SIG_THR_RESTART);
/* If the RESTART signal gets lost, we can still lose. That should be */
/* less likely than losing the SUSPEND signal, since we don't do much */
@@ -417,16 +436,9 @@ void GC_stop_init() {
if (sigfillset(&act.sa_mask) != 0) {
ABORT("sigfillset() failed");
}
-# ifdef NO_SIGNALS
- if (sigdelset(&act.sa_mask, SIGINT) != 0
- || sigdelset(&act.sa_mask, SIGQUIT != 0)
- || sigdelset(&act.sa_mask, SIGABRT != 0)
- || sigdelset(&act.sa_mask, SIGTERM != 0)) {
- ABORT("sigdelset() failed");
- }
-# endif
-
- /* SIG_THR_RESTART is unmasked by the handler when necessary. */
+ GC_remove_allowed_signals(&act.sa_mask);
+ /* SIG_THR_RESTART is set in the resulting mask. */
+ /* It is unmasked by the handler when necessary. */
act.sa_handler = GC_suspend_handler;
if (sigaction(SIG_SUSPEND, &act, NULL) != 0) {
ABORT("Cannot set SIG_SUSPEND handler");
@@ -437,6 +449,12 @@ void GC_stop_init() {
ABORT("Cannot set SIG_THR_RESTART handler");
}
+ /* Inititialize suspend_handler_mask. It excludes SIG_THR_RESTART. */
+ if (sigfillset(&suspend_handler_mask) != 0) ABORT("sigfillset() failed");
+ GC_remove_allowed_signals(&suspend_handler_mask);
+ if (sigdelset(&suspend_handler_mask, SIG_THR_RESTART) != 0)
+ ABORT("sigdelset() failed");
+
/* Check for GC_RETRY_SIGNALS. */
if (0 != GETENV("GC_RETRY_SIGNALS")) {
GC_retry_signals = TRUE;
diff --git a/tests/test.c b/tests/test.c
index ccec876f..e1676aad 100644
--- a/tests/test.c
+++ b/tests/test.c
@@ -1255,9 +1255,11 @@ void run_one_test()
FAIL;
}
if (!TEST_FAIL_COUNT(1)) {
-# if!(defined(RS6000) || defined(POWERPC) || defined(IA64))
+# if!(defined(RS6000) || defined(POWERPC) || defined(IA64)) || defined(M68K)
/* ON RS6000s function pointers point to a descriptor in the */
/* data segment, so there should have been no failures. */
+ /* The same applies to IA64. Something similar seems to */
+ /* be going on with NetBSD/M68K. */
(void)GC_printf0("GC_is_visible produced wrong failure indication\n");
FAIL;
# endif
diff --git a/version.h b/version.h
index 3f46a40d..e8f1a3ab 100644
--- a/version.h
+++ b/version.h
@@ -3,7 +3,7 @@
/* it to keep the old-style build process working. */
#define GC_TMP_VERSION_MAJOR 6
#define GC_TMP_VERSION_MINOR 3
-#define GC_TMP_ALPHA_VERSION 5
+#define GC_TMP_ALPHA_VERSION 6
#ifndef GC_NOT_ALPHA
# define GC_NOT_ALPHA 0xff