summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--Makefile.am2
-rw-r--r--Makefile.direct4
-rw-r--r--Makefile.in2
-rw-r--r--allchblk.c6
-rw-r--r--alloc.c4
-rwxr-xr-xconfigure45
-rw-r--r--configure.in9
-rw-r--r--darwin_stop_world.c27
-rw-r--r--dbg_mlc.c22
-rw-r--r--doc/README2
-rw-r--r--doc/README.changes39
-rw-r--r--doc/gcinterface.html11
-rw-r--r--dyn_load.c14
-rw-r--r--headers.c2
-rw-r--r--include/gc.h21
-rw-r--r--include/gc_config_macros.h15
-rw-r--r--include/gc_cpp.h2
-rw-r--r--include/gc_pthread_redirects.h3
-rw-r--r--include/leak_detector.h2
-rw-r--r--include/private/gc_locks.h39
-rw-r--r--include/private/gc_pmark.h3
-rw-r--r--include/private/gc_priv.h14
-rw-r--r--include/private/gcconfig.h63
-rw-r--r--malloc.c26
-rw-r--r--mark.c1
-rw-r--r--misc.c11
-rw-r--r--os_dep.c19
-rw-r--r--powerpc_darwin_mach_dep.s20
-rw-r--r--pthread_stop_world.c30
-rw-r--r--pthread_support.c23
-rw-r--r--threadlibs.c4
-rw-r--r--version.h2
33 files changed, 388 insertions, 103 deletions
diff --git a/Makefile b/Makefile
index 1f03b51..462a54f 100644
--- a/Makefile
+++ b/Makefile
@@ -144,9 +144,9 @@ HOSTCFLAGS=$(CFLAGS)
# -DJAVA_FINALIZATION makes it somewhat safer to finalize objects out of
# order by specifying a nonstandard finalization mark procedure (see
# finalize.c). Objects reachable from finalizable objects will be marked
-# in a sepearte postpass, and hence their memory won't be reclaimed.
+# in a separate postpass, and hence their memory won't be reclaimed.
# Not recommended unless you are implementing a language that specifies
-# these semantics. Since 5.0, determines only only the initial value
+# these semantics. Since 5.0, determines only the initial value
# of GC_java_finalization variable.
# -DFINALIZE_ON_DEMAND causes finalizers to be run only in response
# to explicit GC_invoke_finalizers() calls.
diff --git a/Makefile.am b/Makefile.am
index 89594f9..1ff290e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -95,7 +95,7 @@ gctest_LDADD = ./libgc.la $(THREADDLLIBS) $(UNWINDLIBS) $(EXTRA_TEST_LIBS)
test_cpp_SOURCES = tests/test_cpp.cc
test_cpp_LDADD = ./libgc.la ./libgccpp.la $(THREADDLLIBS) $(UNWINDLIBS) $(EXTRA_TEST_LIBS)
-TESTS = gctest $(extra_checks)
+TESTS = $(check_PROGRAMS)
## FIXME: relies on internal code generated by automake.
all_objs = @addobjs@ $(libgc_la_OBJECTS)
diff --git a/Makefile.direct b/Makefile.direct
index 1f03b51..462a54f 100644
--- a/Makefile.direct
+++ b/Makefile.direct
@@ -144,9 +144,9 @@ HOSTCFLAGS=$(CFLAGS)
# -DJAVA_FINALIZATION makes it somewhat safer to finalize objects out of
# order by specifying a nonstandard finalization mark procedure (see
# finalize.c). Objects reachable from finalizable objects will be marked
-# in a sepearte postpass, and hence their memory won't be reclaimed.
+# in a separate postpass, and hence their memory won't be reclaimed.
# Not recommended unless you are implementing a language that specifies
-# these semantics. Since 5.0, determines only only the initial value
+# these semantics. Since 5.0, determines only the initial value
# of GC_java_finalization variable.
# -DFINALIZE_ON_DEMAND causes finalizers to be run only in response
# to explicit GC_invoke_finalizers() calls.
diff --git a/Makefile.in b/Makefile.in
index c89c84c..8f3f492 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -359,7 +359,7 @@ gctest_SOURCES = tests/test.c
gctest_LDADD = ./libgc.la $(THREADDLLIBS) $(UNWINDLIBS) $(EXTRA_TEST_LIBS)
test_cpp_SOURCES = tests/test_cpp.cc
test_cpp_LDADD = ./libgc.la ./libgccpp.la $(THREADDLLIBS) $(UNWINDLIBS) $(EXTRA_TEST_LIBS)
-TESTS = gctest $(extra_checks)
+TESTS = $(check_PROGRAMS)
all_objs = @addobjs@ $(libgc_la_OBJECTS)
@COMPILER_XLC_FALSE@ASM_CPP_OPTIONS = -Wp,-P -x assembler-with-cpp
@COMPILER_XLC_TRUE@ASM_CPP_OPTIONS =
diff --git a/allchblk.c b/allchblk.c
index 1a1efc6..3e020a8 100644
--- a/allchblk.c
+++ b/allchblk.c
@@ -529,7 +529,7 @@ int index; /* Index of free list */
/* free blocks in GC_add_to_fl. */
# endif
# ifdef USE_MUNMAP
- hhdr -> hb_last_reclaimed = GC_gc_no;
+ hhdr -> hb_last_reclaimed = (unsigned short)GC_gc_no;
# endif
hhdr -> hb_sz = h_size;
GC_add_to_fl(h, hhdr);
@@ -793,7 +793,7 @@ signed_word size;
GC_remove_counts(hbp, (word)size);
hhdr->hb_sz = size;
# ifdef USE_MUNMAP
- hhdr -> hb_last_reclaimed = GC_gc_no;
+ hhdr -> hb_last_reclaimed = (unsigned short)GC_gc_no;
# endif
/* Check for duplicate deallocation in the easy case */
@@ -821,7 +821,7 @@ signed_word size;
GC_remove_from_fl(prevhdr, FL_UNKNOWN);
prevhdr -> hb_sz += hhdr -> hb_sz;
# ifdef USE_MUNMAP
- prevhdr -> hb_last_reclaimed = GC_gc_no;
+ prevhdr -> hb_last_reclaimed = (unsigned short)GC_gc_no;
# endif
GC_remove_header(hbp);
hbp = prev;
diff --git a/alloc.c b/alloc.c
index 9b4869f..9b91e6c 100644
--- a/alloc.c
+++ b/alloc.c
@@ -206,7 +206,7 @@ word GC_adj_words_allocd()
/* had been reallocated this round. Finalization is user */
/* visible progress. And if we don't count this, we have */
/* stability problems for programs that finalize all objects. */
- if ((GC_words_wasted >> 3) < result)
+ if ((signed_word)(GC_words_wasted >> 3) < result)
result += GC_words_wasted;
/* This doesn't reflect useful work. But if there is lots of */
/* new fragmentation, the same is probably true of the heap, */
@@ -402,7 +402,7 @@ GC_stop_func stop_func;
/*
* Perform n units of garbage collection work. A unit is intended to touch
* roughly GC_RATE pages. Every once in a while, we do more than that.
- * This needa to be a fairly large number with our current incremental
+ * This needs to be a fairly large number with our current incremental
* GC strategy, since otherwise we allocate too much during GC, and the
* cleanup gets expensive.
*/
diff --git a/configure b/configure
index 059365d..372c8a8 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.59 for gc 6.6.
+# Generated by GNU Autoconf 2.59 for gc 6.7.
#
# Report bugs to <Hans.Boehm@hp.com>.
#
@@ -429,8 +429,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='gc'
PACKAGE_TARNAME='gc'
-PACKAGE_VERSION='6.6'
-PACKAGE_STRING='gc 6.6'
+PACKAGE_VERSION='6.7'
+PACKAGE_STRING='gc 6.7'
PACKAGE_BUGREPORT='Hans.Boehm@hp.com'
ac_unique_file="gcj_mlc.c"
@@ -956,7 +956,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.6 to adapt to many kinds of systems.
+\`configure' configures gc 6.7 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1023,7 +1023,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of gc 6.6:";;
+ short | recursive ) echo "Configuration of gc 6.7:";;
esac
cat <<\_ACEOF
@@ -1167,7 +1167,7 @@ fi
test -n "$ac_init_help" && exit 0
if $ac_init_version; then
cat <<\_ACEOF
-gc configure 6.6
+gc configure 6.7
generated by GNU Autoconf 2.59
Copyright (C) 2003 Free Software Foundation, Inc.
@@ -1181,7 +1181,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.6, which was
+It was created by gc $as_me 6.7, which was
generated by GNU Autoconf 2.59. Invocation command line was
$ $0 $@
@@ -1953,7 +1953,7 @@ fi
# Define the identity of the package.
PACKAGE='gc'
- VERSION='6.6'
+ VERSION='6.7'
cat >>confdefs.h <<_ACEOF
@@ -4041,6 +4041,23 @@ _ACEOF
INCLUDES="$INCLUDES -pthread"
THREADDLLIBS=-pthread
;;
+ *-*-netbsd*)
+ { echo "$as_me:$LINENO: WARNING: \"Only on NetBSD 2.0 or later.\"" >&5
+echo "$as_me: WARNING: \"Only on NetBSD 2.0 or later.\"" >&2;}
+ cat >>confdefs.h <<\_ACEOF
+#define GC_NETBSD_THREADS 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define _REENTRANT 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define _PTHREADS 1
+_ACEOF
+
+ THREADDLLIBS="-lpthread -lrt"
+ ;;
*-*-solaris*)
cat >>confdefs.h <<\_ACEOF
#define GC_SOLARIS_THREADS 1
@@ -6052,7 +6069,7 @@ test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
case $host in
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 6055 "configure"' > conftest.$ac_ext
+ echo '#line 6072 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -6625,7 +6642,7 @@ chmod -w .
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
compiler_c_o=no
-if { (eval echo configure:6628: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
+if { (eval echo configure:6645: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
if test -s out/conftest.err; then
@@ -8552,7 +8569,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 8555 "configure"
+#line 8572 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -8650,7 +8667,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 8653 "configure"
+#line 8670 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10272,7 +10289,7 @@ _ASBOX
} >&5
cat >&5 <<_CSEOF
-This file was extended by gc $as_me 6.6, which was
+This file was extended by gc $as_me 6.7, which was
generated by GNU Autoconf 2.59. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -10330,7 +10347,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-gc config.status 6.6
+gc config.status 6.7
configured by $0, generated by GNU Autoconf 2.59,
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
diff --git a/configure.in b/configure.in
index d81e2ea..247760c 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.6,Hans.Boehm@hp.com)
+AC_INIT(gc,6.7,Hans.Boehm@hp.com)
## version must conform to [0-9]+[.][0-9]+(alpha[0-9]+)?
AC_CONFIG_SRCDIR(gcj_mlc.c)
AC_CANONICAL_TARGET
@@ -110,6 +110,13 @@ case "$THREADS" in
INCLUDES="$INCLUDES -pthread"
THREADDLLIBS=-pthread
;;
+ *-*-netbsd*)
+ AC_MSG_WARN("Only on NetBSD 2.0 or later.")
+ AC_DEFINE(GC_NETBSD_THREADS)
+ AC_DEFINE(_REENTRANT)
+ AC_DEFINE(_PTHREADS)
+ THREADDLLIBS="-lpthread -lrt"
+ ;;
*-*-solaris*)
AC_DEFINE(GC_SOLARIS_THREADS)
AC_DEFINE(GC_SOLARIS_PTHREADS)
diff --git a/darwin_stop_world.c b/darwin_stop_world.c
index 4c08b9f..665e896 100644
--- a/darwin_stop_world.c
+++ b/darwin_stop_world.c
@@ -1,5 +1,7 @@
#include "private/pthread_support.h"
+/* This probably needs more porting work to ppc64. */
+
# if defined(GC_DARWIN_THREADS)
/* From "Inside Mac OS X - Mach-O Runtime Architecture" published by Apple
@@ -36,7 +38,7 @@ unsigned long FindTopOfStack(unsigned int stack_start) {
# if CPP_WORDSZ == 32
__asm__ volatile("lwz %0,0(r1)" : "=r" (frame));
# else
- __asm__ volatile("ldz %0,0(r1)" : "=r" (frame));
+ __asm__ volatile("ld %0,0(r1)" : "=r" (frame));
# endif
# endif
} else {
@@ -73,7 +75,13 @@ void GC_push_all_stacks() {
GC_thread p;
pthread_t me;
ptr_t lo, hi;
+#if defined(POWERPC)
ppc_thread_state_t state;
+#elif defined(I386)
+ i386_thread_state_t state;
+#else
+# error FIXME for non-x86 || ppc architectures
+#endif
mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
me = pthread_self();
@@ -93,6 +101,17 @@ void GC_push_all_stacks() {
&thread_state_count);
if(r != KERN_SUCCESS) ABORT("thread_get_state failed");
+#if defined(I386)
+ lo = state.esp;
+
+ GC_push_one(state.eax);
+ GC_push_one(state.ebx);
+ GC_push_one(state.ecx);
+ GC_push_one(state.edx);
+ GC_push_one(state.edi);
+ GC_push_one(state.esi);
+ GC_push_one(state.ebp);
+#elif defined(POWERPC)
lo = (void*)(state.r1 - PPC_RED_ZONE_SIZE);
GC_push_one(state.r0);
@@ -126,6 +145,9 @@ void GC_push_all_stacks() {
GC_push_one(state.r29);
GC_push_one(state.r30);
GC_push_one(state.r31);
+#else
+# error FIXME for non-x86 || ppc architectures
+#endif
} /* p != me */
if(p->flags & MAIN_THREAD)
hi = GC_stackbottom;
@@ -247,6 +269,7 @@ void GC_push_all_stacks() {
# endif
GC_push_all_stack(lo, hi);
} /* for(p=GC_threads[i]...) */
+ vm_deallocate(current_task(), (vm_address_t)act_list, sizeof(thread_t) * listcount);
}
#endif /* !DARWIN_DONT_PARSE_STACK */
@@ -390,6 +413,7 @@ void GC_stop_world()
changes = result;
prev_list = act_list;
prevcount = listcount;
+ vm_deallocate(current_task(), (vm_address_t)act_list, sizeof(thread_t) * listcount);
} while (changes);
@@ -461,6 +485,7 @@ void GC_start_world()
}
}
}
+ vm_deallocate(current_task(), (vm_address_t)act_list, sizeof(thread_t) * listcount);
# if DEBUG_THREADS
GC_printf0("World started\n");
# endif
diff --git a/dbg_mlc.c b/dbg_mlc.c
index aacbb7a..3cabaf4 100644
--- a/dbg_mlc.c
+++ b/dbg_mlc.c
@@ -14,6 +14,8 @@
* modified is included with the above copyright notice.
*/
+#include <errno.h>
+#include <string.h>
#include "private/dbg_mlc.h"
void GC_default_print_heap_obj_proc();
@@ -714,6 +716,26 @@ GC_PTR p;
}
# ifdef __STDC__
+ char *GC_debug_strdup(const char *str, GC_EXTRA_PARAMS)
+#else
+ char *GC_debug_strdup(str, s, i)
+ char *str;
+ char *s;
+ int i;
+#endif
+{
+ char *copy;
+ if (str == NULL) return NULL;
+ copy = GC_debug_malloc_atomic(strlen(str) + 1, OPT_RA s, i);
+ if (copy == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ strcpy(copy, str);
+ return copy;
+}
+
+# ifdef __STDC__
GC_PTR GC_debug_malloc_uncollectable(size_t lb, GC_EXTRA_PARAMS)
# else
GC_PTR GC_debug_malloc_uncollectable(lb, s, i)
diff --git a/doc/README b/doc/README
index a19cb30..46651ec 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.6 of a conservative garbage collector for C and C++.
+This is version 6.7 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 97b0b68..2b6ff9a 100644
--- a/doc/README.changes
+++ b/doc/README.changes
@@ -2245,6 +2245,45 @@ Since 6.5
to Ben Hutchings for the observation and patch.)
- Move up struct callinfo declaration to make gcc 4.0.2. happy.
+Since 6.6:
+ - Add "int" to Solaris "end" and "etext" declaration in gc.h. Declared
+ the symbols with underscores and as arrays, since that's what's actually
+ used. Perhaps this could all just be removed? (Thanks to John Bowman.)
+ - Fixed ARM GC_test_and_set code. (Thanks to Kazu Hirata and Paul Brook.)
+ - Added casts for assignments to hb_last_reclaimed, which truncate the
+ value. Added a cast to GC_adj_words_allocd. Use GetModuleHandleA
+ when retrieving a handle to kernel32.dll under win32. (Thanks to the
+ Visual Prolog developers.)
+ - Added Tandem S-Series support. (Thanks to Craig McDaniel. A modified
+ version of his patch was applied, and hence breakage is probably not
+ his fault.)
+ - Remove spurious gc:: qualifier for operator delete[] in gc_cpp.h.
+ (Thanks to Hanno Boeck.)
+ - Changed a test for LINUX in config_macros.h to one for __linux__.
+ - Fix ppc 64 test_and_set code by removing it. (Thanks to Christian
+ Thalinger.)
+ - Add prototypes for GC_finalizer_notifier and GC_thr_init. (Thanks to
+ David Ayers.)
+ - Use ld instead of nonexistent ldz instruction in Darwin FindTopOfStack.
+ (Thanks to Andreas Tobler.)
+ - Add support for Darwin/X86. (Thanks to Geoff Norton and the Mono
+ developers.)
+ - Merge in some recent gcc fixes. Add ppc64 asm code. (Thanks to Bryce
+ McKinley and other gcj developers.)
+ - Scan MEM_PRIVATE sections under Windows ME and predecessors.
+ - Interior pointers with some largish offsets into large objects could
+ be ignored, if GC_all_interior_pointers was set. (Oddly this worked
+ correctly for stack references if it was not set. Otherwise it failed
+ for both stack and heap references.) Thanks to Andrew McKinlay for the
+ critical test case.
+ - Integrated Tatsuya Bizenn's NETBSD threads support, with some
+ minimally tested changes.
+ - Added GC_strdup and friends to make leak detection work correctly
+ for strdup clients. (Thanks to Jon Moore.) Fixed the existing strdup
+ with malloc redirection to handle a null malloc return correctly.
+ - Fix Makefile.am, so it handles exe extensions under Cygwin correctly
+ for gctest.
+
To do:
- The USE_MUNMAP code should really use a separate data structure
indexed by physical page to keep track of time since last use of
diff --git a/doc/gcinterface.html b/doc/gcinterface.html
index 1716514..ed16950 100644
--- a/doc/gcinterface.html
+++ b/doc/gcinterface.html
@@ -34,6 +34,12 @@ after defining the appropriate <TT>GC_</tt><I>XXXX</i><TT>_THREADS</tt> macro.
The header file <TT>gc.h</tt> must be included
in files that use either GC or threads primitives, since threads primitives
will be redefined to cooperate with the GC on many platforms.
+<P>
+Thread users should also be aware that on many platforms objects reachable
+only from thread-local variables may be prematurely reclaimed.
+Thus objects pointed to by thread-local variables should also be pointed to
+by a globally visible data structure. (This is viewed as a bug, but as
+one that is exceedingly hard to fix without some libc hooks.)
<DL>
<DT> <B>void * GC_MALLOC(size_t <I>nbytes</i>)</b>
<DD>
@@ -180,6 +186,11 @@ but are scanned for pointers to collectable objects.
They are allocated by <TT>GC_MALLOC_UNCOLLECTABLE</tt>, as described
above, and through some interfaces described below.
<P>
+(On most platforms, the collector may not trace correctly from in-flight
+exception objects. Thus objects thrown as exceptions should only
+point to otherwise reachable memory. This is another bug whose
+proper repair requires platform hooks.)
+<P>
The easiest way to ensure that collectable objects are properly referenced
is to allocate only collectable objects. This requires that every
allocation go through one of the following interfaces, each one of
diff --git a/dyn_load.c b/dyn_load.c
index 749bf82..c910609 100644
--- a/dyn_load.c
+++ b/dyn_load.c
@@ -776,8 +776,8 @@ void GC_register_dynamic_libraries()
/* this automatically, and rely largely on user input. */
/* We expect that any mapping with type MEM_MAPPED (which */
/* apparently excludes library data sections) can be safely */
- /* ignored. But we're too chicken to do that in this */
- /* version. */
+ /* ignored. But we're too completely remove this code in */
+ /* this version. */
/* Based on a very limited sample, it appears that: */
/* - Frame buffer mappings appear as mappings of large */
/* length, usually a bit less than a power of two. */
@@ -844,6 +844,9 @@ void GC_register_dynamic_libraries()
}
# endif /* DEBUG_VIRTUALQUERY */
+ extern GC_bool GC_wnt; /* Is Windows NT derivative. */
+ /* Defined and set in os_dep.c. */
+
void GC_register_dynamic_libraries()
{
MEMORY_BASIC_INFORMATION buf;
@@ -885,7 +888,12 @@ void GC_register_dynamic_libraries()
* !is_frame_buffer(p, buf.RegionSize, buf.Type)
* instead of just checking for MEM_IMAGE.
* If something breaks, change it back. */
- && buf.Type == MEM_IMAGE) {
+ /* There is some evidence that we cannot always
+ * ignore MEM_PRIVATE sections under Windows ME
+ * and predecessors. Hence we now also check for
+ * that case. */
+ && (buf.Type == MEM_IMAGE ||
+ !GC_wnt && buf.Type == MEM_PRIVATE)) {
# ifdef DEBUG_VIRTUALQUERY
GC_dump_meminfo(&buf);
# endif
diff --git a/headers.c b/headers.c
index b7be1d8..90c5884 100644
--- a/headers.c
+++ b/headers.c
@@ -210,7 +210,7 @@ register struct hblk * h;
result = alloc_hdr();
SET_HDR(h, result);
# ifdef USE_MUNMAP
- result -> hb_last_reclaimed = GC_gc_no;
+ result -> hb_last_reclaimed = (unsigned short)GC_gc_no;
# endif
return(result);
}
diff --git a/include/gc.h b/include/gc.h
index 3d4de46..e1bbdeb 100644
--- a/include/gc.h
+++ b/include/gc.h
@@ -129,7 +129,7 @@ GC_API int GC_java_finalization;
/* ordered finalization. Default value is */
/* determined by JAVA_FINALIZATION macro. */
-GC_API void (* GC_finalizer_notifier)();
+GC_API void (* GC_finalizer_notifier) GC_PROTO((void));
/* Invoked by the collector when there are */
/* objects to be finalized. Invoked at most */
/* once per GC cycle. Never invoked unless */
@@ -267,6 +267,7 @@ GC_API void GC_init GC_PROTO((void));
*/
GC_API GC_PTR GC_malloc GC_PROTO((size_t size_in_bytes));
GC_API GC_PTR GC_malloc_atomic GC_PROTO((size_t size_in_bytes));
+GC_API char *GC_strdup GC_PROTO((const char *str));
GC_API GC_PTR GC_malloc_uncollectable GC_PROTO((size_t size_in_bytes));
GC_API GC_PTR GC_malloc_stubborn GC_PROTO((size_t size_in_bytes));
@@ -523,6 +524,8 @@ GC_API GC_PTR GC_debug_malloc
GC_PROTO((size_t size_in_bytes, GC_EXTRA_PARAMS));
GC_API GC_PTR GC_debug_malloc_atomic
GC_PROTO((size_t size_in_bytes, GC_EXTRA_PARAMS));
+GC_API char *GC_debug_strdup
+ GC_PROTO((const char *str, GC_EXTRA_PARAMS));
GC_API GC_PTR GC_debug_malloc_uncollectable
GC_PROTO((size_t size_in_bytes, GC_EXTRA_PARAMS));
GC_API GC_PTR GC_debug_malloc_stubborn
@@ -557,6 +560,7 @@ GC_API GC_PTR GC_debug_realloc_replacement
# ifdef GC_DEBUG
# define GC_MALLOC(sz) GC_debug_malloc(sz, GC_EXTRAS)
# define GC_MALLOC_ATOMIC(sz) GC_debug_malloc_atomic(sz, GC_EXTRAS)
+# define GC_STRDUP(s) GC_debug_strdup((s), GC_EXTRAS)
# define GC_MALLOC_UNCOLLECTABLE(sz) \
GC_debug_malloc_uncollectable(sz, GC_EXTRAS)
# define GC_MALLOC_IGNORE_OFF_PAGE(sz) \
@@ -580,6 +584,7 @@ GC_API GC_PTR GC_debug_realloc_replacement
# else
# define GC_MALLOC(sz) GC_malloc(sz)
# define GC_MALLOC_ATOMIC(sz) GC_malloc_atomic(sz)
+# define GC_STRDUP(s) GC_strdup(s)
# define GC_MALLOC_UNCOLLECTABLE(sz) GC_malloc_uncollectable(sz)
# define GC_MALLOC_IGNORE_OFF_PAGE(sz) \
GC_malloc_ignore_off_page(sz)
@@ -889,7 +894,7 @@ GC_API void (*GC_is_visible_print_proc)
GC_PTR GC_malloc_many(size_t lb);
#define GC_NEXT(p) (*(GC_PTR *)(p)) /* Retrieve the next element */
/* in returned list. */
-extern void GC_thr_init(); /* Needed for Solaris/X86 */
+extern void GC_thr_init GC_PROTO((void));/* Needed for Solaris/X86 */
#endif /* THREADS && !SRC_M3 */
@@ -940,8 +945,16 @@ extern void GC_thr_init(); /* Needed for Solaris/X86 */
* from the statically loaded program section.
* This circumvents a Solaris 2.X (X<=4) linker bug.
*/
-# define GC_INIT() { extern end, etext; \
- GC_noop(&end, &etext); }
+# ifdef __cplusplus
+# define GC_INIT() { extern int _end[], _etext[]; \
+ extern "C" void GC_noop1(GC_word); \
+ GC_noop1((GC_word)_end); \
+ GC_noop1((GC_word)_etext); }
+# else
+# define GC_INIT() { extern int _end[], _etext[]; \
+ extern void GC_noop(); \
+ GC_noop(_end, _etext); }
+# endif /* !__cplusplus */
#else
# if defined(__CYGWIN32__) || defined (_AIX)
/*
diff --git a/include/gc_config_macros.h b/include/gc_config_macros.h
index 4671864..8e3a8ae 100644
--- a/include/gc_config_macros.h
+++ b/include/gc_config_macros.h
@@ -42,12 +42,17 @@
|| defined(GC_SOLARIS_PTHREADS) \
|| defined(GC_HPUX_THREADS) \
|| defined(GC_AIX_THREADS) \
- || defined(GC_LINUX_THREADS))
+ || defined(GC_LINUX_THREADS) \
+ || defined(GC_NETBSD_THREADS))
# define _REENTRANT
/* Better late than never. This fails if system headers that */
/* depend on this were previously included. */
#endif
+#if !defined(_PTHREADS) && defined(GC_NETBSD_THREADS)
+# define _PTHREADS
+#endif
+
#if defined(GC_DGUX386_THREADS) && !defined(_POSIX4A_DRAFT10_SOURCE)
# define _POSIX4A_DRAFT10_SOURCE 1
#endif
@@ -56,7 +61,7 @@
defined(GC_IRIX_THREADS) || defined(GC_LINUX_THREADS) || \
defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) || \
defined(GC_DGUX386_THREADS) || defined(GC_DARWIN_THREADS) || \
- defined(GC_AIX_THREADS) || \
+ defined(GC_AIX_THREADS) || defined(GC_NETBSD_THREADS) || \
(defined(GC_WIN32_THREADS) && defined(__CYGWIN32__))
# define GC_PTHREADS
# endif
@@ -66,7 +71,7 @@
# define GC_LINUX_THREADS
# define GC_PTHREADS
# endif
-# if !defined(LINUX) && (defined(_PA_RISC1_1) || defined(_PA_RISC2_0) \
+# if !defined(__linux__) && (defined(_PA_RISC1_1) || defined(_PA_RISC2_0) \
|| defined(hppa) || defined(__HPPA))
# define GC_HPUX_THREADS
# define GC_PTHREADS
@@ -91,6 +96,10 @@
# define GC_FREEBSD_THREADS
# define GC_PTHREADS
# endif
+# if !defined(GC_PTHREADS) && defined(__NetBSD__)
+# define GC_NETBSD_THREADS
+# define GC_PTHREADS
+# endif
# if defined(DGUX) && (defined(i386) || defined(__i386__))
# define GC_DGUX386_THREADS
# define GC_PTHREADS
diff --git a/include/gc_cpp.h b/include/gc_cpp.h
index 4f56f0d..da2fac0 100644
--- a/include/gc_cpp.h
+++ b/include/gc_cpp.h
@@ -180,7 +180,7 @@ class gc {public:
inline void* operator new[]( size_t size, void *p );
inline void operator delete[]( void* obj );
# ifdef GC_PLACEMENT_DELETE
- inline void gc::operator delete[]( void*, void* );
+ inline void operator delete[]( void*, void* );
# endif
#endif /* GC_OPERATOR_NEW_ARRAY */
};
diff --git a/include/gc_pthread_redirects.h b/include/gc_pthread_redirects.h
index 842518c..21e9c9f 100644
--- a/include/gc_pthread_redirects.h
+++ b/include/gc_pthread_redirects.h
@@ -73,6 +73,9 @@
# define pthread_detach GC_pthread_detach
#ifndef GC_DARWIN_THREADS
+# ifdef pthread_sigmask
+# undef pthread_sigmask
+# endif /* pthread_sigmask */
# define pthread_sigmask GC_pthread_sigmask
# define dlopen GC_dlopen
#endif
diff --git a/include/leak_detector.h b/include/leak_detector.h
index 0674ab4..1d02f40 100644
--- a/include/leak_detector.h
+++ b/include/leak_detector.h
@@ -4,4 +4,6 @@
#define calloc(m,n) GC_MALLOC((m)*(n))
#define free(p) GC_FREE(p)
#define realloc(p,n) GC_REALLOC((p),(n))
+#undef strdup
+#define strdup(s) GC_STRDUP((s))
#define CHECK_LEAKS() GC_gcollect()
diff --git a/include/private/gc_locks.h b/include/private/gc_locks.h
index c9539c1..c1565b2 100644
--- a/include/private/gc_locks.h
+++ b/include/private/gc_locks.h
@@ -155,25 +155,6 @@
# define GC_TEST_AND_SET_DEFINED
# endif
# if defined(POWERPC)
-# if CPP_WORDSZ == 64
- inline static int GC_test_and_set(volatile unsigned int *addr) {
- unsigned long oldval;
- unsigned long temp = 1; /* locked value */
-
- __asm__ __volatile__(
- "1:\tldarx %0,0,%3\n" /* load and reserve */
- "\tcmpdi %0, 0\n" /* if load is */
- "\tbne 2f\n" /* non-zero, return already set */
- "\tstdcx. %2,0,%1\n" /* else store conditional */
- "\tbne- 1b\n" /* retry if lost reservation */
- "\tsync\n" /* import barrier */
- "2:\t\n" /* oldval is zero if we set */
- : "=&r"(oldval), "=p"(addr)
- : "r"(temp), "1"(addr)
- : "cr0","memory");
- return (int)oldval;
- }
-# else
inline static int GC_test_and_set(volatile unsigned int *addr) {
int oldval;
int temp = 1; /* locked value */
@@ -191,7 +172,6 @@
: "cr0","memory");
return oldval;
}
-# endif
# define GC_TEST_AND_SET_DEFINED
inline static void GC_clear(volatile unsigned int *addr) {
__asm__ __volatile__("lwsync" : : : "memory");
@@ -239,14 +219,17 @@
# ifdef ARM32
inline static int GC_test_and_set(volatile unsigned int *addr) {
int oldval;
- /* SWP on ARM is very similar to XCHG on x86. Doesn't lock the
- * bus because there are no SMP ARM machines. If/when there are,
- * this code will likely need to be updated. */
- /* See linuxthreads/sysdeps/arm/pt-machine.h in glibc-2.1 */
- __asm__ __volatile__("swp %0, %1, [%2]"
- : "=r"(oldval)
- : "r"(1), "r"(addr)
- : "memory");
+ /* SWP on ARM is very similar to XCHG on x86. */
+ /* The first operand is the result, the second the value */
+ /* to be stored. Both registers must be different from addr. */
+ /* Make the address operand an early clobber output so it */
+ /* doesn't overlap with the other operands. The early clobber*/
+ /* on oldval is neccessary to prevent the compiler allocating */
+ /* them to the same register if they are both unused. */
+ __asm__ __volatile__("swp %0, %2, [%3]"
+ : "=&r"(oldval), "=&r"(addr)
+ : "r"(1), "1"(addr)
+ : "memory");
return oldval;
}
# define GC_TEST_AND_SET_DEFINED
diff --git a/include/private/gc_pmark.h b/include/private/gc_pmark.h
index 5198191..714fc42 100644
--- a/include/private/gc_pmark.h
+++ b/include/private/gc_pmark.h
@@ -248,7 +248,8 @@ exit_label: ; \
if (map_entry == OFFSET_TOO_BIG) { \
map_entry = displ % (hhdr -> hb_sz); \
displ -= map_entry; \
- if (displ + (hhdr -> hb_sz) > BYTES_TO_WORDS(HBLKSIZE)) { \
+ if (displ + (hhdr -> hb_sz) > BYTES_TO_WORDS(HBLKSIZE) \
+ && displ != 0) { \
GC_ADD_TO_BLACK_LIST_NORMAL((word)current, source); \
goto exit_label; \
} \
diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h
index 3d634ce..2abd27d 100644
--- a/include/private/gc_priv.h
+++ b/include/private/gc_priv.h
@@ -755,17 +755,9 @@ struct hblk {
# ifdef LARGE_CONFIG
# define MAX_ROOT_SETS 4096
# else
-# ifdef PCR
-# define MAX_ROOT_SETS 1024
-# else
-# if defined(MSWIN32) || defined(MSWINCE)
-# define MAX_ROOT_SETS 1024
- /* Under NT, we add only written pages, which can result */
- /* in many small root sets. */
-# else
-# define MAX_ROOT_SETS 256
-# endif
-# endif
+ /* GCJ LOCAL: MAX_ROOT_SETS increased to permit more shared */
+ /* libraries to be loaded. */
+# define MAX_ROOT_SETS 1024
# endif
# define MAX_EXCLUSIONS (MAX_ROOT_SETS/4)
diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h
index c028e5d..ccba470 100644
--- a/include/private/gcconfig.h
+++ b/include/private/gcconfig.h
@@ -302,9 +302,10 @@
# if defined(__ppc__) || defined(__ppc64__)
# define POWERPC
# define mach_type_known
-# elif defined(__i386__)
+# endif
+# if defined(__i386__)
# define I386
- --> Not really supported, but at least we recognize it.
+# define mach_type_known
# endif
# endif
# if defined(NeXT) && defined(mc68000)
@@ -448,6 +449,13 @@
# define mach_type_known
# endif
# endif
+# if defined(__TANDEM)
+ /* Nonstop S-series */
+ /* FIXME: Should recognize Integrity series? */
+# define MIPS
+# define NONSTOP
+# define mach_type_known
+# endif
/* Feel free to add more clauses here */
@@ -469,8 +477,8 @@
/* FREEBSD, THREE86BSD, MSWIN32, */
/* BSDI,SUNOS5, NEXT, other variants) */
/* NS32K ==> Encore Multimax */
- /* MIPS ==> R2000 or R3000 */
- /* (RISCOS, ULTRIX variants) */
+ /* MIPS ==> R2000 through R14K */
+ /* (many variants) */
/* VAX ==> DEC VAX */
/* (BSD, ULTRIX variants) */
/* RS6000 ==> IBM RS/6000 AIX3.X */
@@ -1301,6 +1309,29 @@
/* # define MPROTECT_VDB Not quite working yet? */
# define DYNAMIC_LOADING
# endif
+# ifdef DARWIN
+# define OS_TYPE "DARWIN"
+# define DARWIN_DONT_PARSE_STACK
+# define DYNAMIC_LOADING
+ /* XXX: see get_end(3), get_etext() and get_end() should not be used.
+ These aren't used when dyld support is enabled (it is by default) */
+# define DATASTART ((ptr_t) get_etext())
+# define DATAEND ((ptr_t) get_end())
+# define STACKBOTTOM ((ptr_t) 0xc0000000)
+# define USE_MMAP
+# define USE_MMAP_ANON
+# define USE_ASM_PUSH_REGS
+ /* This is potentially buggy. It needs more testing. See the comments in
+ os_dep.c. It relies on threads to track writes. */
+# ifdef GC_DARWIN_THREADS
+/* # define MPROTECT_VDB -- disabled for now. May work for some apps. */
+# endif
+# include <unistd.h>
+# define GETPAGESIZE() getpagesize()
+ /* There seems to be some issues with trylock hanging on darwin. This
+ should be looked into some more */
+# define NO_PTHREAD_TRYLOCK
+# endif /* DARWIN */
# endif
# ifdef NS32K
@@ -1406,8 +1437,8 @@
# define DATAEND /* not needed */
# endif
# if defined(NETBSD)
-# define ALIGNMENT 4
# define OS_TYPE "NETBSD"
+# define ALIGNMENT 4
# define HEURISTIC2
# define USE_GENERIC_PUSH_REGS
# ifdef __ELF__
@@ -1420,6 +1451,16 @@
# define STACKBOTTOM ((ptr_t) 0x7ffff000)
# endif /* _ELF_ */
# endif
+# if defined(NONSTOP)
+# define CPP_WORDSZ 32
+# define OS_TYPE "NONSTOP"
+# define ALIGNMENT 4
+# define DATASTART ((ptr_t) 0x08000000)
+ extern int _end[];
+# define DATAEND (_end)
+# define STACKBOTTOM ((ptr_t) 0x4fffffff)
+# define USE_GENERIC_PUSH_REGS
+# endif
# endif
# ifdef RS6000
@@ -1885,7 +1926,7 @@
# define OS_TYPE "NETBSD"
# define HEURISTIC2
# define DATASTART GC_data_start
-# define USE_GENERIC_PUSH_REGS
+# define USE_GENERIC_PUSH_REGS
# define DYNAMIC_LOADING
# endif
# endif
@@ -2027,6 +2068,11 @@
# define SUNOS5SIGS
# endif
+# ifdef GC_NETBSD_THREADS
+# define SIGRTMIN 33
+# define SIGRTMAX 63
+# endif
+
# if defined(SVR4) || defined(LINUX) || defined(IRIX5) || defined(HPUX) \
|| defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD) \
|| defined(DGUX) || defined(BSD) || defined(SUNOS4) \
@@ -2117,6 +2163,9 @@
# if defined(GC_LINUX_THREADS) && !defined(LINUX)
--> inconsistent configuration
# endif
+# if defined(GC_NETBSD_THREADS) && !defined(NETBSD)
+ --> inconsistent configuration
+# endif
# if defined(GC_SOLARIS_THREADS) && !defined(SUNOS5)
--> inconsistent configuration
# endif
@@ -2250,7 +2299,7 @@
+ GC_page_size) \
+ GC_page_size-1)
# else
-# if defined(NEXT) || defined(DOS4GW) || \
+# if defined(NEXT) || defined(DOS4GW) || defined(NONSTOP) || \
(defined(AMIGA) && !defined(GC_AMIGA_FASTALLOC)) || \
(defined(SUNOS5) && !defined(USE_MMAP))
# define GET_MEM(bytes) HBLKPTR((size_t) \
diff --git a/malloc.c b/malloc.c
index cb3f376..b7617df 100644
--- a/malloc.c
+++ b/malloc.c
@@ -15,6 +15,8 @@
/* Boehm, February 7, 1996 4:32 pm PST */
#include <stdio.h>
+#include <string.h>
+#include <errno.h>
#include "private/gc_priv.h"
extern ptr_t GC_clear_stack(); /* in misc.c, behaves like identity */
@@ -271,6 +273,26 @@ DCL_LOCK_STATE;
}
}
+/* provide a version of strdup() that uses the collector to allocate the
+ copy of the string */
+# ifdef __STDC__
+ char *GC_strdup(const char *s)
+# else
+ char *GC_strdup(s)
+ char *s;
+#endif
+{
+ char *copy;
+
+ if (s == NULL) return NULL;
+ if ((copy = GC_malloc_atomic(strlen(s) + 1)) == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ strcpy(copy, s);
+ return copy;
+}
+
/* Allocate lb bytes of composite (pointerful) data */
# ifdef __STDC__
GC_PTR GC_malloc(size_t lb)
@@ -370,6 +392,10 @@ DCL_LOCK_STATE;
{
size_t len = strlen(s) + 1;
char * result = ((char *)REDIRECT_MALLOC(len+1));
+ if (result == 0) {
+ errno = ENOMEM;
+ return 0;
+ }
BCOPY(s, result, len+1);
return result;
}
diff --git a/mark.c b/mark.c
index 09dfe92..c56fb4d 100644
--- a/mark.c
+++ b/mark.c
@@ -1486,7 +1486,6 @@ ptr_t top;
ptr_t cold_gc_frame;
{
if (!NEED_FIXUP_POINTER && GC_all_interior_pointers) {
-# define EAGER_BYTES 1024
/* Push the hot end of the stack eagerly, so that register values */
/* saved inside GC frames are marked before they disappear. */
/* The rest of the marking can be deferred until later. */
diff --git a/misc.c b/misc.c
index 52567b7..3cd1566 100644
--- a/misc.c
+++ b/misc.c
@@ -34,6 +34,10 @@
# include <tchar.h>
#endif
+#ifdef NONSTOP
+# include <floss.h>
+#endif
+
# ifdef THREADS
# ifdef PCR
# include "il/PCR_IL.h"
@@ -477,10 +481,11 @@ void GC_init()
#if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)
if (!GC_is_initialized) {
BOOL (WINAPI *pfn) (LPCRITICAL_SECTION, DWORD) = NULL;
- HMODULE hK32 = GetModuleHandle("kernel32.dll");
+ HMODULE hK32 = GetModuleHandleA("kernel32.dll");
if (hK32)
- (FARPROC) pfn = GetProcAddress(hK32,
- "InitializeCriticalSectionAndSpinCount");
+ pfn = (BOOL (WINAPI *) (LPCRITICAL_SECTION, DWORD))
+ GetProcAddress (hK32,
+ "InitializeCriticalSectionAndSpinCount");
if (pfn)
pfn(&GC_allocate_ml, 4000);
else
diff --git a/os_dep.c b/os_dep.c
index fb50a45..b6068c9 100644
--- a/os_dep.c
+++ b/os_dep.c
@@ -1181,12 +1181,15 @@ void GC_register_data_segments()
/* This used to be set for gcc, to avoid dealing with */
/* the structured exception handling issues. But we now have */
/* assembly code to do that right. */
+ GC_bool GC_wnt = FALSE;
+ /* This is a Windows NT derivative, i.e. NT, W2K, XP or later. */
void GC_init_win32()
{
/* if we're running under win32s, assume that no DLLs will be loaded */
DWORD v = GetVersion();
- GC_no_win32_dlls |= ((v & 0x80000000) && (v & 0xff) <= 3);
+ GC_wnt = !(v & 0x80000000);
+ GC_no_win32_dlls |= ((!GC_wnt) && (v & 0xff) <= 3);
}
/* Return the smallest address a such that VirtualQuery */
@@ -1498,7 +1501,7 @@ void GC_register_data_segments()
# if !defined(OS2) && !defined(PCR) && !defined(AMIGA) \
&& !defined(MSWIN32) && !defined(MSWINCE) \
- && !defined(MACOS) && !defined(DOS4GW)
+ && !defined(MACOS) && !defined(DOS4GW) && !defined(NONSTOP)
# ifdef SUNOS4
extern caddr_t sbrk();
@@ -3799,8 +3802,12 @@ catch_exception_raise(
mach_msg_type_number_t exc_state_count = PPC_EXCEPTION_STATE64_COUNT;
ppc_exception_state64_t exc_state;
# endif
+# elif defined(I386)
+ thread_state_flavor_t flavor = i386_EXCEPTION_STATE;
+ mach_msg_type_number_t exc_state_count = i386_EXCEPTION_STATE_COUNT;
+ i386_exception_state_t exc_state;
# else
-# error FIXME for non-ppc darwin
+# error FIXME for non-ppc/x86 darwin
# endif
@@ -3830,7 +3837,13 @@ catch_exception_raise(
}
/* This is the address that caused the fault */
+#if defined(POWERPC)
addr = (char*) exc_state.dar;
+#elif defined (I386)
+ addr = (char*) exc_state.faultvaddr;
+#else
+# error FIXME for non POWERPC/I386
+#endif
if((HDR(addr)) == 0) {
/* Ugh... just like the SIGBUS problem above, it seems we get a bogus
diff --git a/powerpc_darwin_mach_dep.s b/powerpc_darwin_mach_dep.s
index fd23110..1121ee8 100644
--- a/powerpc_darwin_mach_dep.s
+++ b/powerpc_darwin_mach_dep.s
@@ -1,10 +1,21 @@
+#if defined(__ppc64__)
+#define MODE_CHOICE(x, y) y
+#else
+#define MODE_CHOICE(x, y) x
+#endif
+
+#define lgu MODE_CHOICE(lwzu, ldu)
+
+#define g_long MODE_CHOICE(long, quad) /* usage is ".g_long" */
+
+#define LOG2_GPR_BYTES MODE_CHOICE(2,3) /* log2(GPR_BYTES) */
; GC_push_regs function. Under some optimization levels GCC will clobber
; some of the non-volatile registers before we get a chance to save them
; therefore, this cannot be inline asm.
.text
- .align 2
+ .align LOG2_GPR_BYTES
.globl _GC_push_regs
_GC_push_regs:
@@ -65,7 +76,7 @@ _GC_push_regs:
.data
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
- .align 2
+ .align LOG2_GPR_BYTES
L_GC_push_one$stub:
.indirect_symbol _GC_push_one
mflr r0
@@ -74,12 +85,11 @@ L0$_GC_push_one:
mflr r11
addis r11,r11,ha16(L_GC_push_one$lazy_ptr-L0$_GC_push_one)
mtlr r0
- lwzu r12,lo16(L_GC_push_one$lazy_ptr-L0$_GC_push_one)(r11)
+ lgu r12,lo16(L_GC_push_one$lazy_ptr-L0$_GC_push_one)(r11)
mtctr r12
bctr
.data
.lazy_symbol_pointer
L_GC_push_one$lazy_ptr:
.indirect_symbol _GC_push_one
- .long dyld_stub_binding_helper
-
+ .g_long dyld_stub_binding_helper
diff --git a/pthread_stop_world.c b/pthread_stop_world.c
index b9034dc..66d7b5c 100644
--- a/pthread_stop_world.c
+++ b/pthread_stop_world.c
@@ -107,7 +107,7 @@ void GC_brief_async_signal_safe_sleep()
*/
#ifndef SIG_THR_RESTART
-# if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS)
+# if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) || defined(GC_NETBSD_THREADS)
# ifdef _SIGRTMIN
# define SIG_THR_RESTART _SIGRTMIN + 5
# else
@@ -120,6 +120,13 @@ void GC_brief_async_signal_safe_sleep()
sem_t GC_suspend_ack_sem;
+#ifdef GC_NETBSD_THREADS
+# define GC_NETBSD_THREADS_WORKAROUND
+ /* It seems to be necessary to wait until threads have restarted. */
+ /* But it is unclear why that is the case. */
+ sem_t GC_restart_ack_sem;
+#endif
+
void GC_suspend_handler_inner(ptr_t sig_arg);
#if defined(IA64) || defined(HP_PA)
@@ -227,6 +234,10 @@ void GC_restart_handler(int sig)
if (sig != SIG_THR_RESTART) ABORT("Bad signal in suspend_handler");
+#ifdef GC_NETBSD_THREADS_WORKAROUND
+ sem_post(&GC_restart_ack_sem);
+#endif
+
/*
** Note: even if we don't do anything useful here,
** it would still be necessary to have a signal handler,
@@ -303,6 +314,8 @@ void GC_push_all_stacks()
(unsigned long) bs_lo, (unsigned long) bs_hi);
# endif
if (pthread_equal(p -> id, me)) {
+ /* FIXME: This may add an unbounded number of entries, */
+ /* and hence overflow the mark stack, which is bad. */
GC_push_all_eager(bs_lo, bs_hi);
} else {
GC_push_all_stack(bs_lo, bs_hi);
@@ -439,6 +452,9 @@ void GC_start_world()
register GC_thread p;
register int n_live_threads = 0;
register int result;
+#ifdef GC_NETBSD_THREADS_WORKAROUND
+ int code;
+#endif
# if DEBUG_THREADS
GC_printf0("World starting\n");
@@ -468,6 +484,14 @@ void GC_start_world()
}
}
}
+#ifdef GC_NETBSD_THREADS_WORKAROUND
+ for (i = 0; i < n_live_threads; i++)
+ while (0 != (code = sem_wait(&GC_restart_ack_sem)))
+ if (errno != EINTR) {
+ GC_err_printf1("sem_wait() returned %ld\n", (unsigned long)code);
+ ABORT("sem_wait() for restart handler failed");
+ }
+#endif
#if DEBUG_THREADS
GC_printf0("World started\n");
#endif
@@ -478,6 +502,10 @@ void GC_stop_init() {
if (sem_init(&GC_suspend_ack_sem, 0, 0) != 0)
ABORT("sem_init failed");
+#ifdef GC_NETBSD_THREADS_WORKAROUND
+ if (sem_init(&GC_restart_ack_sem, 0, 0) != 0)
+ ABORT("sem_init failed");
+#endif
act.sa_flags = SA_RESTART;
if (sigfillset(&act.sa_mask) != 0) {
diff --git a/pthread_support.c b/pthread_support.c
index 5b3808e..e8f4902 100644
--- a/pthread_support.c
+++ b/pthread_support.c
@@ -67,7 +67,8 @@
# endif
# if (defined(GC_DGUX386_THREADS) || defined(GC_OSF1_THREADS) || \
- defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS)) \
+ defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS) || \
+ defined(GC_NETBSD_THREADS)) \
&& !defined(USE_PTHREAD_SPECIFIC)
# define USE_PTHREAD_SPECIFIC
# endif
@@ -120,7 +121,10 @@
# include <sys/sysctl.h>
#endif /* GC_DARWIN_THREADS */
-
+#if defined(GC_NETBSD_THREADS)
+# include <sys/param.h>
+# include <sys/sysctl.h>
+#endif /* GC_NETBSD_THREADS */
#if defined(GC_DGUX386_THREADS)
# include <sys/dg_sys_info.h>
@@ -836,6 +840,18 @@ int GC_get_nprocs()
}
#endif /* GC_DGUX386_THREADS */
+#if defined(GC_NETBSD_THREADS)
+static int get_ncpu(void)
+{
+ int mib[] = {CTL_HW,HW_NCPU};
+ int res;
+ size_t len = sizeof(res);
+
+ sysctl(mib, sizeof(mib)/sizeof(int), &res, &len, NULL, 0);
+ return res;
+}
+#endif /* GC_NETBSD_THREADS */
+
/* We hold the allocation lock. */
void GC_thr_init()
{
@@ -881,6 +897,9 @@ void GC_thr_init()
GC_nprocs = sysconf(_SC_NPROC_ONLN);
if (GC_nprocs <= 0) GC_nprocs = 1;
# endif
+# if defined(GC_NETBSD_THREADS)
+ GC_nprocs = get_ncpu();
+# endif
# if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS)
int ncpus = 1;
size_t len = sizeof(ncpus);
diff --git a/threadlibs.c b/threadlibs.c
index 9078c8d..6999fb8 100644
--- a/threadlibs.c
+++ b/threadlibs.c
@@ -22,6 +22,10 @@ int main()
printf("-pthread\n");
# endif
# endif
+# if defined(GC_NETBSD_THREADS)
+ printf("-lpthread -lrt\n");
+# endif
+
# if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS)
printf("-lpthread -lrt\n");
# endif
diff --git a/version.h b/version.h
index e1fe24b..930f3f2 100644
--- a/version.h
+++ b/version.h
@@ -2,7 +2,7 @@
/* Eventually this one may become unnecessary. For now we need */
/* it to keep the old-style build process working. */
#define GC_TMP_VERSION_MAJOR 6
-#define GC_TMP_VERSION_MINOR 6
+#define GC_TMP_VERSION_MINOR 7
#define GC_TMP_ALPHA_VERSION GC_NOT_ALPHA
#ifndef GC_NOT_ALPHA