]> granicus.if.org Git - gc/commitdiff
gc2.6 tarball import gc2_6
authorHans Boehm <boehm@acm.org>
Tue, 27 Apr 1993 00:00:00 +0000 (00:00 +0000)
committerIvan Maidanski <ivmai@mail.ru>
Sat, 17 May 2014 12:09:35 +0000 (16:09 +0400)
25 files changed:
Makefile
OS2_MAKEFILE
PCR-Makefile
README
alloc.c
allochblk.c
black_list.c
config.h [new file with mode: 0644]
debug_malloc.c
dynamic_load.c
gc.h
gc_private.h
headers.c
if_mach.c [new file with mode: 0644]
if_not_there.c [new file with mode: 0644]
mach_dep.c
mark.c
mark_roots.c
misc.c
obj_map.c
os_dep.c
pcr_interface.c
reclaim.c
setjmp_test.c
test.c

index 0f0d9cf8e944640e4e389049778a640e77aecd48..ab77025e1a78b8bb20c2b24876a570d7d30d9ac3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,12 @@ OBJS= alloc.o reclaim.o allochblk.o misc.o mach_dep.o os_dep.o mark_roots.o head
 
 CSRCS= reclaim.c allochblk.c misc.c alloc.c mach_dep.c os_dep.c mark_roots.c headers.c mark.c obj_map.c pcr_interface.c black_list.c finalize.c new_hblk.c real_malloc.c dynamic_load.c debug_malloc.c
 
-SRCS= $(CSRCS) mips_mach_dep.s rs6000_mach_dep.s interface.c gc.h gc_headers.h gc_private.h gc_inline.h gc.man
+SRCS= $(CSRCS) mips_mach_dep.s rs6000_mach_dep.s interface.c gc.h gc_headers.h gc_private.h config.h gc_inline.h gc.man if_mach.c if_not_there.c
+
+# The following is irrelevant on most systems.  But a few
+# versions of make otherwise fork the shell specified in
+# the SHELL environment variable.
+SHELL= /bin/sh
 
 CC= cc
 CFLAGS= -O
@@ -17,40 +22,34 @@ SPECIALCFLAGS =
 
 all: gc.a gctest
 
-pcr: PCR-Makefile gc_private.h gc_headers.h gc.h $(SRCS)
+pcr: PCR-Makefile gc_private.h gc_headers.h gc.h config.h mach_dep.o $(SRCS)
+       make -f PCR-Makefile depend
        make -f PCR-Makefile
 
-$(OBJS) test.o: gc_private.h gc_headers.h gc.h Makefile
+$(OBJS) test.o: gc_private.h gc_headers.h gc.h config.h Makefile
 
-#  On some machines, the ranlib command may have to be removed.
-#  On an SGI for example, ranlib doesn't exist, and is not needed.
-#  Ditto for Solaris 2.X.
 gc.a: $(OBJS)
        ar ru gc.a $(OBJS)
-       ranlib gc.a
-
-# On a MIPS-based machine, replace the rule for mach_dep.o by the
-# following:
-# mach_dep.o: mips_mach_dep.s
-#      as -o mach_dep.o mips_mach_dep.s
-# On an IBM RS6000, use the following two lines:
-# mach_dep.o: rs6000_mach_dep.s
-#      as -o mach_dep.o rs6000_mach_dep.s
-mach_dep.o: mach_dep.c
-       $(CC) -c $(SPECIALCFLAGS) mach_dep.c
+       ranlib gc.a || cat /dev/null
+#      ignore ranlib failure; that usually means it doesn't exist, and isn't needed
+
+mach_dep.o: mach_dep.c mips_mach_dep.s rs6000_mach_dep.s if_mach if_not_there
+       rm -f mach_dep.o
+       ./if_mach MIPS "" as -o mach_dep.o mips_mach_dep.s
+       ./if_mach RS6000 "" as -o mach_dep.o rs6000_mach_dep.s
+       ./if_not_there mach_dep.o $(CC) -c $(SPECIALCFLAGS) mach_dep.c
+
+if_mach: if_mach.c config.h
+       $(CC) $(CFLAGS) -o if_mach if_mach.c
+       
+if_not_there: if_not_there.c
+       $(CC) $(CFLAGS) -o if_not_there if_not_there.c
 
 clean: 
        rm -f gc.a test.o gctest output-local output-diff $(OBJS) \
              setjmp_test  mon.out gmon.out a.out core
        -rm -f *~
 
-
-# On a MIPS system, the BSD version of libc.a should be used to get
-# sigsetmask.  I found it necessary to link against the system V
-# library first, to get a working version of fprintf.  But this may have
-# been due to my failure to find the right version of stdio.h or some
-# such thing.
-# On a Solaris 2.X system, also make sure you're using BSD libraries.
 gctest: test.o gc.a
        $(CC) $(CFLAGS) -o gctest test.o gc.a
 
index 249486dfe72a79f9e92dffeab5a7e9cf4073395f..07460d84de8025457bd4fc61d6b3b86f63b2cb4d 100644 (file)
@@ -4,12 +4,13 @@
 # look at another threads registers.
 
 # We also haven't figured out how to do partial links or build static libraries.  Hence a
-# client currentlu needs to link against all of the following:
+# client currently needs to link against all of the following:
 
 OBJS= alloc.obj reclaim.obj allochblk.obj misc.obj mach_dep.obj os_dep.obj mark_roots.obj headers.obj mark.obj obj_map.obj black_list.obj finalize.obj new_hblk.obj real_malloc.obj dynamic_load.obj debug_malloc.obj
 
 CC= icc
-CFLAGS= /Ti /Q
+CFLAGS= /O /Q
+# Use /Ti instead of /O for debugging
 # Setjmp_test may yield overly optimistic results when compiled
 # without optimization.
 
index 616ffdc7f997981f6fae2fd650270d2ab829161f..a432999bf7d19acee51d3b2a1a13b2c813fbd28e 100644 (file)
@@ -1,41 +1,44 @@
 OBJS= alloc.o reclaim.o allochblk.o misc.o mach_dep.o os_dep.o mark_roots.o headers.o mark.o obj_map.o pcr_interface.o black_list.o finalize.o new_hblk.o real_malloc.o dynamic_load.o debug_malloc.o
 
+CSRCS= reclaim.c allochblk.c misc.c alloc.c mach_dep.c os_dep.c mark_roots.c headers.c mark.c obj_map.c pcr_interface.c black_list.c finalize.c new_hblk.c real_malloc.c dynamic_load.c debug_malloc.c
+
+SHELL= /bin/sh
+
 # Fix to point to local pcr installation directory.
-PCRDIR= /project/ppcr/dev
+PCRDIR= /project/ppcr/v1.5
 CC= gcc
 CFLAGS= -g -DPCR -I$(PCRDIR) -I$(PCRDIR)/pcr -I$(PCRDIR)/pcr/ansi -I$(PCRDIR)/pcr/posix
-# On Sun systems under 4.x, it's safer to link with -Bstatic.
-# On other systems, -Bstatic usually doesn't make sense, and should be
-# removed.
-# Setjmp_test may yield overly optimistic results when compiled
-# without optimization.
-
-SPECIALCFLAGS = 
-# Alternative flags to the C compiler for mach_dep.c.
-# Mach_dep.c often doesn't like optimization, and it's
-# not time-critical anyway.
-# Set SPECIALCFLAGS to -q nodirect_code on Encore.
-
-PCRINCLS= $(PCRDIR)/pcr/il/PCR_IL.h $(PCRDIR)/pcr/th/PCR_ThCtl.h $(PCRDIR)/pcr/mm/PCR_MM.h
 
+# We assume that mach_dep.o has already been built by top level makefile.  It doesn't
+# care about pcr vs UNIX, and we don't want to repeat that cruft.
 
 all: gc.o test.o gcpcr
 
 gcpcr: gc.o test.o $(PCRDIR)/pcr/base/pcr.o $(PCRDIR)/pcr/base/PCR_BaseMain.o
-       $(CC) -static -o gcpcr $(PCRDIR)/pcr/base/pcr.o $(PCRDIR)/pcr/base/PCR_BaseMain.o gc.o test.o
-
-$(OBJS) test.o: gc_private.h gc_headers.h gc.h PCR-Makefile $(PCRINCLS)
+       $(CC) -o gcpcr $(PCRDIR)/pcr/base/pcr.o $(PCRDIR)/pcr/base/PCR_BaseMain.o gc.o test.o -ldl
 
 gc.o: $(OBJS)
        -ld -r -o gc.o $(OBJS)
 
-# On a MIPS machine, replace the rule for mach_dep.o by the
-# following:
-# mach_dep.o: mips_mach_dep.s
-#      as -o mach_dep.o mips_mach_dep.s
-# On an IBM RS6000, use the following two lines:
-# mach_dep.o: rs6000_mach_dep.s
-#      as -o mach_dep.o rs6000_mach_dep.s
-mach_dep.o: mach_dep.c
-       $(CC) -c ${SPECIALCFLAGS} mach_dep.c
+#
+# Dependency construction
+#
+# NOTE: the makefile must include "# DO NOT DELETE THIS LINE" after the
+#   last target.  "make depend" will replace everything following that line
+#   by a newly-constructed list of dependencies.
+#
+depend: $(CSRCS)
+       rm -f makedep eddep ; \
+    $(CC) -M $(CFLAGS) $(CSRCS) \
+                       | sed -e '/:$$/d' > makedep ; \
+    echo '/^# DO NOT DELETE THIS LINE/+1,$$d' >eddep ; \
+       echo '$$r makedep' >>eddep ; \
+       echo 'w' >>eddep ; \
+       cp PCR-Makefile PCR-Makefile.bak ; \
+       ex - PCR-Makefile < eddep ; \
+       rm -f eddep makedep
+       touch depend
+       
+# DO NOT DELETE THIS LINE
+
 
diff --git a/README b/README
index 13133fa6dea91ac2f59283c385e652964f9cb07d..390f50b202f611994137d70fedfd46b2e390ce23 100644 (file)
--- a/README
+++ b/README
@@ -8,7 +8,7 @@ Permission is hereby granted to copy this garbage collector for any purpose,
 provided the above notices are retained on all copies.
 
 
-This is version 2.4.  Note that functions were renamed since version 1.9
+This is version 2.6.  Note that functions were renamed since version 1.9
 to make naming consistent with PCR collectors.
 
 HISTORY -
@@ -542,3 +542,16 @@ for PPCR.
   under 4.1.1U1, but apparently not 4.1.1.  If you have such a machine,
   use -Bstatic.)
   
+  Version 2.5 added Solaris dynamic libary support, Solaris/Intel support,
+  and fixed the following bugs:
+- Removed an explicit call to exit(1)
+- Fixed calls to GC_printf and GC_err_printf, so the correct number of
+  arguments are always supplied.  The OS/2 C compiler gets confused if
+  the number of actuals and the number of formals differ.  (ANSI C
+  doesn't require this to work.  The ANSI sanctioned way of doing things
+  causes too many compatibility problems.)
+  
+  Version 2.6 fixed a bug diagnosed by Al Dosser at DEC.  The marker
+  could lose some pointers in the event of a mark stack overflow, a case
+  it was intended to handle correctly.  (He also pointed out a performance
+  bug that was tickled under the same circumstances.)
diff --git a/alloc.c b/alloc.c
index e97492f024bcc46597abe6b75e6e9b322872cdc3..1456d5291bb7edde6bfc63580034a64789c3cae0 100644 (file)
--- a/alloc.c
+++ b/alloc.c
@@ -10,7 +10,7 @@
  *
  * This file contains the functions:
  *     static void clear_marks()
- *     void GC_gcollect_inner(force)
+ *     bool GC_gcollect_inner(force)
  *     void GC_gcollect()
  *     bool GC_expand_hp(n)
  *     ptr_t GC_allocobj(sz, kind)
@@ -86,7 +86,12 @@ char * GC_copyright[] =
 extern signed_word GC_mem_found;  /* Number of reclaimed longwords     */
                                  /* after garbage collection           */
 
-extern errno;
+/* clear all mark bits in the header */
+void GC_clear_hdr_marks(hhdr)
+register hdr * hhdr;
+{
+    bzero((char *)hhdr -> hb_marks, (int)(MARK_BITS_SZ*sizeof(word)));
+}
 
 /*
  * Clear all mark bits associated with block h.
@@ -97,11 +102,8 @@ struct hblk *h;
 word dummy;
 {
     register hdr * hhdr = HDR(h);
-    register int j;
     
-    for (j = 0; j < MARK_BITS_SZ; j++) {
-       hhdr -> hb_marks[j] = 0;
-    }
+    GC_clear_hdr_marks(hhdr);
 }
 
 /*
@@ -136,6 +138,36 @@ static word min_words_allocd()
     return(BYTES_TO_WORDS(GC_heapsize + total_root_size)/GC_free_space_divisor);
 }
 
+/* Return the number of words allocated, adjusted for explicit storage */
+/* management.  This number can be used in deciding when to trigger    */
+/* collections.                                                                */
+word GC_adj_words_allocd()
+{
+    register signed_word result;
+    register signed_word expl_managed =
+               BYTES_TO_WORDS((long)GC_non_gc_bytes
+                               - (long)GC_non_gc_bytes_at_gc);
+    
+    /* Don't count what was explicitly freed, or newly allocated for   */
+    /* explicit management.  Note that deallocating an explicitly      */
+    /* managed object should not alter result, assuming the client     */
+    /* is playing by the rules.                                                */
+    result = (signed_word)GC_words_allocd
+            - (signed_word)GC_mem_freed - expl_managed;
+    if (result > (signed_word)GC_words_allocd) result = GC_words_allocd;
+       /* probably client bug or unfortunate scheduling */
+    if (result < (signed_word)(GC_words_allocd >> 2)) {
+       /* Always count at least 1/8 of the allocations.  We don't want */
+       /* to collect too infrequently, since that would inhibit        */
+       /* coalescing of free storage blocks.                           */
+       /* This also makes us partially robust against client bugs.     */
+        return(GC_words_allocd >> 3);
+    } else {
+        return(result);
+    }
+}
+
+
 /* Clear up a few frames worth og garbage left at the top of the stack.        */
 /* This is used to prevent us from accidentally treating garbade left  */
 /* on the stack by other parts of the collector as roots.  This        */
@@ -156,8 +188,10 @@ void GC_clear_a_few_frames()
  * garbage collection)
  * We assume we hold the allocation lock, and are not interruptable by
  * signals, if that matters.
+ * If force is FALSE and we didn't do anything, return FALSE.
+ * Otherwise return TRUE
  */
-void GC_gcollect_inner(force)
+bool GC_gcollect_inner(force)
 bool force;    /* Collect even if only a small amount of allocation    */
                /* has taken place.  Otherwise we refuse, allowing the  */
                /* heap to grow.                                        */
@@ -169,12 +203,12 @@ bool force;       /* Collect even if only a small amount of allocation    */
 #   endif
 
     if (!force && !GC_dont_expand
-        && GC_words_allocd < min_words_allocd()) return;
+        && GC_adj_words_allocd() < min_words_allocd()) return(FALSE);
 #   ifdef PRINTTIMES
        GET_TIME(start_time);
 #   endif
 #   ifdef PRINTSTATS
-       GC_printf("Collection %lu reclaimed %ld bytes\n",
+       GC_printf2("Collection %lu reclaimed %ld bytes\n",
                  (unsigned long) GC_gc_no,
                  (long)WORDS_TO_BYTES(GC_mem_found));
 #   endif
@@ -185,15 +219,14 @@ bool force;       /* Collect even if only a small amount of allocation    */
         GC_atomic_in_use = 0;
 #   endif
 #   ifdef PRINTSTATS
-      GC_printf("Collection number %lu after %lu allocated bytes ",
+      GC_printf2("Collection number %lu after %lu allocated bytes ",
                (unsigned long) GC_gc_no,
                (unsigned long) WORDS_TO_BYTES(GC_words_allocd));
-      GC_printf("(heapsize = %lu bytes)\n",
+      GC_printf1("(heapsize = %lu bytes)\n",
                (unsigned long) GC_heapsize);
       /* Printf arguments may be pushed in funny places.  Clear the    */
       /* space.                                                                */
-      GC_printf("", (unsigned long)0, (unsigned long)0, (unsigned long)0,
-                   (unsigned long)0, (unsigned long)0, (unsigned long)0);
+      GC_printf0("");
 #   endif                      
 
     clear_marks();
@@ -278,7 +311,7 @@ bool force; /* Collect even if only a small amount of allocation    */
 
 
 #     ifdef PRINTSTATS
-       GC_printf("Bytes recovered before GC_reclaim - f.l. count = %ld\n",
+       GC_printf1("Bytes recovered before GC_reclaim - f.l. count = %ld\n",
                  (long)WORDS_TO_BYTES(GC_mem_found));
 #     endif
 
@@ -288,25 +321,29 @@ bool force;       /* Collect even if only a small amount of allocation    */
 #   endif /* FIND_LEAK */
 
 #   ifdef PRINTSTATS
-       GC_printf("Immediately reclaimed %ld bytes in heap of size %lu bytes\n",
+       GC_printf2(
+                 "Immediately reclaimed %ld bytes in heap of size %lu bytes\n",
                  (long)WORDS_TO_BYTES(GC_mem_found),
                  (unsigned long)GC_heapsize);
-       GC_printf("%lu (atomic) + %lu (composite) bytes in use\n",
-                 (unsigned long)WORDS_TO_BYTES(GC_atomic_in_use),
-                 (unsigned long)WORDS_TO_BYTES(GC_composite_in_use));
+       GC_printf2("%lu (atomic) + %lu (composite) bytes in use\n",
+                  (unsigned long)WORDS_TO_BYTES(GC_atomic_in_use),
+                  (unsigned long)WORDS_TO_BYTES(GC_composite_in_use));
 #   endif
 
     /* Reset or increment counters for next cycle */
       GC_words_allocd_before_gc += GC_words_allocd;
+      GC_non_gc_bytes_at_gc = GC_non_gc_bytes;
       GC_words_allocd = 0;
+      GC_mem_freed = 0;
 
   /* Get final time */
 #   ifdef PRINTTIMES
        GET_TIME(done_time);
-       GC_printf("Garbage collection took %lu + %lu msecs\n",
-                 MS_TIME_DIFF(mark_time,start_time),
-                 MS_TIME_DIFF(done_time,mark_time));
+       GC_printf2("Garbage collection took %lu + %lu msecs\n",
+                  MS_TIME_DIFF(mark_time,start_time),
+                  MS_TIME_DIFF(done_time,mark_time));
 #   endif
+    return(TRUE);
 }
 
 /* Externally callable version of above */
@@ -319,7 +356,7 @@ void GC_gcollect()
     if (!GC_is_initialized) GC_init_inner();
     /* Minimize junk left in my registers */
       GC_noop(0,0,0,0,0,0);
-    GC_gcollect_inner(TRUE);
+    (void) GC_gcollect_inner(TRUE);
     UNLOCK();
     ENABLE_SIGNALS();
 }
@@ -388,7 +425,7 @@ word n;
        return(FALSE);
     }
 #   ifdef PRINTSTATS
-       GC_printf("Increasing heap size by %lu\n",
+       GC_printf1("Increasing heap size by %lu\n",
                   (unsigned long)bytes);
 #   endif
     expansion_slop = 8 * WORDS_TO_BYTES(min_words_allocd());
@@ -429,6 +466,26 @@ int n;
     return(result);
 }
 
+void GC_collect_or_expand(needed_blocks)
+word needed_blocks;
+{
+    static int count = 0;  /* How many failures? */
+    
+    if (GC_dont_gc || !GC_gcollect_inner(FALSE)) {
+      if (!GC_expand_hp_inner(GC_hincr + needed_blocks)
+        && !GC_expand_hp_inner(needed_blocks)) {
+       if (count++ < 20) {
+           WARN("Out of Memory!  Trying to continue ...\n");
+           (void) GC_gcollect_inner(TRUE);
+       } else {
+           GC_err_printf0("Out of Memory!  Giving up!\n");
+           EXIT();
+       }
+      }
+      update_GC_hincr;
+    }
+}
+
 /*
  * Make sure the object free list for sz is not empty.
  * Return a pointer to the first object on the free list.
@@ -440,25 +497,16 @@ word sz;
 int kind;
 {
     register ptr_t * flh = &(GC_obj_kinds[kind].ok_freelist[sz]);
+    
     if (sz == 0) return(0);
 
-    if (*flh == 0) {
+    while (*flh == 0) {
       GC_continue_reclaim(sz, kind);
-    }
-    if (*flh == 0) {
-      if (!GC_sufficient_hb(sz, kind) && !GC_dont_gc) {
-       if (GC_DIV * GC_non_gc_bytes < GC_MULT * GC_heapsize) {
-         GC_gcollect_inner(FALSE);
-         GC_continue_reclaim(sz, kind);
-       } else {
-         if (!GC_expand_hp_inner(NON_GC_HINCR)) {
-             GC_gcollect_inner(FALSE);
-             GC_continue_reclaim(sz, kind);
-         }
-       }
+      if (*flh == 0) {
+        GC_new_hblk(sz, kind);
       }
       if (*flh == 0) {
-         GC_new_hblk(sz, kind);
+        GC_collect_or_expand((word)1);
       }
     }
     return(*flh);
index 1dcf581be6b434c6371dcd20f7bd4245610040b5..48212b7fe35e06ad91d46585532bc900a21767d2 100644 (file)
@@ -38,61 +38,24 @@ struct hblk *GC_savhbp = (struct hblk *)0;  /* heap block preceding next */
                                         /* block to be examined by   */
                                         /* GC_allochblk.                */
 
-/*
- * Return TRUE if there is a heap block sufficient for object size sz,
- * FALSE otherwise.  Advance GC_savhbp to point to the block prior to the
- * first such block.
- */
-bool GC_sufficient_hb(sz, kind)
-word sz;
+/* Initialize hdr for a block containing the indicated size and        */
+/* kind of objects.                                                    */
+static setup_header(hhdr, sz, kind)
+register hdr * hhdr;
+word sz;       /* object size in words */
 int kind;
 {
-register struct hblk *hbp;
-register hdr * hhdr;
-struct hblk *prevhbp;
-signed_word size_needed;
-signed_word size_avail;
-bool first_time = TRUE;
-
-    size_needed = WORDS_TO_BYTES(sz);
-    size_needed = (size_needed+HDR_BYTES+HBLKSIZE-1) & ~HBLKMASK;
-#   ifdef DEBUG
-       GC_printf("GC_sufficient_hb: sz = %ld, size_needed = 0x%lx\n",
-                 (long)sz, (unsigned long)size_needed);
-#   endif
-    /* search for a big enough block in free list */
-       hbp = GC_savhbp;
-       hhdr = HDR(hbp);
-       for(;;) {
-           prevhbp = hbp;
-           hbp = ((prevhbp == (struct hblk *)0)
-                   ? GC_hblkfreelist
-                   : hhdr->hb_next);
-           hhdr = HDR(hbp);
-
-           if( prevhbp == GC_savhbp && !first_time) {
-               /* no sufficiently big blocks on free list */
-               return(FALSE);
-           }
-           first_time = 0;
-           if( hbp == (struct hblk *)0 ) continue;
-           size_avail = hhdr->hb_sz;
-           if ( kind != PTRFREE || size_needed > MAX_BLACK_LIST_ALLOC) {
-             struct hblk * thishbp;
-             struct hblk * lasthbp = hbp;
-             
-             while ((ptr_t)lasthbp - (ptr_t)hbp < size_avail
-                    && (thishbp = GC_is_black_listed(lasthbp,
-                                                     (word)size_needed))) {
-                 lasthbp = thishbp;
-             }
-             size_avail -= (ptr_t)lasthbp - (ptr_t)hbp;
-           }
-           if( size_avail >= size_needed ) {
-               GC_savhbp = prevhbp;
-               return(TRUE);
-           }
-       }
+    /* Set size, kind and mark proc fields */
+      hhdr -> hb_sz = sz;
+      hhdr -> hb_obj_kind = kind;
+      hhdr -> hb_mark_proc = GC_obj_kinds[kind].ok_mark_proc;
+      
+    /* Add description of valid object pointers */
+      GC_add_map_entry(sz);
+      hhdr -> hb_map = GC_obj_map[sz > MAXOBJSZ? 0 : sz];
+      
+    /* Clear mark bits */
+      GC_clear_hdr_marks(hhdr);
 }
 
 /*
@@ -134,31 +97,10 @@ int kind;
            hhdr = HDR(hbp);
 
            if( prevhbp == GC_savhbp && !first_time) {
-               /* no sufficiently big blocks on free list, */
-               /* let thishbp --> a newly-allocated block, */
-               /* free it (to merge into existing block    */
-               /* list) and start the search again, this   */
-               /* time with guaranteed success.            */
-                  word size_to_get = size_needed + GC_hincr * HBLKSIZE;
-
-                 if (! GC_expand_hp_inner(divHBLKSZ(size_to_get))) {
-                     if (! GC_expand_hp_inner(divHBLKSZ((word)size_needed)))
-                     {
-                         /* GC_printf("Out of Memory!  Giving up ...\n"); */
-                         /* There are other things we could try.  It   */
-                         /* would probably be reasonable to clear      */
-                         /* black lists at tthis point.                */
-                         return(0);
-                     } else {
-                         WARN("Out of Memory!  Trying to continue ...\n");
-                         GC_gcollect_inner(TRUE);
-                     }
-                 }
-                  update_GC_hincr;
-                  return (GC_allochblk(sz, kind));
+               return(0);
            }
 
-           first_time = 0;
+           first_time = FALSE;
 
            if( hbp == 0 ) continue;
 
@@ -205,7 +147,30 @@ int kind;
                      phdr = hhdr;
                      hbp = thishbp;
                      hhdr = thishdr;
-             } 
+             } else if (size_avail == 0
+                        && size_needed == HBLKSIZE
+                        && prevhbp != 0) {
+                 static unsigned count = 0;
+                 
+                 /* The block is completely blacklisted.  We need      */
+                 /* to drop some such blocks, since otherwise we spend */
+                 /* all our time traversing them if pointerfree        */
+                 /* blocks are unpopular.                              */
+                 /* A dropped block will be reconsidered at next GC.   */
+                 if ((++count & 3) == 0) {
+                   /* Allocate and drop the block */
+                     phdr -> hb_next = hhdr -> hb_next;
+                     GC_install_counts(hbp, hhdr->hb_sz);
+                     setup_header(hhdr,
+                                  BYTES_TO_WORDS(hhdr->hb_sz - HDR_BYTES),
+                                  PTRFREE);
+                     if (GC_savhbp == hbp) GC_savhbp = prevhbp;
+                   /* Restore hbp to point at free block */
+                     hbp = prevhbp;
+                     hhdr = phdr;
+                     if (hbp == GC_savhbp) first_time = TRUE;
+                 }
+             }
            }
            if( size_avail >= size_needed ) {
                /* found a big enough block       */
@@ -237,34 +202,16 @@ int kind;
            }
        }
 
-    /* set size and mask field of *thishbp correctly */
-       thishdr->hb_sz = sz;
-
     /* Clear block if necessary */
        if (sz > MAXOBJSZ && GC_obj_kinds[kind].ok_init) {
            bzero((char *)thishbp + HDR_BYTES,  (int)(size_needed - HDR_BYTES));
        }
-       
-    /* Clear mark bits */
-       {
-           register word *p = (word *)(&(thishdr -> hb_marks[0]));
-           register word * plim =
-                       (word *)(&(thishdr -> hb_marks[MARK_BITS_SZ]));
-           while (p < plim) {
-               *p++ = 0;
-           }
-       }
-       
-    /* Add it to data structure describing hblks in use */
-        GC_install_counts(thishbp, (word)size_needed);
-        
-    /* Add description of valid object pointers. */
-        GC_add_map_entry(sz);
-        thishdr -> hb_map = GC_obj_map[sz > MAXOBJSZ? 0 : sz];
+
+    /* Set up header */
+        setup_header(thishdr, sz, kind);
         
-    /* Set kind related fields */
-        thishdr -> hb_obj_kind = kind;
-        thishdr -> hb_mark_proc = GC_obj_kinds[kind].ok_mark_proc;
+    /* Add it to map of valid blocks */
+       GC_install_counts(thishbp, (word)size_needed);
 
     return( thishbp );
 }
@@ -311,10 +258,10 @@ register signed_word size;
     /* Check for duplicate deallocation in the easy case */
       if (hbp != 0 && (ptr_t)p + size > (ptr_t)hbp
         || prevhbp != 0 && (ptr_t)prevhbp + prevhdr->hb_sz > (ptr_t)p) {
-        GC_printf("Duplicate large block deallocation of 0x%lx\n",
-                 (unsigned long) p);
-        GC_printf("Surrounding free blocks are 0x%lx and 0x%lx\n",
-                 (unsigned long) prevhbp, (unsigned long) hbp);
+        GC_printf1("Duplicate large block deallocation of 0x%lx\n",
+                  (unsigned long) p);
+        GC_printf2("Surrounding free blocks are 0x%lx and 0x%lx\n",
+                  (unsigned long) prevhbp, (unsigned long) hbp);
       }
 
     /* Coalesce with successor, if possible */
index 9471dc52ddb8451dd6d3b816c9f46a33d9b6f6c1..ba54f892ffda9a3127785d5828c0906f718510e6 100644 (file)
@@ -114,8 +114,8 @@ word p;
         if (HDR(p) == 0 || get_bl_entry_from_index(GC_new_normal_bl, index)) {
 #          ifdef PRINTBLACKLIST
                if (!get_bl_entry_from_index(GC_incomplete_normal_bl, index)) {
-                 GC_printf("Black listing (normal) 0x%lx\n",
-                           (unsigned long) p);
+                 GC_printf1("Black listing (normal) 0x%lx\n",
+                            (unsigned long) p);
                }
 #           endif
             set_bl_entry_from_index(GC_incomplete_normal_bl, index);
@@ -134,8 +134,8 @@ word p;
     if (HDR(p) == 0 || get_bl_entry_from_index(GC_new_stack_bl, index)) {
 #      ifdef PRINTBLACKLIST
            if (!get_bl_entry_from_index(GC_incomplete_stack_bl, index)) {
-                 GC_printf("Black listing (stack) 0x%lx\n",
-                           (unsigned long)p);
+                 GC_printf1("Black listing (stack) 0x%lx\n",
+                            (unsigned long)p);
            }
 #       endif
        set_bl_entry_from_index(GC_incomplete_stack_bl, index);
diff --git a/config.h b/config.h
new file mode 100644 (file)
index 0000000..48464e4
--- /dev/null
+++ b/config.h
@@ -0,0 +1,375 @@
+#ifndef CONFIG_H
+
+# define CONFIG_H
+
+/* Machine dependent parameters.  Some tuning parameters can be found  */
+/* near the top of gc_private.h.                                       */
+
+/* Machine specific parts contributed by various people.  See README file. */
+
+/* Determine the machine type: */
+# if defined(sun) && defined(mc68000)
+#    define M68K
+#    define SUNOS
+#    define mach_type_known
+# endif
+# if defined(hp9000s300)
+#    define M68K
+#    define HP
+#    define mach_type_known
+# endif
+# if defined(vax)
+#    define VAX
+#    ifdef ultrix
+#      define ULTRIX
+#    else
+#      define BSD
+#    endif
+#    define mach_type_known
+# endif
+# if defined(mips)
+#    define MIPS
+#    ifdef ultrix
+#      define ULTRIX
+#    else
+#      define RISCOS
+#    endif
+#    define mach_type_known
+# endif
+# if defined(sequent) && defined(i386)
+#    define I386
+#    define SEQUENT
+#    define mach_type_known
+# endif
+# if defined(sun) && defined(i386)
+#    define I386
+#    define SUNOS5
+#    define mach_type_known
+# endif
+# if defined(__OS2__) && defined(__32BIT__)
+#    define I386
+#    define OS2
+#    define mach_type_known
+# endif
+# if defined(ibm032)
+#   define RT
+#   define mach_type_known
+# endif
+# if defined(sun) && defined(sparc)
+#   define SPARC
+    /* Test for SunOS 5.x */
+#     include <errno.h>
+#     ifdef ECHRNG
+#       define SUNOS5
+#     else
+#      define SUNOS4
+#     endif
+#   define mach_type_known
+# endif
+# if defined(_IBMR2)
+#   define IBMRS6000
+#   define mach_type_known
+# endif
+# if defined(SCO)
+#   define I386
+#   define SCO
+#   define mach_type_known
+/*     --> incompletely implemented */
+# endif
+# if defined(_AUX_SOURCE)
+#   define M68K
+#   define SYSV
+#   define mach_type_known
+# endif
+# if defined(_PA_RISC1_0) || defined(_PA_RISC1_1)
+#   define HP_PA
+#   define mach_type_known
+# endif
+# if defined(linux) && defined(i386)
+#    define I386
+#    define LINUX
+#    define mach_type_known
+# endif
+
+/* Feel free to add more clauses here */
+
+/* Or manually define the machine type here.  A machine type is        */
+/* characterized by the architecture.  Some                            */
+/* machine types are further subdivided by OS.                         */
+/* the macros ULTRIX, RISCOS, and BSD to distinguish.                  */
+/* Note that SGI IRIX is treated identically to RISCOS.                        */
+/* SYSV on an M68K actually means A/UX.                                        */
+/* The distinction in these cases is usually the stack starting address */
+# ifndef mach_type_known
+       --> unknown machine type
+# endif
+                   /* Mapping is: M68K       ==> Motorola 680X0        */
+                   /*             (SUNOS, HP, and SYSV (A/UX) variants)*/
+                   /*             M68K_HP    ==> HP9000/300            */
+                   /*             M68K_SYSV  ==> A/UX, maybe others    */
+                   /*             I386       ==> Intel 386             */
+                   /*              (SEQUENT, OS2, SCO, LINUX variants) */
+                   /*               SCO is incomplete.                 */
+                    /*             NS32K      ==> Encore Multimax      */
+                    /*             MIPS       ==> R2000 or R3000       */
+                    /*                 (RISCOS, ULTRIX variants)       */
+                    /*            VAX        ==> DEC VAX               */
+                    /*                 (BSD, ULTRIX variants)          */
+                    /*            RS6000     ==> IBM RS/6000 AIX3.1    */
+                    /*            RT         ==> IBM PC/RT             */
+                    /*            HP_PA      ==> HP9000/700 & /800     */
+                    /*                           HP/UX                 */
+                   /*             SPARC      ==> SPARC under SunOS     */
+                   /*                  (SUNOS4, SUNOS5 variants)
+
+
+/*
+ * For each architecture and OS, the following need to be defined:
+ *
+ * CPP_WORD_SZ is a simple integer constant representing the word size.
+ * in bits.  We assume byte addressibility, where a byte has 8 bits.
+ * We also assume CPP_WORD_SZ is either 32 or 64.  Only 32 is completely
+ * implemented.  (We care about the length of pointers, not hardware
+ * bus widths.  Thus a 64 bit processor with a C compiler that uses
+ * 32 bit pointers should use CPP_WORD_SZ of 32, not 64.)
+ *
+ * MACH_TYPE is a string representation of the machine type.
+ * OS_TYPE is analogous for the OS.
+ *
+ * ALIGNMENT is the largest N, such that
+ * all pointer are guaranteed to be aligned on N byte boundaries.
+ * defining it to be 1 will always work, but perform poorly.
+ *
+ * DATASTART is the beginning of the data segment.
+ * On UNIX systems, the collector will scan the area between DATASTART
+ * and &end for root pointers.
+ *
+ * STACKBOTTOM is the cool end of the stack, which is usually the
+ * highest address in the stack.
+ * Under PCR or OS/2, we have other ways of finding thread stacks.
+ * For each machine, the following should:
+ * 1) define STACK_GROWS_UP if the stack grows toward higher addresses, and
+ * 2) define exactly one of
+ *     STACKBOTTOM (should be defined to be an expression)
+ *     HEURISTIC1
+ *     HEURISTIC2
+ * If either of the last two macros are defined, then STACKBOTTOM is computed
+ * during collector startup using one of the following two heuristics:
+ * HEURISTIC1:  Take an address inside GC_init's frame, and round it up to
+ *             the next multiple of 16 MB.
+ * HEURISTIC2:  Take an address inside GC_init's frame, increment it repeatedly
+ *             in small steps (decrement if STACK_GROWS_UP), and read the value
+ *             at each location.  Remember the value when the first
+ *             Segmentation violation or Bus error is signalled.  Round that
+ *             to the nearest plausible page boundary, and use that instead
+ *             of STACKBOTTOM.
+ *
+ * If no expression for STACKBOTTOM can be found, and neither of the above
+ * heuristics are usable, the collector can still be used with all of the above
+ * undefined, provided one of the following is done:
+ * 1) GC_mark_roots can be changed to somehow mark from the correct stack(s)
+ *    without reference to STACKBOTTOM.  This is appropriate for use in
+ *    conjunction with thread packages, since there will be multiple stacks.
+ *    (Allocating thread stacks in the heap, and treating them as ordinary
+ *    heap data objects is also possible as a last resort.  However, this is
+ *    likely to introduce significant amounts of excess storage retention
+ *    unless the dead parts of the thread stacks are periodically cleared.)
+ * 2) Client code may set GC_stackbottom before calling any GC_ routines.
+ *    If the author of the client code controls the main program, this is
+ *    easily accomplished by introducing a new main program, setting
+ *    GC_stackbottom to the address of a local variable, and then calling
+ *    the original main program.  The new main program would read something
+ *    like:
+ *
+ *             # include "gc_private.h"
+ *
+ *             main(argc, argv, envp)
+ *             int argc;
+ *             char **argv, **envp;
+ *             {
+ *                 int dummy;
+ *
+ *                 GC_stackbottom = (ptr_t)(&dummy);
+ *                 return(real_main(argc, argv, envp));
+ *             }
+ */
+
+
+# ifdef M68K
+#   define MACH_TYPE "M68K"
+#   define ALIGNMENT 2
+#   ifdef SUNOS
+#      define OS_TYPE "SUNOS"
+       extern char etext;
+#      define DATASTART ((ptr_t)((((word) (&etext)) + 0x1ffff) & ~0x1ffff))
+#      define HEURISTIC1       /* differs      */
+#   endif
+#   ifdef HP
+#      define OS_TYPE "HP"
+       extern char etext;
+#       define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff))
+#       define STACKBOTTOM ((ptr_t) 0xffeffffc)
+                             /* empirically determined.  seems to work. */
+#   endif
+#   ifdef SYSV
+#      define OS_TYPE "SYSV"
+       extern etext;
+#      define DATASTART ((ptr_t)((((word) (&etext)) + 0x3fffff) \
+                                  & ~0x3fffff) \
+                                 +((word)&etext & 0x1fff))
+       /* This only works for shared-text binaries with magic number 0413.
+          The other sorts of SysV binaries put the data at the end of the text,
+          in which case the default of &etext would work.  Unfortunately,
+          handling both would require having the magic-number available.
+                               -- Parag
+          */
+#      define STACKBOTTOM ((ptr_t)0xFFFFFFFE)
+                       /* The stack starts at the top of memory, but   */
+                       /* 0x0 cannot be used as setjump_test complains */
+                       /* that the stack direction is incorrect.  Two  */
+                       /* bytes down from 0x0 should be safe enough.   */
+                       /*              --Parag                         */
+#   endif
+# endif
+
+# ifdef VAX
+#   define MACH_TYPE "VAX"
+#   define ALIGNMENT 4 /* Pointers are longword aligned by 4.2 C compiler */
+    extern char etext;
+#   define DATASTART ((ptr_t)(&etext))
+#   ifdef BSD
+#      define OS_TYPE "BSD"
+#      define HEURISTIC1
+                       /* HEURISTIC2 may be OK, but it's hard to test. */
+#   endif
+#   ifdef ULTRIX
+#      define OS_TYPE "ULTRIX"
+#      define STACKBOTTOM ((ptr_t) 0x7fffc800)
+#   endif
+# endif
+
+# ifdef RT
+#   define MACH_TYPE "RT"
+#   define ALIGNMENT 4
+#   define DATASTART ((ptr_t) 0x10000000)
+#   define STACKBOTTOM ((ptr_t) 0x1fffd800)
+# endif
+
+# ifdef SPARC
+#   define MACH_TYPE "SPARC"
+#   define ALIGNMENT 4 /* Required by hardware */
+    extern int etext;
+#   ifdef SUNOS5
+#      define OS_TYPE "SUNOS5"
+#       define DATASTART ((ptr_t)((((word) (&etext)) + 0x10003) & ~0x3))
+               /* Experimentally determined.                   */
+               /* Inconsistent with man a.out, which appears   */
+               /* to be wrong.                                 */
+#   endif
+#   ifdef SUNOS4
+#      define OS_TYPE "SUNOS4"
+#       define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff))
+               /* On very old SPARCs this is too conservative. */
+#   endif
+#   define HEURISTIC1
+# endif
+
+# ifdef I386
+#   define MACH_TYPE "I386"
+#   define ALIGNMENT 4 /* 32-bit compilers align pointers */
+#   ifdef SEQUENT
+#      define OS_TYPE "SEQUENT"
+       extern int etext;
+#       define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff))
+#       define STACKBOTTOM ((ptr_t) 0x3ffff000) 
+#   endif
+#   ifdef SUNOS5
+#      define OS_TYPE "SUNOS5"
+       extern int etext;
+#       define DATASTART ((ptr_t)((((word) (&etext)) + 0x1003) & ~0x3))
+       extern int _start();
+#      define STACKBOTTOM ((ptr_t)(&_start))
+#   endif
+#   ifdef SCO
+#      define OS_TYPE "SCO"
+#      define DATASTART ((ptr_t)((((word) (&etext)) + 0x3fffff) \
+                                 & ~0x3fffff) \
+                                +((word)&etext & 0xfff))
+#      define STACKBOTTOM ((ptr_t) 0x7ffffffc)
+#   endif
+#   ifdef LINUX
+#      define OS_TYPE "LINUX"
+       extern int etext;
+#       define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff))
+#      define STACKBOTTOM ((ptr_t)0xc0000000)
+#   endif
+#   ifdef OS2
+#      define OS_TYPE "OS2"
+#      define DATASTART ((ptr_t)((((word) (&etext)) + 0x3fffff) \
+                                 & ~0x3fffff) \
+                                +((word)&etext & 0xfff))
+               /* STACKBOTTOM is handled specially in GC_init_inner.   */
+               /* OS2 actually has the right system call!              */
+#   endif
+# endif
+
+# ifdef NS32K
+#   define MACH_TYPE "NS32K"
+#   define ALIGNMENT 4
+    extern char **environ;
+#   define DATASTART ((ptr_t)(&environ))
+                             /* hideous kludge: environ is the first   */
+                             /* word in crt0.o, and delimits the start */
+                             /* of the data segment, no matter which   */
+                             /* ld options were passed through.        */
+#   define STACKBOTTOM ((ptr_t) 0xfffff000) /* for Encore */
+# endif
+
+# ifdef MIPS
+#   define MACH_TYPE "MIPS"
+#   define ALIGNMENT 4 /* Required by hardware */
+#   define DATASTART 0x10000000
+                             /* Could probably be slightly higher since */
+                             /* startup code allocates lots of junk     */
+#   define HEURISTIC2
+# endif
+
+# ifdef RS6000
+#   define MACH_TYPE "RS6000"
+#   define ALIGNMENT 4
+#   define DATASTART ((ptr_t)0x20000000)
+#   define STACKBOTTOM ((ptr_t)0x2ff80000)
+# endif
+
+# ifdef HP_PA
+#   define MACH_TYPE "HP_PA"
+#   define ALIGNMENT 4
+    extern int __data_start;
+#   define DATASTART ((ptr_t)(&__data_start))
+#   define HEURISTIC2
+#   define STACK_GROWS_UP
+# endif
+
+# ifndef STACK_GROWS_UP
+#   define STACK_GROWS_DOWN
+# endif
+
+# ifndef CPP_WORDSZ
+#   define CPP_WORDSZ 32
+# endif
+
+# ifndef OS_TYPE
+#   define OS_TYPE ""
+# endif
+
+# if CPP_WORDSZ != 32 && CPP_WORDSZ != 64
+   -> bad word size
+# endif
+
+# ifdef PCR
+#   undef STACKBOTTOM
+#   undef HEURISTIC1
+#   undef HEURISTIC2
+# endif
+
+# endif
index f8b27d22d284efd188c08b0b69c131a250e32905..6bb6198077ebe97c04738167688151c8c7da192d 100644 (file)
@@ -94,25 +94,25 @@ ptr_t p;
 {
     register oh * ohdr = (oh *)GC_base(p);
     
-    GC_err_printf("0x%lx (", (unsigned long)ohdr + sizeof(oh));
+    GC_err_printf1("0x%lx (", (unsigned long)ohdr + sizeof(oh));
     GC_err_puts(ohdr -> oh_string);
-    GC_err_printf(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
-                                    (unsigned long)(ohdr -> oh_sz));
+    GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
+                                     (unsigned long)(ohdr -> oh_sz));
 }
 void GC_print_smashed_obj(p, clobbered_addr)
 ptr_t p, clobbered_addr;
 {
     register oh * ohdr = (oh *)GC_base(p);
     
-    GC_err_printf("0x%lx in object at 0x%lx(", (unsigned long)clobbered_addr,
-                                              (unsigned long)p);
+    GC_err_printf2("0x%lx in object at 0x%lx(", (unsigned long)clobbered_addr,
+                                               (unsigned long)p);
     if (clobbered_addr <= (ptr_t)(&(ohdr -> oh_sz))) {
-        GC_err_printf("<smashed>, appr. sz = %ld)\n",
-                     BYTES_TO_WORDS(GC_size((ptr_t)ohdr)));
+        GC_err_printf1("<smashed>, appr. sz = %ld)\n",
+                      BYTES_TO_WORDS(GC_size((ptr_t)ohdr)));
     } else {
         GC_err_puts(ohdr -> oh_string);
-        GC_err_printf(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
-                                        (unsigned long)(ohdr -> oh_sz));
+        GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
+                                         (unsigned long)(ohdr -> oh_sz));
     }
 }
 
@@ -128,10 +128,10 @@ ptr_t p, clobbered_addr;
     extern_ptr_t result = GC_malloc(lb + DEBUG_BYTES);
     
     if (result == 0) {
-        GC_err_printf("GC_debug_malloc(%ld) returning NIL (",
-                     (unsigned long) lb);
+        GC_err_printf1("GC_debug_malloc(%ld) returning NIL (",
+                      (unsigned long) lb);
         GC_err_puts(s);
-        GC_err_printf(":%ld)\n", (unsigned long)i);
+        GC_err_printf1(":%ld)\n", (unsigned long)i);
         return(0);
     }
     if (!GC_debugging_started) {
@@ -153,10 +153,10 @@ ptr_t p, clobbered_addr;
     extern_ptr_t result = GC_malloc_atomic(lb + DEBUG_BYTES);
     
     if (result == 0) {
-        GC_err_printf("GC_debug_malloc_atomic(%ld) returning NIL (",
+        GC_err_printf1("GC_debug_malloc_atomic(%ld) returning NIL (",
                      (unsigned long) lb);
         GC_err_puts(s);
-        GC_err_printf(":%ld)\n", (unsigned long)i);
+        GC_err_printf1(":%ld)\n", (unsigned long)i);
         return(0);
     }
     if (!GC_debugging_started) {
@@ -176,17 +176,18 @@ ptr_t p, clobbered_addr;
     register ptr_t clobbered;
     
     if (base == 0) {
-        GC_err_printf("Attempt to free invalid pointer %lx\n",
-                     (unsigned long)p);
+        GC_err_printf1("Attempt to free invalid pointer %lx\n",
+                      (unsigned long)p);
         ABORT("free(invalid pointer)");
     }
     if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
-        GC_err_printf("GC_debug_free called on pointer %lx wo debugging info\n",
+        GC_err_printf1(
+                 "GC_debug_free called on pointer %lx wo debugging info\n",
                  (unsigned long)p);
     } else {
       clobbered = GC_check_annotated_obj((oh *)base);
       if (clobbered != 0) {
-        GC_err_printf("GC_debug_free: found smashed object at ");
+        GC_err_printf0("GC_debug_free: found smashed object at ");
         GC_print_smashed_obj(p, clobbered);
       }
     }
@@ -210,19 +211,19 @@ ptr_t p, clobbered_addr;
     register size_t old_sz;
     
     if (base == 0) {
-        GC_err_printf(
+        GC_err_printf1(
               "Attempt to free invalid pointer %lx\n", (unsigned long)p);
         ABORT("realloc(invalid pointer)");
     }
     if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
-        GC_err_printf(
+        GC_err_printf1(
                "GC_debug_realloc called on pointer %lx wo debugging info\n",
                (unsigned long)p);
         return(GC_realloc(p, lb));
     }
     clobbered = GC_check_annotated_obj((oh *)base);
     if (clobbered != 0) {
-        GC_err_printf("GC_debug_realloc: found smashed object at ");
+        GC_err_printf0("GC_debug_realloc: found smashed object at ");
         GC_print_smashed_obj(p, clobbered);
     }
     old_sz = ((oh *)base) -> oh_sz;
@@ -255,7 +256,7 @@ word dummy;
                ptr_t clobbered = GC_check_annotated_obj((oh *)p);
                
                if (clobbered != 0) {
-                   GC_err_printf(
+                   GC_err_printf0(
                        "GC_check_heap_block: found smashed object at ");
                    GC_print_smashed_obj((ptr_t)p, clobbered);
                }
@@ -305,4 +306,5 @@ struct closure {
     register struct closure * cl = (struct closure *) data;
     
     (*(cl -> cl_fn))((extern_ptr_t)((char *)obj + sizeof(oh)), cl -> cl_data);
-} 
\ No newline at end of file
+} 
+
index 80eda3a9b41c5f91de38955975e4078dd849d640..c5e111e18984f002662d2690c144ed6e9f2a2049 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1991,1992 by Xerox Corporation.  All rights reserved.
+ * Copyright (c) 1991-1993 by Xerox Corporation.  All rights reserved.
  *
  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  * Author: Bill Janssen
  * Modified by: Hans Boehm
  */
+
+/*
+ * This is incredibly OS specific code for tracking down data sections in
+ * dynamic libraries.  There appears to be no way of doing this quickly
+ * without groveling through undocumented data structures.  We would argue
+ * that this is a bug in the design of the dlopen interface.  THIS CODE
+ * MAY BREAK IN FUTURE OS RELEASES.  If this matters to you, don't hesitate
+ * to let your vendor know ...
+ */
 #include "gc_private.h"
 #ifdef DYNAMIC_LOADING
-#if !defined(M68K_SUN) && !defined(SPARC)
+#if !(defined(M68K) && defined(SUNOS)) && !defined(SPARC)
  --> We only know how to find data segments of dynamic libraries under SunOS 4.X
 #endif
-#include <sys/types.h>
+
 #include <stdio.h>
-#include <dlfcn.h>
-#include <link.h>
-#include <a.out.h>
-#include <stab.h>
+#if defined SUNOS5
+#   include <sys/elf.h>
+#   include <dlfcn.h>
+#   include <link.h>
+#else
+#   include <dlfcn.h>
+#   include <link.h>
+#   include <a.out.h>
+  /* struct link_map field overrides */
+#   define l_next      lm_next
+#   define l_addr      lm_addr
+#   define l_name      lm_name
+# endif
+
 
-extern struct link_dynamic _DYNAMIC;
+#ifdef SUNOS5
 
-void GC_setup_dynamic_loading()
+static struct link_map *
+GC_FirstDLOpenedLinkMap()
 {
-  struct link_map *lm;
-  struct exec *e;
-
-  if (&_DYNAMIC == 0) {
-      /* No dynamic libraries.  Furthermore, the rest of this would    */
-      /* segment fault.                                                        */
-      return;
-  }
-  for (lm = _DYNAMIC.ld_un.ld_1->ld_loaded;
-       lm != (struct link_map *) 0;  lm = lm->lm_next)
-    {
-      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)));
+    extern Elf32_Dyn _DYNAMIC;
+    Elf32_Dyn *dp;
+    struct r_debug *r;
+    static struct link_map * cachedResult = 0;
+
+    if( &_DYNAMIC == 0) {
+        return(0);
+    }
+    if( cachedResult == 0 ) {
+        int tag;
+        for( dp = ((Elf32_Dyn *)(&_DYNAMIC)); (tag = dp->d_tag) != 0; dp++ ) {
+            if( tag == DT_DEBUG ) {
+                struct link_map *lm
+                        = ((struct r_debug *)(dp->d_un.d_ptr))->r_map;
+                if( lm != 0 ) cachedResult = lm->l_next; /* might be NIL */
+                break;
+            }
+        }
     }
+    return cachedResult;
 }
 
-#ifdef DEFINE_DLOPEN
-char *GC_dlopen (path, mode) 
-     char *path;
-     int  mode;
+# endif
+
+# ifdef SUNOS4
+
+static struct link_map *
+GC_FirstDLOpenedLinkMap()
 {
-  char *etext, *end;
-  struct link_map *lm;
-  struct exec *e;
-  char *handle;
+    extern struct link_dynamic _DYNAMIC;
 
-  handle = dlopen(path, mode);
-  if (handle == NULL)
-    {
-      fprintf (stderr,
-              "GC_sun_dlopen:  dlopen(%s, %d) failed:  %s.\n",
-              path, mode, dlerror());
-      return (NULL);
+    if( &_DYNAMIC == 0) {
+        return(0);
     }
+    return(_DYNAMIC.ld_un.ld_1->ld_loaded);
+}
 
-  for (lm = _DYNAMIC.ld_un.ld_1->ld_loaded;
-       lm != (struct link_map *) 0;  lm = lm->lm_next)
-    {
-      if (strcmp(path, lm->lm_name) == 0)
-       {
-         e = (struct exec *) lm->lm_addr;
-         etext = (void *) (N_DATOFF(*e) + lm->lm_addr);
-         end = (void *) (N_BSSADDR(*e) + e->a_bss + lm->lm_addr);
-         GC_add_roots (etext, end);
-         break;
-       }
-    }
 
-  if (lm == (struct link_map *) 0)
+# endif
+
+/* Add dynamic library data sections to the root set.          */
+# if !defined(PCR) && defined(THREADS)
+       --> fix mutual exclusion with dlopen
+# endif
+void GC_register_dynamic_libraries()
+{
+  struct link_map *lm = GC_FirstDLOpenedLinkMap();
+  
+
+  for (lm = GC_FirstDLOpenedLinkMap();
+       lm != (struct link_map *) 0;  lm = lm->l_next)
     {
-      fprintf (stderr,
-             "GC_sun_dlopen:  couldn't find \"%s\" in _DYNAMIC link list.\n",
-             path);
-      dlclose(handle);
-      return (NULL);
+#     ifdef SUNOS4
+       struct exec *e;
+        
+        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)));
+#     endif
+#     ifdef SUNOS5
+       Elf32_Ehdr * e;
+        Elf32_Phdr * p;
+        unsigned long offset;
+        char * start;
+        register int i;
+        
+       e = (Elf32_Ehdr *) lm->l_addr;
+        p = ((Elf32_Phdr *)(((char *)(e)) + e->e_phoff));
+        offset = ((unsigned long)(lm->l_addr));
+        for( i = 0; i < e->e_phnum; ((i++),(p++)) ) {
+          switch( p->p_type ) {
+            case PT_LOAD:
+              {
+                if( !(p->p_flags & PF_W) ) break;
+                start = ((char *)(p->p_vaddr)) + offset;
+                GC_add_roots_inner(
+                  start,
+                  start + p->p_memsz
+                );
+              }
+              break;
+            default:
+              break;
+          }
+       }
+#     endif
     }
-  else
-    return (handle);
 }
-#endif
+
 #else
+void GC_register_dynamic_libraries(){}
+
 int GC_no_dynamic_loading;
 #endif
diff --git a/gc.h b/gc.h
index e090522d690e7ecc778415f8bdb0e5be8e0c700b..7814f46c7f8c14c2bad8bf2a2afb27e45230c0c6 100644 (file)
--- a/gc.h
+++ b/gc.h
@@ -44,7 +44,7 @@ extern int GC_dont_expand;
                        
 extern word GC_non_gc_bytes;
                        /* Bytes not considered candidates for collection. */
-
+                       /* Used only to control scheduling of collections. */
 
 extern word GC_free_space_divisor;
                        /* We try to make sure that we allocate at      */
index 2ef4450389820eef26538e4f559241e303cc9299..1e09370f409c456bf12581715c819f6430b3d761 100644 (file)
@@ -10,7 +10,6 @@
  * provided the above notices are retained on all copies.
  */
  
-/* Machine specific parts contributed by various people.  See README file. */
 
 # ifndef GC_PRIVATE_H
 # define GC_PRIVATE_H
 #   include "gc.h"
 # endif
 
+# ifndef CONFIG_H
+#   include "config.h"
+# endif
+
 # ifndef HEADERS_H
 #   include "gc_headers.h"
 # endif
@@ -41,6 +44,10 @@ typedef char * ptr_t;        /* A generic pointer to which we can add        */
     typedef char * extern_ptr_t;
 #endif
 
+# ifndef OS2
+#   include <sys/types.h>
+# endif
+
 /*********************************/
 /*                               */
 /* Definitions for conservative  */
@@ -54,113 +61,6 @@ typedef char * ptr_t;       /* A generic pointer to which we can add        */
 /*                               */
 /*********************************/
 
-# if defined(sun) && defined(mc68000)
-#    define M68K_SUN
-#    define mach_type_known
-# endif
-# if defined(hp9000s300)
-#    define M68K_HP
-#    define mach_type_known
-# endif
-# if defined(vax)
-#    define VAX
-#    ifdef ultrix
-#      define ULTRIX
-#    else
-#      define BSD
-#    endif
-#    define mach_type_known
-# endif
-# if defined(mips)
-#    define MIPS
-#    ifdef ultrix
-#      define ULTRIX
-#    else
-#      define RISCOS
-#    endif
-#    define mach_type_known
-# endif
-# if defined(sequent) && defined(i386)
-#    define I386
-#    define SEQUENT
-#    define mach_type_known
-# endif
-# if defined(__OS2__) && defined(__32BIT__)
-#    define I386
-#    define OS2
-#    define mach_type_known
-# endif
-# if defined(ibm032)
-#   define RT
-#   define mach_type_known
-# endif
-# if defined(sun) && defined(sparc)
-#   define SPARC
-#   define mach_type_known
-# endif
-# if defined(_IBMR2)
-#   define IBMRS6000
-#   define mach_type_known
-# endif
-# if defined(SCO)
-#   define I386
-#   define SCO
-#   define mach_type_known
-/*     --> incompletely implemented */
-# endif
-# if defined(_AUX_SOURCE)
-#   define M68K_SYSV
-#   define mach_type_known
-# endif
-# if defined(_PA_RISC1_0) || defined(_PA_RISC1_1)
-#   define HP_PA
-#   define mach_type_known
-# endif
-# if defined(linux) && defined(i386)
-#    define I386
-#    define LINUX
-#    define mach_type_known
-# endif
-
-# ifndef OS2
-#   include <sys/types.h>
-# endif
-
-/* Feel free to add more clauses here */
-
-/* Or manually define the machine type here.  A machine type is        */
-/* characterized by the architecture and assembler syntax.  Some       */
-/* machine types are further subdivided by OS.  In that case, we use   */
-/* the macros ULTRIX, RISCOS, and BSD to distinguish.                  */
-/* Note that SGI IRIX is treated identically to RISCOS.                        */
-/* The distinction in these cases is usually the stack starting address */
-# ifndef mach_type_known
-#   define M68K_SUN /* Guess "Sun" */
-                   /* Mapping is: M68K_SUN   ==> Sun3 assembler        */
-                   /*             M68K_HP    ==> HP9000/300            */
-                   /*             M68K_SYSV  ==> A/UX, maybe others    */
-                   /*             I386       ==> Intel 386             */
-                   /*              (SEQUENT, OS2, SCO, LINUX variants) */
-                   /*               SCO is incomplete.                 */
-                    /*             NS32K      ==> Encore Multimax      */
-                    /*             MIPS       ==> R2000 or R3000       */
-                    /*                 (RISCOS, ULTRIX variants)       */
-                    /*            VAX        ==> DEC VAX               */
-                    /*                 (BSD, ULTRIX variants)          */
-                    /*            RS6000     ==> IBM RS/6000 AIX3.1    */
-                    /*            RT         ==> IBM PC/RT             */
-                    /*            HP_PA      ==> HP9000/700 & /800     */
-                    /*                           HP/UX                 */
-                   /*             SPARC      ==> SPARC under SunOS     */
-# endif
-
-# ifdef SPARC
-  /* Test for SunOS 5.x */
-#   include <errno.h>
-#   ifdef ECHRNG
-#     define SUNOS5
-#   endif
-# endif
 
 #define ALL_INTERIOR_POINTERS
                    /* Forces all pointers into the interior of an      */
@@ -231,9 +131,11 @@ typedef char * ptr_t;      /* A generic pointer to which we can add        */
                         /* apparently required by SPARC architecture. */
 #endif
 
-#if defined(SPARC) || defined(M68K_SUN)
-# if !defined(PCR) && !defined(SUNOS5)
+#if defined(SPARC) || defined(M68K) && defined(SUNOS)
+# if !defined(PCR)
 #   define DYNAMIC_LOADING /* Search dynamic libraries for roots.      */
+# else
+    /* PCR handles any dynamic loading whether with dlopen or otherwise */
 # endif
 #endif
 
@@ -253,261 +155,6 @@ typedef char * ptr_t;     /* A generic pointer to which we can add        */
 #   define MERGE_SIZES
 # endif
 
-#if defined(M68K_SUN) || defined(M68K_SYSV)
-#  define ALIGNMENT   2   /* Pointers are aligned on 2 byte boundaries */
-                         /* by the Sun C compiler.                    */
-#else
-#  ifdef VAX
-#    define ALIGNMENT 4   /* Pointers are longword aligned by 4.2 C compiler */
-#  else
-#    ifdef RT
-#      define ALIGNMENT 4
-#    else
-#      ifdef SPARC
-#        define ALIGNMENT 4
-#      else
-#        ifdef I386
-#           define ALIGNMENT 4      /* 32-bit compilers align pointers */
-#        else
-#          ifdef NS32K
-#            define ALIGNMENT 4     /* Pointers are aligned on NS32K */
-#          else
-#            ifdef MIPS
-#              define ALIGNMENT 4   /* MIPS hardware requires pointer */
-                                   /* alignment                      */
-#            else
-#              ifdef M68K_HP
-#                define ALIGNMENT 2 /* 2 byte alignment inside struct/union, */
-                                   /* 4 bytes elsewhere                     */
-#              else
-#               ifdef IBMRS6000
-#                 define ALIGNMENT 4
-#               else
-#                 ifdef HP_PA
-#                   define ALIGNMENT 4
-#                 else
-                    --> specify alignment <--
-#                 endif
-#               endif
-#              endif
-#            endif
-#          endif
-#        endif
-#      endif
-#    endif
-#  endif
-# endif
-
-/*
- * STACKBOTTOM is the cool end of the stack, which is usually the
- * highest address in the stack.
- * Under PCR or OS/2, we have other ways of finding thread stacks.
- * For each machine, the following should:
- * 1) define STACK_GROWS_UP if the stack grows toward higher addresses, and
- * 2) define exactly one of
- *     STACKBOTTOM (should be defined to be an expression)
- *     HEURISTIC1
- *     HEURISTIC2
- * If either of the last two macros are defined, then STACKBOTTOM is computed
- * during collector startup using one of the following two heuristics:
- * HEURISTIC1:  Take an address inside GC_init's frame, and round it up to
- *             the next multiple of 16 MB.
- * HEURISTIC2:  Take an address inside GC_init's frame, increment it repeatedly
- *             in small steps (decrement if STACK_GROWS_UP), and read the value
- *             at each location.  Remember the value when the first
- *             Segmentation violation or Bus error is signalled.  Round that
- *             to the nearest plausible page boundary, and use that instead
- *             of STACKBOTTOM.
- *
- * If no expression for STACKBOTTOM can be found, and neither of the above
- * heuristics are usable, the collector can still be used with all of the above
- * undefined, provided one of the following is done:
- * 1) GC_mark_roots can be changed to somehow mark from the correct stack(s)
- *    without reference to STACKBOTTOM.  This is appropriate for use in
- *    conjunction with thread packages, since there will be multiple stacks.
- *    (Allocating thread stacks in the heap, and treating them as ordinary
- *    heap data objects is also possible as a last resort.  However, this is
- *    likely to introduce significant amounts of excess storage retention
- *    unless the dead parts of the thread stacks are periodically cleared.)
- * 2) Client code may set GC_stackbottom before calling any GC_ routines.
- *    If the author of the client code controls the main program, this is
- *    easily accomplished by introducing a new main program, setting
- *    GC_stackbottom to the address of a local variable, and then calling
- *    the original main program.  The new main program would read something
- *    like:
- *
- *             # include "gc_private.h"
- *
- *             main(argc, argv, envp)
- *             int argc;
- *             char **argv, **envp;
- *             {
- *                 int dummy;
- *
- *                 GC_stackbottom = (ptr_t)(&dummy);
- *                 return(real_main(argc, argv, envp));
- *             }
- */
-#ifndef PCR
-# ifdef RT
-#   define STACKBOTTOM ((ptr_t) 0x1fffd800)
-# else
-#   ifdef I386
-#     ifdef SEQUENT
-#       define STACKBOTTOM ((ptr_t) 0x3ffff000)  /* For Sequent */
-#     else
-#      ifdef SCO
-#        define STACKBOTTOM ((ptr_t) 0x7ffffffc)
-#      else
-#        ifdef LINUX
-#          define STACKBOTTOM ((ptr_t)0xc0000000)
-#        else
-#          ifdef OS2
-               /* This is handled specially in GC_init_inner.  */
-               /* OS2 actually has the right system call!      */
-#          else
-                --> Your OS isnt supported yet
-#          endif
-#        endif
-#      endif
-#     endif
-#   else
-#     ifdef NS32K
-#       define STACKBOTTOM ((ptr_t) 0xfffff000) /* for Encore */
-#     else
-#       ifdef M68K_SYSV
-#        define STACKBOTTOM ((ptr_t)0xFFFFFFFE)
-                       /* The stack starts at the top of memory, but   */
-                       /* 0x0 cannot be used as setjump_test complains */
-                       /* that the stack direction is incorrect.  Two  */
-                       /* bytes down from 0x0 should be safe enough.   */
-                       /*              --Parag                         */
-#       else
-#         ifdef M68K_HP
-#           define STACKBOTTOM ((ptr_t) 0xffeffffc)
-                             /* empirically determined.  seems to work. */
-#        else
-#          ifdef IBMRS6000
-#            define STACKBOTTOM ((ptr_t) 0x2ff80000)
-#           else
-#            if defined(VAX) && defined(ULTRIX)
-#              ifdef ULTRIX
-#                define STACKBOTTOM ((ptr_t) 0x7fffc800)
-#              else
-#                define HEURISTIC1
-                       /* HEURISTIC2 may be OK, but it's hard to test. */
-#              endif
-#            else
-                 /* Sun systems, HP PA systems, and DEC MIPS systems have  */
-                 /* STACKBOTTOM values that differ between machines that   */
-                 /* are intended to be object code compatible.             */
-#                  if defined(SPARC) || defined(M68K_SUN)
-#                    define HEURISTIC1
-#                  else
-#                    ifdef HP_PA
-#                      define STACK_GROWS_UP
-#                    endif
-#                    define HEURISTIC2
-#                  endif
-#            endif
-#          endif
-#         endif
-#       endif
-#     endif
-#   endif
-# endif
-#endif /* PCR */
-
-
-# ifndef STACK_GROWS_UP
-#   define STACK_GROWS_DOWN
-# endif
-
-/* Start of data segment for each of the above systems.  Note that the */
-/* default case works only for contiguous text and data, such as on a  */
-/* Vax.                                                                */
-# ifdef M68K_SUN
-    extern char etext;
-#   define DATASTART ((ptr_t)((((word) (&etext)) + 0x1ffff) & ~0x1ffff))
-# else
-#   ifdef RT
-#     define DATASTART ((ptr_t) 0x10000000)
-#   else
-#     if (defined(I386) && (defined(SEQUENT)||defined(LINUX))) || defined(SPARC)
-       extern int etext;
-#      ifdef SUNOS5
-#         define DATASTART ((ptr_t)((((word) (&etext)) + 0x10003) & ~0x3))
-               /* Experimentally determined.                   */
-               /* Inconsistent with man a.out, which appears   */
-               /* to be wrong.                                 */
-#      else
-#         define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff))
-               /* On very old SPARCs this is too conservative. */
-#      endif
-#     else
-#       ifdef NS32K
-         extern char **environ;
-#         define DATASTART ((ptr_t)(&environ))
-                             /* hideous kludge: environ is the first   */
-                             /* word in crt0.o, and delimits the start */
-                             /* of the data segment, no matter which   */
-                             /* ld options were passed through.        */
-#       else
-#         ifdef MIPS
-#           define DATASTART 0x10000000
-                             /* Could probably be slightly higher since */
-                             /* startup code allocates lots of junk     */
-#         else
-#           ifdef M68K_HP
-             extern char etext;
-#             define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff))
-#          else
-#             ifdef IBMRS6000
-#              define DATASTART ((ptr_t)0x20000000)
-#            else
-#              ifdef I386
-#                ifdef SCO
-#                  define DATASTART ((ptr_t)((((word) (&etext)) + 0x3fffff) \
-                                           & ~0x3fffff) \
-                                           +((word)&etext & 0xfff))
-#                else
-#                  ifdef OS2
-#                    define DATASTART ((ptr_t)((((word) (&etext)) + 0x3fffff) \
-                                           & ~0x3fffff) \
-                                           +((word)&etext & 0xfff))
-#                  else
-                       --> Your OS not supported yet
-#                  endif
-#                endif
-#              else
-#                ifdef M68K_SYSV
-       /* This only works for shared-text binaries with magic number 0413.
-          The other sorts of SysV binaries put the data at the end of the text,
-          in which case the default of &etext would work.  Unfortunately,
-          handling both would require having the magic-number available.
-                               -- Parag
-          */
-                   extern etext;
-#                  define DATASTART ((ptr_t)((((word) (&etext)) + 0x3fffff) \
-                                             & ~0x3fffff) \
-                                             +((word)&etext & 0x1fff))    
-#                 else
-#                  ifdef HP_PA
-                       extern int __data_start;
-#                      define DATASTART ((ptr_t)(&__data_start))
-#                  else
-                       extern char etext;
-#                      define DATASTART ((ptr_t)(&etext))
-#                  endif
-#                endif
-#              endif
-#            endif
-#           endif
-#         endif
-#       endif
-#     endif
-#   endif
-# endif
 
 # define HINCR 16          /* Initial heap increment, in blocks of 4K        */
 # define MAXHINCR 512      /* Maximum heap increment, in blocks              */
@@ -549,7 +196,17 @@ typedef char * ptr_t;      /* A generic pointer to which we can add        */
                (1000.0*(double)((a)-(b))/(double)CLOCKS_PER_SEC))
 
 /* We use bzero and bcopy internally.  They may not be available.      */
-# ifdef OS2
+# if defined(SPARC) && defined(SUNOS4)
+#   define BCOPY_EXISTS
+# endif
+# if defined(M68K) && defined(SUNOS)
+#   define BCOPY_EXISTS
+# endif
+# if defined(VAX)
+#   define BCOPY_EXISTS
+# endif
+
+# ifndef BCOPY_EXISTS
 #   include <string.h>
 #   define bcopy(x,y,n) memcpy(y,x,n)
 #   define bzero(x,n)  memset(x, 0, n)
@@ -674,7 +331,7 @@ typedef char * ptr_t;       /* A generic pointer to which we can add        */
 # endif
 
 /* Print warning message, e.g. almost out of memory.   */
-# define WARN(s) GC_printf(s)
+# define WARN(s) GC_printf0(s)
 
 /*********************************/
 /*                               */
@@ -682,22 +339,25 @@ typedef char * ptr_t;     /* A generic pointer to which we can add        */
 /*                               */
 /*********************************/
 
-#define WORDS_TO_BYTES(x)   ((x)<<2)
-#define BYTES_TO_WORDS(x)   ((x)>>2)
+#if CPP_WORDSZ == 32
+#  define WORDS_TO_BYTES(x)   ((x)<<2)
+#  define BYTES_TO_WORDS(x)   ((x)>>2)
+#  define LOGWL               ((word)5)    /* log[2] of CPP_WORDSZ */
+#  define modWORDSZ(n) ((n) & 0x1f)          /* n mod size of word         */
+#endif
+
+#if CPP_WORDSZ == 64
+#  define WORDS_TO_BYTES(x)   ((x)<<3)
+#  define BYTES_TO_WORDS(x)   ((x)>>3)
+#  define LOGWL               ((word)6)    /* log[2] of CPP_WORDSZ */
+#  define modWORDSZ(n) ((n) & 0x3f)          /* n mod size of word         */
+#endif
 
-#define CPP_WORDSZ              32
 #define WORDSZ ((word)CPP_WORDSZ)
-#define LOGWL               ((word)5)    /* log[2] of above */
+#define SIGNB  ((word)1 << (WORDSZ-1))
 #define BYTES_PER_WORD      ((word)(sizeof (word)))
-#define ONES                0xffffffff
-#define MSBYTE              0xff000000
-#define SIGNB               0x80000000
-#define MAXSHORT            0x7fff
-#define modHALFWORDSZ(n) ((n) & 0xf)    /* mod n by size of half word    */
-#define divHALFWORDSZ(n) ((n) >> 4)    /* divide n by size of half word */
-#define modWORDSZ(n) ((n) & 0x1f)       /* mod n by size of word         */
-#define divWORDSZ(n) ((n) >> 5)         /* divide n by size of word      */
-#define twice(n) ((n) << 1)             /* double n                      */
+#define ONES                ((word)(-1))
+#define divWORDSZ(n) ((n) >> LOGWL)       /* divide n by size of word      */
 
 /*********************/
 /*                   */
@@ -841,6 +501,13 @@ struct _GC_arrays {
 # endif
   word _words_allocd;
        /* Number of words allocated during this collection cycle */
+  word _non_gc_bytes_at_gc;
+       /* Number of explicitly managed bytes of storage        */
+       /* at last collection.                                  */
+  word _mem_freed;
+       /* Number of explicitly deallocated words of memory     */
+       /* since last collection.                               */
+       
   ptr_t _objfreelist[MAXOBJSZ+1];
                          /* free list for objects */
 # ifdef MERGE_SIZES
@@ -913,6 +580,8 @@ extern struct _GC_arrays GC_arrays;
 # define GC_last_heap_addr GC_arrays._last_heap_addr
 # define GC_prev_heap_addr GC_arrays._prev_heap_addr
 # define GC_words_allocd GC_arrays._words_allocd
+# define GC_non_gc_bytes_at_gc GC_arrays._non_gc_bytes_at_gc
+# define GC_mem_freed GC_arrays._mem_freed
 # define GC_heapsize GC_arrays._heapsize
 # define GC_words_allocd_before_gc GC_arrays._words_allocd_before_gc
 # ifdef GATHERSTATS
@@ -1031,7 +700,10 @@ void GC_mark_all_stack(/*b,t*/);    /* Mark from everything in a range,       */
 void GC_remark();      /* Mark from all marked objects.  Used  */
                        /* only if we had to drop something.    */
 void GC_tl_mark(/*p*/);        /* Mark from a single root.             */
+void GC_clear_hdr_marks(/* hhdr */);  /* Clear the mark bits in a header */
 void GC_add_roots_inner();
+void GC_register_dynamic_libraries();
+               /* Add dynamic library data sections to the root set. */
 
 /* Machine dependent startup routines */
 ptr_t GC_get_stack_base();
@@ -1099,8 +771,16 @@ void GC_continue_reclaim(/*size, kind*/);
                                /* kind, as long as possible, and       */
                                /* as long as the corr. free list is    */
                                /* empty.                               */
-void GC_gcollect_inner();      /* Collect; caller must have acquired   */
+bool GC_gcollect_inner(/* force */);
+                               /* Collect; caller must have acquired   */
                                /* lock and disabled signals.           */
+                               /* FALSE return indicates nothing was   */
+                               /* done due to insufficient allocation. */
+void GC_collect_or_expand(/* needed_blocks */);
+                               /* Collect or expand heap in an attempt */
+                               /* make the indicated number of free    */
+                               /* blocks available.  Should be called  */
+                               /* until it succeeds or exits.          */
 void GC_init();                        /* Initialize collector.                */
 
 ptr_t GC_generic_malloc(/* bytes, kind */);
@@ -1147,16 +827,41 @@ void GC_check_heap();
                        /* debugging info are intact.  Print            */
                        /* descriptions of any that are not.            */
 
-void GC_printf(/* format, ... */);
+void GC_printf(/* format, a, b, c, d, e, f */);
                        /* A version of printf that doesn't allocate,   */
                        /* is restricted to long arguments, and         */
                        /* (unfortunately) doesn't use varargs for      */
                        /* portability.  Restricted to 6 args and       */
                        /* 1K total output length.                      */
                        /* (We use sprintf.  Hopefully that doesn't     */
-                       /* allocate for long arguments.                 */
-void GC_err_printf(/* format, ... */);
+                       /* allocate for long arguments.)                */
+# define GC_printf0(f) GC_printf(f, 0l, 0l, 0l, 0l, 0l, 0l)
+# define GC_printf1(f,a) GC_printf(f, (long)a, 0l, 0l, 0l, 0l, 0l)
+# define GC_printf2(f,a,b) GC_printf(f, (long)a, (long)b, 0l, 0l, 0l, 0l)
+# define GC_printf3(f,a,b,c) GC_printf(f, (long)a, (long)b, (long)c, 0l, 0l, 0l)
+# define GC_printf4(f,a,b,c,d) GC_printf(f, (long)a, (long)b, (long)c, \
+                                           (long)d, 0l, 0l)
+# define GC_printf5(f,a,b,c,d,e) GC_printf(f, (long)a, (long)b, (long)c, \
+                                             (long)d, (long)e, 0l)
+# define GC_printf6(f,a,b,c,d,e,g) GC_printf(f, (long)a, (long)b, (long)c, \
+                                               (long)d, (long)e, (long)g)
+
+void GC_err_printf(/* format, a, b, c, d, e, f */);
+# define GC_err_printf0(f) GC_err_puts(f)
+# define GC_err_printf1(f,a) GC_err_printf(f, (long)a, 0l, 0l, 0l, 0l, 0l)
+# define GC_err_printf2(f,a,b) GC_err_printf(f, (long)a, (long)b, 0l, 0l, 0l, 0l)
+# define GC_err_printf3(f,a,b,c) GC_err_printf(f, (long)a, (long)b, (long)c, \
+                                                 0l, 0l, 0l)
+# define GC_err_printf4(f,a,b,c,d) GC_err_printf(f, (long)a, (long)b, \
+                                                   (long)c, (long)d, 0l, 0l)
+# define GC_err_printf5(f,a,b,c,d,e) GC_err_printf(f, (long)a, (long)b, \
+                                                     (long)c, (long)d, \
+                                                     (long)e, 0l)
+# define GC_err_printf6(f,a,b,c,d,e,g) GC_err_printf(f, (long)a, (long)b, \
+                                                       (long)c, (long)d, \
+                                                       (long)e, (long)g)
                        /* Ditto, writes to stderr.                     */
+                       
 void GC_err_puts(/* char *s */);
                        /* Write s to stderr, don't buffer, don't add   */
                        /* newlines, don't ...                          */
index 3873ee8f75f532de344bcb90a1273ef15b604cc8..15fda4153a90f937c9b6f5f9517ac7e0157d7c9a 100644 (file)
--- a/headers.c
+++ b/headers.c
@@ -73,10 +73,10 @@ register word bytes;
          
         scratch_free_ptr = (char *)GET_MEM(bytes_to_get);
         if (scratch_free_ptr == 0) {
-            GC_printf("Out of memory - trying to allocate less\n");
+            GC_err_printf0("Out of memory - trying to allocate less\n");
             result = (char *)GET_MEM(bytes);
             if (result == 0) {
-                GC_printf("Out of memory - giving up\n");
+                GC_err_printf0("Out of memory - giving up\n");
             } else {
                 scratch_free_ptr -= bytes;
                 return(result);
diff --git a/if_mach.c b/if_mach.c
new file mode 100644 (file)
index 0000000..7359a4f
--- /dev/null
+++ b/if_mach.c
@@ -0,0 +1,22 @@
+/* Conditionally execute a command based on machine and OS from config.h */
+# include "config.h"
+# include <stdio.h>
+
+int main(argc, argv, envp)
+int argc;
+char ** argv;
+char ** envp;
+{
+    if (argc < 4) goto Usage;
+    if (strcmp(MACH_TYPE, argv[1]) != 0) return(0);
+    if (strcmp(OS_TYPE, "") != 0 && strcmp(argv[2], "") != 0
+        && strcmp(OS_TYPE, argv[2]) != 0) return(0);
+    execvp(argv[3], argv+3);
+    
+Usage:
+    fprintf(stderr, "Usage: %s mach_type os_type command\n", argv[0]);
+    fprintf(stderr, "Currently mach_type = %s, os_type = %s\n",
+           MACH_TYPE, OS_TYPE);
+    return(1);
+}
+
diff --git a/if_not_there.c b/if_not_there.c
new file mode 100644 (file)
index 0000000..806eed6
--- /dev/null
@@ -0,0 +1,24 @@
+/* Conditionally execute a command based if the file argv[1] doesn't exist */
+/* Except for execvp, we stick to ANSI C.                                 */
+# include "config.h"
+# include <stdio.h>
+
+int main(argc, argv, envp)
+int argc;
+char ** argv;
+char ** envp;
+{
+    FILE * f;
+    if (argc < 3) goto Usage;
+    if ((f = fopen(argv[1], "rb")) != 0
+        || (f = fopen(argv[1], "r")) != 0) {
+        fclose(f);
+        return(0);
+    }
+    execvp(argv[2], argv+2);
+    
+Usage:
+    fprintf(stderr, "Usage: %s file_name command\n", argv[0]);
+    return(1);
+}
+
index 670579d80545f5248f7efa358c3b4725207e7b65..8e3ac078170e99e73d897b871f072b28f422aeea 100644 (file)
@@ -27,8 +27,8 @@ GC_mark_regs()
          asm("pushl r7");      asm("calls $1,_GC_tl_mark");
          asm("pushl r6");      asm("calls $1,_GC_tl_mark");
 #       endif
-#       ifdef M68K_SUN
-       /*  M68K_SUN - could be replaced by generic code */
+#       if defined(M68K) && defined(SUNOS)
+       /*  M68K SUNOS - could be replaced by generic code */
          /* a0, a1 and d1 are caller save          */
          /*  and therefore are on stack or dead.   */
        
@@ -50,8 +50,8 @@ GC_mark_regs()
          asm("addqw #0x4,sp");         /* put stack back where it was  */
 #       endif
 
-#       ifdef M68K_HP
-       /*  M68K_HP - could be replaced by generic code */
+#       if defined(M68K) && defined(HP)
+       /*  M68K HP - could be replaced by generic code */
          /* a0, a1 and d1 are caller save.  */
        
          asm("subq.w &0x4,%sp");       /* allocate word on top of stack */
@@ -70,9 +70,9 @@ GC_mark_regs()
          asm("mov.l %d7,(%sp)"); asm("jsr _GC_tl_mark");
 
          asm("addq.w &0x4,%sp");       /* put stack back where it was  */
-#       endif /* M68K_HP */
+#       endif /* M68K HP */
 
-#       if defined(I386) && !defined(OS2)
+#       if defined(I386) && !defined(OS2) && !defined(SUNOS5)
        /* I386 code, generic code does not appear to work */
        /* It does appear to work under OS2, and asms dont */
          asm("pushl %eax");  asm("call _GC_tl_mark"); asm("addl $4,%esp");
@@ -83,6 +83,17 @@ GC_mark_regs()
          asm("pushl %ebx");  asm("call _GC_tl_mark"); asm("addl $4,%esp");
 #       endif
 
+#       if defined(I386) && defined(SUNOS5)
+       /* I386 code, generic code does not appear to work */
+       /* It does appear to work under OS2, and asms dont */
+         asm("pushl %eax");  asm("call GC_tl_mark"); asm("addl $4,%esp");
+         asm("pushl %ecx");  asm("call GC_tl_mark"); asm("addl $4,%esp");
+         asm("pushl %edx");  asm("call GC_tl_mark"); asm("addl $4,%esp");
+         asm("pushl %esi");  asm("call GC_tl_mark"); asm("addl $4,%esp");
+         asm("pushl %edi");  asm("call GC_tl_mark"); asm("addl $4,%esp");
+         asm("pushl %ebx");  asm("call GC_tl_mark"); asm("addl $4,%esp");
+#       endif
+
 #       ifdef NS32K
          asm ("movd r3, tos"); asm ("bsr ?_GC_tl_mark"); asm ("adjspb $-4");
          asm ("movd r4, tos"); asm ("bsr ?_GC_tl_mark"); asm ("adjspb $-4");
@@ -111,7 +122,7 @@ GC_mark_regs()
            asm("cas r11, r15, r0"); GC_tl_mark(TMP_SP);
 #       endif
 
-#       ifdef M68K_SYSV
+#       if defined(M68K) && defined(SYSV)
        /*  Once again similar to SUN and HP, though setjmp appears to work.
                --Parag
         */
@@ -150,7 +161,7 @@ GC_mark_regs()
   
          asm("addq.w &0x4,%sp");       /* put stack back where it was  */
 #        endif /* !__GNUC__ */
-#       endif /* M68K_SYSV */
+#       endif /* M68K/SYSV */
 
 
 #     if defined(HP_PA) || (defined(I386) && defined(OS2))
@@ -174,9 +185,13 @@ GC_mark_regs()
 #     endif
 
       /* other machines... */
-#       if !(defined M68K_SUN) && !defined(M68K_HP) && !(defined VAX) && !(defined RT) && !(defined SPARC) && !(defined I386) &&!(defined NS32K) &&!defined(HP_PA) && !defined(M68K_SYSV)
+#       if !(defined M68K) && !(defined VAX) && !(defined RT) 
+#      if !(defined SPARC) && !(defined I386) &&!(defined NS32K)
+#      if !defined(HP_PA)
            --> bad news <--
 #       endif
+#       endif
+#       endif
 }
 
 /* On register window machines, we need a way to force registers into  */
diff --git a/mark.c b/mark.c
index aab8aa440fdca3d2a9a82bc10bf95a353dff15d6..96935fb4fc5678c18699bd96ffa3bdf3d98ee9a9 100644 (file)
--- a/mark.c
+++ b/mark.c
@@ -31,8 +31,7 @@
 /*
  * Limits of stack for GC_mark routine.  Set by caller to GC_mark.
  * All items between GC_mark_stack_top and GC_mark_stack_bottom-1 still need
- * to be marked.  All items on the stack satisfy quicktest.  They do
- * not necessarily reference real objects.
+ * to be marked.
  */
  
 mse * GC_mark_stack;
@@ -88,9 +87,7 @@ register mse * msp, * msl;
 /*
  * Mark all objects pointed to by the regions described by
  * mark stack entries between GC_mark_stack and GC_mark_stack_top,
- * inclusive.  We assume and preserve the invariant
- * that everything on the mark stack points into a hblk that has an
- * allocated header.  Assumes the upper limit of a mark stack entry
+ * inclusive.  Assumes the upper limit of a mark stack entry
  * is never 0.
  */
 void GC_mark()
@@ -206,8 +203,8 @@ word n;
         }
     } else {
         if (new_stack == 0) {
-            GC_printf("No space for mark stack\n");
-            exit(1);
+            GC_err_printf0("No space for mark stack\n");
+            EXIT();
         }
         GC_mark_stack = new_stack;
         GC_mark_stack_size = n;
@@ -229,8 +226,8 @@ void GC_mark_reliable()
     while (dropped_some) {
         dropped_some = FALSE;
 #      ifdef PRINTSTATS
-           GC_printf("Mark stack overflow; current size = %lu entries\n",
-                     GC_mark_stack_size);
+           GC_printf1("Mark stack overflow; current size = %lu entries\n",
+                      GC_mark_stack_size);
 #      endif      
         alloc_mark_stack(2*GC_mark_stack_size);
         GC_remark();
@@ -332,7 +329,7 @@ word dummy;
     register word * lim;
     register mse * GC_mark_stack_top_reg = GC_mark_stack_top;
     
-    if (sz < 0) return;
+    if (hhdr -> hb_obj_kind == PTRFREE) return;
     if (sz > MAXOBJSZ) {
         lim = (word *)(h + 1);
     } else {
@@ -348,6 +345,7 @@ word dummy;
              GC_mark_stack_top_reg -> mse_end = p + sz;
          }
     }
+    GC_mark_stack_top = GC_mark_stack_top_reg;
     GC_mark();   
 }
 
index 5cc55649af4e4c1e8d9af2bdc65cdd2ac11b6da9..132d59e3d11f05df6181c8db16946df3d1cd6b6b 100644 (file)
@@ -1,20 +1,77 @@
 # include <stdio.h>
 # include "gc_private.h"
-# define MAX_ROOT_SETS 50
+
 # ifdef PCR
+#   define MAX_ROOT_SETS 1024
 #   include "pcr/il/PCR_IL.h"
 #   include "pcr/th/PCR_ThCtl.h"
 #   include "pcr/mm/PCR_MM.h"
+# else
+#   define MAX_ROOT_SETS 64
 # endif
 
+/* Data structure for list of root sets.                               */
+/* We keep a hash table, so that we can filter out duplicate additions.        */
 struct roots {
        ptr_t r_start;
        ptr_t r_end;
+       struct roots * r_next;
 };
 
 static struct roots static_roots[MAX_ROOT_SETS];
+
 static n_root_sets = 0;
 
+       /* static_roots[0..n_root_sets) contains the valid root sets. */
+
+#define RT_SIZE 64  /* Power of 2, may be != MAX_ROOT_SETS */
+#define LOG_RT_SIZE 6
+
+static struct roots * root_index[RT_SIZE];
+       /* Hash table header.  Used only to check whether a range is    */
+       /* already present.                                             */
+
+static int rt_hash(addr)
+char * addr;
+{
+    word result = (word) addr;
+#   if CPP_WORDSZ > 8*LOG_RT_SIZE
+       result ^= result >> 8*LOG_RT_SIZE;
+#   endif
+#   if CPP_WORDSZ > 4*LOG_RT_SIZE
+       result ^= result >> 4*LOG_RT_SIZE;
+#   endif
+    result ^= result >> 2*LOG_RT_SIZE;
+    result ^= result >> LOG_RT_SIZE;
+    result &= (RT_SIZE-1);
+    return(result);
+}
+
+/* Is a range starting at addr already in the table? */
+static bool roots_present(b, e)
+char *b, *e;
+{
+    register int h = rt_hash(b);
+    register struct roots *p = root_index[h];
+    
+    while (p != 0) {
+        if (p -> r_start == (ptr_t)b && p -> r_end >= (ptr_t)e) return(TRUE);
+        p = p -> r_next;
+    }
+    return(FALSE);
+}
+
+/* Add the given root structure to the index. */
+static void add_roots_to_index(p)
+struct roots *p;
+{
+    register int h = rt_hash(p -> r_start);
+    
+    p -> r_next = root_index[h];
+    root_index[h] = p;
+}
+
+
 word GC_root_size = 0;
 
 void GC_add_roots(b, e)
@@ -30,7 +87,10 @@ char * b; char * e;
 }
 
 
-
+/* Add [b,e) to the root set.  Adding the same interval a second time  */
+/* 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)
 char * b; char * e;
 {
@@ -47,11 +107,14 @@ char * b; char * e;
     } else if ((ptr_t)b < endGC_arrays && (ptr_t)e > endGC_arrays) {
         b = (char *)endGC_arrays;
     }
+    if (roots_present(b,e)) return;
     if (n_root_sets == MAX_ROOT_SETS) {
         ABORT("Too many root sets\n");
     }
     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_next = 0;
+    add_roots_to_index(static_roots + n_root_sets);
     GC_root_size += (ptr_t)e - (ptr_t)b;
     n_root_sets++;
 }
@@ -125,36 +188,19 @@ GC_mark_roots()
        
         /* Add new static data areas of dynamically loaded modules.    */
         {
-          PCR_IL_LoadedFile * p = PCR_IL_GetLoadedFiles();
-          static PCR_IL_LoadedFile * last_already_added = NIL;
-               /* Last file that was already added to the list of roots. */
-          PCR_IL_LoadedFile * last_committed;
+          PCR_IL_LoadedFile * p = PCR_IL_GetLastLoadedFile();
           PCR_IL_LoadedSegment * q;
           
-          if (p != NIL && last_already_added == NIL) {
-            /* Switch to obtaining roots from the dynamic loader. */
-              /* Make sure the loader is properly initialized and that */
-              /* it has a correct description of PCR static data.      */
-                PCR_IL_Lock(PCR_Bool_false,
-                           PCR_allSigsBlocked, PCR_waitForever);
-               PCR_IL_Unlock();
-             /* Discard old root sets. */
-               n_root_sets = 0;
-               GC_root_size = 0;
-             /* We claim there are no dynamic libraries, or they       */
-             /* don't contain roots, since they allocate using the     */
-             /* system malloc, and they can't retain our pointers.     */
-          }
           /* Skip uncommited files */
           while (p != NIL && !(p -> lf_commitPoint)) {
               /* The loading of this file has not yet been committed   */
               /* Hence its description could be inconsistent.                  */
-              /* Furthermore, it hasn't yet been run.  Hence it's data  */
-              /* segments can possibly reference heap allocated objects.*/
+              /* Furthermore, it hasn't yet been run.  Hence its data  */
+              /* segments can't possibly reference heap allocated      */
+              /* objects.                                              */
               p = p -> lf_prev;
           }
-          last_committed = p;
-          for (; p != last_already_added; p = p -> lf_prev) {
+          for (; p != NIL; p = p -> lf_prev) {
             for (q = p -> lf_ls; q != NIL; q = q -> ls_next) {
               if ((q -> ls_flags & PCR_IL_SegFlags_Traced_MASK)
                   == PCR_IL_SegFlags_Traced_on) {
@@ -164,7 +210,6 @@ GC_mark_roots()
               }
             }
           }
-          last_already_added = last_committed;
         }
         
         
@@ -181,12 +226,15 @@ GC_mark_roots()
 #        else
            GC_mark_all_stack( GC_stackbottom, GC_approx_sp() );
 #        endif
+
 #   endif
 
+    /* Reregister dynamic libraries, in case one got added.    */
+       GC_register_dynamic_libraries();
     /* Mark everything in static data areas                             */
-    for (i = 0; i < n_root_sets; i++) {
+      for (i = 0; i < n_root_sets; i++) {
         GC_mark_all(static_roots[i].r_start, static_roots[i].r_end);
-    }
+      }
 }
 
 /*
diff --git a/misc.c b/misc.c
index a19e0dcafc1c52c12730b382afd8e2ac2a7c1f44..3179ef441bd0dfa6995a04341d9591e674afdff0 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -34,8 +34,10 @@ struct _GC_arrays GC_arrays = { 0 };
 /* This must be done statically since they may be accessed before      */
 /* GC_init is called.                                                  */
 struct obj_kind GC_obj_kinds[MAXOBJKINDS] = {
-/* PTRFREE */ { GC_aobjfreelist, GC_areclaim_list, GC_no_mark_proc, FALSE },
-/* NORMAL  */ { GC_objfreelist, GC_reclaim_list, GC_normal_mark_proc, TRUE },
+/* PTRFREE */ { &GC_aobjfreelist[0], &GC_areclaim_list[0],
+               GC_no_mark_proc, FALSE },
+/* NORMAL  */ { &GC_objfreelist[0], &GC_reclaim_list[0],
+               GC_normal_mark_proc, TRUE },
 };
 
 ptr_t GC_stackbottom = 0;
@@ -235,10 +237,9 @@ DCL_LOCK_STATE;
        
        if (!GC_is_initialized) GC_init_inner();
        lw = ROUNDED_UP_WORDS(lb);
-       if (!GC_sufficient_hb(lw, k) && !GC_dont_gc) {
-            GC_gcollect_inner(FALSE);
+       while ((h = GC_allochblk(lw, k)) == 0) {
+          GC_collect_or_expand(divHBLKSZ(lb) + 1);
        }
-       h = GC_allochblk(lw, k);
        if (h == 0) {
            op = 0;
        } else {
@@ -505,6 +506,7 @@ int obj_kind;
     h = HBLKPTR(p);
     hhdr = HDR(h);
     sz = hhdr -> hb_sz;
+    GC_mem_freed += sz;
     ok = &GC_obj_kinds[hhdr -> hb_obj_kind];
   
     if (sz > MAXOBJSZ) {
@@ -546,56 +548,59 @@ void GC_init_inner()
       }
 #   endif
     if  (sizeof (ptr_t) != sizeof(word)) {
-        GC_printf("sizeof (ptr_t) != sizeof(word)\n");
+        GC_err_printf0("sizeof (ptr_t) != sizeof(word)\n");
         ABORT("sizeof (ptr_t) != sizeof(word)\n");
     }
     if  (sizeof (signed_word) != sizeof(word)) {
-        GC_printf("sizeof (signed_word) != sizeof(word)\n");
+        GC_err_printf0("sizeof (signed_word) != sizeof(word)\n");
         ABORT("sizeof (signed_word) != sizeof(word)\n");
     }
     if  (sizeof (struct hblk) != HBLKSIZE) {
-        GC_printf("sizeof (struct hblk) != HBLKSIZE\n");
+        GC_err_printf0("sizeof (struct hblk) != HBLKSIZE\n");
         ABORT("sizeof (struct hblk) != HBLKSIZE\n");
     }
 #   ifndef THREADS
 #     if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN)
-       GC_printf(
+       GC_err_printf0(
          "Only one of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");
        ABORT("stack direction 1\n");
 #     endif
 #     if !defined(STACK_GROWS_UP) && !defined(STACK_GROWS_DOWN)
-       GC_printf(
+       GC_err_printf0(
          "One of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");
        ABORT("stack direction 2\n");
 #     endif
 #     ifdef STACK_GROWS_DOWN
         if ((word)(&dummy) > (word)GC_stackbottom) {
-          GC_printf("STACK_GROWS_DOWN is defd, but stack appears to grow up\n");
-          GC_printf("sp = 0x%lx, GC_stackbottom = 0x%lx\n",
-                   (unsigned long) (&dummy),
-                   (unsigned long) GC_stackbottom);
+          GC_err_printf0(
+               "STACK_GROWS_DOWN is defd, but stack appears to grow up\n");
+          GC_err_printf2("sp = 0x%lx, GC_stackbottom = 0x%lx\n",
+                        (unsigned long) (&dummy),
+                        (unsigned long) GC_stackbottom);
           ABORT("stack direction 3\n");
         }
 #     else
         if ((word)(&dummy) < (word)GC_stackbottom) {
-          GC_printf("STACK_GROWS_UP is defd, but stack appears to grow down\n");
-          GC_printf("sp = 0x%lx, GC_stackbottom = 0x%lx\n",
-                   (unsigned long) (&dummy),
-                   (unsigned long) GC_stackbottom);
+          GC_err_printf0(
+               "STACK_GROWS_UP is defd, but stack appears to grow down\n");
+          GC_err_printf2("sp = 0x%lx, GC_stackbottom = 0x%lx\n",
+                        (unsigned long) (&dummy),
+                        (unsigned long) GC_stackbottom);
           ABORT("stack direction 4");
         }
 #     endif
 #   endif
 #   if !defined(_AUX_SOURCE) || defined(__GNUC__)
       if ((word)(-1) < (word)0) {
-       GC_printf("The type word should be an unsigned integer type\n");
-       GC_printf("It appears to be signed\n");
+       GC_err_printf0("The type word should be an unsigned integer type\n");
+       GC_err_printf0("It appears to be signed\n");
        ABORT("word");
       }
 #   endif
     if ((signed_word)(-1) >= (signed_word)0) {
-       GC_printf("The type signed_word should be a signed integer type\n");
-       GC_printf("It appears to be unsigned\n");
+       GC_err_printf0(
+               "The type signed_word should be a signed integer type\n");
+       GC_err_printf0("It appears to be unsigned\n");
        ABORT("signed_word");
     }
     
@@ -604,7 +609,7 @@ void GC_init_inner()
     GC_bl_init();
     GC_mark_init();
     if (!GC_expand_hp_inner(GC_hincr)) {
-        GC_printf("Can't start up: no memory\n");
+        GC_printf0("Can't start up: no memory\n");
         EXIT();
     }
     GC_register_displacement_inner(0L);
@@ -614,11 +619,13 @@ void GC_init_inner()
     /* Add initial guess of root sets */
       GC_register_data_segments();
 #   ifdef PCR
+      PCR_IL_Lock(PCR_Bool_false, PCR_allSigsBlocked, PCR_waitForever);
+      PCR_IL_Unlock();
       GC_pcr_install();
 #   endif
     /* Get black list set up */
-      GC_gcollect_inner(TRUE);
-      GC_gcollect_inner(TRUE);
+      (void)GC_gcollect_inner(TRUE);
+      (void)GC_gcollect_inner(TRUE);
     /* Convince lint that some things are used */
       {
           extern char * GC_copyright[];
@@ -633,7 +640,6 @@ void GC_init_inner()
 /* Assumes that all arguments have been converted to something of the    */
 /* same size as long, and that the format conversions expect something   */
 /* of that size.                                                         */
-/*VARARGS1*/
 void GC_printf(format, a, b, c, d, e, f)
 char * format;
 long a, b, c, d, e, f;
@@ -652,7 +658,6 @@ long a, b, c, d, e, f;
 #   endif
 }
 
-/*VARARGS1*/
 void GC_err_printf(format, a, b, c, d, e, f)
 char * format;
 long a, b, c, d, e, f;
index 6ea00763e4af27eec9884f3fcbba7b4bd67bb2d2..fc3bfd99196770ee4f9e67308ff44b61f0c31372 100644 (file)
--- a/obj_map.c
+++ b/obj_map.c
@@ -100,7 +100,7 @@ word sz;
     }
     new_map = GC_scratch_alloc(MAP_SIZE);
 #   ifdef PRINTSTATS
-        GC_printf("Adding block map for size %lu\n", (unsigned long)sz);
+        GC_printf1("Adding block map for size %lu\n", (unsigned long)sz);
 #   endif
     for (displ = 0; displ < HBLKSIZE; displ++) {
         MAP_ENTRY(new_map,displ) = OBJ_INVALID;
index c1726d4c8c9c7f194a8915f2724f8a77ceb7887f..9a8df5f86409b3e14da33361d0f1bdcdd1299b2a 100644 (file)
--- a/os_dep.c
+++ b/os_dep.c
@@ -1,7 +1,19 @@
+/*
+ * Copyright (c) 1991-1993 by Xerox Corporation.  All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to copy this garbage collector for any purpose,
+ * provided the above notices are retained on all copies.
+ */
 # include "gc_private.h"
 # include <stdio.h>
 # include <signal.h>
 
+/* Blatantly OS dependent routines, except for those that are related  */
+/* dynamic loading.                                                    */
+
 /* Disable and enable signals during nontrivial allocations    */
 
 # ifdef OS2
@@ -43,40 +55,66 @@ void GC_enable_signals(void)
 
 # else
 
-static int old_mask;
+#  ifndef PCR
+
+#   ifdef sigmask
+       /* Use the traditional BSD interface */
+#      define SIGSET_T int
+#      define SIG_DEL(set, signal) (set) &= ~(sigmask(signal))
+#      define SIG_FILL(set)  (set) = 0x7fffffff
+         /* Setting the leading bit appears to provoke a bug in some   */
+         /* longjmp implementations.  Most systems appear not to have  */
+         /* a signal 32.                                               */
+#      define SIGSETMASK(old, new) (old) = sigsetmask(new)
+#   else
+       /* Use POSIX/SYSV interface     */
+#      define SIGSET_T sigset_t
+#      define SIG_DEL(set, signal) sigdelset(&(set), (signal))
+#      define SIG_FILL(set) sigfillset(&set)
+#      define SIGSETMASK(old, new) sigprocmask(SIG_SETMASK, &(new), &(old))
+#   endif
+
+static bool mask_initialized = FALSE;
+
+static SIGSET_T new_mask;
+
+static SIGSET_T old_mask;
+
+static SIGSET_T dummy;
 
 void GC_disable_signals()
 {
-    int mask = 0x7fffffff;
-       /* Setting the leading bit appears to provoke a bug in some     */
-       /* longjmp implementations.  Most systems appear not to have    */
-       /* a signal 32.                                                 */
-
-    mask &= ~(1<<(SIGSEGV-1));
-    mask &= ~(1<<(SIGILL-1));
-    mask &= ~(1<<(SIGQUIT-1));
-#   ifdef SIGBUS
-        mask &= ~(1<<(SIGBUS-1));
-#   endif
-#   ifdef SIGIOT
-        mask &= ~(1<<(SIGIOT-1));
-#   endif
-#   ifdef SIGEMT
-        mask &= ~(1<<(SIGEMT-1));
-#   endif
-#   ifdef SIGTRAP
-        mask &= ~(1<<(SIGTRAP-1));
-#   endif      
-    old_mask = sigsetmask(mask);
+    if (!mask_initialized) {
+       SIG_FILL(new_mask);
+
+       SIG_DEL(new_mask, SIGSEGV);
+       SIG_DEL(new_mask, SIGILL);
+       SIG_DEL(new_mask, SIGQUIT);
+#      ifdef SIGBUS
+           SIG_DEL(new_mask, SIGBUS);
+#      endif
+#      ifdef SIGIOT
+           SIG_DEL(new_mask, SIGIOT);
+#      endif
+#      ifdef SIGEMT
+           SIG_DEL(new_mask, SIGEMT);
+#      endif
+#      ifdef SIGTRAP
+           SIG_DEL(new_mask, SIGTRAP);
+#      endif 
+       mask_initialized = TRUE;
+    }     
+    SIGSETMASK(old_mask,new_mask);
 }
 
 void GC_enable_signals()
 {
-    (void)sigsetmask(old_mask);
+    SIGSETMASK(dummy,old_mask);
 }
 
+#  endif  /* !PCR */
 
-# endif
+# endif /*!OS/2 */
 
 /*
  * Find the base of the stack.
@@ -93,7 +131,7 @@ ptr_t GC_get_stack_base()
     PPIB ppib;
     
     if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {
-       fprintf(stderr, "DosGetInfoBlocks failed\n");
+       GC_err_printf0("DosGetInfoBlocks failed\n");
        ABORT("DosGetInfoBlocks failed\n");
     }
     return((ptr_t)(ptib -> tib_pstacklimit));
@@ -172,8 +210,8 @@ ptr_t GC_get_stack_base()
              result += MIN_PAGE_SIZE;
 #         endif
 #      endif /* HEURISTIC2 */
+       return(result);
 #   endif /* STACKBOTTOM */
-    return(result);
 }
 
 # endif /* ! OS2 */
@@ -203,12 +241,12 @@ void GC_register_data_segments()
     
     
     if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) {
-       fprintf(stderr, "DosGetInfoBlocks failed\n");
+       GC_err_printf0("DosGetInfoBlocks failed\n");
        ABORT("DosGetInfoBlocks failed\n");
     }
     module_handle = ppib -> pib_hmte;
     if (DosQueryModuleName(module_handle, PBUFSIZ, path) != NO_ERROR) {
-       fprintf(stderr, "DosQueryModuleName failed\n");
+       GC_err_printf0("DosQueryModuleName failed\n");
        ABORT("DosGetInfoBlocks failed\n");
     }
     myexefile = fopen(path, "rb");
@@ -269,7 +307,7 @@ void GC_register_data_segments()
       if (!(flags & OBJWRITE)) continue;
       if (!(flags & OBJREAD)) continue;
       if (flags & OBJINVALID) {
-          fprintf(stderr, "Object with invalid pages?\n");
+          GC_err_printf0("Object with invalid pages?\n");
           continue;
       } 
       GC_add_roots_inner(O32_BASE(seg), O32_BASE(seg)+O32_SIZE(seg));
@@ -281,15 +319,12 @@ void GC_register_data_segments()
 void GC_register_data_segments()
 {
     extern int end;
-        
-    GC_add_roots_inner(DATASTART, (char *)(&end));
-#   ifdef DYNAMIC_LOADING
-       {
-          extern void GC_setup_dynamic_loading();
-              
-          GC_setup_dynamic_loading();
-       }
+#   ifndef PCR      
+      GC_add_roots_inner(DATASTART, (char *)(&end));
 #   endif
+    /* Dynamic libraries are added at every collection, since they may  */
+    /* change.                                                         */
 }
 
 # endif  /* ! OS2 */
index 851678041110f8223a29b8969a71f190e2c5e27e..573d34f7da1e9537db8a637322bfc323681f17cf 100644 (file)
@@ -36,8 +36,6 @@ void * GC_AllocProc(size_t size, PCR_Bool ptrFree, PCR_Bool clear )
 
 # define GC_FreeProc GC_free
 
-void GC_NoOpProc () {}
-
 typedef struct {
   PCR_ERes (*ed_proc)(void *p, size_t size, PCR_Any data);
   bool ed_pointerfree;
@@ -92,14 +90,18 @@ PCR_ERes GC_EnumerateProc(
     }
 }
 
+void GC_DummyFreeProc(void *p) {};
+
+void GC_DummyShutdownProc(void) {};
+
 struct PCR_MM_ProcsRep GC_Rep = {
        MY_MAGIC,
        GC_AllocProc,
        GC_ReallocProc,
-       GC_NoOpProc,  /* mmp_free */
-       GC_FreeProc,  /* mmp_unsafeFree */
+       GC_DummyFreeProc,       /* mmp_free */
+       GC_FreeProc,            /* mmp_unsafeFree */
        GC_EnumerateProc,
-       GC_NoOpProc,  /* mmp_shutdown */
+       GC_DummyShutdownProc    /* mmp_shutdown */
 };
 
 void GC_pcr_install()
index 357c0a675376c5bba4bbe3242c785acdf81255f9..9bf101581b31040d58f97534b441fa7a3d373a7d 100644 (file)
--- a/reclaim.c
+++ b/reclaim.c
@@ -21,14 +21,14 @@ ptr_t p;
 word sz;
 {
     if (HDR(p) -> hb_obj_kind == PTRFREE) {
-        GC_err_printf("Leaked atomic object at ");
+        GC_err_printf0("Leaked atomic object at ");
     } else {
-        GC_err_printf("Leaked composite object at ");
+        GC_err_printf0("Leaked composite object at ");
     }
     if (GC_debugging_started && GC_has_debug_info(p)) {
         GC_print_obj(p);
     } else {
-        GC_err_printf("0x%lx (appr. size = %ld)\n",
+        GC_err_printf1("0x%lx (appr. size = %ld)\n",
                              (unsigned long)WORDS_TO_BYTES(sz));
     }
 }
@@ -434,13 +434,13 @@ int abort_if_found;               /* Abort if a reclaimable object is found */
     sz = hhdr -> hb_sz;
     ok = &GC_obj_kinds[hhdr -> hb_obj_kind];
 #   ifdef PRINTBLOCKS
-        GC_printf("%ld(", (unsigned long)sz);
+        GC_printf1("%ld(", (unsigned long)sz);
         if (hhdr -> hb_obj_kind == PTRFREE) {
-            GC_printf("a");
+            GC_printf0("a");
         } else if (hhdr -> hb_obj_kind == NORMAL){
-            GC_printf("c");
+            GC_printf0("c");
         } else {
-            GC_printf("o");
+            GC_printf0("o");
         }
 #   endif
 
@@ -472,7 +472,7 @@ int abort_if_found;         /* Abort if a reclaimable object is found */
         }
     }
 #   ifdef PRINTBLOCKS
-        if (empty) {GC_printf("e),");} else {GC_printf("n),");}
+        if (empty) {GC_printf0("e),");} else {GC_printf0("n),");}
 #   endif
 }
 
@@ -507,7 +507,7 @@ int abort_if_found;         /* Abort if a GC_reclaimable object is found */
       }
     
 #   ifdef PRINTBLOCKS
-        GC_printf("GC_reclaim: current block sizes:\n");
+        GC_printf0("GC_reclaim: current block sizes:\n");
 #   endif
 
   /* Go through all heap blocks (in hblklist) and reclaim unmarked objects */
@@ -515,7 +515,7 @@ int abort_if_found;         /* Abort if a GC_reclaimable object is found */
     GC_apply_to_all_blocks(GC_reclaim_block, abort_if_found);
     
 #   ifdef PRINTBLOCKS
-        GC_printf("\n");
+        GC_printf0("\n");
 #   endif
 }
 
index 8426fd3df474d8365bd8f90509d159d53d98bda1..6c2c8737168b7515e3f0522ba77d99d31fc5e20d 100644 (file)
@@ -10,7 +10,7 @@
 /* code.)                                                   */
 #include <stdio.h>
 #include <setjmp.h>
-#include "gc_private.h"
+#include "config.h"
 
 #ifdef __hpux
 /* X/OPEN PG3 defines "void* sbrk();" and this clashes with the definition */
@@ -26,6 +26,16 @@ getpagesize()
 }
 #endif
 
+#if defined(SUNOS5)
+#define _CLASSIC_XOPEN_TYPES
+#include <unistd.h>
+int
+getpagesize()
+{
+    return sysconf(_SC_PAGESIZE);
+}
+#endif
+
 #ifdef _AUX_SOURCE
 #include <sys/mmu.h>
 int
@@ -95,7 +105,7 @@ main()
        if (y == 1) {
            if (x == 2) {
                printf("Generic mark_regs code probably wont work\n");
-#              if defined(SPARC) || defined(IBMRS6000)
+#              if defined(SPARC) || defined(IBMRS6000) || defined(VAX) || defined(MIPS) || defined(M68K) || defined(I386) || defined(NS32K) || defined(RT)
                    printf("Assembly code supplied\n");
 #              else
                    printf("Need assembly code\n");
diff --git a/test.c b/test.c
index 027aa80ca864ae05647c0ab8399a9f4800e7d05c..be4fa0671efa8d3f69b4381e54e0c08fdac35045 100644 (file)
--- a/test.c
+++ b/test.c
@@ -69,6 +69,24 @@ sexpr y;
     return(r);
 }
 
+sexpr small_cons (x, y)
+sexpr x;
+sexpr y;
+{
+    register sexpr r;
+    register int *p;
+    
+    r = (sexpr) GC_MALLOC(sizeof(struct SEXPR));
+    if (r == 0) {
+        (void)printf("Out of memory\n");
+        exit(1);
+    }
+    r -> sexpr_car = x;
+    r -> sexpr_cdr = y;
+    return(r);
+}
+
+
 /* Return reverse(x) concatenated with y */
 sexpr reverse1(x, y)
 sexpr x, y;
@@ -92,7 +110,7 @@ int low, up;
     if (low > up) {
        return(nil);
     } else {
-        return(cons((sexpr)low, ints(low+1, up)));
+        return(small_cons(small_cons((sexpr)low, 0), ints(low+1, up)));
     }
 }
 
@@ -100,7 +118,7 @@ void check_ints(list, low, up)
 sexpr list;
 int low, up;
 {
-    if ((int)(car(list)) != low) {
+    if ((int)(car(car(list))) != low) {
         (void)printf(
            "List reversal produced incorrect list - collector is broken\n");
         exit(1);
@@ -122,7 +140,7 @@ sexpr x;
     if (is_nil(x)) {
         (void)printf("NIL\n");
     } else {
-        (void)printf("%d", car(x));
+        (void)printf("(%d)", car(car(x)));
         if (!is_nil(cdr(x))) {
             (void)printf(", ");
             (void)print_int_list(cdr(x));
@@ -147,9 +165,11 @@ reverse_test()
 {
     int i;
     sexpr b;
+    sexpr c;
 
     a = ints(1, 100);
     b = ints(1, 50);
+    c = ints(1, 4500);
     for (i = 0; i < 50; i++) {
         b = reverse(reverse(b));
     }
@@ -168,7 +188,8 @@ reverse_test()
     }
     check_ints(a,1,100);
     check_ints(b,1,50);
-    a = b = 0;
+    check_ints(c,1,4500);
+    a = b = c = 0;
 }
 
 /*