gc6.3alpha6 tarball import gc6_3alpha6
authorHans Boehm <boehm@acm.org>
Thu, 6 May 2004 00:00:00 +0000 (00:00 +0000)
committerIvan Maidanski <ivmai@mail.ru>
Sat, 17 May 2014 14:55:00 +0000 (18:55 +0400)
24 files changed:
Makefile
Makefile.direct
Makefile.in
checksums.c
configure
configure.in
dbg_mlc.c
doc/Makefile.am
doc/Makefile.in
doc/README
doc/README.changes
doc/simple_example.html [new file with mode: 0644]
dyn_load.c
include/gc.h
include/gc_allocator.h
include/gc_config_macros.h
include/private/gcconfig.h
ltconfig [deleted file]
mark.c
new_hblk.c
os_dep.c
pthread_stop_world.c
tests/test.c
version.h

index 74929c1..f2b3224 100644 (file)
--- 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 \
index 74929c1..f2b3224 100644 (file)
@@ -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 \
index 2c7c1b7..5477b55 100644 (file)
@@ -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)
 
index 121c36d..57a6ebc 100644 (file)
 /* 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);
index 3ede246..84b7f1c 100755 (executable)
--- 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'`\\"
 
index 635742c..3e3aba3 100644 (file)
@@ -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
index 9daa0b0..aacbb7a 100644 (file)
--- 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 */
 }
 
index 9144630..9446bcb 100644 (file)
@@ -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
 
index 1e9dd92..708fd51 100644 (file)
@@ -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
index 0776e67..ae978c1 100644 (file)
@@ -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
 
index 38bde34..129738c 100644 (file)
@@ -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 (file)
index 0000000..0bc0953
--- /dev/null
@@ -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>
index 70eb764..9bd9e06 100644 (file)
 /* 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
 
index 58a2ff5..ae555ae 100644 (file)
@@ -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)
index 87c8509..b0c188c 100644 (file)
  * 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 */
index 4aaca2d..d8d3114 100644 (file)
 # 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
 
index 734bd85..94b446b 100644 (file)
 #   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
 #   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"
          extern char etext[];
 #        define DATASTART ((ptr_t)(etext))
 #       endif
+#      define USE_GENERIC_PUSH_REGS
 #   endif
 #   ifdef LINUX
 #       define OS_TYPE "LINUX"
 #            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        */
 #       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
             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
 
 #   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 (file)
index 962057f..0000000
--- 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 4b65468..dd1fbd5 100644 (file)
--- 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);
         }
index 1aa2c7a..e5580e4 100644 (file)
@@ -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
index cb32bdd..29eee4e 100644 (file)
--- a/os_dep.c
+++ b/os_dep.c
 
 #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));
index 1cdda21..832c49c 100644 (file)
@@ -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;
index ccec876..e1676aa 100644 (file)
@@ -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
index 3f46a40..e8f1a3a 100644 (file)
--- 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