gc6.2alpha5 tarball import gc6_2alpha5
authorHans Boehm <boehm@acm.org>
Wed, 14 May 2003 00:00:00 +0000 (00:00 +0000)
committerIvan Maidanski <ivmai@mail.ru>
Sat, 17 May 2014 14:44:47 +0000 (18:44 +0400)
31 files changed:
Makefile.am
Makefile.in
alloc.c
configure
configure.in
cord/cordbscs.c
dbg_mlc.c
doc/Makefile.in
doc/README
doc/README.changes
doc/README.macros
doc/README.win32
dyn_load.c
finalize.c
include/Makefile.in
include/gc.h
include/gc_config_macros.h
include/private/gc_locks.h
include/private/gc_priv.h
include/private/gcconfig.h
linux_threads.c
mark.c
mark_rts.c
misc.c
os_dep.c
ptr_chck.c
reclaim.c
tests/test.c
threadlibs.c
version.h
win32_threads.c

index 5c1ed96..7b851e2 100644 (file)
@@ -25,7 +25,9 @@ SUBDIRS = doc include
 EXTRA_DIST = 
     ## more items will be succesively added below
 
-lib_LTLIBRARIES = libgc.la
+lib_LTLIBRARIES = libgc.la @addlibs@
+
+EXTRA_LTLIBRARIES = libgccpp.la
 
 include_HEADERS = include/gc.h include/gc_local_alloc.h \
 include/gc_pthread_redirects.h include/gc_config_macros.h \
@@ -49,7 +51,11 @@ libgc_la_LDFLAGS = -version-info 1:2:0
 EXTRA_libgc_la_SOURCES = alpha_mach_dep.S \
     mips_sgi_mach_dep.S mips_ultrix_mach_dep.s powerpc_macosx_mach_dep.s \
     rs6000_mach_dep.s sparc_mach_dep.S sparc_netbsd_mach_dep.s \
-    sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s gc_cpp.cc
+    sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s
+
+libgccpp_la_SOURCES = gc_cpp.cc
+libgccpp_la_LIBADD = $(THREADLIBS)
+libgccpp_la_LDFLAGS = -version-info 1:2:0
 
 EXTRA_DIST += alpha_mach_dep.S mips_sgi_mach_dep.S sparc_mach_dep.S
 
@@ -71,10 +77,14 @@ test_cpp.o: $(srcdir)/tests/test_cpp.cc
 gctest_SOURCES = tests/test.c
 gctest_LDADD = ./libgc.la $(THREADLIBS) $(EXTRA_TEST_LIBS)
 test_cpp_SOURCES = tests/test_cpp.cc
-test_cpp_LDADD = ./libgc.la $(THREADLIBS) $(EXTRA_TEST_LIBS)
-TESTS_ENVIRONMENT = LD_LIBRARY_PATH=../../gcc
+test_cpp_LDADD = ./libgc.la ./libgccpp.la $(THREADLIBS) $(EXTRA_TEST_LIBS)
+
 TESTS = gctest @addtests@
 
+test_cpp$(EXEEXT): test_cpp.o
+       $(LIBTOOL) --mode=link $(CXX) $(AM_CFLAGS) $(MY_CFLAGS) \
+               test_cpp.o $(test_cpp_LDADD) $(LDFLAGS) -o $@
+
 ## FIXME: relies on internal code generated by automake.
 all_objs = @addobjs@ $(libgc_la_OBJECTS)
 $(all_objs) : include/private/gcconfig.h include/private/gc_priv.h \
index aa388c8..4d3ee55 100644 (file)
@@ -111,6 +111,7 @@ STRIP = @STRIP@
 THREADLIBS = @THREADLIBS@
 VERSION = @VERSION@
 addincludes = @addincludes@
+addlibs = @addlibs@
 addobjs = @addobjs@
 addtests = @addtests@
 am__include = @am__include@
@@ -161,7 +162,9 @@ cord/cordbscs.c cord/cordtest.c cord/de.c cord/de_win.c \
     cord/de_win.h cord/de_win.RC\
 libtool.m4
 
-lib_LTLIBRARIES = libgc.la
+lib_LTLIBRARIES = libgc.la @addlibs@
+
+EXTRA_LTLIBRARIES = libgccpp.la
 
 include_HEADERS = include/gc.h include/gc_local_alloc.h \
 include/gc_pthread_redirects.h include/gc_config_macros.h \
@@ -187,8 +190,12 @@ libgc_la_LDFLAGS = -version-info 1:2:0
 EXTRA_libgc_la_SOURCES = alpha_mach_dep.S \
     mips_sgi_mach_dep.S mips_ultrix_mach_dep.s powerpc_macosx_mach_dep.s \
     rs6000_mach_dep.s sparc_mach_dep.S sparc_netbsd_mach_dep.s \
-    sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s gc_cpp.cc
+    sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s
+
 
+libgccpp_la_SOURCES = gc_cpp.cc
+libgccpp_la_LIBADD = $(THREADLIBS)
+libgccpp_la_LDFLAGS = -version-info 1:2:0
 
 AM_CXXFLAGS = @GC_CFLAGS@
 AM_CFLAGS = @GC_CFLAGS@
@@ -200,8 +207,8 @@ EXTRA_PROGRAMS = test_cpp
 gctest_SOURCES = tests/test.c
 gctest_LDADD = ./libgc.la $(THREADLIBS) $(EXTRA_TEST_LIBS)
 test_cpp_SOURCES = tests/test_cpp.cc
-test_cpp_LDADD = ./libgc.la $(THREADLIBS) $(EXTRA_TEST_LIBS)
-TESTS_ENVIRONMENT = LD_LIBRARY_PATH=../../gcc
+test_cpp_LDADD = ./libgc.la ./libgccpp.la $(THREADLIBS) $(EXTRA_TEST_LIBS)
+
 TESTS = gctest @addtests@
 
 all_objs = @addobjs@ $(libgc_la_OBJECTS)
@@ -238,6 +245,9 @@ am_libgc_la_OBJECTS = allchblk.lo alloc.lo blacklst.lo checksums.lo \
        reclaim.lo solaris_pthreads.lo solaris_threads.lo specific.lo \
        stubborn.lo typd_mlc.lo backgraph.lo win32_threads.lo
 libgc_la_OBJECTS = $(am_libgc_la_OBJECTS)
+libgccpp_la_DEPENDENCIES =
+am_libgccpp_la_OBJECTS = gc_cpp.lo
+libgccpp_la_OBJECTS = $(am_libgccpp_la_OBJECTS)
 EXTRA_PROGRAMS = test_cpp$(EXEEXT)
 check_PROGRAMS = gctest$(EXEEXT) @addtests@
 am_gctest_OBJECTS = test.$(OBJEXT)
@@ -246,7 +256,7 @@ gctest_DEPENDENCIES = ./libgc.la
 gctest_LDFLAGS =
 am_test_cpp_OBJECTS = test_cpp.$(OBJEXT)
 test_cpp_OBJECTS = $(am_test_cpp_OBJECTS)
-test_cpp_DEPENDENCIES = ./libgc.la
+test_cpp_DEPENDENCIES = ./libgc.la ./libgccpp.la
 test_cpp_LDFLAGS =
 SCRIPTS = $(dist_noinst_SCRIPTS)
 
@@ -294,7 +304,7 @@ CXXLD = $(CXX)
 CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
        $(AM_LDFLAGS) $(LDFLAGS) -o $@
 DIST_SOURCES = $(libgc_la_SOURCES) $(EXTRA_libgc_la_SOURCES) \
-       $(gctest_SOURCES) $(test_cpp_SOURCES)
+       $(libgccpp_la_SOURCES) $(gctest_SOURCES) $(test_cpp_SOURCES)
 HEADERS = $(dist_noinst_HEADERS) $(include_HEADERS)
 
 
@@ -307,7 +317,7 @@ DIST_COMMON = $(dist_noinst_HEADERS) $(dist_noinst_SCRIPTS) \
        aclocal.m4 config.guess config.sub configure configure.in \
        depcomp install-sh ltconfig ltmain.sh missing mkinstalldirs
 DIST_SUBDIRS = $(SUBDIRS)
-SOURCES = $(libgc_la_SOURCES) $(EXTRA_libgc_la_SOURCES) $(gctest_SOURCES) $(test_cpp_SOURCES)
+SOURCES = $(libgc_la_SOURCES) $(EXTRA_libgc_la_SOURCES) $(libgccpp_la_SOURCES) $(gctest_SOURCES) $(test_cpp_SOURCES)
 
 all: all-recursive
 
@@ -358,7 +368,9 @@ clean-libLTLIBRARIES:
          rm -f "$${dir}/so_locations"; \
        done
 libgc.la: $(libgc_la_OBJECTS) $(libgc_la_DEPENDENCIES) 
-       $(CXXLINK) -rpath $(libdir) $(libgc_la_LDFLAGS) $(libgc_la_OBJECTS) $(libgc_la_LIBADD) $(LIBS)
+       $(LINK) -rpath $(libdir) $(libgc_la_LDFLAGS) $(libgc_la_OBJECTS) $(libgc_la_LIBADD) $(LIBS)
+libgccpp.la: $(libgccpp_la_OBJECTS) $(libgccpp_la_DEPENDENCIES) 
+       $(CXXLINK)  $(libgccpp_la_LDFLAGS) $(libgccpp_la_OBJECTS) $(libgccpp_la_LIBADD) $(LIBS)
 
 clean-checkPROGRAMS:
        @list='$(check_PROGRAMS)'; for p in $$list; do \
@@ -371,9 +383,6 @@ gctest$(EXEEXT): $(gctest_OBJECTS) $(gctest_DEPENDENCIES)
        @rm -f gctest$(EXEEXT)
        $(LINK) $(gctest_LDFLAGS) $(gctest_OBJECTS) $(gctest_LDADD) $(LIBS)
 test_cpp.$(OBJEXT): tests/test_cpp.cc
-test_cpp$(EXEEXT): $(test_cpp_OBJECTS) $(test_cpp_DEPENDENCIES) 
-       @rm -f test_cpp$(EXEEXT)
-       $(CXXLINK) $(test_cpp_LDFLAGS) $(test_cpp_OBJECTS) $(test_cpp_LDADD) $(LIBS)
 
 mostlyclean-compile:
        -rm -f *.$(OBJEXT) core *.core
@@ -878,6 +887,10 @@ test.o:    $(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
+
+test_cpp$(EXEEXT): test_cpp.o
+       $(LIBTOOL) --mode=link $(CXX) $(AM_CFLAGS) $(MY_CFLAGS) \
+               test_cpp.o $(test_cpp_LDADD) $(LDFLAGS) -o $@
 $(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/alloc.c b/alloc.c
index 4cb7a4c..d2b874f 100644 (file)
--- a/alloc.c
+++ b/alloc.c
@@ -72,6 +72,13 @@ int GC_full_freq = 19;          /* Every 20th collection is a full   */
 GC_bool GC_need_full_gc = FALSE;
                           /* Need full GC do to heap growth.   */
 
+#ifdef THREADS
+  GC_bool GC_world_stopped = FALSE;
+# define IF_THREADS(x) x
+#else
+# define IF_THREADS(x)
+#endif
+
 word GC_used_heap_size_after_full = 0;
 
 char * GC_copyright[] =
@@ -470,6 +477,7 @@ GC_stop_func stop_func;
         GC_cond_register_dynamic_libraries();
 #   endif
     STOP_WORLD();
+    IF_THREADS(GC_world_stopped = TRUE);
 #   ifdef CONDPRINT
       if (GC_print_stats) {
        GC_printf1("--> Marking for collection %lu ",
@@ -500,6 +508,7 @@ GC_stop_func stop_func;
                      }
 #                  endif
                    GC_deficit = i; /* Give the mutator a chance. */
+                    IF_THREADS(GC_world_stopped = FALSE);
                    START_WORLD();
                    return(FALSE);
            }
@@ -533,6 +542,7 @@ GC_stop_func stop_func;
             (*GC_check_heap)();
         }
     
+    IF_THREADS(GC_world_stopped = FALSE);
     START_WORLD();
 #   ifdef PRINTTIMES
        GET_TIME(current_time);
index dcd4524..db84f60 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,7 +1,7 @@
 #! /bin/sh
 # From configure.in Revision: 1.2 .
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.53 for gc 6.2alpha4.
+# Generated by GNU Autoconf 2.53 for gc 6.2alpha5.
 #
 # 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.2alpha4'
-PACKAGE_STRING='gc 6.2alpha4'
+PACKAGE_VERSION='6.2alpha5'
+PACKAGE_STRING='gc 6.2alpha5'
 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.2alpha4 to adapt to many kinds of systems.
+\`configure' configures gc 6.2alpha5 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.2alpha4:";;
+     short | recursive ) echo "Configuration of gc 6.2alpha5:";;
    esac
   cat <<\_ACEOF
 
@@ -1010,7 +1010,7 @@ Optional Features:
                           (and sometimes confusing) to the casual installer
   --enable-threads=TYPE   choose threading package
   --enable-parallel-mark       parallelize marking and free list construction
-  --enable-cplusplus           include C++ support in GC library and include directory
+  --enable-cplusplus           install C++ support
   --enable-shared=PKGS  build shared libraries default=yes
   --enable-static=PKGS  build static libraries default=yes
   --enable-fast-install=PKGS  optimize for fast installation default=yes
@@ -1106,7 +1106,7 @@ fi
 test -n "$ac_init_help" && exit 0
 if $ac_init_version; then
   cat <<\_ACEOF
-gc configure 6.2alpha4
+gc configure 6.2alpha5
 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.2alpha4, which was
+It was created by gc $as_me 6.2alpha5, 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.2alpha4
+ VERSION=6.2alpha5
 
 
 cat >>confdefs.h <<_ACEOF
@@ -3688,6 +3688,10 @@ echo "$as_me: error: $THREADS is an unknown thread package" >&2;}
 esac
 
 
+# I'm not too familiar with autoconf, is this the best way to do this? -Brian
+case "$host" in
+  *-*-darwin*) ;;
+  *)
 
 echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
 echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6
@@ -3748,6 +3752,9 @@ if test $ac_cv_lib_dl_dlopen = yes; then
   EXTRA_TEST_LIBS="$EXTRA_TEST_LIBS -ldl"
 fi
 
+    ;;
+esac
+
 
 
 target_all=libgc.la
@@ -3763,6 +3770,7 @@ if test "${with_ecos+set}" = set; then
 fi;
 
 addobjs=
+addlibs=
 addincludes=
 addtests=
 CXXINCLUDES=
@@ -3780,7 +3788,7 @@ _ACEOF
 esac
 
 if test "${enable_cplusplus}" = yes; then
-      addobjs="$addobjs gc_cpp.lo"
+      addlibs="$addlibs libgccpp.la"
       addincludes="$addincludes include/gc_cpp.h include/gc_allocator.h"
       addtests="$addtests test_cpp"
 fi
@@ -3903,6 +3911,7 @@ addobjs="$addobjs $machdep"
 
 
 
+
 # Check whether --enable-static or --disable-static was given.
 if test "${enable_static+set}" = set; then
   enableval="$enable_static"
@@ -5335,7 +5344,7 @@ test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
 case $host in
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 5338 "configure"' > conftest.$ac_ext
+  echo '#line 5347 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -5871,7 +5880,7 @@ chmod -w .
 save_CFLAGS="$CFLAGS"
 CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
 compiler_c_o=no
-if { (eval echo configure:5874: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
+if { (eval echo configure:5883: \"$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
@@ -7664,7 +7673,7 @@ else
     lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 7667 "configure"
+#line 7676 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -7762,7 +7771,7 @@ else
     lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 7765 "configure"
+#line 7774 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -9191,7 +9200,7 @@ _ASBOX
 } >&5
 cat >&5 <<_CSEOF
 
-This file was extended by gc $as_me 6.2alpha4, which was
+This file was extended by gc $as_me 6.2alpha5, which was
 generated by GNU Autoconf 2.53.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -9248,7 +9257,7 @@ _ACEOF
 
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
-gc config.status 6.2alpha4
+gc config.status 6.2alpha5
 configured by $0, generated by GNU Autoconf 2.53,
   with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
 
@@ -9499,6 +9508,7 @@ s,@INCLUDES@,$INCLUDES,;t t
 s,@CXXINCLUDES@,$CXXINCLUDES,;t t
 s,@addobjs@,$addobjs,;t t
 s,@addincludes@,$addincludes,;t t
+s,@addlibs@,$addlibs,;t t
 s,@addtests@,$addtests,;t t
 s,@LN_S@,$LN_S,;t t
 s,@ECHO@,$ECHO,;t t
index 092447c..2e18090 100644 (file)
@@ -17,7 +17,7 @@ dnl Process this file with autoconf to produce configure.
 # Initialization
 # ==============
 
-AC_INIT(gc,6.2alpha4,Hans.Boehm@hp.com) 
+AC_INIT(gc,6.2alpha5,Hans.Boehm@hp.com) 
     ## version must conform to [0-9]+[.][0-9]+(alpha[0-9]+)?
 AC_CONFIG_SRCDIR(gcj_mlc.c)
 AC_CANONICAL_TARGET 
@@ -64,7 +64,7 @@ AC_ARG_ENABLE(parallel-mark,
 )
 
 AC_ARG_ENABLE(cplusplus,
-[  --enable-cplusplus          include C++ support in GC library and include directory],
+[  --enable-cplusplus          install C++ support],
 )
 
 INCLUDES=-I${srcdir}/include
@@ -183,6 +183,7 @@ TARGET_ECOS="$with_ecos"
 )
 
 addobjs=
+addlibs=
 addincludes=
 addtests=
 CXXINCLUDES=
@@ -197,7 +198,7 @@ case "$TARGET_ECOS" in
 esac
 
 if test "${enable_cplusplus}" = yes; then
-      addobjs="$addobjs gc_cpp.lo"
+      addlibs="$addlibs libgccpp.la"
       addincludes="$addincludes include/gc_cpp.h include/gc_allocator.h"
       addtests="$addtests test_cpp"
 fi
@@ -276,6 +277,7 @@ fi
 addobjs="$addobjs $machdep"
 AC_SUBST(addobjs)
 AC_SUBST(addincludes)
+AC_SUBST(addlibs)
 AC_SUBST(addtests)
 
 AC_PROG_LIBTOOL
index 9fc894d..d83f406 100644 (file)
@@ -219,7 +219,7 @@ CORD CORD_cat_char_star(CORD x, const char * y, size_t leny)
        result->len = result_len;
        result->left = x;
        result->right = y;
-       if (depth > MAX_DEPTH) {
+       if (depth >= MAX_DEPTH) {
            return(CORD_balance((CORD)result));
        } else {
            return((CORD) result);
@@ -260,7 +260,11 @@ CORD CORD_cat(CORD x, CORD y)
        result->len = result_len;
        result->left = x;
        result->right = y;
-       return((CORD) result);
+       if (depth >= MAX_DEPTH) {
+           return(CORD_balance((CORD)result));
+       } else {
+           return((CORD) result);
+       }
     }
 }
 
index eb48993..f640930 100644 (file)
--- a/dbg_mlc.c
+++ b/dbg_mlc.c
@@ -924,9 +924,11 @@ void GC_print_all_smashed_proc ()
 void GC_check_heap_proc()
 {
 #   ifndef SMALL_CONFIG
-       if (sizeof(oh) & (2 * sizeof(word) - 1) != 0) {
-           ABORT("Alignment problem: object header has inappropriate size\n");
-       }
+#     ifdef ALIGN_DOUBLE
+        GC_STATIC_ASSERT((sizeof(oh) & (2 * sizeof(word) - 1)) == 0);
+#     else
+        GC_STATIC_ASSERT((sizeof(oh) & (sizeof(word) - 1)) == 0);
+#     endif
 #   endif
     GC_apply_to_all_blocks(GC_check_heap_block, (word)0);
 }
index ea2a214..c8d1ccc 100644 (file)
@@ -108,6 +108,7 @@ STRIP = @STRIP@
 THREADLIBS = @THREADLIBS@
 VERSION = @VERSION@
 addincludes = @addincludes@
+addlibs = @addlibs@
 addobjs = @addobjs@
 addtests = @addtests@
 am__include = @am__include@
index afe2d52..581d69d 100644 (file)
@@ -28,7 +28,7 @@ are GPL'ed, but with an exception that should cover all uses in the
 collector.  (If you are concerned about such things, I recommend you look
 at the notice in config.guess or ltmain.sh.)
 
-This is version 6.2alpha3 of a conservative garbage collector for C and C++.
+This is version 6.2alpha5 of a conservative garbage collector for C and C++.
 
 You might find a more recent version of this at
 
index 627ddae..125f83f 100644 (file)
@@ -1780,6 +1780,62 @@ Since 6.2alpha3:
    when it should have called the lower case version, since it was
    explicitly computing a base pointer.
 
+Since 6.2alpha4:
+ - GC_invoke_finalizers could, under rare conditions, set
+   GC_finalizer_mem_freed to an essentially random value.  This could
+   possibly cause unbounded heap growth for long-running applications
+   under some conditions.  (The bug was introduced in 6.1alpha5, and
+   is not in gcc3.3.  Thanks to Ben Hutchings for finding it.)
+ - Attempted to sanitize the various DLL macros.  GC_USE_DLL disappeared.
+   GC_DLL is used instead.  All internal tests are now on GC_DLL.
+   README.macros is now more precise about the intended meaning.
+ - Include DllMain in the multithreaded win32 version only if the
+   collector is actually built as a dll.  (Thanks to Mohan Embar for
+   a version of the patch.)
+ - Hide the cygwin threadAttach/Detach functions.  They were violating our
+   namespace rules.  
+ - Fixed an assertion in GC_check_heap_proc.  Added GC_STATIC_ASSERT.
+   (Thanks again to Ben Hutchings.)
+ - Removed some obsolete definitions for Linux/PowerPC in gcconfig.h.
+ - CORD_cat was not rebalancing unbalanced trees in some cases, violating
+   a CORD invariant.  Also tweaked the rebalancing rule for
+   CORD_cat_char_star.  (Thanks to Alexandr Petrosian for the bug report
+   and patch.)
+ - Added hand-coded structured exception handling support to mark.c.
+   This should enable support of dynamic libraries under win32 with
+   gcc-compiled code.  (Thanks to Ranjit Mathew for the patch.)
+   Turned on dynamic library scanning for win32/gcc.
+ - Removed some remnants of read wrapping.  (Thanks to Kenneth Schalk.)
+   GC_USE_LD_WRAP ws probably broken in recent versions.
+ - The build could fail on some platforms since gcconfig.h could include
+   declarations mentioning ptr_t, which was not defined, e.g. when if_mach
+   was built.  (Thanks to Yann Dirson for pointing this out.)  Also
+   cleaned up tests for GC_PRIVATE_H in gcconfig.h a bit. 
+ - The GC_LOOP_ON_ABORT environment variable interfered with incremental
+   collection, since the write fault handler was erroneously overridden.
+   Handlers are now set up in the correct order.
+ - It used to be possible to call GC_mark_thread_local_free_lists() while
+   the world was not stopped during an incremental GC.  This was not safe.
+   Fortunately, it was also unnecessary.  Added GC_world_stopped flag
+   to avoid it.  (This caused occasional crashes in GC_set_fl_marks
+   with thread local allocation and incremental GC.  This probably happened
+   primarily on old, slow multiprocessors.)
+ - Allowed overriding of MAX_THREADS in win32_threads.c from the build
+   command line.  (Patch from Yannis Bres.)
+ - Taught the IA64/linux code to determine the register backing store base from
+   /proc/self/maps after checking the __libc symbol, but before guessing.
+   (__libc symbols are on the endangered list, and the guess is likely to not
+   always be right for 2.6 kernels.)  Restructured the code to read and parse
+   /proc/self/maps so it only exists in one place (all platforms).
+ - The -DUSE_PROC_FOR_LIBRARIES code was broken on Linux.  It claimed that it
+   also registered the main data segment, but didn't actually do so.  (I don't
+   think anyone actually uses this configuration, but ...)
+ - Made another attempt to get --enablecplusplus to do the right thing.
+   Since there are unavoidable problems with C programs linking against a
+   dynamic library that includes C++ code, I separated out the c++ code into
+   libgccpp.
+    
+
 To do:
  - MacOSX thread support still appears to be a bit unreliable.
  - A dynamic libgc.so references dlopen unconditionally, but doesn't link
index d9df8dd..b5fe679 100644 (file)
@@ -51,7 +51,18 @@ _DLL         Defined by Visual C++ if dynamic libraries are being built
                __declspec(dllexport) needs to be added to declarations
                to support the case in which the collector is in a dll.
 
-GC_DLL         User-settable macro that forces the effect of _DLL.
+GC_DLL         User-settable macro that forces the effect of _DLL.  Set
+               by gc.h if _DLL is defined and GC_NOT_DLL is undefined.
+               This is the macro that is tested internally to determine
+               whether the GC is in its own dynamic library.  May need
+               to be set by clients before including gc.h.  Note that
+               inside the GC implementation it indicates that the
+               collector is in its own dynamic library, should export
+               its symbols, etc.  But in clients it indicates that the
+               GC resides in a different DLL, its entry points should
+               be referenced accordingly, and precautions may need to
+               be taken to properly deal with statically allocated 
+               variables in the main program.  Used only for MS Windows.
 
 GC_NOT_DLL     User-settable macro that overrides _DLL, e.g. if dynamic
                libraries are used, but the collector is in a static library.
index c95f149..a40b375 100644 (file)
@@ -161,7 +161,7 @@ To compile the collector and testing programs use the command:
 All programs using gc should be compiled with 4-byte alignment.
 For further explanations on this see comments about Borland.
 
-If gc compiled as dll, the macro ``GC_DLL'' should be defined before
+If the gc is compiled as dll, the macro ``GC_DLL'' should be defined before
 including "gc.h" (for example, with -DGC_DLL compiler option). It's
 important, otherwise resulting programs will not run.
 
index dbdf3f4..aacdaf6 100644 (file)
@@ -283,56 +283,23 @@ extern ssize_t GC_repeat_read(int fd, char *buf, size_t count);
        /* Repeatedly read until buffer is filled, or EOF is encountered */
        /* Defined in os_dep.c.                                          */
 
-static char *parse_map_entry(char *buf_ptr, word *start, word *end,
-                             char *prot_buf, unsigned int *maj_dev);
+char *GC_parse_map_entry(char *buf_ptr, word *start, word *end,
+                         char *prot_buf, unsigned int *maj_dev);
+word GC_apply_to_maps(word (*fn)(char *));
+       /* From os_dep.c        */
 
-void GC_register_dynamic_libraries()
+word GC_register_map_entries(char *maps)
 {
-    int f;
-    int result;
     char prot_buf[5];
-    int maps_size;
-    char maps_temp[32768];
-    char *maps_buf;
-    char *buf_ptr;
+    char *buf_ptr = maps;
     int count;
     word start, end;
-    unsigned int maj_dev, min_dev;
+    unsigned int maj_dev;
     word least_ha, greatest_ha;
     unsigned i;
     word datastart = (word)(DATASTART);
 
-    /* Read /proc/self/maps    */
-        /* Note that we may not allocate, and thus can't use stdio.    */
-        f = open("/proc/self/maps", O_RDONLY);
-        if (-1 == f) ABORT("Couldn't open /proc/self/maps");
-       /* stat() doesn't work for /proc/self/maps, so we have to
-          read it to find out how large it is... */
-       maps_size = 0;
-       do {
-           result = GC_repeat_read(f, maps_temp, sizeof(maps_temp));
-           if (result <= 0) ABORT("Couldn't read /proc/self/maps");
-           maps_size += result;
-       } while (result == sizeof(maps_temp));
-
-       if (maps_size > sizeof(maps_temp)) {
-           /* If larger than our buffer, close and re-read it. */
-           close(f);
-           f = open("/proc/self/maps", O_RDONLY);
-           if (-1 == f) ABORT("Couldn't open /proc/self/maps");
-           maps_buf = alloca(maps_size);
-           if (NULL == maps_buf) ABORT("/proc/self/maps alloca failed");
-           result = GC_repeat_read(f, maps_buf, maps_size);
-           if (result <= 0) ABORT("Couldn't read /proc/self/maps");
-       } else {
-           /* Otherwise use the fixed size buffer */
-           maps_buf = maps_temp;
-       }
-
-       close(f);
-        maps_buf[result] = '\0';
-        buf_ptr = maps_buf;
-    /* Compute heap bounds. Should be done by add_to_heap?     */
+    /* Compute heap bounds. FIXME: Should be done by add_to_heap?      */
        least_ha = (word)(-1);
        greatest_ha = 0;
        for (i = 0; i < GC_n_heap_sects; ++i) {
@@ -343,11 +310,10 @@ void GC_register_dynamic_libraries()
         }
        if (greatest_ha < (word)GC_scratch_last_end_ptr)
            greatest_ha = (word)GC_scratch_last_end_ptr; 
-    for (;;) {
-
-        buf_ptr = parse_map_entry(buf_ptr, &start, &end, prot_buf, &maj_dev);
-       if (buf_ptr == NULL) return;
 
+    for (;;) {
+        buf_ptr = GC_parse_map_entry(buf_ptr, &start, &end, prot_buf, &maj_dev);
+       if (buf_ptr == NULL) return 1;
        if (prot_buf[1] == 'w') {
            /* This is a writable mapping.  Add it to           */
            /* the root set unless it is already otherwise      */
@@ -359,16 +325,7 @@ void GC_register_dynamic_libraries()
 #          ifdef THREADS
              if (GC_segment_is_thread_stack(start, end)) continue;
 #          endif
-           /* The rest of this assumes that there is no mapping        */
-           /* spanning the beginning of the data segment, or extending */
-           /* beyond the entire heap at both ends.                     */
-           /* Empirically these assumptions hold.                      */
-           
-           if (start < (word)DATAEND && end > (word)DATAEND) {
-               /* Rld may use space at the end of the main data        */
-               /* segment.  Thus we add that in.                       */
-               start = (word)DATAEND;
-           }
+           /* We no longer exclude the main data segment.              */
            if (start < least_ha && end > least_ha) {
                end = least_ha;
            }
@@ -378,7 +335,14 @@ void GC_register_dynamic_libraries()
            if (start >= least_ha && end <= greatest_ha) continue;
            GC_add_roots_inner((char *)start, (char *)end, TRUE);
        }
-     }
+    }
+    return 1;
+}
+
+void GC_register_dynamic_libraries()
+{
+   if (!GC_apply_to_maps(GC_register_map_entries))
+       ABORT("Failed to read /proc for library registration.");
 }
 
 /* We now take care of the main data segment ourselves: */
@@ -388,73 +352,6 @@ GC_bool GC_register_main_static_data()
 }
   
 # define HAVE_REGISTER_MAIN_STATIC_DATA
-//
-//  parse_map_entry parses an entry from /proc/self/maps so we can
-//  locate all writable data segments that belong to shared libraries.
-//  The format of one of these entries and the fields we care about
-//  is as follows:
-//  XXXXXXXX-XXXXXXXX r-xp 00000000 30:05 260537     name of mapping...\n
-//  ^^^^^^^^ ^^^^^^^^ ^^^^          ^^
-//  start    end      prot          maj_dev
-//  0        9        18            32
-//  
-//  For 64 bit ABIs:
-//  0       17       34            56
-//
-//  The parser is called with a pointer to the entry and the return value
-//  is either NULL or is advanced to the next entry(the byte after the
-//  trailing '\n'.)
-//
-#if CPP_WORDSZ == 32
-# define OFFSET_MAP_START   0
-# define OFFSET_MAP_END     9
-# define OFFSET_MAP_PROT   18
-# define OFFSET_MAP_MAJDEV 32
-# define ADDR_WIDTH        8
-#endif
-
-#if CPP_WORDSZ == 64
-# define OFFSET_MAP_START   0
-# define OFFSET_MAP_END    17
-# define OFFSET_MAP_PROT   34
-# define OFFSET_MAP_MAJDEV 56
-# define ADDR_WIDTH       16
-#endif
-
-static char *parse_map_entry(char *buf_ptr, word *start, word *end,
-                             char *prot_buf, unsigned int *maj_dev)
-{
-    int i;
-    char *tok;
-
-    if (buf_ptr == NULL || *buf_ptr == '\0') {
-        return NULL;
-    }
-
-    memcpy(prot_buf, buf_ptr+OFFSET_MAP_PROT, 4); // do the protections first
-    prot_buf[4] = '\0';
-
-    if (prot_buf[1] == 'w') { // we can skip all of this if it's not writable
-
-        tok = buf_ptr;
-        buf_ptr[OFFSET_MAP_START+ADDR_WIDTH] = '\0';
-        *start = strtoul(tok, NULL, 16);
-
-        tok = buf_ptr+OFFSET_MAP_END;
-        buf_ptr[OFFSET_MAP_END+ADDR_WIDTH] = '\0';
-        *end = strtoul(tok, NULL, 16);
-
-        buf_ptr += OFFSET_MAP_MAJDEV;
-        tok = buf_ptr;
-        while (*buf_ptr != ':') buf_ptr++;
-        *buf_ptr++ = '\0';
-        *maj_dev = strtoul(tok, NULL, 16);
-    }
-
-    while (*buf_ptr && *buf_ptr++ != '\n');
-
-    return buf_ptr;
-}
 
 #endif /* USE_PROC_FOR_LIBRARIES */
 
index 8350605..3b9d9f5 100644 (file)
@@ -764,7 +764,6 @@ int GC_invoke_finalizers()
     struct finalizable_object * curr_fo;
     int count = 0;
     word mem_freed_before;
-    GC_bool first_time = TRUE;
     DCL_LOCK_STATE;
     
     while (GC_finalize_now != 0) {
@@ -772,9 +771,8 @@ int GC_invoke_finalizers()
            DISABLE_SIGNALS();
            LOCK();
 #      endif
-       if (first_time) {
+       if (count == 0) {
            mem_freed_before = GC_mem_freed;
-           first_time = FALSE;
        }
        curr_fo = GC_finalize_now;
 #      ifdef THREADS
@@ -797,7 +795,7 @@ int GC_invoke_finalizers()
            GC_free((GC_PTR)curr_fo);
 #      endif
     }
-    if (mem_freed_before != GC_mem_freed) {
+    if (count != 0 && mem_freed_before != GC_mem_freed) {
         LOCK();
        GC_finalizer_mem_freed += (GC_mem_freed - mem_freed_before);
        UNLOCK();
index a8dab02..cb650a8 100644 (file)
@@ -108,6 +108,7 @@ STRIP = @STRIP@
 THREADLIBS = @THREADLIBS@
 VERSION = @VERSION@
 addincludes = @addincludes@
+addlibs = @addlibs@
 addobjs = @addobjs@
 addtests = @addtests@
 am__include = @am__include@
index b1c64ce..dfecfca 100644 (file)
@@ -344,14 +344,14 @@ GC_API void GC_add_roots GC_PROTO((char * low_address,
 /* Add a displacement to the set of those considered valid by the      */
 /* collector.  GC_register_displacement(n) means that if p was returned */
 /* by GC_malloc, then (char *)p + n will be considered to be a valid   */
-/* pointer to n.  N must be small and less than the size of p.         */
+/* pointer to p.  N must be small and less than the size of p.         */
 /* (All pointers to the interior of objects from the stack are         */
 /* considered valid in any case.  This applies to heap objects and     */
 /* static data.)                                                       */
 /* Preferably, this should be called before any other GC procedures.   */
 /* Calling it later adds to the probability of excess memory           */
 /* retention.                                                          */
-/* This is a no-op if the collector was compiled with recognition of   */
+/* This is a no-op if the collector has recognition of                 */
 /* arbitrary interior pointers enabled, which is now the default.      */
 GC_API void GC_register_displacement GC_PROTO((GC_word n));
 
@@ -883,7 +883,7 @@ extern void GC_thr_init();  /* Needed for Solaris/X86       */
    * and does then use DllMain to keep track of thread creations.  But new code
    * should be built to call GC_CreateThread.
    */
-  HANDLE WINAPI GC_CreateThread(
+  GC_API HANDLE GC_CreateThread(
       LPSECURITY_ATTRIBUTES lpThreadAttributes,
       DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress,
       LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId );
@@ -917,7 +917,7 @@ extern void GC_thr_init();  /* Needed for Solaris/X86       */
 #   define GC_INIT() { extern end, etext; \
                       GC_noop(&end, &etext); }
 #else
-# if defined(__CYGWIN32__) && defined(GC_USE_DLL) || defined (_AIX)
+# if defined(__CYGWIN32__) && defined(GC_DLL) || defined (_AIX)
     /*
      * Similarly gnu-win32 DLLs need explicit initialization from
      * the main program, as does AIX.
index 763e02f..01de9c5 100644 (file)
     typedef long ptrdiff_t;    /* ptrdiff_t is not defined */
 # endif
 
-#if defined(__MINGW32__) && defined(_DLL) && !defined(GC_NOT_DLL)
+#if defined(_DLL) && !defined(GC_NOT_DLL) && !defined(GC_DLL)
+# define GC_DLL
+#endif
+
+#if defined(__MINGW32__) && defined(GC_DLL)
 # ifdef GC_BUILD
 #   define GC_API __declspec(dllexport)
 # else
 # endif
 #endif
 
-#if (defined(__DMC__) || defined(_MSC_VER)) \
-               && (defined(_DLL) && !defined(GC_NOT_DLL) \
-                   || defined(GC_DLL))
+#if (defined(__DMC__) || defined(_MSC_VER)) && defined(GC_DLL)
 # ifdef GC_BUILD
 #   define GC_API extern __declspec(dllexport)
 # else
index 35c3716..61397b1 100644 (file)
          {
           char result;
           __asm__ __volatile__("lock; cmpxchgl %2, %0; setz %1"
-               : "=m"(*(addr)), "=r"(result)
-               : "r" (new_val), "0"(*(addr)), "a"(old) : "memory");
+               : "+m"(*(addr)), "=r"(result)
+               : "r" (new_val), "a"(old) : "memory");
           return (GC_bool) result;
          }
 #      endif /* !GENERIC_COMPARE_AND_SWAP */
index f2df5d4..3822555 100644 (file)
@@ -905,7 +905,7 @@ struct _GC_arrays {
                       /* OFFSET_TOO_BIG if the value j would be too    */
                       /* large to fit in the entry.  (Note that the    */
                       /* size of these entries matters, both for       */
-                      /* space consumption and for cache utilization.  */
+                      /* space consumption and for cache utilization.) */
 #   define OFFSET_TOO_BIG 0xfe
 #   define OBJ_INVALID 0xff
 #   define MAP_ENTRY(map, bytes) (map)[bytes]
@@ -1180,6 +1180,10 @@ extern long GC_large_alloc_warn_interval;
 extern long GC_large_alloc_warn_suppressed;
        /* Number of warnings suppressed so far.        */
 
+#ifdef THREADS
+  extern GC_bool GC_world_stopped;
+#endif
+
 /* Operations */
 # ifndef abs
 #   define abs(x)  ((x) < 0? (-(x)) : (x))
@@ -1846,6 +1850,10 @@ void GC_err_puts GC_PROTO((GC_CONST char *s));
 #      define GC_ASSERT(expr)
 # endif
 
+/* Check a compile time assertion at compile time.  The error  */
+/* message for failure is a bit baroque, but ...               */
+# define GC_STATIC_ASSERT(expr) sizeof(char[(expr)? 1 : -1])
+
 # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
     /* We need additional synchronization facilities from the thread   */
     /* support.  We believe these are less performance critical                */
index 2290d3d..35d47fd 100644 (file)
 
 # define GCCONFIG_H
 
+# ifndef GC_PRIVATE_H
+    /* Fake ptr_t declaration, just to avoid compilation errors.       */
+    /* This avoids many instances if "ifndef GC_PRIVATE_H" below.      */
+    typedef struct GC_undefined_struct * ptr_t;
+# endif
+
 /* Machine dependent parameters.  Some tuning parameters can be found  */
 /* near the top of gc_private.h.                                       */
 
       /* executable on a 64 bit kernel.                                        */
 #     define LINUX_STACKBOTTOM
 #     define DYNAMIC_LOADING
-#     undef STACK_GRAN
-#     define STACK_GRAN 0x10000000
-       /* Stack usually starts at 0x80000000 */
 #     define SEARCH_FOR_DATA_START
       extern int _end[];
 #     define DATAEND (_end)
     /* platforms as well, though it should be avoided in win32.                */
 # endif /* LINUX */
 
-# if defined(SEARCH_FOR_DATA_START) && defined(GC_PRIVATE_H)
+# if defined(SEARCH_FOR_DATA_START)
     extern ptr_t GC_data_start;
 #   define DATASTART GC_data_start
 # endif
                                              + GC_page_size-1)
 #     else
 #      ifdef MSWIN32
-#        ifdef GC_PRIVATE_H
-                 extern ptr_t GC_win32_get_mem();
-#        endif
+         extern ptr_t GC_win32_get_mem();
 #         define GET_MEM(bytes) (struct hblk *)GC_win32_get_mem(bytes)
 #      else
 #        ifdef MACOS
 #          endif
 #        else
 #          ifdef MSWINCE
-#            ifdef GC_PRIVATE_H
-               extern ptr_t GC_wince_get_mem();
-#            endif
+             extern ptr_t GC_wince_get_mem();
 #            define GET_MEM(bytes) (struct hblk *)GC_wince_get_mem(bytes)
 #          else
 #            if defined(AMIGA) && defined(GC_AMIGA_FASTALLOC)
                          GC_amiga_get_mem((size_t)bytes + GC_page_size) \
                          + GC_page_size-1)
 #            else
-#              ifdef GC_PRIVATE_H
-                 extern ptr_t GC_unix_get_mem();
-#              endif
+               extern ptr_t GC_unix_get_mem();
 #               define GET_MEM(bytes) (struct hblk *)GC_unix_get_mem(bytes)
 #            endif
 #          endif
index 96943d3..ab5820a 100644 (file)
@@ -724,6 +724,7 @@ void GC_suspend_handler(int sig)
 
 void GC_restart_handler(int sig)
 {
+    pthread_t my_thread = pthread_self();
     GC_thread me;
 
     if (sig != SIG_THR_RESTART) ABORT("Bad signal in suspend_handler");
@@ -733,7 +734,7 @@ void GC_restart_handler(int sig)
     /* of a thread which holds the allocation lock in order    */
     /* to stop the world.  Thus concurrent modification of the */
     /* data structure is impossible.                           */
-    me = GC_lookup_thread(pthread_self());
+    me = GC_lookup_thread(my_thread);
     me->signal = SIG_THR_RESTART;
 
     /*
@@ -967,8 +968,9 @@ int GC_suspend_all()
 /* Caller holds allocation lock.       */
 void GC_stop_world()
 {
-    register int i;
-    register int n_live_threads;
+    int i;
+    int n_live_threads;
+    int code;
 
     /* Make sure all free list construction has stopped before we start. */
     /* No new construction can start, since free list construction is  */
@@ -1017,10 +1019,12 @@ void GC_stop_world()
     for (i = 0; i < n_live_threads; i++) {
 #      ifdef GC_MACOSX_THREADS
          if (KERN_SUCCESS != semaphore_wait(GC_suspend_ack_sem))
-             ABORT("semaphore_wait in handler failed");
+             ABORT("semaphore_wait for handler failed");
 #      else
-         if (0 != sem_wait(&GC_suspend_ack_sem))
-             ABORT("sem_wait in handler failed");
+         if (0 != (code = sem_wait(&GC_suspend_ack_sem))) {
+             GC_err_printf1("Sem_wait returned %ld\n", (unsigned long)code);
+             ABORT("sem_wait for handler failed");
+         }
 #      endif
     }
 #   ifdef PARALLEL_MARK
@@ -1174,11 +1178,9 @@ int GC_get_nprocs()
     /* appears to be buggy in many cases.                              */
     /* We look for lines "cpu<n>" in /proc/stat.                       */
 #   define STAT_BUF_SIZE 4096
-#   if defined(GC_USE_LD_WRAP)
-#      define STAT_READ __real_read
-#   else
-#      define STAT_READ read
-#   endif    
+#   define STAT_READ read
+       /* If read is wrapped, this may need to be redefined to call    */
+       /* the real one.                                                */
     char stat_buf[STAT_BUF_SIZE];
     int f;
     char c;
diff --git a/mark.c b/mark.c
index 33f4ff8..ca94729 100644 (file)
--- a/mark.c
+++ b/mark.c
 # include <stdio.h>
 # include "private/gc_pmark.h"
 
+#if defined(MSWIN32) && defined(__GNUC__)
+# include <excpt.h>
+#endif
+
 /* We put this here to minimize the risk of inlining. */
 /*VARARGS*/
 #ifdef __WATCOMC__
@@ -261,20 +265,20 @@ static void alloc_mark_stack();
 /* remains valid until all marking is complete.                */
 /* A zero value indicates that it's OK to miss some    */
 /* register values.                                    */
-GC_bool GC_mark_some(cold_gc_frame)
-ptr_t cold_gc_frame;
+/* We hold the allocation lock.  In the case of        */
+/* incremental collection, the world may not be stopped.*/
+#ifdef MSWIN32
+  /* For win32, this is called after we establish a structured */
+  /* exception handler, in case Windows unmaps one of our root */
+  /* segments.  See below.  In either case, we acquire the     */
+  /* allocator lock long before we get here.                   */
+  GC_bool GC_mark_some_inner(cold_gc_frame)
+  ptr_t cold_gc_frame;
+#else
+  GC_bool GC_mark_some(cold_gc_frame)
+  ptr_t cold_gc_frame;
+#endif
 {
-#if defined(MSWIN32) && !defined(__GNUC__)
-  /* Windows 98 appears to asynchronously create and remove writable   */
-  /* memory mappings, for reasons we haven't yet understood.  Since    */
-  /* we look for writable regions to determine the root set, we may    */
-  /* try to mark from an address range that disappeared since we       */
-  /* started the collection.  Thus we have to recover from faults here. */
-  /* This code does not appear to be necessary for Windows 95/NT/2000. */ 
-  /* Note that this code should never generate an incremental GC write */
-  /* fault.                                                            */
-  __try {
-#endif /* defined(MSWIN32) && !defined(__GNUC__) */
     switch(GC_mark_state) {
        case MS_NONE:
            return(FALSE);
@@ -395,23 +399,130 @@ ptr_t cold_gc_frame;
            ABORT("GC_mark_some: bad state");
            return(FALSE);
     }
-#if defined(MSWIN32) && !defined(__GNUC__)
-  } __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
-           EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
-#   ifdef CONDPRINT
-      if (GC_print_stats) {
-       GC_printf0("Caught ACCESS_VIOLATION in marker. "
-                  "Memory mapping disappeared.\n");
+}
+
+
+#ifdef MSWIN32
+
+# ifdef __GNUC__
+
+    typedef struct {
+      EXCEPTION_REGISTRATION ex_reg;
+      void *alt_path;
+    } ext_ex_regn;
+
+
+    static EXCEPTION_DISPOSITION mark_ex_handler(
+        struct _EXCEPTION_RECORD *ex_rec, 
+        void *est_frame,
+        struct _CONTEXT *context,
+        void *disp_ctxt)
+    {
+        if (ex_rec->ExceptionCode == STATUS_ACCESS_VIOLATION) {
+          ext_ex_regn *xer = (ext_ex_regn *)est_frame;
+
+          /* Unwind from the inner function assuming the standard */
+          /* function prologue.                                   */
+          /* Assumes code has not been compiled with              */
+          /* -fomit-frame-pointer.                                */
+          context->Esp = context->Ebp;
+          context->Ebp = *((DWORD *)context->Esp);
+          context->Esp = context->Esp - 8;
+
+          /* Resume execution at the "real" handler within the    */
+          /* wrapper function.                                    */
+          context->Eip = (DWORD )(xer->alt_path);
+
+          return ExceptionContinueExecution;
+
+        } else {
+            return ExceptionContinueSearch;
+        }
+    }
+# endif /* __GNUC__ */
+
+
+  GC_bool GC_mark_some(cold_gc_frame)
+  ptr_t cold_gc_frame;
+  {
+      GC_bool ret_val;
+
+#   ifndef __GNUC__
+      /* Windows 98 appears to asynchronously create and remove  */
+      /* writable memory mappings, for reasons we haven't yet    */
+      /* understood.  Since we look for writable regions to      */
+      /* determine the root set, we may try to mark from an      */
+      /* address range that disappeared since we started the     */
+      /* collection.  Thus we have to recover from faults here.  */
+      /* This code does not appear to be necessary for Windows   */
+      /* 95/NT/2000. Note that this code should never generate   */
+      /* an incremental GC write fault.                          */
+
+      __try {
+
+#   else /* __GNUC__ */
+
+      /* Manually install an exception handler since GCC does    */
+      /* not yet support Structured Exception Handling (SEH) on  */
+      /* Win32.                                                  */
+
+      ext_ex_regn er;
+
+      er.alt_path = &&handle_ex;
+      er.ex_reg.handler = mark_ex_handler;
+      asm volatile ("movl %%fs:0, %0" : "=r" (er.ex_reg.prev));
+      asm volatile ("movl %0, %%fs:0" : : "r" (&er));
+
+#   endif /* __GNUC__ */
+
+          ret_val = GC_mark_some_inner(cold_gc_frame);
+
+#   ifndef __GNUC__
+
+      } __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
+                EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
+
+#   else /* __GNUC__ */
+
+          /* Prevent GCC from considering the following code unreachable */
+          /* and thus eliminating it.                                    */
+          if (er.alt_path != 0)
+              goto rm_handler;
+
+handle_ex:
+          /* Execution resumes from here on an access violation. */
+
+#   endif /* __GNUC__ */
+
+#         ifdef CONDPRINT
+            if (GC_print_stats) {
+             GC_printf0("Caught ACCESS_VIOLATION in marker. "
+                        "Memory mapping disappeared.\n");
+            }
+#         endif /* CONDPRINT */
+
+          /* We have bad roots on the stack.  Discard mark stack.  */
+          /* Rescan from marked objects.  Redetermine roots.    */
+          GC_invalidate_mark_state();  
+          scan_ptr = 0;
+
+          ret_val = FALSE;
+
+#   ifndef __GNUC__
+
       }
-#   endif /* CONDPRINT */
-    /* We have bad roots on the stack.  Discard mark stack.    */
-    /* Rescan from marked objects.  Redetermine roots.         */
-    GC_invalidate_mark_state();        
-    scan_ptr = 0;
-    return FALSE;
+
+#   else /* __GNUC__ */
+
+rm_handler:
+      /* Uninstall the exception handler */
+      asm volatile ("mov %0, %%fs:0" : : "r" (er.ex_reg.prev));
+
+#   endif /* __GNUC__ */
+
+      return ret_val;
   }
-#endif /* defined(MSWIN32) && !defined(__GNUC__) */
-}
+#endif /* MSWIN32 */
 
 
 GC_bool GC_mark_stack_empty()
index f663dcd..2aae516 100644 (file)
@@ -573,8 +573,11 @@ ptr_t cold_gc_frame;
 
      /* Mark thread local free lists, even if their mark       */
      /* descriptor excludes the link field.                    */
+     /* If the world is not stopped, this is unsafe.  It is    */
+     /* also unnecessary, since we will do this again with the */
+     /* world stopped.                                         */
 #      ifdef THREAD_LOCAL_ALLOC
-         GC_mark_thread_local_free_lists();
+         if (GC_world_stopped) GC_mark_thread_local_free_lists();
 #      endif
 
     /*
diff --git a/misc.c b/misc.c
index ef90c00..60857f5 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -49,7 +49,7 @@
 #          if defined(GC_WIN32_THREADS) 
 #             if defined(GC_PTHREADS)
                  pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER;
-#            elif !defined(GC_NOT_DLL) && (defined(_DLL) || defined(GC_DLL))
+#            elif defined(GC_DLL)
                 __declspec(dllexport) CRITICAL_SECTION GC_allocate_ml;
 #            else
                 CRITICAL_SECTION GC_allocate_ml;
@@ -499,6 +499,22 @@ void GC_init()
 
 extern void GC_setpagesize();
 
+
+#ifdef MSWIN32
+extern GC_bool GC_no_win32_dlls;
+#else
+# define GC_no_win32_dlls FALSE
+#endif
+
+void GC_exit_check GC_PROTO((void))
+{
+   GC_gcollect();
+}
+
+#ifdef SEARCH_FOR_DATA_START
+  extern void GC_init_linux_data_start GC_PROTO((void));
+#endif
+
 #ifdef UNIX_LIKE
 
 extern void GC_set_and_save_fault_handler GC_PROTO((void (*handler)(int)));
@@ -509,21 +525,23 @@ int sig;
     GC_err_printf1("Caught signal %d: looping in handler\n", sig);
     for(;;);
 }
-#endif
 
-#ifdef MSWIN32
-extern GC_bool GC_no_win32_dlls;
-#else
-# define GC_no_win32_dlls FALSE
-#endif
+static GC_bool installed_looping_handler = FALSE;
 
-void GC_exit_check GC_PROTO((void))
+void maybe_install_looping_handler()
 {
-   GC_gcollect();
+    /* Install looping handler before the write fault handler, so we   */
+    /* handle write faults correctly.                                  */
+      if (!installed_looping_handler && 0 != GETENV("GC_LOOP_ON_ABORT")) {
+        GC_set_and_save_fault_handler(looping_handler);
+        installed_looping_handler = TRUE;
+      }
 }
 
-#ifdef SEARCH_FOR_DATA_START
-  extern void GC_init_linux_data_start GC_PROTO((void));
+#else /* !UNIX_LIKE */
+
+# define maybe_install_looping_handler()
+
 #endif
 
 void GC_init_inner()
@@ -590,11 +608,7 @@ void GC_init_inner()
         }
       }
     }
-#   ifdef UNIX_LIKE
-      if (0 != GETENV("GC_LOOP_ON_ABORT")) {
-        GC_set_and_save_fault_handler(looping_handler);
-      }
-#   endif
+    maybe_install_looping_handler();
     /* Adjust normal object descriptor for extra allocation.   */
     if (ALIGNMENT > GC_DS_TAGS && EXTRA_BYTES != 0) {
       GC_obj_kinds[NORMAL].ok_descriptor = ((word)(-ALIGNMENT) | GC_DS_LENGTH);
@@ -641,9 +655,9 @@ void GC_init_inner()
 #      endif
       }
 #   endif
-    GC_ASSERT(sizeof (ptr_t) == sizeof(word));
-    GC_ASSERT(sizeof (signed_word) == sizeof(word));
-    GC_ASSERT(sizeof (struct hblk) == HBLKSIZE);
+    GC_STATIC_ASSERT(sizeof (ptr_t) == sizeof(word));
+    GC_STATIC_ASSERT(sizeof (signed_word) == sizeof(word));
+    GC_STATIC_ASSERT(sizeof (struct hblk) == HBLKSIZE);
 #   ifndef THREADS
 #     if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN)
        ABORT(
@@ -765,8 +779,9 @@ void GC_enable_incremental GC_PROTO(())
     if (GC_incremental) goto out;
     GC_setpagesize();
     if (GC_no_win32_dlls) goto out;
-#   ifndef GC_SOLARIS_THREADS
-        GC_dirty_init();
+#   ifndef GC_SOLARIS_THREADS 
+      maybe_install_looping_handler();  /* Before write fault handler! */
+      GC_dirty_init();
 #   endif
     if (!GC_is_initialized) {
         GC_init_inner();
index a2a31c2..668cd26 100644 (file)
--- a/os_dep.c
+++ b/os_dep.c
 # define OPT_PROT_EXEC 0
 #endif
 
+#if defined(LINUX) && \
+    (defined(USE_PROC_FOR_LIBRARIES) || defined(IA64) || !defined(SMALL_CONFIG))
+
+/* We need to parse /proc/self/maps, either to find dynamic libraries, */
+/* and/or to find the register backing store base (IA64).  Do it once  */
+/* here.                                                               */
+
+#define READ read
+
+/* Repeatedly perform a read call until the buffer is filled or        */
+/* we encounter EOF.                                           */
+ssize_t GC_repeat_read(int fd, char *buf, size_t count)
+{
+    ssize_t num_read = 0;
+    ssize_t result;
+    
+    while (num_read < count) {
+       result = READ(fd, buf + num_read, count - num_read);
+       if (result < 0) return result;
+       if (result == 0) break;
+       num_read += result;
+    }
+    return num_read;
+}
+
+/*
+ * Apply fn to a buffer containing the contents of /proc/self/maps.
+ * Return the result of fn or, if we failed, 0.
+ */
+
+word GC_apply_to_maps(word (*fn)(char *))
+{
+    int f;
+    int result;
+    int maps_size;
+    char maps_temp[32768];
+    char *maps_buf;
+
+    /* Read /proc/self/maps    */
+        /* Note that we may not allocate, and thus can't use stdio.    */
+        f = open("/proc/self/maps", O_RDONLY);
+        if (-1 == f) return 0;
+       /* stat() doesn't work for /proc/self/maps, so we have to
+          read it to find out how large it is... */
+       maps_size = 0;
+       do {
+           result = GC_repeat_read(f, maps_temp, sizeof(maps_temp));
+           if (result <= 0) return 0;
+           maps_size += result;
+       } while (result == sizeof(maps_temp));
+
+       if (maps_size > sizeof(maps_temp)) {
+           /* If larger than our buffer, close and re-read it. */
+           close(f);
+           f = open("/proc/self/maps", O_RDONLY);
+           if (-1 == f) return 0;
+           maps_buf = alloca(maps_size);
+           if (NULL == maps_buf) return 0;
+           result = GC_repeat_read(f, maps_buf, maps_size);
+           if (result <= 0) return 0;
+       } else {
+           /* Otherwise use the fixed size buffer */
+           maps_buf = maps_temp;
+       }
+
+       close(f);
+        maps_buf[result] = '\0';
+       
+    /* Apply fn to result. */
+       return fn(maps_buf);
+}
+
+#endif /* Need GC_apply_to_maps */
+
+#if defined(LINUX) && (defined(USE_PROC_FOR_LIBRARIES) || defined(IA64))
+//
+//  GC_parse_map_entry parses an entry from /proc/self/maps so we can
+//  locate all writable data segments that belong to shared libraries.
+//  The format of one of these entries and the fields we care about
+//  is as follows:
+//  XXXXXXXX-XXXXXXXX r-xp 00000000 30:05 260537     name of mapping...\n
+//  ^^^^^^^^ ^^^^^^^^ ^^^^          ^^
+//  start    end      prot          maj_dev
+//  0        9        18            32
+//  
+//  For 64 bit ABIs:
+//  0       17       34            56
+//
+//  The parser is called with a pointer to the entry and the return value
+//  is either NULL or is advanced to the next entry(the byte after the
+//  trailing '\n'.)
+//
+#if CPP_WORDSZ == 32
+# define OFFSET_MAP_START   0
+# define OFFSET_MAP_END     9
+# define OFFSET_MAP_PROT   18
+# define OFFSET_MAP_MAJDEV 32
+# define ADDR_WIDTH        8
+#endif
+
+#if CPP_WORDSZ == 64
+# define OFFSET_MAP_START   0
+# define OFFSET_MAP_END    17
+# define OFFSET_MAP_PROT   34
+# define OFFSET_MAP_MAJDEV 56
+# define ADDR_WIDTH       16
+#endif
+
+/*
+ * Assign various fields of the first line in buf_ptr to *start, *end,
+ * *prot_buf and *maj_dev.  Only *prot_buf may be set for unwritable maps.
+ */
+char *GC_parse_map_entry(char *buf_ptr, word *start, word *end,
+                                char *prot_buf, unsigned int *maj_dev)
+{
+    int i;
+    char *tok;
+
+    if (buf_ptr == NULL || *buf_ptr == '\0') {
+        return NULL;
+    }
+
+    memcpy(prot_buf, buf_ptr+OFFSET_MAP_PROT, 4); // do the protections first
+    prot_buf[4] = '\0';
+
+    if (prot_buf[1] == 'w') { // we can skip all of this if it's not writable
+
+        tok = buf_ptr;
+        buf_ptr[OFFSET_MAP_START+ADDR_WIDTH] = '\0';
+        *start = strtoul(tok, NULL, 16);
+
+        tok = buf_ptr+OFFSET_MAP_END;
+        buf_ptr[OFFSET_MAP_END+ADDR_WIDTH] = '\0';
+        *end = strtoul(tok, NULL, 16);
+
+        buf_ptr += OFFSET_MAP_MAJDEV;
+        tok = buf_ptr;
+        while (*buf_ptr != ':') buf_ptr++;
+        *buf_ptr++ = '\0';
+        *maj_dev = strtoul(tok, NULL, 16);
+    }
+
+    while (*buf_ptr && *buf_ptr++ != '\n');
+
+    return buf_ptr;
+}
+
+#endif /* Need to parse /proc/self/maps. */    
+
 #if defined(SEARCH_FOR_DATA_START)
   /* The I386 case can be handled without a search.  The Alpha case    */
   /* used to be handled differently as well, but the rules changed     */
@@ -679,6 +828,33 @@ ptr_t GC_get_stack_base()
   extern ptr_t __libc_stack_end;
 
 # ifdef IA64
+    /* Try to read the backing store base from /proc/self/maps.        */
+    /* We look for the writable mapping with a 0 major device,  */
+    /* which is        as close to our frame as possible, but below it.*/
+    static word backing_store_base_from_maps(char *maps)
+    {
+      char prot_buf[5];
+      char *buf_ptr = maps;
+      word start, end;
+      unsigned int maj_dev;
+      word current_best = 0;
+      word dummy;
+  
+      for (;;) {
+        buf_ptr = GC_parse_map_entry(buf_ptr, &start, &end, prot_buf, &maj_dev);
+       if (buf_ptr == NULL) return current_best;
+       if (prot_buf[1] == 'w' && maj_dev == 0) {
+           if (end < (word)(&dummy) && start > current_best) current_best = start;
+       }
+      }
+      return current_best;
+    }
+
+    static word backing_store_base_from_proc(void)
+    {
+        return GC_apply_to_maps(backing_store_base_from_maps);
+    }
+
 #   pragma weak __libc_ia64_register_backing_store_base
     extern ptr_t __libc_ia64_register_backing_store_base;
 
@@ -692,9 +868,15 @@ ptr_t GC_get_stack_base()
        /* Hence we check for both nonzero address and value.           */
        return __libc_ia64_register_backing_store_base;
       } else {
-       word result = (word)GC_stackbottom - BACKING_STORE_DISPLACEMENT;
-       result += BACKING_STORE_ALIGNMENT - 1;
-       result &= ~(BACKING_STORE_ALIGNMENT - 1);
+       word result = backing_store_base_from_proc();
+       if (0 == result) {
+         /* Use dumb heuristics.  Works only for default configuration. */
+         result = (word)GC_stackbottom - BACKING_STORE_DISPLACEMENT;
+         result += BACKING_STORE_ALIGNMENT - 1;
+         result &= ~(BACKING_STORE_ALIGNMENT - 1);
+         /* Verify that it's at least readable.  If not, we goofed. */
+         GC_noop1(*(word *)result); 
+       }
        return (ptr_t)result;
       }
     }
@@ -706,11 +888,8 @@ ptr_t GC_get_stack_base()
     /* using direct I/O system calls in order to avoid calling malloc   */
     /* in case REDIRECT_MALLOC is defined.                             */ 
 #   define STAT_BUF_SIZE 4096
-#   if defined(GC_USE_LD_WRAP)
-#      define STAT_READ __real_read
-#   else
-#      define STAT_READ read
-#   endif    
+#   define STAT_READ read
+         /* Should probably call the real read, if read is wrapped.    */
     char stat_buf[STAT_BUF_SIZE];
     int f;
     char c;
@@ -945,12 +1124,10 @@ void GC_register_data_segments()
   /* all real work is done by GC_register_dynamic_libraries.  Under    */
   /* win32s, we cannot find the data segments associated with dll's.   */
   /* We register the main data segment here.                           */
-#  ifdef __GCC__
-  GC_bool GC_no_win32_dlls = TRUE;
-                        /* GCC can't do SEH, so we can't use VirtualQuery */
-#  else
   GC_bool GC_no_win32_dlls = FALSE;     
-#  endif
+       /* 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.                              */
   
   void GC_init_win32()
   {
@@ -2583,7 +2760,10 @@ void GC_dirty_init()
        sigaction(SIGSEGV, 0, &oldact);
        sigaction(SIGSEGV, &act, 0);
 #     else
-       sigaction(SIGSEGV, &act, &oldact);
+       {
+         int res = sigaction(SIGSEGV, &act, &oldact);
+         if (res != 0) ABORT("Sigaction failed");
+       }
 #     endif
 #     if defined(_sigargs) || defined(HURD) || !defined(SA_SIGINFO)
        /* This is Irix 5.x, not 6.x.  Irix 5.x does not have   */
@@ -2879,13 +3059,6 @@ word n;
 {
 }
 
-# else /* !MPROTECT_VDB */
-
-#   ifdef GC_USE_LD_WRAP
-      ssize_t __wrap_read(int fd, void *buf, size_t nbyte)
-      { return __real_read(fd, buf, nbyte); }
-#   endif
-
 # endif /* MPROTECT_VDB */
 
 # ifdef PROC_VDB
@@ -3465,7 +3638,7 @@ struct callinfo info[NFRAMES];
                }
                name = result_buf;
                pclose(pipe);
-               out:
+               out:;
            }
 #        endif /* LINUX */
          GC_err_printf1("\t\t%s\n", name);
@@ -3481,31 +3654,6 @@ struct callinfo info[NFRAMES];
 
 #endif /* NEED_CALLINFO */
 
-#if defined(LINUX) && defined(__ELF__) && \
-    (!defined(SMALL_CONFIG) || defined(USE_PROC_FOR_LIBRARIES))
-#ifdef GC_USE_LD_WRAP
-#   define READ __real_read
-#else
-#   define READ read
-#endif
-
-
-/* Repeatedly perform a read call until the buffer is filled or        */
-/* we encounter EOF.                                           */
-ssize_t GC_repeat_read(int fd, char *buf, size_t count)
-{
-    ssize_t num_read = 0;
-    ssize_t result;
-    
-    while (num_read < count) {
-       result = READ(fd, buf + num_read, count - num_read);
-       if (result < 0) return result;
-       if (result == 0) break;
-       num_read += result;
-    }
-    return num_read;
-}
-#endif /* LINUX && ... */
 
 
 #if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG)
@@ -3513,20 +3661,16 @@ ssize_t GC_repeat_read(int fd, char *buf, size_t count)
 /* Dump /proc/self/maps to GC_stderr, to enable looking up names for
    addresses in FIND_LEAK output. */
 
+static word dump_maps(char *maps)
+{
+    GC_err_write(maps, strlen(maps));
+    return 1;
+}
+
 void GC_print_address_map()
 {
-    int f;
-    int result;
-    char maps_temp[32768];
     GC_err_printf0("---------- Begin address map ----------\n");
-        f = open("/proc/self/maps", O_RDONLY);
-        if (-1 == f) ABORT("Couldn't open /proc/self/maps");
-       do {
-           result = GC_repeat_read(f, maps_temp, sizeof(maps_temp));
-           if (result <= 0) ABORT("Couldn't read /proc/self/maps");
-           GC_err_write(maps_temp, result);
-       } while (result == sizeof(maps_temp));
-       close(f);     
+    GC_apply_to_maps(dump_maps);
     GC_err_printf0("---------- End address map ----------\n");
 }
 
index af49d5f..d83d730 100644 (file)
@@ -79,7 +79,7 @@ void (*GC_same_obj_print_proc) GC_PROTO((GC_PTR, GC_PTR))
        return(p);
     }
     sz = WORDS_TO_BYTES(hhdr -> hb_sz);
-    if (sz > WORDS_TO_BYTES(MAXOBJSZ)) {
+    if (sz > MAXOBJBYTES) {
       base = (ptr_t)HBLKPTR(p);
       limit = base + sz;
       if ((ptr_t)p >= limit) {
@@ -165,7 +165,7 @@ void (*GC_is_valid_displacement_print_proc) GC_PROTO((GC_PTR)) =
     pdispl = HBLKDISPL(p);
     map_entry = MAP_ENTRY((hhdr -> hb_map), pdispl);
     if (map_entry == OBJ_INVALID
-       || sz > MAXOBJSZ && (ptr_t)p >= (ptr_t)h + sz) {
+       || sz > MAXOBJBYTES && (ptr_t)p >= (ptr_t)h + sz) {
        goto fail;
     }
     return(p);
index 93c7b99..323d420 100644 (file)
--- a/reclaim.c
+++ b/reclaim.c
@@ -904,7 +904,7 @@ void GC_print_block_list()
  * Clear *flp.
  * This must be done before dropping a list of free gcj-style objects,
  * since may otherwise end up with dangling "descriptor" pointers.
- * It may help for other pointer-containg objects.
+ * It may help for other pointer-containing objects.
  */
 void GC_clear_fl_links(flp)
 ptr_t *flp;
index 84b57a6..43ebe8c 100644 (file)
 # endif
 
 # ifdef GC_WIN32_THREADS
-#   ifndef MSWINCE
-      /* FIXME - Why is this here? */
-#     include <process.h>
-#     define GC_CreateThread(a,b,c,d,e,f) ((HANDLE) _beginthreadex(a,b,c,d,e,f))
-#   endif
     static CRITICAL_SECTION incr_cs;
 # endif
 
@@ -534,7 +529,7 @@ struct {
 #ifdef THREADS
 
 # if defined(GC_WIN32_THREADS) && !defined(CYGWIN32)
-    unsigned __stdcall tiny_reverse_test(void * arg)
+    DWORD  __stdcall tiny_reverse_test(void * arg)
 # else
     void * tiny_reverse_test(void * arg)
 # endif
@@ -569,7 +564,7 @@ struct {
 # elif defined(GC_WIN32_THREADS)
     void fork_a_thread()
     {
-       unsigned thread_id;
+       DWORD thread_id;
        HANDLE h;
        h = GC_CreateThread(NULL, 0, tiny_reverse_test, 0, 0, &thread_id);
         if (h == (HANDLE)NULL) {
@@ -762,6 +757,7 @@ VOLATILE int dropped_something = 0;
      FAIL;
   }
   finalized_count++;
+  t -> level = -1;     /* detect duplicate finalization immediately */
 # ifdef PCR
     PCR_ThCrSec_ExitSys();
 # endif
@@ -1503,7 +1499,7 @@ void SetMinimumStack(long minSize)
 
 #if defined(GC_WIN32_THREADS) && !defined(CYGWIN32)
 
-unsigned __stdcall thr_run_one_test(void *arg)
+DWORD __stdcall thr_run_one_test(void *arg)
 {
   run_one_test();
   return 0;
@@ -1535,7 +1531,7 @@ LRESULT CALLBACK window_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
   return ret;
 }
 
-unsigned __stdcall thr_window(void *arg)
+DWORD __stdcall thr_window(void *arg)
 {
   WNDCLASS win_class = {
     CS_NOCLOSE,
@@ -1597,10 +1593,11 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int n)
 # ifdef MSWINCE
     HANDLE win_thr_h;
 # endif
-  unsigned thread_id;
+  DWORD thread_id;
 # if 0
     GC_enable_incremental();
 # endif
+  GC_init();
   InitializeCriticalSection(&incr_cs);
   (void) GC_set_warn_proc(warn_proc);
 # ifdef MSWINCE
index 4c6ad58..7db05f5 100644 (file)
@@ -4,7 +4,7 @@
 int main()
 {
 #   if defined(GC_USE_LD_WRAP)
-       printf("-Wl,--wrap -Wl,read -Wl,--wrap -Wl,dlopen "
+       printf("-Wl,--wrap -Wl,dlopen "
               "-Wl,--wrap -Wl,pthread_create -Wl,--wrap -Wl,pthread_join "
               "-Wl,--wrap -Wl,pthread_detach "
               "-Wl,--wrap -Wl,pthread_sigmask -Wl,--wrap -Wl,sleep\n");
index ebcb35c..384dcbe 100644 (file)
--- a/version.h
+++ b/version.h
@@ -3,7 +3,7 @@
 /* it to keep the old-style build process working.             */
 #define GC_TMP_VERSION_MAJOR 6
 #define GC_TMP_VERSION_MINOR 2
-#define GC_TMP_ALPHA_VERSION 4
+#define GC_TMP_ALPHA_VERSION 5
 
 #if defined(GC_VERSION_MAJOR)
 # if GC_TMP_VERSION_MAJOR != GC_VERSION_MAJOR || \
index 9b58416..6e06101 100755 (executable)
 
 #endif
 
-
-#if 0
-#define STRICT
-#include <windows.h>
+#ifndef MAX_THREADS
+# define MAX_THREADS 64
 #endif
 
-#define MAX_THREADS 64
-
 struct thread_entry {
   LONG in_use;
   DWORD id;
@@ -373,9 +369,11 @@ void GC_get_next_stack(char *start, char **lo, char **hi)
     if (*lo < start) *lo = start;
 }
 
-#if !defined(MSWINCE) && !(defined(__MINGW32__) && !defined(_DLL))
+#if !defined(MSWINCE) && defined(GC_DLL)
 
-HANDLE WINAPI GC_CreateThread(
+/* We register threads from DllMain */
+
+GC_API HANDLE GC_CreateThread(
     LPSECURITY_ATTRIBUTES lpThreadAttributes, 
     DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, 
     LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId )
@@ -384,7 +382,10 @@ HANDLE WINAPI GC_CreateThread(
                         lpParameter, dwCreationFlags, lpThreadId);
 }
 
-#else /* !defined(MSWINCE) && !(defined(__MINGW32__) && !defined(_DLL))  */
+#else /* defined(MSWINCE) || !defined(GC_DLL))  */
+
+/* We have no DllMain to take care of new threads.  Thus we    */
+/* must properly intercept thread creation.                    */
 
 typedef struct {
     HANDLE child_ready_h, parent_ready_h;
@@ -565,10 +566,11 @@ DWORD WINAPI main_thread_start(LPVOID arg)
 
 LONG WINAPI GC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info);
 
-/* threadAttach/threadDetach routines used by both CYGWIN and DLL implementation,
-   since both recieve explicit notification on thread creation/destruction
+/* threadAttach/threadDetach routines used by both CYGWIN and DLL
+ * implementation, since both recieve explicit notification on thread
+ * creation/destruction.
  */
-void threadAttach() {
+static void threadAttach() {
   int i;
   /* It appears to be unsafe to acquire a lock here, since this        */
   /* code is apparently not preeemptible on some systems.      */
@@ -617,7 +619,7 @@ void threadAttach() {
   while (GC_please_stop) Sleep(20);
 }
 
-void threadDetach(DWORD thread_id) {
+static void threadDetach(DWORD thread_id) {
   int i;
 
   LOCK();
@@ -783,7 +785,8 @@ void GC_thread_exit_proc(void *arg)
     int i;
 
 #   if DEBUG_CYGWIN_THREADS
-      GC_printf2("thread 0x%x(0x%x) called pthread_exit().\n",(int)pthread_self(),GetCurrentThreadId());
+      GC_printf2("thread 0x%x(0x%x) called pthread_exit().\n",
+                (int)pthread_self(),GetCurrentThreadId());
 #   endif
 
     LOCK();
@@ -806,12 +809,13 @@ int GC_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) {
 int GC_pthread_detach(pthread_t thread) {
   return pthread_detach(thread);
 }
-#else
+#else /* !CYGWIN32 */
 
 /*
  * We avoid acquiring locks here, since this doesn't seem to be preemptable.
  * Pontus Rydin suggests wrapping the thread start routine instead.
  */
+#ifdef GC_DLL
 BOOL WINAPI DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved)
 {
   switch (reason) {
@@ -852,7 +856,8 @@ BOOL WINAPI DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved)
   }
   return TRUE;
 }
-#endif /* CYGWIN32 */
+#endif /* GC_DLL */
+#endif /* !CYGWIN32 */
 
 # endif /* !MSWINCE */