summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile16
-rw-r--r--Makefile.am2
-rw-r--r--Makefile.direct16
-rw-r--r--Makefile.in4
-rw-r--r--NT_STATIC_THREADS_MAKEFILE2
-rw-r--r--allchblk.c16
-rw-r--r--alloc.c14
-rw-r--r--checksums.c34
-rwxr-xr-xconfigure24
-rw-r--r--configure.in4
-rw-r--r--darwin_stop_world.c27
-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.changes50
-rw-r--r--doc/simple_example.html202
-rw-r--r--dyn_load.c14
-rw-r--r--headers.c2
-rw-r--r--include/gc.h5
-rw-r--r--include/gc_allocator.h17
-rw-r--r--include/gc_config_macros.h5
-rw-r--r--include/private/gc_priv.h8
-rw-r--r--include/private/gcconfig.h46
-rw-r--r--ltconfig3
-rw-r--r--mark.c10
-rw-r--r--new_hblk.c12
-rw-r--r--os_dep.c84
-rw-r--r--pthread_stop_world.c58
-rw-r--r--solaris_pthreads.c4
-rw-r--r--solaris_threads.c16
-rw-r--r--tests/middle.c25
-rw-r--r--tests/test.c4
-rw-r--r--threadlibs.c1
-rw-r--r--version.h2
35 files changed, 576 insertions, 167 deletions
diff --git a/Makefile b/Makefile
index 74929c1..20fa40a 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
+ tests/leak_test.c tests/thread_leak_test.c tests/middle.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.am b/Makefile.am
index ed24152..2aba243 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -85,7 +85,7 @@ test.o: $(srcdir)/tests/test.c
$(COMPILE) -c $(srcdir)/tests/test.c
# Using $< in the above seems to fail with the HP/UX on Itanium make.
test_cpp.o: $(srcdir)/tests/test_cpp.cc
- $(COMPILE) -c $(srcdir)/tests/test_cpp.cc
+ $(CXXCOMPILE) -c $(srcdir)/tests/test_cpp.cc
## FIXME: this is probably the reason why some files from BUILT_SOURCES
## are included in the distribution
diff --git a/Makefile.direct b/Makefile.direct
index 74929c1..20fa40a 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
+ tests/leak_test.c tests/thread_leak_test.c tests/middle.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 2c7c1b7..fb52a37 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)
@@ -902,7 +902,7 @@ test.o: $(srcdir)/tests/test.c
$(COMPILE) -c $(srcdir)/tests/test.c
# Using $< in the above seems to fail with the HP/UX on Itanium make.
test_cpp.o: $(srcdir)/tests/test_cpp.cc
- $(COMPILE) -c $(srcdir)/tests/test_cpp.cc
+ $(CXXCOMPILE) -c $(srcdir)/tests/test_cpp.cc
$(all_objs) : include/private/gcconfig.h include/private/gc_priv.h \
include/private/gc_hdrs.h include/gc.h include/gc_gcj.h \
include/gc_pthread_redirects.h include/gc_config_macros.h \
diff --git a/NT_STATIC_THREADS_MAKEFILE b/NT_STATIC_THREADS_MAKEFILE
index 7238c94..a7582af 100644
--- a/NT_STATIC_THREADS_MAKEFILE
+++ b/NT_STATIC_THREADS_MAKEFILE
@@ -1,4 +1,4 @@
-# Makefile for Windows NT. Assumes Microsoft compiler, and a single thread.
+# Makefile for Windows NT. Assumes Microsoft compiler.
# DLLs are included in the root set under NT, but not under win32S.
# Use "nmake nodebug=1 all" for optimized versions of library, gctest and editor.
diff --git a/allchblk.c b/allchblk.c
index 1bd17da..793c468 100644
--- a/allchblk.c
+++ b/allchblk.c
@@ -111,7 +111,7 @@ void GC_print_hblkfreelist()
for (i = 0; i <= N_HBLK_FLS; ++i) {
h = GC_hblkfreelist[i];
# ifdef USE_MUNMAP
- if (0 != h) GC_printf1("Free list %ld (Total size %ld):\n",
+ if (0 != h) GC_printf1("Free list %ld:\n",
(unsigned long)i);
# else
if (0 != h) GC_printf2("Free list %ld (Total size %ld):\n",
@@ -133,10 +133,12 @@ void GC_print_hblkfreelist()
h = hhdr -> hb_next;
}
}
- if (total_free != GC_large_free_bytes) {
+# ifndef USE_MUNMAP
+ if (total_free != GC_large_free_bytes) {
GC_printf1("GC_large_free_bytes = %lu (INCONSISTENT!!)\n",
(unsigned long) GC_large_free_bytes);
- }
+ }
+# endif
GC_printf1("Total of %lu bytes on free list\n", (unsigned long)total_free);
}
@@ -181,7 +183,7 @@ void GC_dump_regions()
hhdr = HDR(p);
GC_printf1("\t0x%lx ", (unsigned long)p);
if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
- GC_printf1("Missing header!!\n", hhdr);
+ GC_printf1("Missing header!!(%ld)\n", hhdr);
p += HBLKSIZE;
continue;
}
@@ -468,7 +470,11 @@ int index;
if (total_size == bytes) return h;
rest = (struct hblk *)((word)h + bytes);
rest_hdr = GC_install_header(rest);
- if (0 == rest_hdr) return(0);
+ if (0 == rest_hdr) {
+ /* This may be very bad news ... */
+ WARN("Header allocation failed: Dropping block.\n", 0);
+ return(0);
+ }
rest_hdr -> hb_sz = total_size - bytes;
rest_hdr -> hb_flags = 0;
# ifdef GC_ASSERTIONS
diff --git a/alloc.c b/alloc.c
index aaf9124..1ac6ff8 100644
--- a/alloc.c
+++ b/alloc.c
@@ -133,7 +133,7 @@ int GC_n_attempts = 0; /* Number of attempts at finishing */
if (GC_print_stats) {
GC_printf0("Abandoning stopped marking after ");
GC_printf1("%lu msecs", (unsigned long)time_diff);
- GC_printf1("(attempt %d)\n", (unsigned long) GC_n_attempts);
+ GC_printf1("(attempt %ld)\n", (unsigned long) GC_n_attempts);
}
# endif
return(1);
@@ -942,12 +942,7 @@ word n;
(GC_PTR)GC_min((ptr_t)GC_least_plausible_heap_addr,
(ptr_t)space - expansion_slop);
}
- /* Force GC before we are likely to allocate past expansion_slop */
- GC_collect_at_heapsize =
- GC_heapsize + expansion_slop - 2*MAXHINCR*HBLKSIZE;
# if defined(LARGE_CONFIG)
- if (GC_collect_at_heapsize < GC_heapsize /* wrapped */)
- GC_collect_at_heapsize = (word)(-1);
if (((ptr_t)GC_greatest_plausible_heap_addr <= (ptr_t)space + bytes
|| (ptr_t)GC_least_plausible_heap_addr >= (ptr_t)space)
&& GC_heapsize > 0) {
@@ -958,6 +953,13 @@ word n;
GC_prev_heap_addr = GC_last_heap_addr;
GC_last_heap_addr = (ptr_t)space;
GC_add_to_heap(space, bytes);
+ /* Force GC before we are likely to allocate past expansion_slop */
+ GC_collect_at_heapsize =
+ GC_heapsize + expansion_slop - 2*MAXHINCR*HBLKSIZE;
+# if defined(LARGE_CONFIG)
+ if (GC_collect_at_heapsize < GC_heapsize /* wrapped */)
+ GC_collect_at_heapsize = (word)(-1);
+# endif
return(TRUE);
}
diff --git a/checksums.c b/checksums.c
index 121c36d..57a6ebc 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 3ede246..7c4d08b 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.3.
#
# 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.3'
+PACKAGE_STRING='gc 6.3'
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.3 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.3:";;
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.3
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.3, 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.3
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.3, 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.3
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 635742c..7914692 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.3,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/darwin_stop_world.c b/darwin_stop_world.c
index 02d751e..36378cb 100644
--- a/darwin_stop_world.c
+++ b/darwin_stop_world.c
@@ -210,22 +210,39 @@ int GC_suspend_thread_list(thread_act_array_t act_list, int count,
mach_msg_type_number_t outCount = THREAD_INFO_MAX;
kern_return_t kern_result = thread_info(thread, THREAD_BASIC_INFO,
(thread_info_t)&info, &outCount);
- if(kern_result != KERN_SUCCESS) ABORT("thread_info failed");
+ if(kern_result != KERN_SUCCESS) {
+ /* the thread may have quit since the thread_threads () call
+ * we mark already_suspended so it's not dealt with anymore later
+ */
+ if (!found) {
+ GC_mach_threads[GC_mach_threads_count].already_suspended = TRUE;
+ GC_mach_threads_count++;
+ }
+ continue;
+ }
# if DEBUG_THREADS
GC_printf2("Thread state for 0x%lx = %d\n", thread, info.run_state);
# endif
if (!found) {
- GC_mach_threads[GC_mach_threads_count].already_suspended =
- (info.run_state != TH_STATE_RUNNING);
+ GC_mach_threads[GC_mach_threads_count].already_suspended = info.suspend_count;
}
- if (info.run_state != TH_STATE_RUNNING) continue;
+ if (info.suspend_count) continue;
# if DEBUG_THREADS
GC_printf1("Suspending 0x%lx\n", thread);
# endif
/* Suspend the thread */
kern_result = thread_suspend(thread);
- if(kern_result != KERN_SUCCESS) ABORT("thread_suspend failed");
+ if(kern_result != KERN_SUCCESS) {
+ /* the thread may have quit since the thread_threads () call
+ * we mark already_suspended so it's not dealt with anymore later
+ */
+ if (!found) {
+ GC_mach_threads[GC_mach_threads_count].already_suspended = TRUE;
+ GC_mach_threads_count++;
+ }
+ continue;
+ }
}
if (!found) GC_mach_threads_count++;
}
diff --git a/dbg_mlc.c b/dbg_mlc.c
index 9daa0b0..aacbb7a 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 9144630..9446bcb 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 1e9dd92..708fd51 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 0776e67..ff77113 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.3 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 38bde34..e27e7d6 100644
--- a/doc/README.changes
+++ b/doc/README.changes
@@ -2049,9 +2049,57 @@ 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.
+
+Since gc6.3alpha6:
+ - Compile test_cpp.cc with CXXCOMPILE instead of COMPILE.
+ - Very large allocations could cause a collector hang. Correct
+ calculation of GC_collect_at_heapsize.
+ - GC_print_hblkfreelist printed some bogus results if USE_MUNMAP
+ was defined.
+ - The generic GC_THREADS macro didn't work correctly on Solaris,
+ since the implementation failed to include gc_config_macros.h
+ before deciding whether or not to compile the rest of the file.
+ - Threadlibs.c failed to expand the generic GC_THREADS macro.
+ - Correct MacOSX thread stop code. (Thanks to Dick Porter.)
+ - SMALL_OBJ definition was off by one. This could cause crashes
+ at startup. (Thanks to Zoltan Varga for narrowing this down to
+ a trivial test case.)
+ - Integrate Paolo Molara's patch to deal with a race in the Darwin
+ thread stopping code.
+ - Changed X86_64 implementation to use SA_SIGINFO in the MPROTECT_VDB
+ implementation. The old approach appears to have been broken by
+ recent kernels.
+ - Add GC_ATTR_UNUSED to eliminate a warning in gc_allocator.h. (Thanks
+ to Andrew Begel.)
+ - Fix GC_task_self declaration in os_dep.c. (Thanks to Andrew Pinski.)
+ - Increase INITIAL_BUF_SZ in os_dep.c for Solaris /proc reads.
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 0000000..0bc0953
--- /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 70eb764..9bd9e06 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/headers.c b/headers.c
index 0aa5139..b7be1d8 100644
--- a/headers.c
+++ b/headers.c
@@ -206,7 +206,7 @@ register struct hblk * h;
{
hdr * result;
- if (!get_index((word) h)) return(FALSE);
+ if (!get_index((word) h)) return(0);
result = alloc_hdr();
SET_HDR(h, result);
# ifdef USE_MUNMAP
diff --git a/include/gc.h b/include/gc.h
index 58a2ff5..2a89009 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)
@@ -929,7 +930,7 @@ extern void GC_thr_init(); /* Needed for Solaris/X86 */
* no-op and the collector self-initializes. But a number of platforms
* make that too hard.
*/
-#if defined(sparc) || defined(__sparc)
+#if (defined(sparc) || defined(__sparc)) && defined(sun)
/*
* If you are planning on putting
* the collector in a SunOS 5 dynamic library, you need to call GC_INIT()
diff --git a/include/gc_allocator.h b/include/gc_allocator.h
index 87c8509..200f181 100644
--- a/include/gc_allocator.h
+++ b/include/gc_allocator.h
@@ -35,7 +35,17 @@
* library, which itself was derived from the SGI STL implementation.
*/
-#include "gc.h" // For size_t
+#ifndef GC_ALLOCATOR_H
+
+#define GC_ALLOCATOR_H
+
+#include "gc.h"
+
+#if defined(__GNUC__)
+# define GC_ATTR_UNUSED __attribute__((unused))
+#else
+# define GC_ATTR_UNUSED
+#endif
/* First some helpers to allow us to dispatch on whether or not a type
* is known to be pointerfree.
@@ -118,7 +128,7 @@ public:
}
// __p is not permitted to be a null pointer.
- void deallocate(pointer __p, size_type GC_n)
+ void deallocate(pointer __p, size_type GC_ATTR_UNUSED GC_n)
{ GC_FREE(__p); }
size_type max_size() const throw()
@@ -194,7 +204,7 @@ public:
}
// __p is not permitted to be a null pointer.
- void deallocate(pointer __p, size_type GC_n)
+ void deallocate(pointer __p, size_type GC_ATTR_UNUSED GC_n)
{ GC_FREE(__p); }
size_type max_size() const throw()
@@ -230,3 +240,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 4aaca2d..d8d3114 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/gc_priv.h b/include/private/gc_priv.h
index b957691..08dd8ea 100644
--- a/include/private/gc_priv.h
+++ b/include/private/gc_priv.h
@@ -550,7 +550,7 @@ extern GC_warn_proc GC_current_warn_proc;
#define CPP_MAXOBJBYTES (CPP_HBLKSIZE/2)
#define MAXOBJBYTES ((word)CPP_MAXOBJBYTES)
-#define CPP_MAXOBJSZ BYTES_TO_WORDS(CPP_HBLKSIZE/2)
+#define CPP_MAXOBJSZ BYTES_TO_WORDS(CPP_MAXOBJBYTES)
#define MAXOBJSZ ((word)CPP_MAXOBJSZ)
# define divHBLKSZ(n) ((n) >> LOG_HBLKSIZE)
@@ -578,7 +578,7 @@ extern GC_warn_proc GC_current_warn_proc;
# else
# define ALIGNED_WORDS(n) ROUNDED_UP_WORDS(n)
# endif
-# define SMALL_OBJ(bytes) ((bytes) < (MAXOBJBYTES - EXTRA_BYTES))
+# define SMALL_OBJ(bytes) ((bytes) <= (MAXOBJBYTES - EXTRA_BYTES))
# define ADD_SLOP(bytes) ((bytes) + EXTRA_BYTES)
# ifndef MIN_WORDS
/* MIN_WORDS is the size of the smallest allocated object. */
@@ -938,11 +938,11 @@ struct _GC_arrays {
char _valid_offsets[VALID_OFFSET_SZ];
/* GC_valid_offsets[i] == TRUE ==> i */
/* is registered as a displacement. */
-# define OFFSET_VALID(displ) \
- (GC_all_interior_pointers || GC_valid_offsets[displ])
char _modws_valid_offsets[sizeof(word)];
/* GC_valid_offsets[i] ==> */
/* GC_modws_valid_offsets[i%sizeof(word)] */
+# define OFFSET_VALID(displ) \
+ (GC_all_interior_pointers || GC_valid_offsets[displ])
# ifdef STUBBORN_ALLOC
page_hash_table _changed_pages;
/* Stubborn object pages that were changes since last call to */
diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h
index 734bd85..94b446b 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 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..c645bc0 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);
}
@@ -1739,7 +1739,7 @@ register hdr * hhdr;
{
register int sz = hhdr -> hb_sz;
- if (sz < MAXOBJSZ) {
+ if (sz <= MAXOBJSZ) {
return(GC_page_was_dirty(h));
} else {
register ptr_t p = (ptr_t)h;
diff --git a/new_hblk.c b/new_hblk.c
index 1aa2c7a..e5580e4 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 cb32bdd..21d0563 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 */
@@ -2192,7 +2192,7 @@ GC_bool is_ptrfree;
/* Using vm_protect (mach syscall) over mprotect (BSD syscall) seems to
decrease the likelihood of some of the problems described below. */
#include <mach/vm_map.h>
- extern mach_port_t GC_task_self;
+ static mach_port_t GC_task_self;
#define PROTECT(addr,len) \
if(vm_protect(GC_task_self,(vm_address_t)(addr),(vm_size_t)(len), \
FALSE,VM_PROT_READ) != KERN_SUCCESS) { \
@@ -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
@@ -2280,8 +2280,11 @@ GC_bool is_ptrfree;
# if defined(ALPHA) || defined(M68K)
typedef void (* REAL_SIG_PF)(int, int, s_c *);
# else
-# if defined(IA64) || defined(HP_PA)
+# if defined(IA64) || defined(HP_PA) || defined(X86_64)
typedef void (* REAL_SIG_PF)(int, siginfo_t *, s_c *);
+ /* FIXME: */
+ /* According to SUSV3, the last argument should have type */
+ /* void * or ucontext_t * */
# else
typedef void (* REAL_SIG_PF)(int, s_c);
# endif
@@ -2356,7 +2359,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 +2374,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>
@@ -2394,7 +2397,7 @@ SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */
# if defined(ALPHA) || defined(M68K)
void GC_write_fault_handler(int sig, int code, s_c * sc)
# else
-# if defined(IA64) || defined(HP_PA)
+# if defined(IA64) || defined(HP_PA) || defined(X86_64)
void GC_write_fault_handler(int sig, siginfo_t * si, s_c * scp)
# else
# if defined(ARM32)
@@ -2413,11 +2416,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 +2431,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)
@@ -2455,7 +2463,7 @@ SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */
char * addr = (char *) (scp -> si_addr);
# endif
# ifdef LINUX
-# if defined(I386) || defined (X86_64)
+# if defined(I386)
char * addr = (char *) (sc.cr2);
# else
# if defined(M68K)
@@ -2490,7 +2498,7 @@ SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */
# ifdef ALPHA
char * addr = get_fault_addr(sc);
# else
-# if defined(IA64) || defined(HP_PA)
+# if defined(IA64) || defined(HP_PA) || defined(X86_64)
char * addr = si -> si_addr;
/* I believe this is claimed to work on all platforms for */
/* Linux 2.3.47 and later. Hopefully we don't have to */
@@ -2533,6 +2541,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 +2561,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
@@ -2561,7 +2579,7 @@ SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */
# if defined(ALPHA) || defined(M68K)
(*(REAL_SIG_PF)old_handler) (sig, code, sc);
# else
-# if defined(IA64) || defined(HP_PA)
+# if defined(IA64) || defined(HP_PA) || defined(X86_64)
(*(REAL_SIG_PF)old_handler) (sig, si, scp);
# else
(*(REAL_SIG_PF)old_handler) (sig, sc);
@@ -2655,7 +2673,8 @@ void GC_dirty_init()
struct sigaction act, oldact;
/* We should probably specify SA_SIGINFO for Linux, and handle */
/* the different architectures more uniformly. */
-# if defined(IRIX5) || defined(LINUX) || defined(OSF1) || defined(HURD)
+# if defined(IRIX5) || defined(LINUX) && !defined(X86_64) \
+ || defined(OSF1) || defined(HURD)
act.sa_flags = SA_RESTART;
act.sa_handler = (SIG_PF)GC_write_fault_handler;
# else
@@ -2678,7 +2697,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 +2721,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 +2753,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 +2767,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) {
@@ -3032,7 +3052,7 @@ word n;
#include <sys/procfs.h>
#include <sys/stat.h>
-#define INITIAL_BUF_SZ 4096
+#define INITIAL_BUF_SZ 16384
word GC_proc_buf_size = INITIAL_BUF_SZ;
char *GC_proc_buf;
@@ -3146,7 +3166,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));
@@ -3367,8 +3387,6 @@ extern kern_return_t exception_raise_state_identity(
#define MAX_EXCEPTION_PORTS 16
-static mach_port_t GC_task_self;
-
static struct {
mach_msg_type_number_t count;
exception_mask_t masks[MAX_EXCEPTION_PORTS];
diff --git a/pthread_stop_world.c b/pthread_stop_world.c
index 1cdda21..832c49c 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/solaris_pthreads.c b/solaris_pthreads.c
index bae7719..1e43d09 100644
--- a/solaris_pthreads.c
+++ b/solaris_pthreads.c
@@ -16,8 +16,10 @@
* Modified by Peter C. for Solaris Posix Threads.
*/
-# if defined(GC_SOLARIS_PTHREADS)
+# if defined(GC_SOLARIS_PTHREADS) || defined(GC_THREADS)
# include "private/gc_priv.h"
+# endif
+# if defined(GC_SOLARIS_PTHREADS)
# include <pthread.h>
# include <thread.h>
# include <signal.h>
diff --git a/solaris_threads.c b/solaris_threads.c
index 5f05b19..0a07690 100644
--- a/solaris_threads.c
+++ b/solaris_threads.c
@@ -16,9 +16,12 @@
*/
/* Boehm, September 14, 1994 4:44 pm PDT */
-# if defined(GC_SOLARIS_THREADS) || defined(GC_SOLARIS_PTHREADS)
+# if defined(GC_SOLARIS_THREADS) || defined(GC_SOLARIS_PTHREADS) \
+ || defined(GC_THREADS)
+# include "private/gc_priv.h"
+# endif
-# include "private/gc_priv.h"
+# if defined(GC_SOLARIS_THREADS) || defined(GC_SOLARIS_PTHREADS)
# include "private/solaris_threads.h"
# include <thread.h>
# include <synch.h>
@@ -786,6 +789,7 @@ void GC_thr_init(void)
{
GC_thread t;
thread_t tid;
+ int ret;
if (GC_thr_initialized)
return;
@@ -803,9 +807,11 @@ void GC_thr_init(void)
t = GC_new_thread(thr_self());
t -> stack_size = 0;
t -> flags = DETACHED | CLIENT_OWNS_STACK;
- if (thr_create(0 /* stack */, 0 /* stack_size */, GC_thr_daemon,
- 0 /* arg */, THR_DETACHED | THR_DAEMON,
- &tid /* thread_id */) != 0) {
+ ret = thr_create(0 /* stack */, 0 /* stack_size */, GC_thr_daemon,
+ 0 /* arg */, THR_DETACHED | THR_DAEMON,
+ &tid /* thread_id */);
+ if (ret != 0) {
+ GC_err_printf1("Thr_create returned %ld\n", ret);
ABORT("Cant fork daemon");
}
thr_setprio(tid, 126);
diff --git a/tests/middle.c b/tests/middle.c
new file mode 100644
index 0000000..5d9360a
--- /dev/null
+++ b/tests/middle.c
@@ -0,0 +1,25 @@
+/*
+ * Test at the boundary between small and large objects.
+ * Inspired by a test case from Zoltan Varga.
+ */
+#include <gc.h>
+#include <stdio.h>
+
+int main ()
+{
+ int i;
+
+ GC_all_interior_pointers = 0;
+
+ for (i = 0; i < 20000; ++i) {
+ GC_malloc_atomic (4096);
+ GC_malloc (4096);
+ }
+ for (i = 0; i < 20000; ++i) {
+ GC_malloc_atomic (2048);
+ GC_malloc (2048);
+ }
+ printf("Final heap size is %ld\n", GC_get_heap_size());
+ return 0;
+}
+
diff --git a/tests/test.c b/tests/test.c
index ccec876..e1676aa 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/threadlibs.c b/threadlibs.c
index 247d3c6..264b724 100644
--- a/threadlibs.c
+++ b/threadlibs.c
@@ -1,3 +1,4 @@
+# include "gc_config_macros.h"
# include "private/gcconfig.h"
# include <stdio.h>
diff --git a/version.h b/version.h
index 3f46a40..93000c3 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 GC_NOT_ALPHA
#ifndef GC_NOT_ALPHA
# define GC_NOT_ALPHA 0xff