]> granicus.if.org Git - gc/commitdiff
gc4.5 tarball import gc4_5
authorHans Boehm <boehm@acm.org>
Wed, 14 Jun 1995 00:00:00 +0000 (00:00 +0000)
committerIvan Maidanski <ivmai@mail.ru>
Sat, 17 May 2014 13:17:07 +0000 (17:17 +0400)
23 files changed:
Makefile
PCR-Makefile
README
README.debugging
README.win32
allchblk.c
alloc.c
checksums.c
config.h
cord/cordxtra.c
cord/gc.h
dbg_mlc.c
dyn_load.c
gc.h
gc_priv.h
include/gc.h
malloc.c
mark_rts.c
misc.c
os_dep.c
pcr_interface.c
reclaim.c
test.c

index aee1b11a425a94407a2c16b92844dca60975df6c..c1f8175013e4b9976447e663f6906413669407ea 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@
 #               and runs some tests of collector and cords.  Does not add cords or
 #       c++ interface to gc.a
 # cord/de - builds dumb editor based on cords.
-CC= gcc
+CC= cc
 CXX=g++ -ansi
 # Needed only for "make c++", which adds the c++ interface
 AS=as
@@ -30,6 +30,9 @@ CFLAGS= -O -DALL_INTERIOR_POINTERS -DNO_SIGNALS -DSILENT
 # -DSMALL_CONFIG tries to tune the collector for small heap sizes,
 #   usually causing it to use less space in such situations.
 #   Incremental collection no longer works in this case.
+# -DLARGE_CONFIG tunes the collector for unusually large heaps.
+#   Necessary for heaps larger than about 500 MB on most machines.
+#   Recommended for heaps larger than about 64 MB.
 # -DDONT_ADD_BYTE_AT_END is meaningful only with
 #   -DALL_INTERIOR_POINTERS.  Normally -DALL_INTERIOR_POINTERS
 #   causes all objects to be padded so that pointers just past the end of
@@ -54,6 +57,8 @@ CFLAGS= -O -DALL_INTERIOR_POINTERS -DNO_SIGNALS -DSILENT
 #   existing code, but it often does.  Neither works on all platforms,
 #   since some ports use malloc or calloc to obtain system memory.
 #   (Probably works for UNIX, and win32.)
+# -DNO_DEBUG removes GC_dump and the debugging routines it calls.
+#   Reduces code size slightly at the expense of debuggability.
 
 CXXFLAGS= $(CFLAGS)
 AR= ar
@@ -138,7 +143,7 @@ cords: $(CORD_OBJS) cord/cordtest
 
 gc_cpp.o: $(srcdir)/gc_cpp.cc $(srcdir)/gc_cpp.h $(srcdir)/gc.h Makefile
        $(CXX) -c $(CXXFLAGS) $(srcdir)/gc_cpp.cc
-       
+
 test_cpp: $(srcdir)/test_cpp.cc $(srcdir)/gc_cpp.h gc_cpp.o $(srcdir)/gc.h gc.a
        $(CXX) $(CXXFLAGS) -o test_cpp $(srcdir)/test_cpp.cc gc_cpp.o gc.a
 
@@ -157,6 +162,10 @@ dyn_load_sunos53.o: dyn_load.c
 libgc.so: $(OBJS) dyn_load_sunos53.o
        $(CC) -G -o libgc.so $(OBJS) dyn_load_sunos53.o -ldl
 
+# Alpha/OSF shared library version of the collector
+libalphagc.so: $(OBJS)
+       ld -shared -o libalphagc.so $(OBJS) dyn_load.o -lc
+
 mach_dep.o: $(srcdir)/mach_dep.c $(srcdir)/mips_mach_dep.s $(srcdir)/rs6000_mach_dep.s if_mach if_not_there
        rm -f mach_dep.o
        ./if_mach MIPS "" $(AS) -o mach_dep.o $(srcdir)/mips_mach_dep.s
@@ -215,7 +224,6 @@ clean:
 
 gctest: test.o gc.a if_mach if_not_there
        rm -f gctest
-       ./if_mach ALPHA "" $(CC) $(CFLAGS) -o gctest $(ALPHACFLAGS) test.o gc.a
        ./if_mach SPARC SUNOS5 $(CC) $(CFLAGS) -o gctest  test.o gc.a -lthread -ldl
        ./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o gctest  test.o gc.a -lucb
        ./if_not_there gctest $(CC) $(CFLAGS) -o gctest test.o gc.a
@@ -224,9 +232,7 @@ gctest: test.o gc.a if_mach if_not_there
 # odds are your compiler is broken.  Gctest may still work.
 # Try compiling setjmp_t.c unoptimized.
 setjmp_test: $(srcdir)/setjmp_t.c $(srcdir)/gc.h if_mach if_not_there
-       rm -f setjmp_test
-       ./if_mach ALPHA "" $(CC) $(CFLAGS) -o setjmp_test $(ALPHACFLAGS) $(srcdir)/setjmp_t.c
-       ./if_not_there setjmp_test $(CC) $(CFLAGS) -o setjmp_test $(srcdir)/setjmp_t.c
+       $(CC) $(CFLAGS) -o setjmp_test $(srcdir)/setjmp_t.c
 
 test:  KandRtest cord/cordtest
        cord/cordtest
@@ -238,7 +244,7 @@ KandRtest: setjmp_test gctest
 
 gc.tar: $(SRCS) $(OTHER_FILES)
        tar cvf gc.tar $(SRCS) $(OTHER_FILES)
-       
+
 pc_gc.tar: $(SRCS) $(OTHER_FILES)
        tar cvfX pc_gc.tar pc_excludes $(SRCS) $(OTHER_FILES)
 
@@ -258,7 +264,7 @@ gc.tar.Z: gc.tar
 
 lint: $(CSRCS) test.c
        lint -DLINT $(CSRCS) test.c | egrep -v "possible pointer alignment problem|abort|exit|sbrk|mprotect|syscall"
-       
+
 # BTL: added to test shared library version of collector.
 # Currently works only under SunOS5.  Requires GC_INIT call from statically
 # loaded client code.
index fb8a1f54b89afda70eb1dc22ea5c724f18026ba5..a5d04dd4fdc6f9aab948280029ae567297a0c7ad 100644 (file)
@@ -39,9 +39,9 @@ LDFLAGS = $(CONFIG_LDFLAGS)
 # Fix to point to local pcr installation directory.
 PCRDIR= ..
 
-COBJ= alloc.o reclaim.o allchblk.o misc.o os_dep.o mark_rts.o headers.o mark.o obj_map.o pcr_interface.o blacklst.o finalize.o new_hblk.o real_malloc.o dyn_load.o dbg_mlc.o malloc.o stubborn.o checksums.o solaris_threads.o typd_mlc.o
+COBJ= alloc.o reclaim.o allchblk.o misc.o os_dep.o mark_rts.o headers.o mark.o obj_map.o pcr_interface.o blacklst.o finalize.o new_hblk.o real_malloc.o dyn_load.o dbg_mlc.o malloc.o stubborn.o checksums.o solaris_threads.o typd_mlc.o ptr_chck.o
 
-CSRC= reclaim.c allchblk.c misc.c alloc.c mach_dep.c os_dep.c mark_rts.c headers.c mark.c obj_map.c pcr_interface.c blacklst.c finalize.c new_hblk.c real_malloc.c dyn_load.c dbg_mlc.c malloc.c stubborn.c checksums.c solaris_threads.c typd_mlc.c
+CSRC= reclaim.c allchblk.c misc.c alloc.c mach_dep.c os_dep.c mark_rts.c headers.c mark.c obj_map.c pcr_interface.c blacklst.c finalize.c new_hblk.c real_malloc.c dyn_load.c dbg_mlc.c malloc.c stubborn.c checksums.c solaris_threads.c typd_mlc.c ptr_chck.c
 
 SHELL= /bin/sh
 
diff --git a/README b/README
index 16eab21f0704c8c3af850b5727cd398f06b6f14a..53d4935ab28303aa3a9bde7260450624e9837efa 100644 (file)
--- a/README
+++ b/README
@@ -10,7 +10,7 @@ Permission to modify the code and to distribute modified code is granted,
 provided the above notices are retained, and a notice that the code was
 modified is included with the above copyright notice.
 
-This is version 4.4 of a conservative garbage collector for C and C++.
+This is version 4.5 of a conservative garbage collector for C and C++.
 
 HISTORY -
 
@@ -93,7 +93,7 @@ is a fairly sophisticated string package "cord" that makes use of the collector.
 
 GENERAL DESCRIPTION
 
-  This is a garbage colecting storage allocator that is intended to be
+  This is a garbage collecting storage allocator that is intended to be
 used as a plug-in replacement for C's malloc.
 
   Since the collector does not require pointers to be tagged, it does not
@@ -120,7 +120,7 @@ cause any pointer into an object (or one past the end) to retain the
 object.  A routine GC_register_displacement is provided to allow for
 more controlled interior pointer use in the heap.  Defining
 ALL_INTERIOR_POINTERS is somewhat dangerous, in that it can result
-in unnecessary memroy retention.  However this is much less of a
+in unnecessary memory retention.  However this is much less of a
 problem than with older collector versions.  The routine
 GC_register_displacement is described in gc.h.
 
@@ -144,17 +144,16 @@ read-only data.  However if the shared library mechanism can introduce
 discontiguous data areas that may contain pointers, then the collector does
 need to be informed.
 
-  Signal processing for most signals is normally deferred during collection,
+  Signal processing for most signals may be deferred during collection,
 and during uninterruptible parts of the allocation process.  Unlike
-standard ANSI C mallocs, it is intended to be safe to invoke malloc
+standard ANSI C mallocs, it can be safe to invoke malloc
 from a signal handler while another malloc is in progress, provided
 the original malloc is not restarted.  (Empirically, many UNIX
-applications already asssume this.)  Even this modest level of signal-
-safety may be too expensive on some systems.  If so, ENABLE_SIGNALS
-and DISABLE_SIGNALS may be redefined to the empty statement in gc_private.h.
+applications already assume this.)  To obtain this level  of signal
+safety, remove the definition of -DNO_SIGNALS in Makefile.
 
   The allocator/collector can also be configured for thread-safe operation.
-(Full signal safety can also be acheived, but only at the cost of two system
+(Full signal safety can also be achieved, but only at the cost of two system
 calls per malloc, which is usually unacceptable.)
 
 INSTALLATION AND PORTABILITY
@@ -216,7 +215,7 @@ trademarks of their respective holders):
            DEC Alpha running OSF/1
            SGI workstations under IRIX 4 & 5
            Sony News
-           Apple MacIntosh under A/UX or MacOS
+           Apple Macintosh under A/UX or MacOS
            Commodore Amiga (see README.amiga)
            NeXT machines
 
@@ -239,7 +238,7 @@ On other machines we recommend that you do one of the following:
 
   In all cases we assume that pointer alignment is consistent with that
 enforced by the standard C compilers.  If you use a nonstandard compiler
-you may have to adjust the alignment parameters defined in gc_private.h.
+you may have to adjust the alignment parameters defined in gc_priv.h.
 
   A port to a machine that is not byte addressed, or does not use 32 bit
 or 64 bit addresses will require a major effort.  A port to MSDOS is hard,
@@ -266,7 +265,7 @@ following are likely to require change:
    On some machines, it is difficult to obtain such a value that is
    valid across a variety of MMUs, OS releases, etc.  A number of
    alternatives exist for using the collector in spite of this.  See the
-   discussion in config.h.h immediately preceding the various
+   discussion in config.h immediately preceding the various
    definitions of STACKBOTTOM.
    
 2.  mach_dep.c.
@@ -345,7 +344,7 @@ good way for the collector to compute this value.)  Client code may include
 
 2)  GC_malloc_atomic(nbytes)
     - allocate an object of size nbytes that is guaranteed not to contain any
-      pointers.  The returned object is not guaranteed to be cleeared.
+      pointers.  The returned object is not guaranteed to be cleared.
       (Can always be replaced by GC_malloc, but results in faster collection
       times.  The collector will probably run faster if large character
       arrays, etc. are allocated with GC_malloc_atomic than if they are
@@ -412,7 +411,7 @@ considered as a candidate for collection.  Careless use may, of course, result
 in excessive memory consumption.
 
   Some additional tuning is possible through the parameters defined
-near the top of gc_private.h.
+near the top of gc_priv.h.
   
   If only GC_malloc is intended to be used, it might be appropriate to define:
 
@@ -435,7 +434,7 @@ THE C++ INTERFACE TO THE ALLOCATOR:
   The Ellis-Hull C++ interface to the collector is included in
 the collector distribution.  If you intend to use this, type
 "make c++" after the initial build of the collector is complete.
-See gc_cpp.h for the difinition of the interface.  This interface
+See gc_cpp.h for the definition of the interface.  This interface
 tries to approximate the Ellis-Detlefs C++ garbage collection
 proposal without compiler changes.
 
@@ -504,7 +503,7 @@ NIL.
   GC_debug_malloc checking  during garbage collection is enabled
 with the first call to GC_debug_malloc.  This will result in some
 slowdown during collections.  If frequent heap checks are desired,
-this can be acheived by explicitly invoking GC_gcollect, e.g. from
+this can be achieved by explicitly invoking GC_gcollect, e.g. from
 the debugger.
 
   GC_debug_malloc allocated objects should not be passed to GC_realloc
@@ -650,7 +649,7 @@ for PPCR.
   Version 2.2 added debugging allocation, and fixed various bugs.  Among them:
 - GC_realloc could fail to extend the size of the object for certain large object sizes.
 - A blatant subscript range error in GC_printf, which unfortunately
-  wasn't excercised on machines with sufficient stack alignment constraints.
+  wasn't exercised on machines with sufficient stack alignment constraints.
 - GC_register_displacement did the wrong thing if it was called after
   any allocation had taken place.
 - The leak finding code would eventually break after 2048 byte
@@ -705,7 +704,7 @@ for PPCR.
   a dynamic library.  
 - A fix for a bug in GC_base that could result in a memory fault.
 - A fix for a performance bug (and several other misfeatures) pointed
-  out by Dave Detelfs and Al Dosser.
+  out by Dave Detlefs and Al Dosser.
 - Use of dirty bit information for static data under Solaris 2.X.
 - DEC Alpha/OSF1 support (thanks to Al Dosser).
 - Incremental collection on more platforms.
@@ -760,7 +759,7 @@ for PPCR.
   that the old version was correct.
 - Fixed an incremental collection bug that prevented it from
   working at all when HBLKSIZE != getpagesize()
-- Changed dynamic_loading.c to include gc_private.h before testing
+- Changed dynamic_loading.c to include gc_priv.h before testing
   DYNAMIC_LOADING.  SunOS dynamic library scanning
   must have been broken in 3.4.
 - Object size rounding now adapts to program behavior.
@@ -988,7 +987,7 @@ functionality not tested by the other programs.
   suggestion).
 - Renamed C++ related files so they could live in a FAT
   file system. (Charles Fiterman's suggestion.)
-- Changed Windoes NT Makefile to include C++ support in
+- Changed Windows NT Makefile to include C++ support in
   gc.lib.  Added C++ test as Makefile target.
   
 Since version 4.3:
@@ -1044,3 +1043,39 @@ Since version 4.3:
  - Fixed a win32 specific performance bug that could result in scanning of
    objects allocated with the system malloc.
  - Added REDIRECT_MALLOC.
+
+Since version 4.4:
+ - Fixed many minor and one major README bugs. (Thanks to Franklin Chen
+   (chen@adi.com) for pointing out many of them.)
+ - Fixed ALPHA/OSF/1 dynamic library support. (Thanks to Jonathan Bachrach
+   (jonathan@harlequin.com)).
+ - Added incremental GC support (MPROTECT_VDB) for Linux (with some
+   help from Bruno Haible).
+ - Altered SPARC recognition tests in gc.h and config.h (mostly as
+   suggested by Fergus Henderson).
+ - Added basic incremental GC support for win32, as implemented by
+   Windows NT and Windows 95.  GC_enable_incremental is a noop
+   under win32s, which doesn't implement enough of the VM interface.
+ - Added -DLARGE_CONFIG.
+ - Fixed GC_..._ignore_off_page to also function without
+   -DALL_INTERIOR_POINTERS.
+ - (Hopefully) fixed RS/6000 port.  (Only the test was broken.)
+ - Fixed a performance bug in the nonincremental collector running
+   on machines supporting incremental collection with MPROTECT_VDB
+   (e.g. SunOS 4, DEC AXP).  This turned into a correctness bug under
+   win32s with win32 incremental collection.  (Not all memory protection
+   was disabled.)
+ - Fixed some ppcr related bit rot.
+ - Caused dynamic libraries to be unregistered before reregistering.
+   The old way turned out to be a performance bug on some machines.
+ - GC_root_size was not properly maintained under MSWIN32.
+ - Added -DNO_DEBUGGING and GC_dump.
+ - Fixed a couple of bugs arising with SOLARIS_THREADS +
+   REDIRECT_MALLOC.
+ - Added NetBSD/M68K port.  (Thanks to Peter Seebach
+   <seebs@taniemarie.solon.com>.)
+ - Fixed a serious realloc bug.  For certain object sizes, the collector
+   wouldn't scan the expanded part of the object.  (Thanks to Clay Spence
+   (cds@peanut.sarnoff.com) for noticing the problem, and helping me to
+   track it down.)
+   
\ No newline at end of file
index 9219c5cc25e1fb03b34c8b070430f10ecdf5b528..b000aceca5cad066a06528a89e1b4cef9e0c9f87 100644 (file)
@@ -8,8 +8,9 @@ If the collector dies in GC_malloc while trying to remove a free list element:
 If the heap grows too much:
 
 1) Consider using GC_malloc_atomic for objects containing nonpointers.  This is especially important for large arrays containg compressed data, pseudo-random numbers, and the like.  (This isn't all that likely to solve your problem, but it's a useful and easy optimization anyway, and this is a good time to try it.)   If you allocate large objects containg only one or two pointers at the beginning, either try the typed allocation primitives is gc.h, or separate out the pointerfree component.
-2) If you are using the collector in its default mode, with interior pointer recognition enabled, consider using GC_malloc_ignore_off_page to allocate large objects.  (See gc.h for details.  Large means > 100K in most environments.)  You can determine whether this is necessary by compiling the collector with logging on (without -DSILENT).  If the collector expands the heap many times, without intervening colllections, it is unable to find a sufficiently large chunk of memory that is not "referenced" by "false pointers".  In that case, use GC_malloc_ignore_off_page.
-3) GC_print_block_list() will print a list of all currently allocated heap blocks and what size objects they contain.  GC_print_hblkfreelist() will print a list of free heap blocks, and whether they are blacklisted.
+2) If you are using the collector in its default mode, with interior pointer recognition enabled, consider using GC_malloc_ignore_off_page to allocate large objects.  (See gc.h for details.  Large means > 100K in most environments.)  You can determine whether this is necessary by compiling the collector with logging on (without -DSILENT).  If the collector expands the heap many times, without intervening colllections, it is unable to find a sufficiently large chunk of memory that is not "referenced" by "false pointers".  In that case, use GC_malloc_ignore_off_page.  Also
+use GC_malloc_ignore_off_page if you see warnings that blacklisting is being ignored.
+3) GC_print_block_list() will print a list of all currently allocated heap blocks and what size objects they contain.  GC_print_hblkfreelist() will print a list of free heap blocks, and whether they are blacklisted.  GC_dump calls both of these, and also prints information about heap sections, and root segments.
 4) Write a tool that traces back references to the appropriate root.  Send me the code.  (I have code that does this for old PCR.)
 
 
index 7963acad0cbcb93197adeb3014ae409987d091e9..b8fb3cd29e4fff17b4ec801f4581ee326437a938 100644 (file)
@@ -11,7 +11,7 @@ scanned for roots.  Thus the collector sees pointers in DLL data
 segments.  Under win32s, only the main data segment is scanned.
 (The main data segment should always be scanned.  Under some
 versions of win32s, other regions may also be scanned.)
-Thus all accessible objects should be excessible from local variables
+Thus all accessible objects should be accessible from local variables
 or variables in the main data segment.  Alternatively, other data
 segments (e.g. in DLLs) may be registered with the collector by
 calling GC_init() and then GC_register_root_section(a), where
@@ -40,7 +40,8 @@ This may be suboptimal for some tastes and/or sets of default
 window colors.)
 
 For Microsoft development tools, rename NT_MAKEFILE as
-MAKEFILE.  For Borland tools, use BCC_MAKEFILE.  Note that
+MAKEFILE.  (Make sure that the CPU environment variable is defined
+to be i386.) For Borland tools, use BCC_MAKEFILE.  Note that
 Borland's compiler defaults to 1 byte alignment in structures (-a1),
 whereas Visual C++ appears to default to 8 byte alignment (/Zp8).
 The garbage collector in its default configuration EXPECTS AT
@@ -51,3 +52,26 @@ I expect that -a1 introduces major performance penalties on a
 resort, config.h can be changed to allow 1 byte alignment.  But
 this has significant negative performance implications.)
 
+Incremental collection support was recently added.  This is
+currently pretty simpleminded.  Pages are protected.  Protection
+faults are caught by a handler installed at the bottom of the handler
+stack.  This is both slow and interacts poorly with a debugger.
+Whenever possible, I recommend adding a call to
+GC_enable_incremental at the last possible moment, after most
+debugging is complete.  Unlike the UNIX versions, no system
+calls are wrapped by the collector itself.  It may be necessary
+to wrap ReadFile calls that use a buffer in the heap, so that the
+call does not encounter a protection fault while it's running.
+(As usual, none of this is an issue unless GC_enable_incremental
+is called.)
+
+Note that incremental collection is disabled with -DSMALL_CONFIG,
+which is the default for win32.  If you need incremental collection,
+undefine SMALL_CONFIG.
+
+Incremental collection is not supported under win32s, and it may not
+be possible to do so.  However, win32 applications that attempt to use
+incremental collection should continue to run, since the
+colllector detects if it's running under win32s and turns calls to
+GC_enable_incremental() into noops.
+
index ab0ccf71f65516a2098046812da6f94d5b1b6fb2..8912590bc779f5c3fcb57edcd76eae3ba021b988 100644 (file)
@@ -11,7 +11,7 @@
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
  */
-/* Boehm, January 31, 1995 3:01 pm PST */
+/* Boehm, June 13, 1995 3:34 pm PDT */
 
 #define DEBUG
 #undef DEBUG
 #include "gc_priv.h"
 
 
-/**/
-/* allocate/free routines for heap blocks
-/* Note that everything called from outside the garbage collector
-/* should be prepared to abort at any point as the result of a signal.
-/**/
+/*
+ * allocate/free routines for heap blocks
+ * Note that everything called from outside the garbage collector
+ * should be prepared to abort at any point as the result of a signal.
+ */
 
 /*
  * Free heap blocks are kept on a list sorted by address.
@@ -42,6 +42,7 @@ struct hblk *GC_savhbp = (struct hblk *)0;  /* heap block preceding next */
                                         /* block to be examined by   */
                                         /* GC_allochblk.                */
 
+# if !defined(NO_DEBUGGING)
 void GC_print_hblkfreelist()
 {
     struct hblk * h = GC_hblkfreelist;
@@ -66,6 +67,8 @@ void GC_print_hblkfreelist()
     GC_printf1("Total of %lu bytes on free list\n", (unsigned long)total_free);
 }
 
+# endif /* NO_DEBUGGING */
+
 /* Initialize hdr for a block containing the indicated size and        */
 /* kind of objects.                                                    */
 /* Return FALSE on failure.                                            */
@@ -196,7 +199,8 @@ unsigned char flags;  /* IGNORE_OFF_PAGE or 0 */
              } else if (size_needed > BL_LIMIT
                         && orig_avail - size_needed > BL_LIMIT) {
                /* Punt, since anything else risks unreasonable heap growth. */
-               WARN("Need to allocated blacklisted block at %ld\n", (word)hbp);
+               WARN("Needed to allocate blacklisted block at %ld\n",
+                    (word)hbp);
                thishbp = hbp;
                size_avail = orig_avail;
              } else if (size_avail == 0
diff --git a/alloc.c b/alloc.c
index e58590a9bd5054d40a7df751e187c2807596366f..d765094a30ff49513ac24d71e2c80dc14d0a06cd 100644 (file)
--- a/alloc.c
+++ b/alloc.c
@@ -12,7 +12,7 @@
  * modified is included with the above copyright notice.
  *
  */
-/* Boehm, February 10, 1995 1:18 pm PST */
+/* Boehm, April 28, 1995 4:36 pm PDT */
 
 
 # include "gc_priv.h"
@@ -568,6 +568,29 @@ word bytes;
     }
 }
 
+# if !defined(NO_DEBUGGING)
+void GC_print_heap_sects()
+{
+    register unsigned i;
+    
+    GC_printf1("Total heap size: %lu\n", (unsigned long) GC_heapsize);
+    for (i = 0; i < GC_n_heap_sects; i++) {
+        unsigned long start = (unsigned long) GC_heap_sects[i].hs_start;
+        unsigned long len = (unsigned long) GC_heap_sects[i].hs_bytes;
+        struct hblk *h;
+        unsigned nbl = 0;
+        
+       GC_printf3("Section %ld form 0x%lx to 0x%lx ", (unsigned long)i,
+                  start, (unsigned long)(start + len));
+       for (h = (struct hblk *)start; h < (struct hblk *)(start + len); h++) {
+           if (GC_is_black_listed(h, HBLKSIZE)) nbl++;
+       }
+       GC_printf2("%lu/%lu blacklisted\n", (unsigned long)nbl,
+                  (unsigned long)(len/HBLKSIZE));
+    }
+}
+# endif
+
 ptr_t GC_least_plausible_heap_addr = (ptr_t)ONES;
 ptr_t GC_greatest_plausible_heap_addr = 0;
 
index da532637e569b27f0295b39274985f529bab5970..7d9b7b7d2d028208e709bec3114374b459352bff 100644 (file)
@@ -10,7 +10,7 @@
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
  */
-/* Boehm, January 31, 1995 12:36 pm PST */
+/* Boehm, March 29, 1995 12:51 pm PST */
 # ifdef CHECKSUMS
 
 # include "gc_priv.h"
@@ -125,7 +125,7 @@ word dummy;
    GC_bytes_in_used_blocks += bytes;
 }
 
-GC_check_blocks()
+void GC_check_blocks()
 {
     word bytes_in_free_blocks = 0;
     struct hblk * h = GC_hblkfreelist;
@@ -152,7 +152,7 @@ GC_check_blocks()
 void GC_check_dirty()
 {
     register int index;
-    register int i;
+    register unsigned i;
     register struct hblk *h;
     register ptr_t start;
     
index 2ccc7742a80be7436cf362322380048fc41bb952..c0004e63e0b9bc3c133cbc43233927c8b5cb3892 100644 (file)
--- a/config.h
+++ b/config.h
@@ -11,7 +11,7 @@
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
  */
-/* Boehm, February 6, 1995 5:24 pm PST */
+/* Boehm, May 30, 1995 5:04 pm PDT */
  
 #ifndef CONFIG_H
 
 #    define HP
 #    define mach_type_known
 # endif
+# if defined(__NetBSD__) && defined(m68k)
+#    define M68K
+#    define NETBSD
+#    define mach_type_known
+# endif
 # if defined(vax)
 #    define VAX
 #    ifdef ultrix
@@ -74,7 +79,7 @@
 #   define RT
 #   define mach_type_known
 # endif
-# if defined(sun) && defined(sparc)
+# if defined(sun) && (defined(sparc) || defined(__sparc))
 #   define SPARC
     /* Test for SunOS 5.x */
 #     include <errno.h>
 # ifdef M68K
 #   define MACH_TYPE "M68K"
 #   define ALIGNMENT 2
+#   ifdef NETBSD
+#      define OS_TYPE "NETBSD"
+#      define HEURISTIC2
+       extern char etext;
+#      define DATASTART ((ptr_t)(&etext))
+#   endif
 #   ifdef SUNOS4
 #      define OS_TYPE "SUNOS4"
        extern char etext;
        /* was done by Robert Ehrlich, Manuel Serrano, and Bernard      */
        /* Serpette of INRIA.                                           */
        /* This assumes ZMAGIC, i.e. demand-loadable executables.       */
-#       define DATASTART ((ptr_t)(*(int *)0x2004+0x2000))
+#      define TEXTSTART 0x2000
+#       define DATASTART ((ptr_t)(*(int *)(TEXTSTART+0x4)+TEXTSTART))
 #      define MPROTECT_VDB
 #      define HEURISTIC1
 #   endif
        extern int etext;
 #       define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff))
 #      define STACKBOTTOM ((ptr_t)0xc0000000)
+#      define MPROTECT_VDB
 #   endif
 #   ifdef OS2
 #      define OS_TYPE "OS2"
 #      define OS_TYPE "MSWIN32"
                /* STACKBOTTOM and DATASTART are handled specially in   */
                /* os_dep.c.                                            */
+#      define MPROTECT_VDB
 #   endif
 #   ifdef FREEBSD
 #      define OS_TYPE "FREEBSD"
 #   define HEURISTIC2_LIMIT ((ptr_t)((word)(&__start) & ~(getpagesize()-1)))
 #   define CPP_WORDSZ 64
 #   define MPROTECT_VDB
+#   define DYNAMIC_LOADING
 # endif
 
 # ifdef M88K
index e39612c8eec3a8bd715c86a62456dce9a20ebac7..0e4a478f1d6a773fe3ed9cd1a98a128333bfb0b4 100644 (file)
@@ -555,6 +555,17 @@ CORD CORD_from_file_lazy_inner(FILE * f, size_t len)
     register int i;
     
     if (state == 0) OUT_OF_MEMORY;
+    if (len != 0) {
+       /* Dummy read to force buffer allocation.       */
+       /* This greatly increases the probability       */
+       /* of avoiding deadlock if buffer allocation    */
+       /* is redirected to GC_malloc and the           */
+       /* world is multithreaded.                      */
+       char buf[1];
+
+       (void) fread(buf, 1, 1, f); 
+       rewind(f);
+    }
     state -> lf_file = f;
     for (i = 0; i < CACHE_SZ/LINE_SZ; i++) {
         state -> lf_cache[i] = 0;
index 9ebbfe4262bfa1e807f28bb996a0124b32a18eda..c9fb14fc301f074ad5e36669c124fce31e3cd9fb 100644 (file)
--- a/cord/gc.h
+++ b/cord/gc.h
@@ -439,7 +439,7 @@ void GC_debug_end_stubborn_change(/* p */);
 /* code, and should not be considered in determining           */
 /* finalization order.                                         */
 # if defined(__STDC__) || defined(__cplusplus)
-    int GC_register_disappearing_link(void ** link);
+    int GC_register_disappearing_link(void ** /* link */);
 # else
     int GC_register_disappearing_link(/* void ** link */);
 # endif
@@ -463,7 +463,7 @@ void GC_debug_end_stubborn_change(/* p */);
        /* otherwise.                                           */
        /* Only exists for backward compatibility.  See below:  */
 # if defined(__STDC__) || defined(__cplusplus)
-    int GC_general_register_disappearing_link(void ** link, void * obj);
+    int GC_general_register_disappearing_link(void ** /* link */, void * obj);
 # else
     int GC_general_register_disappearing_link(/* void ** link, void * obj */);
 # endif
@@ -485,7 +485,7 @@ void GC_debug_end_stubborn_change(/* p */);
        /* obj may or may not cause link to eventually be       */
        /* cleared.                                             */
 # if defined(__STDC__) || defined(__cplusplus)
-    int GC_unregister_disappearing_link(void ** link);
+    int GC_unregister_disappearing_link(void ** /* link */);
 # else
     int GC_unregister_disappearing_link(/* void ** link */);
 # endif
@@ -650,7 +650,7 @@ void * GC_malloc_many(size_t lb);
  * from the statically loaded program section.
  * This circumvents a Solaris 2.X (X<=4) linker bug.
  */
-#ifdef sparc
+#if defined(sparc) || defined(__sparc)
 #   define GC_INIT() { extern end, etext; \
                       GC_noop(&end, &etext); }
 #else
index 0baa7c6bc32d38f4126c204c55fe4460579e7c9a..16c19c9d378d816c98fb0415031b2a810ba46902 100644 (file)
--- a/dbg_mlc.c
+++ b/dbg_mlc.c
@@ -11,7 +11,7 @@
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
  */
-/* Boehm, October 27, 1994 9:57 am PDT */
+/* Boehm, April 18, 1995 3:29 pm PDT */
 # include "gc_priv.h"
 
 /* Do we want to and know how to save the call stack at the time of    */
@@ -153,6 +153,7 @@ ptr_t p, clobbered_addr;
         }
         GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
                                          (unsigned long)(ohdr -> oh_sz));
+        PRINT_CALL_CHAIN(ohdr);
     }
 }
 
index a48a3021281c34c715ef927bf621d37cf223a665..601c36500217eb17a2d479c7520b0abbcdd03e2a 100644 (file)
@@ -13,7 +13,7 @@
  * Original author: Bill Janssen
  * Heavily modified by Hans Boehm and others
  */
-/* Boehm, September 12, 1994 4:27 pm PDT */
+/* Boehm, April 17, 1995 3:20 pm PDT */
 
 /*
  * This is incredibly OS specific code for tracking down data sections in
@@ -45,7 +45,7 @@
 # endif
 
 #if (defined(DYNAMIC_LOADING) || defined(MSWIN32)) && !defined(PCR)
-#if !defined(SUNOS4) && !defined(SUNOS5DL) && !defined(IRIX5) && !defined(MSWIN32)
+#if !defined(SUNOS4) && !defined(SUNOS5DL) && !defined(IRIX5) && !defined(MSWIN32) && !defined(ALPHA)
  --> We only know how to find data segments of dynamic libraries under SunOS,
  --> IRIX5, DRSNX and Win32.  Additional SVR4 variants might not be too
  --> hard to add.
@@ -202,7 +202,8 @@ void GC_register_dynamic_libraries()
         e = (struct exec *) lm->lm_addr;
         GC_add_roots_inner(
                    ((char *) (N_DATOFF(*e) + lm->lm_addr)),
-                   ((char *) (N_BSSADDR(*e) + e->a_bss + lm->lm_addr)));
+                   ((char *) (N_BSSADDR(*e) + e->a_bss + lm->lm_addr)),
+                   TRUE);
 #     endif
 #     ifdef SUNOS5DL
        Elf32_Ehdr * e;
@@ -222,7 +223,8 @@ void GC_register_dynamic_libraries()
                 start = ((char *)(p->p_vaddr)) + offset;
                 GC_add_roots_inner(
                   start,
-                  start + p->p_memsz
+                  start + p->p_memsz,
+                  TRUE
                 );
               }
               break;
@@ -241,7 +243,7 @@ void GC_register_dynamic_libraries()
        if (common_start == 0) common_start = GC_first_common();
        if (common_start != 0) {
            common_end = GC_find_limit(common_start, TRUE);
-           GC_add_roots_inner((char *)common_start, (char *)common_end);
+           GC_add_roots_inner((char *)common_start, (char *)common_end, TRUE);
        }
       }
 #   endif
@@ -341,7 +343,7 @@ void GC_register_dynamic_libraries()
                }
            }
        }
-        GC_add_roots_inner(start, limit);
+        GC_add_roots_inner(start, limit, TRUE);
       irrelevant: ;
     }
 }
@@ -371,7 +373,7 @@ void GC_register_dynamic_libraries()
        /* Part of the stack; ignore it. */
        return;
     }
-    GC_add_roots_inner(base, limit);
+    GC_add_roots_inner(base, limit, TRUE);
   }
   
   extern bool GC_win32s;
@@ -418,6 +420,9 @@ void GC_register_dynamic_libraries()
 #endif /* MSWIN32 */
 
 #if defined(ALPHA)
+
+#include <loader.h>
+
 void GC_register_dynamic_libraries()
 {
   int status;
@@ -510,7 +515,8 @@ void GC_register_dynamic_libraries()
           /* register region as a garbage collection root */
             GC_add_roots_inner (
                 (char *)regioninfo.lri_mapaddr,
-                (char *)regioninfo.lri_mapaddr + regioninfo.lri_size);
+                (char *)regioninfo.lri_mapaddr + regioninfo.lri_size,
+                TRUE);
 
         }
     }
@@ -548,7 +554,8 @@ void GC_register_dynamic_libraries()
                   == PCR_IL_SegFlags_Traced_on) {
                 GC_add_roots_inner
                        ((char *)(q -> ls_addr), 
-                        (char *)(q -> ls_addr) + q -> ls_bytes);
+                        (char *)(q -> ls_addr) + q -> ls_bytes,
+                        TRUE);
               }
             }
           }
diff --git a/gc.h b/gc.h
index 9ebbfe4262bfa1e807f28bb996a0124b32a18eda..c9fb14fc301f074ad5e36669c124fce31e3cd9fb 100644 (file)
--- a/gc.h
+++ b/gc.h
@@ -439,7 +439,7 @@ void GC_debug_end_stubborn_change(/* p */);
 /* code, and should not be considered in determining           */
 /* finalization order.                                         */
 # if defined(__STDC__) || defined(__cplusplus)
-    int GC_register_disappearing_link(void ** link);
+    int GC_register_disappearing_link(void ** /* link */);
 # else
     int GC_register_disappearing_link(/* void ** link */);
 # endif
@@ -463,7 +463,7 @@ void GC_debug_end_stubborn_change(/* p */);
        /* otherwise.                                           */
        /* Only exists for backward compatibility.  See below:  */
 # if defined(__STDC__) || defined(__cplusplus)
-    int GC_general_register_disappearing_link(void ** link, void * obj);
+    int GC_general_register_disappearing_link(void ** /* link */, void * obj);
 # else
     int GC_general_register_disappearing_link(/* void ** link, void * obj */);
 # endif
@@ -485,7 +485,7 @@ void GC_debug_end_stubborn_change(/* p */);
        /* obj may or may not cause link to eventually be       */
        /* cleared.                                             */
 # if defined(__STDC__) || defined(__cplusplus)
-    int GC_unregister_disappearing_link(void ** link);
+    int GC_unregister_disappearing_link(void ** /* link */);
 # else
     int GC_unregister_disappearing_link(/* void ** link */);
 # endif
@@ -650,7 +650,7 @@ void * GC_malloc_many(size_t lb);
  * from the statically loaded program section.
  * This circumvents a Solaris 2.X (X<=4) linker bug.
  */
-#ifdef sparc
+#if defined(sparc) || defined(__sparc)
 #   define GC_INIT() { extern end, etext; \
                       GC_noop(&end, &etext); }
 #else
index 2750a3354b780ef658361a383660f2d0b3789beb..bc2b0d59ded63c1d7156a0ab8082779ba2f721f5 100644 (file)
--- a/gc_priv.h
+++ b/gc_priv.h
@@ -11,7 +11,7 @@
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
  */
-/* Boehm, January 30, 1995 4:01 pm PST */
+/* Boehm, April 18, 1995 2:51 pm PDT */
  
 
 # ifndef GC_PRIVATE_H
@@ -201,8 +201,13 @@ typedef char * ptr_t;      /* A generic pointer to which we can add        */
 #endif
 
 
-# define MINHINCR 16       /* Minimum heap increment, in blocks of HBLKSIZE  */
-# define MAXHINCR 512      /* Maximum heap increment, in blocks              */
+# ifndef LARGE_CONFIG
+#   define MINHINCR 16 /* Minimum heap increment, in blocks of HBLKSIZE  */
+#   define MAXHINCR 512        /* Maximum heap increment, in blocks              */
+# else
+#   define MINHINCR 64
+#   define MAXHINCR 4096
+# endif
 
 # define TIME_LIMIT 50    /* We try to keep pause times from exceeding  */
                           /* this by much. In milliseconds.             */
@@ -606,9 +611,13 @@ extern GC_warn_proc GC_current_warn_proc;
  * Used by black-listing code, and perhaps by dirty bit maintenance code.
  */
  
-# define LOG_PHT_ENTRIES  14   /* Collisions are likely if heap grows  */
+# ifdef LARGE_CONFIG
+#   define LOG_PHT_ENTRIES  17
+# else
+#   define LOG_PHT_ENTRIES  14 /* Collisions are likely if heap grows  */
                                /* to more than 16K hblks = 64MB.       */
                                /* Each hash table occupies 2K bytes.   */
+# endif
 # define PHT_ENTRIES ((word)1 << LOG_PHT_ENTRIES)
 # define PHT_SIZE (PHT_ENTRIES >> LOGWL)
 typedef word page_hash_table[PHT_SIZE];
@@ -822,7 +831,15 @@ struct _GC_arrays {
       page_hash_table _grungy_pages; /* Pages that were dirty at last     */
                                     /* GC_read_dirty.                     */
 # endif
-# define MAX_HEAP_SECTS 256    /* Separately added heap sections. */
+# ifdef LARGE_CONFIG
+#   if CPP_WORDSZ > 32
+#     define MAX_HEAP_SECTS 4096       /* overflows at roughly 64 GB      */
+#   else
+#     define MAX_HEAP_SECTS 768                /* Separately added heap sections. */
+#   endif
+# else
+#   define MAX_HEAP_SECTS 256
+# endif
   struct HeapSect {
       ptr_t hs_start; word hs_bytes;
   } _heap_sects[MAX_HEAP_SECTS];
@@ -1254,6 +1271,9 @@ void GC_stubborn_init();
 /* Debugging print routines: */
 void GC_print_block_list();
 void GC_print_hblkfreelist();
+void GC_print_heap_sects();
+void GC_print_static_roots();
+void GC_dump();
 
 /* Make arguments appear live to compiler */
 void GC_noop();
index 9ebbfe4262bfa1e807f28bb996a0124b32a18eda..c9fb14fc301f074ad5e36669c124fce31e3cd9fb 100644 (file)
@@ -439,7 +439,7 @@ void GC_debug_end_stubborn_change(/* p */);
 /* code, and should not be considered in determining           */
 /* finalization order.                                         */
 # if defined(__STDC__) || defined(__cplusplus)
-    int GC_register_disappearing_link(void ** link);
+    int GC_register_disappearing_link(void ** /* link */);
 # else
     int GC_register_disappearing_link(/* void ** link */);
 # endif
@@ -463,7 +463,7 @@ void GC_debug_end_stubborn_change(/* p */);
        /* otherwise.                                           */
        /* Only exists for backward compatibility.  See below:  */
 # if defined(__STDC__) || defined(__cplusplus)
-    int GC_general_register_disappearing_link(void ** link, void * obj);
+    int GC_general_register_disappearing_link(void ** /* link */, void * obj);
 # else
     int GC_general_register_disappearing_link(/* void ** link, void * obj */);
 # endif
@@ -485,7 +485,7 @@ void GC_debug_end_stubborn_change(/* p */);
        /* obj may or may not cause link to eventually be       */
        /* cleared.                                             */
 # if defined(__STDC__) || defined(__cplusplus)
-    int GC_unregister_disappearing_link(void ** link);
+    int GC_unregister_disappearing_link(void ** /* link */);
 # else
     int GC_unregister_disappearing_link(/* void ** link */);
 # endif
@@ -650,7 +650,7 @@ void * GC_malloc_many(size_t lb);
  * from the statically loaded program section.
  * This circumvents a Solaris 2.X (X<=4) linker bug.
  */
-#ifdef sparc
+#if defined(sparc) || defined(__sparc)
 #   define GC_INIT() { extern end, etext; \
                       GC_noop(&end, &etext); }
 #else
index 56caa48552c771441100ec99dc5c8fefea82c9ee..67e00fc4ca26adc81421593abb47bd2860e9361a 100644 (file)
--- a/malloc.c
+++ b/malloc.c
@@ -11,7 +11,7 @@
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
  */
-/* Boehm, February 10, 1995 12:55 pm PST */
+/* Boehm, June 13, 1995 3:07 pm PDT */
  
 #include <stdio.h>
 #include "gc_priv.h"
@@ -115,7 +115,6 @@ ptr_t GC_generic_malloc_inner_ignore_off_page(lb, k)
 register size_t lb;
 register int k;
 {
-# ifdef ALL_INTERIOR_POINTERS
     register struct hblk * h;
     register word n_blocks;
     register word lw;
@@ -139,9 +138,6 @@ register int k;
     }
     GC_words_allocd += lw;
     return((ptr_t)op);
-# else
-    return(GC_generic_malloc_inner((word)lb, k));
-# endif
 }
 
 ptr_t GC_generic_malloc_ignore_off_page(lb, k)
@@ -508,11 +504,15 @@ int obj_kind;
 
     if (sz > WORDS_TO_BYTES(MAXOBJSZ)) {
        /* Round it up to the next whole heap block */
+         register word descr;
          
          sz = (sz+HDR_BYTES+HBLKSIZE-1)
                & (~HBLKMASK);
          sz -= HDR_BYTES;
          hhdr -> hb_sz = BYTES_TO_WORDS(sz);
+         descr = GC_obj_kinds[obj_kind].ok_descriptor;
+          if (GC_obj_kinds[obj_kind].ok_relocate_descr) descr += sz;
+          hhdr -> hb_descr = descr;
          if (obj_kind == UNCOLLECTABLE) GC_non_gc_bytes += (sz - orig_sz);
          /* Extra area is already cleared by allochblk. */
     }
index e0a6d9c4ade13bd0d2542e9cbbf3f0acdc2a4288..0b7a48adc981e698eb8e4baecab11b4a9196ef4d 100644 (file)
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
  */
-/* Boehm, September 15, 1994 2:15 pm PDT */
+/* Boehm, April 18, 1995 3:04 pm PDT */
 # include <stdio.h>
 # include "gc_priv.h"
 
-# ifdef PCR
-#   define MAX_ROOT_SETS 1024
+# ifdef LARGE_CONFIG
+#   define MAX_ROOT_SETS 4096
 # else
-#   ifdef MSWIN32
+#   ifdef PCR
+#     define MAX_ROOT_SETS 1024
+#   else
+#     ifdef MSWIN32
 #      define MAX_ROOT_SETS 512
            /* Under NT, we add only written pages, which can result    */
            /* in many small root sets.                                 */
-#   else
+#     else
 #       define MAX_ROOT_SETS 64
+#     endif
 #   endif
 # endif
 
@@ -37,6 +41,8 @@ struct roots {
 #      ifndef MSWIN32
          struct roots * r_next;
 #      endif
+       bool r_tmp;
+               /* Delete before registering new dynamic libraries */
 };
 
 static struct roots static_roots[MAX_ROOT_SETS];
@@ -45,6 +51,32 @@ static int n_root_sets = 0;
 
        /* static_roots[0..n_root_sets) contains the valid root sets. */
 
+# if !defined(NO_DEBUGGING)
+/* For debugging:      */
+void GC_print_static_roots()
+{
+    register int i;
+    size_t total = 0;
+    
+    for (i = 0; i < n_root_sets; i++) {
+        GC_printf2("From 0x%lx to 0x%lx ",
+                  (unsigned long) static_roots[i].r_start,
+                  (unsigned long) static_roots[i].r_end);
+        if (static_roots[i].r_tmp) {
+            GC_printf0(" (temporary)\n");
+        } else {
+            GC_printf0("\n");
+        }
+        total += static_roots[i].r_end - static_roots[i].r_start;
+    }
+    GC_printf1("Total size: %ld\n", (unsigned long) total);
+    if (GC_root_size != total) {
+       GC_printf1("GC_root_size incorrect: %ld!!\n",
+                  (unsigned long) GC_root_size);
+    }
+}
+# endif /* NO_DEBUGGING */
+
 /* Primarily for debugging support:    */
 /* Is the address p in one of the registered static                    */
 /* root sections?                                                      */
@@ -134,7 +166,7 @@ char * b; char * e;
     
     DISABLE_SIGNALS();
     LOCK();
-    GC_add_roots_inner(b, e);
+    GC_add_roots_inner(b, e, FALSE);
     UNLOCK();
     ENABLE_SIGNALS();
 }
@@ -144,8 +176,11 @@ char * b; char * e;
 /* is a moderately fast noop, and hence benign.  We do not handle      */
 /* different but overlapping intervals efficiently.  (We do handle     */
 /* them correctly.)                                                    */
-void GC_add_roots_inner(b, e)
+/* Tmp specifies that the interval may be deleted before               */
+/* reregistering dynamic libraries.                                    */ 
+void GC_add_roots_inner(b, e, tmp)
 char * b; char * e;
+bool tmp;
 {
     struct roots * old;
     
@@ -158,8 +193,8 @@ char * b; char * e;
         } else if ((ptr_t)b >= beginGC_arrays) {
             b = (char *)endGC_arrays;
         } else {
-            GC_add_roots_inner(b, (char *)beginGC_arrays);
-            GC_add_roots_inner((char *)endGC_arrays, e);
+            GC_add_roots_inner(b, (char *)beginGC_arrays, tmp);
+            GC_add_roots_inner((char *)endGC_arrays, e, tmp);
             return;
         }
     }
@@ -178,10 +213,13 @@ char * b; char * e;
             if ((ptr_t)b <= old -> r_end && (ptr_t)e >= old -> r_start) {
                 if ((ptr_t)b < old -> r_start) {
                     old -> r_start = (ptr_t)b;
+                    GC_root_size += (old -> r_start - (ptr_t)b);
                 }
                 if ((ptr_t)e > old -> r_end) {
                     old -> r_end = (ptr_t)e;
+                    GC_root_size += ((ptr_t)e - old -> r_end);
                 }
+                old -> r_tmp &= tmp;
                 break;
             }
         }
@@ -196,14 +234,18 @@ char * b; char * e;
               if ((ptr_t)b <= old -> r_end && (ptr_t)e >= old -> r_start) {
                 if ((ptr_t)b < old -> r_start) {
                     old -> r_start = (ptr_t)b;
+                    GC_root_size += (old -> r_start - (ptr_t)b);
                 }
                 if ((ptr_t)e > old -> r_end) {
                     old -> r_end = (ptr_t)e;
+                    GC_root_size += ((ptr_t)e - old -> r_end);
                 }
+                old -> r_tmp &= other -> r_tmp;
                 /* Delete this entry. */
+                  GC_root_size -= (other -> r_end - other -> r_start);
                   other -> r_start = static_roots[n_root_sets-1].r_start;
                   other -> r_end = static_roots[n_root_sets-1].r_end;
-                  n_root_sets--;
+                                  n_root_sets--;
               }
             }
           return;
@@ -224,6 +266,7 @@ char * b; char * e;
     }
     static_roots[n_root_sets].r_start = (ptr_t)b;
     static_roots[n_root_sets].r_end = (ptr_t)e;
+    static_roots[n_root_sets].r_tmp = tmp;
 #   ifndef MSWIN32
       static_roots[n_root_sets].r_next = 0;
 #   endif
@@ -251,6 +294,33 @@ void GC_clear_roots(NO_PARAMS)
     ENABLE_SIGNALS();
 }
 
+/* Internal use only; lock held.       */
+void GC_remove_tmp_roots()
+{
+    register int i;
+    
+    for (i = 0; i < n_root_sets; ) {
+       if (static_roots[i].r_tmp) {
+           GC_root_size -= (static_roots[i].r_end - static_roots[i].r_start);
+           static_roots[i].r_start = static_roots[n_root_sets-1].r_start;
+           static_roots[i].r_end = static_roots[n_root_sets-1].r_end;
+           static_roots[i].r_tmp = static_roots[n_root_sets-1].r_tmp;
+           n_root_sets--;
+       } else {
+           i++;
+       }
+    }
+#   ifndef MSWIN32
+    {
+       register int i;
+       
+       for (i = 0; i < RT_SIZE; i++) root_index[i] = 0;
+       for (i = 0; i < n_root_sets; i++) add_roots_to_index(static_roots + i);
+    }
+#   endif
+    
+}
+
 ptr_t GC_approx_sp()
 {
     word dummy;
@@ -282,6 +352,7 @@ bool all;
      /* Reregister dynamic libraries, in case one got added.   */
 #      if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(PCR)) \
            && !defined(SRC_M3)
+         GC_remove_tmp_roots();
          GC_register_dynamic_libraries();
 #      endif
      /* Mark everything in static data areas                             */
diff --git a/misc.c b/misc.c
index 31e18c03a13c746542b74062b8fc7d5ac4616713..b0e7e431fed97542067e57eff95532a7120b8509 100644 (file)
--- a/misc.c
+++ b/misc.c
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
  */
-/* Boehm, February 10, 1995 12:37 pm PST */
+/* Boehm, May 2, 1995 11:20 am PDT */
 
 
 #include <stdio.h>
 #include <signal.h>
-#ifdef SOLARIS_THREADS
-# include <sys/syscall.h>
-#endif
 
 #define I_HIDE_POINTERS        /* To make GC_call_with_alloc_lock visible */
 #include "gc_priv.h"
 
+#ifdef SOLARIS_THREADS
+# include <sys/syscall.h>
+#endif
+#ifdef MSWIN32
+# include <windows.h>
+#endif
+
 # ifdef THREADS
 #   ifdef PCR
 #     include "il/PCR_IL.h"
@@ -453,10 +457,11 @@ void GC_init_inner()
        ABORT("signed_word");
     }
     
-    GC_init_headers();
-    /* Add initial guess of root sets */
+    /* Add initial guess of root sets.  Do this first, since sbrk(0)   */
+    /* mightbe used.                                                   */
       GC_register_data_segments();
-    GC_bl_init();
+    GC_init_headers();
+        GC_bl_init();
     GC_mark_init();
     if (!GC_expand_hp_inner((word)MINHINCR)) {
         GC_err_printf0("Can't start up: not enough memory\n");
@@ -495,9 +500,12 @@ void GC_init_inner()
           extern int GC_read();
           extern void GC_register_finalizer_no_order();
           
-          GC_noop(GC_copyright, GC_find_header, GC_print_block_list,
+          GC_noop(GC_copyright, GC_find_header,
                   GC_push_one, GC_call_with_alloc_lock, GC_read,
-                  GC_print_hblkfreelist, GC_dont_expand,
+                  GC_dont_expand,
+#                ifndef NO_DEBUGGING
+                   GC_dump,
+#                endif
                   GC_register_finalizer_no_order);
       }
 #   endif
@@ -511,6 +519,14 @@ void GC_enable_incremental(NO_PARAMS)
     DISABLE_SIGNALS();
     LOCK();
     if (GC_incremental) goto out;
+#   ifdef MSWIN32
+      {
+        extern bool GC_is_win32s();
+
+       /* VirtualProtect is not functional under win32s.       */
+       if (GC_is_win32s()) goto out;
+      }
+#   endif /* MSWIN32 */
 #   ifndef SOLARIS_THREADS
         GC_dirty_init();
 #   endif
@@ -540,7 +556,6 @@ out:
 
 #ifdef MSWIN32
 # define LOG_FILE "gc.log"
-# include <windows.h>
 
   HANDLE GC_stdout = 0, GC_stderr;
   int GC_tmp;
@@ -549,7 +564,8 @@ out:
   void GC_set_files()
   {
     if (!GC_stdout) {
-        GC_stdout = CreateFile(LOG_FILE, GENERIC_WRITE, FILE_SHARE_READ,
+        GC_stdout = CreateFile(LOG_FILE, GENERIC_WRITE,
+                              FILE_SHARE_READ | FILE_SHARE_WRITE,
                               NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH,
                               NULL); 
        if (INVALID_HANDLE_VALUE == GC_stdout) ABORT("Open of log file failed");
@@ -585,23 +601,42 @@ int GC_tmp;  /* Should really be local ... */
 # endif
 #endif
 
-#ifdef SOLARIS_THREADS
-#   define WRITE(f, buf, len) syscall(SYS_write, (f), (buf), (len))
-#else
-# ifdef MSWIN32
+#if !defined(MSWIN32)  && !defined(OS2) && !defined(MACOS)
+int GC_write(fd, buf, len)
+int fd;
+char *buf;
+size_t len;
+{
+     register int bytes_written = 0;
+     register int result;
+     
+     while (bytes_written < len) {
+#      ifdef SOLARIS_THREADS
+           result = syscall(SYS_write, fd, buf + bytes_written,
+                                           len - bytes_written);
+#      else
+           result = write(fd, buf + bytes_written, len - bytes_written);
+#      endif
+       if (-1 == result) return(result);
+       bytes_written += result;
+    }
+    return(bytes_written);
+}
+#endif /* UN*X */
+
+#ifdef MSWIN32
 #   define WRITE(f, buf, len) (GC_set_files(), \
                               GC_tmp = WriteFile((f), (buf), \
                                                  (len), &GC_junk, NULL),\
                               (GC_tmp? 1 : -1))
-# else
+#else
 #   if defined(OS2) || defined(MACOS)
 #   define WRITE(f, buf, len) (GC_set_files(), \
                               GC_tmp = fwrite((buf), 1, (len), (f)), \
                               fflush(f), GC_tmp)
 #   else
-#     define WRITE(f, buf, len) write((f), (buf), (len))
+#     define WRITE(f, buf, len) GC_write((f), (buf), (len))
 #   endif
-# endif
 #endif
 
 /* A version of printf that is unlikely to call malloc, and is thus safer */
@@ -691,3 +726,19 @@ void GC_disable()
     GC_dont_gc++;
 }
 # endif
+
+#if !defined(NO_DEBUGGING)
+
+void GC_dump()
+{
+    GC_printf0("***Static roots:\n");
+    GC_print_static_roots();
+    GC_printf0("\n***Heap sections:\n");
+    GC_print_heap_sects();
+    GC_printf0("\n***Free blocks:\n");
+    GC_print_hblkfreelist();
+    GC_printf0("\n***Blocks in use:\n");
+    GC_print_block_list();
+}
+
+# endif /* NO_DEBUGGING */
index 0519bc5a835a4bc0216b091c88bb5777dbfa7159..1cf3240cfdef1a5791604e6c32135c05ffc43a69 100644 (file)
--- a/os_dep.c
+++ b/os_dep.c
@@ -10,7 +10,7 @@
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
  */
-/* Boehm, February 10, 1995 1:14 pm PST */
+/* Boehm, May 2, 1995 11:20 am PDT */
 
 # include "gc_priv.h"
 # if !defined(OS2) && !defined(PCR) && !defined(AMIGA) && !defined(MACOS)
@@ -245,7 +245,7 @@ void GC_enable_signals()
 /* Get the page size.  */
 word GC_page_size = 0;
 
-word GC_get_page_size()
+word GC_getpagesize()
 {
     SYSTEM_INFO sysinfo;
     
@@ -285,7 +285,7 @@ ptr_t GC_get_stack_base()
 {
     int dummy;
     ptr_t sp = (ptr_t)(&dummy);
-    ptr_t trunc_sp = (ptr_t)((word)sp & ~(GC_get_page_size() - 1));
+    ptr_t trunc_sp = (ptr_t)((word)sp & ~(GC_getpagesize() - 1));
     word size = GC_get_writable_length(trunc_sp, 0);
    
     return(trunc_sp + size);
@@ -564,7 +564,7 @@ void GC_register_data_segments()
           GC_err_printf0("Object with invalid pages?\n");
           continue;
       } 
-      GC_add_roots_inner(O32_BASE(seg), O32_BASE(seg)+O32_SIZE(seg));
+      GC_add_roots_inner(O32_BASE(seg), O32_BASE(seg)+O32_SIZE(seg), FALSE);
     }
 }
 
@@ -580,9 +580,17 @@ void GC_register_data_segments()
   /* We rgister the main data segment here.                            */
   bool GC_win32s = FALSE;      /* We're running under win32s.  */
   
+  bool GC_is_win32s()
+  {
+      DWORD v = GetVersion();
+      
+      /* Check that this is not NT, and Windows major version <= 3     */
+      return ((v & 0x80000000) && (v & 0xff) <= 3);
+  }
+  
   void GC_init_win32()
   {
-      if (GetVersion() & 0x80000000) GC_win32s = TRUE;
+      GC_win32s = GC_is_win32s();
   }
   
   /* Return the smallest address a such that VirtualQuery              */
@@ -599,9 +607,9 @@ void GC_register_data_segments()
     
     GetSystemInfo(&sysinfo);
     limit = sysinfo.lpMinimumApplicationAddress;
-    p = (ptr_t)((word)start & ~(GC_get_page_size() - 1));
+    p = (ptr_t)((word)start & ~(GC_getpagesize() - 1));
     for (;;) {
-       q = (LPVOID)(p - GC_get_page_size());
+       q = (LPVOID)(p - GC_getpagesize());
        if ((ptr_t)q > (ptr_t)p /* underflow */ || q < limit) break;
        result = VirtualQuery(q, &buf, sizeof(buf));
        if (result != sizeof(buf) || buf.AllocationBase == 0) break;
@@ -661,7 +669,7 @@ void GC_register_data_segments()
             if ((char *)p == limit) {
                 limit = new_limit;
             } else {
-                if (base != limit) GC_add_roots_inner(base, limit);
+                if (base != limit) GC_add_roots_inner(base, limit, FALSE);
                 base = p;
                 limit = new_limit;
             }
@@ -669,7 +677,7 @@ void GC_register_data_segments()
         if (p > (LPVOID)new_limit /* overflow */) break;
         p = (LPVOID)new_limit;
       }
-      if (base != limit) GC_add_roots_inner(base, limit);
+      if (base != limit) GC_add_roots_inner(base, limit, FALSE);
   }
   
   void GC_register_data_segments()
@@ -717,7 +725,8 @@ void GC_register_data_segments()
 #       else
           {
 #       endif /* AMIGA_SKIP_SEG */
-          GC_add_roots_inner((char *)&data[1], ((char *)&data[1]) + data[-1]);
+          GC_add_roots_inner((char *)&data[1],
+                            ((char *)&data[1]) + data[-1], FALSE);
          }
     }
   }
@@ -749,10 +758,21 @@ void GC_register_data_segments()
 #   endif
  
 #   if !defined(PCR) && !defined(SRC_M3) && !defined(NEXT) && !defined(MACOS)
-      GC_add_roots_inner(DATASTART, (char *)(&end));
+#     if defined(REDIRECT_MALLOC) && defined(SOLARIS_THREADS)
+       /* As of Solaris 2.3, the Solaris threads implementation        */
+       /* allocates the data structure for the initial thread with     */
+       /* sbrk at process startup.  It needs to be scanned, so that    */
+       /* we don't lose some malloc allocated data structures          */
+       /* hanging from it.  We're on thin ice here ...                 */
+        extern caddr_t sbrk();
+
+       GC_add_roots_inner(DATASTART, (char *)sbrk(0), FALSE);
+#     else
+       GC_add_roots_inner(DATASTART, (char *)(&end), FALSE);
+#     endif
 #   endif
 #   if !defined(PCR) && defined(NEXT)
-      GC_add_roots_inner(DATASTART, (char *) get_end());
+      GC_add_roots_inner(DATASTART, (char *) get_end(), FALSE);
 #   endif
 #   if defined(MACOS)
     {
@@ -760,11 +780,11 @@ void GC_register_data_segments()
        extern void* GC_MacGetDataStart(void);
        /* globals begin above stack and end at a5. */
        GC_add_roots_inner((ptr_t)GC_MacGetDataStart(),
-                          (ptr_t)LMGetCurrentA5());
+                          (ptr_t)LMGetCurrentA5(), FALSE);
 #   else
 #     if defined(__MWERKS__)
        extern long __datastart, __dataend;
-       GC_add_roots_inner((ptr_t)&__datastart, (ptr_t)&__dataend);
+       GC_add_roots_inner((ptr_t)&__datastart, (ptr_t)&__dataend, FALSE);
 #     endif
 #   endif
     }
@@ -1035,7 +1055,7 @@ void (*GC_push_other_roots)() = GC_default_push_other_roots;
  *             or write only to the stack.
  */
  
-bool GC_dirty_maintained;
+bool GC_dirty_maintained = FALSE;
 
 # ifdef DEFAULT_VDB
 
@@ -1118,9 +1138,42 @@ struct hblk *h;
  * not to work under a number of other systems.
  */
 
-# include <sys/mman.h>
-# include <signal.h>
-# include <sys/syscall.h>
+# ifndef MSWIN32
+
+#   include <sys/mman.h>
+#   include <signal.h>
+#   include <sys/syscall.h>
+
+#   define PROTECT(addr, len) \
+         if (mprotect((caddr_t)(addr), (int)(len), \
+                      PROT_READ | PROT_EXEC) < 0) { \
+           ABORT("mprotect failed"); \
+         }
+#   define UNPROTECT(addr, len) \
+         if (mprotect((caddr_t)(addr), (int)(len), \
+                      PROT_WRITE | PROT_READ | PROT_EXEC) < 0) { \
+           ABORT("un-mprotect failed"); \
+         }
+         
+# else
+
+#   include <signal.h>
+
+    static DWORD protect_junk;
+#   define PROTECT(addr, len) \
+         if (!VirtualProtect((addr), (len), PAGE_EXECUTE_READ, \
+                             &protect_junk)) { \
+           DWORD last_error = GetLastError(); \
+           GC_printf1("Last error code: %lx\n", last_error); \
+           ABORT("VirtualProtect failed"); \
+         }
+#   define UNPROTECT(addr, len) \
+         if (!VirtualProtect((addr), (len), PAGE_EXECUTE_READWRITE, \
+                             &protect_junk)) { \
+           ABORT("un-VirtualProtect failed"); \
+         }
+         
+# endif
 
 VOLATILE page_hash_table GC_dirty_pages;
                                /* Pages dirtied since last GC_read_dirty. */
@@ -1130,7 +1183,7 @@ word GC_page_size;
 bool GC_just_outside_heap(addr)
 word addr;
 {
-    register int i;
+    register unsigned i;
     register word start;
     register word end;
     word mask = GC_page_size-1;
@@ -1149,9 +1202,14 @@ word addr;
 #if defined(SUNOS4) || defined(FREEBSD)
     typedef void (* SIG_PF)();
 #endif
-#if defined(SUNOS5SIGS) || defined(ALPHA) /* OSF1 */
+#if defined(SUNOS5SIGS) || defined(ALPHA) /* OSF1 */ || defined(LINUX)
     typedef void (* SIG_PF)(int);
 #endif
+#if defined(MSWIN32)
+    typedef LPTOP_LEVEL_EXCEPTION_FILTER SIG_PF;
+#   undef SIG_DFL
+#   define SIG_DFL (LPTOP_LEVEL_EXCEPTION_FILTER) (-1)
+#endif
 
 #if defined(IRIX5) || defined(ALPHA) /* OSF1 */
     typedef void (* REAL_SIG_PF)(int, int, struct sigcontext *);
@@ -1159,9 +1217,13 @@ word addr;
 #if defined(SUNOS5SIGS)
     typedef void (* REAL_SIG_PF)(int, struct siginfo *, void *);
 #endif
+#if defined(LINUX)
+#   include <asm/signal.h>
+    typedef void (* REAL_SIG_PF)(int, struct sigcontext_struct);
+# endif
 
 SIG_PF GC_old_bus_handler;
-SIG_PF GC_old_segv_handler;
+SIG_PF GC_old_segv_handler;    /* Also old MSWIN32 ACCESS_VIOLATION filter */
 
 /*ARGSUSED*/
 # if defined (SUNOS4) || defined(FREEBSD)
@@ -1191,13 +1253,28 @@ SIG_PF GC_old_segv_handler;
 #     define CODE_OK (code == EACCES)
 #   endif
 # endif
+# if defined(LINUX)
+    void GC_write_fault_handler(int sig, struct sigcontext_struct sc)
+#   define SIG_OK (sig == SIGSEGV)
+#   define CODE_OK TRUE
+       /* Empirically c.trapno == 14, but is that useful?      */
+       /* We assume Intel architecture, so alignment           */
+       /* faults are not possible.                             */
+# endif
 # if defined(SUNOS5SIGS)
     void GC_write_fault_handler(int sig, struct siginfo *scp, void * context)
 #   define SIG_OK (sig == SIGSEGV)
 #   define CODE_OK (scp -> si_code == SEGV_ACCERR)
 # endif
+# if defined(MSWIN32)
+    LONG WINAPI GC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info)
+#   define SIG_OK (exc_info -> ExceptionRecord -> ExceptionCode == \
+                       EXCEPTION_ACCESS_VIOLATION)
+#   define CODE_OK (exc_info -> ExceptionRecord -> ExceptionInformation[0] == 1)
+                       /* Write fault */
+# endif
 {
-    register int i;
+    register unsigned i;
 #   ifdef IRIX5
        char * addr = (char *) (scp -> sc_badvaddr);
 #   endif
@@ -1206,6 +1283,14 @@ SIG_PF GC_old_segv_handler;
 #   endif
 #   ifdef SUNOS5SIGS
        char * addr = (char *) (scp -> si_addr);
+#   endif
+#   ifdef LINUX
+       char * addr = (char *) (sc.cr2);
+#   endif
+#   if defined(MSWIN32)
+       char * addr = (char *) (exc_info -> ExceptionRecord
+                               -> ExceptionInformation[1]);
+#      define sig SIGSEGV
 #   endif
     
     if (SIG_OK && CODE_OK) {
@@ -1221,18 +1306,31 @@ SIG_PF GC_old_segv_handler;
                 old_handler = GC_old_bus_handler;
             }
             if (old_handler == SIG_DFL) {
-                ABORT("Unexpected bus error or segmentation fault");
+#              ifndef MSWIN32
+                    ABORT("Unexpected bus error or segmentation fault");
+#              else
+                   return(EXCEPTION_CONTINUE_SEARCH);
+#              endif
             } else {
 #              if defined (SUNOS4) || defined(FREEBSD)
-                 (*old_handler) (sig, code, scp, addr);
-#              else
-#                if defined (SUNOS5SIGS)
+                   (*old_handler) (sig, code, scp, addr);
+                   return;
+#              endif
+#              if defined (SUNOS5SIGS)
                    (*(REAL_SIG_PF)old_handler) (sig, scp, context);
-#                else
+                   return;
+#              endif
+#              if defined (LINUX)
+                   (*(REAL_SIG_PF)old_handler) (sig, sc);
+                   return;
+#              endif
+#              if defined (IRIX5) || defined(ALPHA)
                    (*(REAL_SIG_PF)old_handler) (sig, code, scp);
-#                endif
+                   return;
+#              endif
+#              ifdef MSWIN32
+                   return((*old_handler)(exc_info));
 #              endif
-               return;
             }
         }
         for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
@@ -1240,17 +1338,18 @@ SIG_PF GC_old_segv_handler;
             
             set_pht_entry_from_index(GC_dirty_pages, index);
         }
-        if (mprotect((caddr_t)h, (int)GC_page_size,
-            PROT_WRITE | PROT_READ | PROT_EXEC) < 0) {
-           ABORT("mprotect failed in handler");
-       }
-#      if defined(IRIX5) || defined(ALPHA)
-           /* IRIX resets the signal handler each time. */
+        UNPROTECT(h, GC_page_size);
+#      if defined(IRIX5) || defined(ALPHA) || defined(LINUX)
+           /* These reset the signal handler each time by default. */
            signal(SIGSEGV, (SIG_PF) GC_write_fault_handler);
 #      endif
        /* The write may not take place before dirty bits are read.     */
        /* But then we'll fault again ...                               */
-       return;
+#      ifdef MSWIN32
+           return(EXCEPTION_CONTINUE_EXECUTION);
+#      else
+           return;
+#      endif
     }
 
     ABORT("Unexpected bus error or segmentation fault");
@@ -1259,11 +1358,13 @@ SIG_PF GC_old_segv_handler;
 void GC_write_hint(h)
 struct hblk *h;
 {
-    register struct hblk * h_trunc =
-                       (struct hblk *)((word)h & ~(GC_page_size-1));
-    register int i;
-    register bool found_clean = FALSE;
+    register struct hblk * h_trunc;
+    register unsigned i;
+    register bool found_clean;
     
+    if (!GC_dirty_maintained) return;
+    h_trunc = (struct hblk *)((word)h & ~(GC_page_size-1));
+    found_clean = FALSE;
     for (i = 0; i < divHBLKSZ(GC_page_size); i++) {
         register int index = PHT_HASH(h_trunc+i);
             
@@ -1273,10 +1374,7 @@ struct hblk *h;
         }
     }
     if (found_clean) {
-       if (mprotect((caddr_t)h_trunc, (int)GC_page_size,
-            PROT_WRITE | PROT_READ | PROT_EXEC) < 0) {
-           ABORT("mprotect failed in GC_write_hint");
-       }
+       UNPROTECT(h_trunc, GC_page_size);
     }
 }
 
@@ -1288,7 +1386,11 @@ GC_getpagesize()
     return sysconf(_SC_PAGESIZE);
 }
 #else
-# define GC_getpagesize() getpagesize()
+# ifdef MSWIN32
+   /* GC_getpagesize() defined above */
+# else
+#  define GC_getpagesize() getpagesize()
+# endif
 #endif
                                 
 void GC_dirty_init()
@@ -1299,6 +1401,9 @@ void GC_dirty_init()
     act.sa_flags       = SA_RESTART | SA_SIGINFO;
     (void)sigemptyset(&act.sa_mask); 
 #endif
+#   ifdef PRINTSTATS
+       GC_printf0("Inititalizing mprotect virtual dirty bit implementation\n");
+#   endif
     GC_dirty_maintained = TRUE;
     GC_page_size = GC_getpagesize();
     if (GC_page_size % HBLKSIZE != 0) {
@@ -1317,7 +1422,7 @@ void GC_dirty_init()
 #      endif
       }
 #   endif
-#   if defined(IRIX5) || defined(ALPHA) || defined(SUNOS4)
+#   if defined(IRIX5) || defined(ALPHA) || defined(SUNOS4) || defined(LINUX)
       GC_old_segv_handler = signal(SIGSEGV, (SIG_PF)GC_write_fault_handler);
       if (GC_old_segv_handler == SIG_IGN) {
         GC_err_printf0("Previously ignored segmentation violation!?");
@@ -1346,6 +1451,16 @@ void GC_dirty_init()
 #       endif
       }
 #    endif
+#   if defined(MSWIN32)
+      GC_old_segv_handler = SetUnhandledExceptionFilter(GC_write_fault_handler);
+      if (GC_old_segv_handler != NULL) {
+#      ifdef PRINTSTATS
+          GC_err_printf0("Replaced other UnhandledExceptionFilter\n");
+#      endif
+      } else {
+          GC_old_segv_handler = SIG_DFL;
+      }
+#   endif
 }
 
 
@@ -1357,16 +1472,14 @@ void GC_protect_heap()
     ptr_t start;
     word offset;
     word len;
-    int i;
+    unsigned i;
     
     for (i = 0; i < GC_n_heap_sects; i++) {
         offset = (word)(GC_heap_sects[i].hs_start) & pmask;
         start = GC_heap_sects[i].hs_start - offset;
         len = GC_heap_sects[i].hs_bytes + offset;
         len += ps-1; len &= ~pmask;
-       if (mprotect((caddr_t)start, (int)len, PROT_READ | PROT_EXEC) < 0) {
-           ABORT("mprotect failed");
-       }
+        PROTECT(start, len);
     }
 }
 
@@ -1431,14 +1544,11 @@ word len;
         
         set_pht_entry_from_index(GC_dirty_pages, index);
     }
-    if (mprotect((caddr_t)start_block,
-                (int)((ptr_t)end_block - (ptr_t)start_block)
-                + HBLKSIZE,
-                PROT_WRITE | PROT_READ | PROT_EXEC) < 0) {
-       ABORT("mprotect failed in GC_unprotect_range:");
-    }
+    UNPROTECT(start_block,
+             ((ptr_t)end_block - (ptr_t)start_block) + HBLKSIZE);
 }
 
+#ifndef MSWIN32
 /* Replacement for UNIX system call.    */
 /* Other calls that write to the heap   */
 /* should be handled similarly.                 */
@@ -1476,6 +1586,7 @@ int nbyte;
     GC_end_syscall();
     return(result);
 }
+#endif /* !MSWIN32 */
 
 /*ARGSUSED*/
 bool GC_page_was_ever_dirty(h)
@@ -1859,12 +1970,12 @@ struct callinfo info[NFRAMES];
     GC_err_printf0("\tCall chain at allocation:\n");
     for (i = 0; i < NFRAMES; i++) {
        if (info[i].ci_pc == 0) break;
-       GC_err_printf1("\t##PC##= 0x%X\n\t\targs: ", info[i].ci_pc);
        for (j = 0; j < NARGS; j++) {
            if (j != 0) GC_err_printf0(", ");
            GC_err_printf2("%d (0x%X)", ~(info[i].ci_arg[j]),
                                        ~(info[i].ci_arg[j]));
        }
+       GC_err_printf1("\t##PC##= 0x%X\n\t\targs: ", info[i].ci_pc);
        GC_err_printf0("\n");
     }
 }
index 1c52938da22060f18aba911b1e8a65f81a080df8..f4a117899d22341319bbd30ad4db42142da3b985 100644 (file)
@@ -10,7 +10,7 @@
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
  */
-/* Boehm, March 28, 1994 1:58 pm PST */
+/* Boehm, April 14, 1995 3:10 pm PDT */
 # include "gc_priv.h"
 
 # ifdef PCR
@@ -25,6 +25,7 @@
 # include <errno.h>
 
 # define MY_MAGIC 17L
+# define MY_DEBUGMAGIC 42L
 
 void * GC_AllocProc(size_t size, PCR_Bool ptrFree, PCR_Bool clear )
 {
@@ -37,9 +38,26 @@ void * GC_AllocProc(size_t size, PCR_Bool ptrFree, PCR_Bool clear )
     }
 }
 
+void * GC_DebugAllocProc(size_t size, PCR_Bool ptrFree, PCR_Bool clear )
+{
+    if (ptrFree) {
+        void * result = (void *)GC_debug_malloc_atomic(size, __FILE__,
+                                                            __LINE__);
+        if (clear && result != 0) BZERO(result, size);
+        return(result);
+    } else {
+        return((void *)GC_debug_malloc(size, __FILE__, __LINE__));
+    }
+}
+
 # define GC_ReallocProc GC_realloc
+void * GC_DebugReallocProc(void * old_object, size_t new_size_in_bytes)
+{
+    return(GC_debug_realloc(old_object, new_size_in_bytes, __FILE__, __LINE__));
+}
 
 # define GC_FreeProc GC_free
+# define GC_DebugFreeProc GC_debug_free
 
 typedef struct {
   PCR_ERes (*ed_proc)(void *p, size_t size, PCR_Any data);
@@ -109,9 +127,21 @@ struct PCR_MM_ProcsRep GC_Rep = {
        GC_DummyShutdownProc    /* mmp_shutdown */
 };
 
+struct PCR_MM_ProcsRep GC_DebugRep = {
+       MY_DEBUGMAGIC,
+       GC_DebugAllocProc,
+       GC_DebugReallocProc,
+       GC_DummyFreeProc,       /* mmp_free */
+       GC_DebugFreeProc,               /* mmp_unsafeFree */
+       GC_EnumerateProc,
+       GC_DummyShutdownProc    /* mmp_shutdown */
+};
+
+bool GC_use_debug = 0;
+
 void GC_pcr_install()
 {
-    PCR_MM_Install(&GC_Rep, &GC_old_allocator);
+    PCR_MM_Install((GC_use_debug? &GC_DebugRep : &GC_Rep), &GC_old_allocator);
 }
 
 PCR_ERes
@@ -126,6 +156,7 @@ PCR_GC_Run(void)
 
     if( !PCR_Base_TestPCRArg("-nogc") ) {
         GC_quiet = ( PCR_Base_TestPCRArg("-gctrace") ? 0 : 1 );
+        GC_use_debug = (bool)PCR_Base_TestPCRArg("-debug_alloc");
         GC_init();
         if( !PCR_Base_TestPCRArg("-nogc_incremental") ) {
             /*
index 2278a5a2d979c84faa19f9f0762d5a9463190013..7dbd134949cd032867646657c16f940c6d77e00e 100644 (file)
--- a/reclaim.c
+++ b/reclaim.c
@@ -11,7 +11,7 @@
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
  */
-/* Boehm, January 19, 1995 5:39 pm PST */
+/* Boehm, April 18, 1995 1:59 pm PDT */
 
 #include <stdio.h>
 #include "gc_priv.h"
@@ -532,6 +532,7 @@ word abort_if_found;                /* Abort if a reclaimable object is found */
     }
 }
 
+#if !defined(NO_DEBUGGING)
 /* Routines to gather and print heap block info        */
 /* intended for debugging.  Otherwise should be called */
 /* with lock.                                          */
@@ -593,6 +594,8 @@ void GC_print_block_list()
               (unsigned long)total_bytes);
 }
 
+#endif /* NO_DEBUGGING */
+
 /*
  * Do the same thing on the entire heap, after first clearing small object
  * free lists (if we are not just looking for leaks).
diff --git a/test.c b/test.c
index 48191be7289157a6cb9b5f2066448903101f07d5..b64695db6197cfa1053c5dcb32a8ab91a2501b1e 100644 (file)
--- a/test.c
+++ b/test.c
@@ -11,7 +11,7 @@
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
  */
-/* Boehm, January 27, 1995 12:58 pm PST */
+/* Boehm, June 13, 1995 2:33 pm PDT */
 /* An incomplete test for the garbage collector.               */
 /* Some more obscure entry points are not tested at all.       */
 
@@ -269,11 +269,17 @@ void reverse_test()
     sexpr c;
     sexpr d;
     sexpr e;
+    sexpr *f, *g, *h;
 #   if defined(MSWIN32) || defined(MACOS)
       /* Win32S only allows 128K stacks */
 #     define BIG 1000
 #   else
-#     define BIG 4500
+#     if defined PCR
+       /* PCR default stack is 100K.  Stack frames are up to 120 bytes. */
+#      define BIG 700
+#     else
+#       define BIG 4500
+#     endif
 #   endif
 
     A.dummy = 17;
@@ -282,9 +288,24 @@ void reverse_test()
     c = ints(1, BIG);
     d = uncollectable_ints(1, 100);
     e = uncollectable_ints(1, 1);
+    /* Check that realloc updates object descriptors correctly */
+    f = (sexpr *)GC_malloc(4 * sizeof(sexpr));
+    f = (sexpr *)GC_realloc(f, 6 * sizeof(sexpr));
+    f[5] = ints(1,17);
+    g = (sexpr *)GC_malloc(513 * sizeof(sexpr));
+    g = (sexpr *)GC_realloc(g, 800 * sizeof(sexpr));
+    g[799] = ints(1,18);
+    h = (sexpr *)GC_malloc(1025 * sizeof(sexpr));
+    h = (sexpr *)GC_realloc(h, 2000 * sizeof(sexpr));
+    h[1999] = ints(1,19);
+    /* Try to force some collections and reuse of small list elements */
+      for (i = 0; i < 10; i++) {
+        (void)ints(1, BIG);
+      }
     /* Superficially test interior pointer recognition on stack */
     c = (sexpr)((char *)c + sizeof(char *));
     d = (sexpr)((char *)d + sizeof(char *));
+
 #   ifdef __STDC__
         GC_FREE((void *)e);
 #   else
@@ -318,6 +339,9 @@ void reverse_test()
     d = (sexpr)((char *)d - sizeof(char *));
     check_ints(c,1,BIG);
     check_uncollectable_ints(d, 1, 100);
+    check_ints(f[5], 1,17);
+    check_ints(g[799], 1,18);
+    check_ints(h[1999], 1,19);
 #   ifndef THREADS
        a = 0;
 #   endif  
@@ -661,10 +685,16 @@ void run_one_test()
     GC_is_valid_displacement_print_proc = fail_proc;
     GC_is_visible_print_proc = fail_proc;
     x = GC_malloc(16);
-    if (GC_base(x + 13) != x || GC_base(y) != 0) {
-       (void)GC_printf0("GC_base produced incorrect result\n");
+    if (GC_base(x + 13) != x) {
+       (void)GC_printf0("GC_base(heap ptr) produced incorrect result\n");
        FAIL;
     }
+#   ifndef PCR
+      if (GC_base(y) != 0) {
+       (void)GC_printf0("GC_base(fn_ptr) produced incorrect result\n");
+       FAIL;
+      }
+#   endif
     if (GC_same_obj(x+5, x) != x + 5) {
        (void)GC_printf0("GC_same_obj produced incorrect result\n");
        FAIL;
@@ -674,8 +704,12 @@ void run_one_test()
        FAIL;
     }
     if (!TEST_FAIL_COUNT(1)) {
-       (void)GC_printf0("GC_is_visible produced wrong failure indication\n");
-       FAIL;
+#      ifndef RS6000
+         /* ON RS6000s function pointers point to a descriptor in the  */
+         /* data segment, so there should have been no failures.       */
+         (void)GC_printf0("GC_is_visible produced wrong failure indication\n");
+         FAIL;
+#      endif
     }
     if (GC_is_valid_displacement(y) != y
         || GC_is_valid_displacement(x) != x
@@ -685,7 +719,11 @@ void run_one_test()
        FAIL;
     }
 #   ifndef ALL_INTERIOR_POINTERS
+#    ifdef RS6000
+      if (!TEST_FAIL_COUNT(1)) {
+#    else
       if (!TEST_FAIL_COUNT(2)) {
+#    endif
        (void)GC_printf0("GC_is_valid_displacement produced wrong failure indication\n");
        FAIL;
       }
@@ -860,7 +898,7 @@ test()
     int code;
 
     n_tests = 0;
-    GC_enable_incremental();
+    /* GC_enable_incremental(); */
     (void) GC_set_warn_proc(warn_proc);
     th1 = PCR_Th_Fork(run_one_test, 0);
     th2 = PCR_Th_Fork(run_one_test, 0);