gc4.13alpha1 tarball import gc4_13alpha1
authorHans Boehm <boehm@acm.org>
Tue, 17 Feb 1998 00:00:00 +0000 (00:00 +0000)
committerIvan Maidanski <ivmai@mail.ru>
Sat, 17 May 2014 13:36:52 +0000 (17:36 +0400)
27 files changed:
Makefile
README
README.sgi
alloc.c
config.h
cord/cordxtra.c
cord/gc.h
dbg_mlc.c
finalize.c
gc.h
gc_alloc.h
gc_priv.h
include/gc.h
include/gc_alloc.h
include/private/config.h
include/private/gc_priv.h
irix_threads.c
malloc.c
mallocx.c
mark_rts.c
mips_sgi_mach_dep.s
os_dep.c
reclaim.c
solaris_pthreads.c
test.c
test_cpp.cc
version.h

index 87fcc3f..8e53118 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -7,15 +7,16 @@
 #               and runs some tests of collector and cords.  Does not add cords or
 #       c++ interface to gc.a
 # cord/de - builds dumb editor based on cords.
-CC=cc
-CXX=CC
-AS=as
+ABI_FLAG= 
+CC=cc $(ABI_FLAG)
+CXX=CC $(ABI_FLAG)
+AS=as $(ABI_FLAG)
 #  The above doesn't work with gas, which doesn't run cpp.
 #  Define AS as `gcc -c -x assembler-with-cpp' instead.
 #  Under Irix 6, you will have to specify the ABI for as if you specify
 #  it for the C compiler.
 
-CFLAGS= -O -DNO_SIGNALS -DALL_INTERIOR_POINTERS -DATOMIC_UNCOLLECTABLE -DNO_EXECUTE_PERMISSION -DSILENT
+CFLAGS= -O -DNO_SIGNALS -DALL_INTERIOR_POINTERS -DNO_EXECUTE_PERMISSION -DSILENT
 
 # Setjmp_test may yield overly optimistic results when compiled
 # without optimization.
@@ -80,6 +81,8 @@ CFLAGS= -O -DNO_SIGNALS -DALL_INTERIOR_POINTERS -DATOMIC_UNCOLLECTABLE -DNO_EXEC
 #   in a sepearte postpass, and hence their memory won't be reclaimed.
 #   Not recommended unless you are implementing a language that specifies
 #   these semantics.
+# -DFINALIZE_ON_DEMAND causes finalizers to be run only in response
+#   to explicit GC_invoke_finalizers() calls.
 # -DATOMIC_UNCOLLECTABLE includes code for GC_malloc_atomic_uncollectable.
 #   This is useful if either the vendor malloc implementation is poor,
 #   or if REDIRECT_MALLOC is used.
@@ -229,10 +232,12 @@ libgc.so: $(OBJS) dyn_load_sunos53.o
 # Alpha/OSF shared library version of the collector
 libalphagc.so: $(OBJS)
        ld -shared -o libalphagc.so $(OBJS) dyn_load.o -lc
+       ln libalphagc.so libgc.so
 
 # IRIX shared library version of the collector
 libirixgc.so: $(OBJS) dyn_load.o
-       ld -shared -o libirixgc.so $(OBJS) dyn_load.o -lc
+       ld -shared $(ABI_FLAG) -o libirixgc.so $(OBJS) dyn_load.o -lc
+       ln libirixgc.so libgc.so
 
 mach_dep.o: $(srcdir)/mach_dep.c $(srcdir)/mips_sgi_mach_dep.s $(srcdir)/mips_ultrix_mach_dep.s $(srcdir)/rs6000_mach_dep.s $(UTILS)
        rm -f mach_dep.o
diff --git a/README b/README
index a1d3998..94604cf 100644 (file)
--- a/README
+++ b/README
@@ -11,7 +11,7 @@ Permission to modify the code and to distribute modified code is granted,
 provided the above notices are retained, and a notice that the code was
 modified is included with the above copyright notice.
 
-This is version 4.12 of a conservative garbage collector for C and C++.
+This is version 4.13alpha1 of a conservative garbage collector for C and C++.
 
 HISTORY -
 
@@ -1324,6 +1324,28 @@ Since 4.11:
    On the other hand, it seems to be needed often enough that it's worth
    adding as a standard facility.
 
+Since 4.12:
+ - Fixed a crucial bug in the Watcom port.  There was a redundant decl
+   of GC_push_one in gc_priv.h.
+ - Added FINALIZE_ON_DEMAND.
+ - Fixed some pre-ANSI cc problems in test.c.
+ - Removed getpagesize() use for Solaris.  It seems to be missing in one
+   or two versions.
+ - Fixed bool handling for SPARCCompiler version 4.2.
+ - Fixed some files in include that had gotten unlinked from the main
+   copy.
+ - Some RS/6000 fixes (missing casts).  Thanks to Toralf Foerster.
+ - Fixed several problems in GC_debug_realloc, affecting mostly the
+   FIND_LEAK case.
+ - GC_exclude_static_roots contained a buggy unsigned comparison to
+   terminate a loop.  (Thanks to Wilson Ho.)
+ - CORD_str failed if the substring occurred at the last possible position.
+   (Only affects cord users.)
+ - Fixed Linux code to deal with RedHat 5.0 and integrated Peter Bigot's
+   os_dep.c code for dealing with various Linux versions.
+ - Added workaround for Irix pthreads sigaction bug and possible signal
+   misdirection problems.
+
 To do:
  - Very large root set sizes (> 16 MB or so) could cause the collector
    to abort with an unexpected mark stack overflow.  (Thanks again to
@@ -1336,6 +1358,11 @@ To do:
    off DYNAMIC_LOADING in the collector as a workaround.  It may also
    be possible to conditionally intercept mmap and use GC_exclude_static_roots.
    The real fix is to walk rld data structures, which looks possible.
- - SGI pthreads and incremental collection don't mix yet.
+ - SGI pthreads and incremental collection don't mix yet.  This actually
+   now appears to work under Irix 6.5, but is not enabled by default.
  - Integrate MIT and DEC pthreads ports.
+ - The Irix pthreads locking mechanism leaves something to be desired.
+   It should eventually resort to nanosleep with exponential backoff.
+   There seem to be associated performance problems with
+   pthreads + incremental GC.
  
index 3174e9c..f21eeb7 100644 (file)
@@ -28,3 +28,12 @@ include gc.h.  Gc.h redefines some of the pthread primitives as macros which
 also provide the collector with information it requires.
 
 4) For the time being, you should not use dlopen.
+
+5) pthread_cond_wait and pthread_cond_timed_wait should be prepared for premature 
+wakeups.  (I believe the pthreads and realted standards require this anyway.
+Irix pthreads often terminate a wait if a signal arrives.  The garbage collector
+uses signals to stop threads.)
+
+6) It is expensive to stop a thread waiting in IO at the time the request is
+initiated.  Applications with many such threads may not exhibit acceptable
+performance with the collector.  (Increasing the heap size may help.)
diff --git a/alloc.c b/alloc.c
index d9584e1..b7cb6f5 100644 (file)
--- a/alloc.c
+++ b/alloc.c
@@ -548,7 +548,7 @@ void GC_finish_collection()
     int result;
     DCL_LOCK_STATE;
     
-    GC_invoke_finalizers();
+    GC_INVOKE_FINALIZERS();
     DISABLE_SIGNALS();
     LOCK();
     ENTER_GC();
@@ -559,7 +559,7 @@ void GC_finish_collection()
     EXIT_GC();
     UNLOCK();
     ENABLE_SIGNALS();
-    if(result) GC_invoke_finalizers();
+    if(result) GC_INVOKE_FINALIZERS();
     return(result);
 }
 
index cffbf6e..d5d618c 100644 (file)
--- a/config.h
+++ b/config.h
 #       endif
 #      define PROC_VDB
 #      define HEURISTIC1
+#      include <unistd.h>
+#       define GETPAGESIZE()  sysconf(_SC_PAGESIZE)
+               /* getpagesize() appeared to be missing from at least one */
+               /* Solaris 5.4 installation.  Weird.                      */
 #   endif
 #   ifdef SUNOS4
 #      define OS_TYPE "SUNOS4"
 #      define MPROTECT_VDB
 #       ifdef __ELF__
 #            define DYNAMIC_LOADING
-#       endif
-#       ifdef __ELF__
-#            define DYNAMIC_LOADING
 #           ifdef UNDEFINED    /* includes ro data */
               extern int _etext;
 #              define DATASTART ((ptr_t)((((word) (&_etext)) + 0xfff) & ~0xfff))
 #           endif
-            extern char **__environ;
-#            define DATASTART ((ptr_t)(&__environ))
+#           include <linux/version.h>
+#           include <features.h>
+#           if LINUX_VERSION_CODE >= 0x20000 && defined(__GLIBC__) && __GLIBC__ >= 2
+                extern int __data_start;
+#               define DATASTART ((ptr_t)(&__data_start))
+#           else
+                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   */
                              /* would include .rodata, which may       */
                              /* contain large read-only data tables    */
                              /* that we'd rather not scan.             */
+#           endif
             extern int _end;
 #           define DATAEND (&_end)
 #      else
 #   define DYNAMIC_LOADING
 #   include <unistd.h>
 #   define GETPAGESIZE() sysconf(_SC_PAGE_SIZE)
+       /* They misspelled the Posix macro?     */
 # endif
 
 # ifdef ALPHA
 # endif
 
 # if defined(SVR4) && !defined(GETPAGESIZE)
-# include <unistd.h>
-  int
-  GC_getpagesize()
-  {
-    return sysconf(_SC_PAGESIZE);
-  }
+#    include <unistd.h>
+#    define GETPAGESIZE()  sysconf(_SC_PAGESIZE)
 # endif
+
 # ifndef GETPAGESIZE
+#   if defined(SUNOS5) || defined(IRIX5)
+#      include <unistd.h>
+#   endif
 #   define GETPAGESIZE() getpagesize()
 # endif
 
index 8566e14..b306fba 100644 (file)
@@ -390,7 +390,7 @@ size_t CORD_str(CORD x, size_t start, CORD s)
         x_buf |= CORD_pos_fetch(xpos);
         CORD_next(xpos);
     }
-    for (match_pos = start; match_pos < xlen - slen; match_pos++) {
+    for (match_pos = start; ; match_pos++) {
        if ((x_buf & mask) == s_buf) {
            if (slen == start_len ||
                CORD_ncmp(x, match_pos + start_len,
@@ -398,11 +398,13 @@ size_t CORD_str(CORD x, size_t start, CORD s)
                return(match_pos);
            }
        }
+       if ( match_pos == xlen - slen ) {
+           return(CORD_NOT_FOUND);
+       }
        x_buf <<= 8;
         x_buf |= CORD_pos_fetch(xpos);
         CORD_next(xpos);
     }
-    return(CORD_NOT_FOUND);
 }
 
 void CORD_ec_flush_buf(CORD_ec x)
index 1e00c2f..2303724 100644 (file)
--- a/cord/gc.h
+++ b/cord/gc.h
@@ -473,6 +473,14 @@ GC_API int GC_unregister_disappearing_link GC_PROTO((GC_PTR * /* link */));
 GC_API GC_PTR GC_make_closure GC_PROTO((GC_finalization_proc fn, GC_PTR data));
 GC_API void GC_debug_invoke_finalizer GC_PROTO((GC_PTR obj, GC_PTR data));
 
+GC_API int GC_invoke_finalizers GC_PROTO((void));
+       /* Run finalizers for all objects that are ready to     */
+       /* be finalized.  Return the number of finalizers       */
+       /* that were run.  Normally this is also called         */
+       /* implicitly during some allocations.  If              */
+       /* FINALIZE_ON_DEMAND is defined, it must be called     */
+       /* explicitly.                                          */
+
 /* GC_set_warn_proc can be used to redirect or filter warning messages.        */
 /* p may not be a NULL pointer.                                                */
 typedef void (*GC_warn_proc) GC_PROTO((char *msg, GC_word arg));
@@ -672,14 +680,6 @@ extern void GC_thr_init(); /* Needed for Solaris/X86       */
 # endif
 #endif
 
-#ifdef __WATCOMC__
-  /* Ivan Demakov: Programs compiled by Watcom C with -5r option
-   * crash without this declaration
-   * HB: Could this go into gc_priv.h?
-   */
-  void GC_noop(void*, ...);
-#endif
-
 #ifdef __cplusplus
     }  /* end of extern "C" */
 #endif
index 094614a..445f123 100644 (file)
--- a/dbg_mlc.c
+++ b/dbg_mlc.c
@@ -1,6 +1,7 @@
 /* 
  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
  * Copyright (c) 1991-1995 by Xerox Corporation.  All rights reserved.
+ * Copyright (c) 1997 by Silicon Graphics.  All rights reserved.
  *
  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
@@ -320,6 +321,33 @@ GC_PTR p;
     return (GC_store_debug_info(result, (word)lb, s, (word)i));
 }
 
+#ifdef ATOMIC_UNCOLLECTABLE
+# ifdef __STDC__
+    GC_PTR GC_debug_malloc_atomic_uncollectable(size_t lb, char * s, int i)
+# else
+    GC_PTR GC_debug_malloc_atomic_uncollectable(lb, s, i)
+    size_t lb;
+    char * s;
+    int i;
+# endif
+{
+    GC_PTR result = GC_malloc_atomic_uncollectable(lb + DEBUG_BYTES);
+    
+    if (result == 0) {
+        GC_err_printf1(
+               "GC_debug_malloc_atomic_uncollectable(%ld) returning NIL (",
+                (unsigned long) lb);
+        GC_err_puts(s);
+        GC_err_printf1(":%ld)\n", (unsigned long)i);
+        return(0);
+    }
+    if (!GC_debugging_started) {
+        GC_start_debugging();
+    }
+    ADD_CALL_CHAIN(result);
+    return (GC_store_debug_info(result, (word)lb, s, (word)i));
+}
+#endif /* ATOMIC_UNCOLLECTABLE */
 
 # ifdef __STDC__
     void GC_debug_free(GC_PTR p)
@@ -386,7 +414,7 @@ GC_PTR p;
 {
     register GC_PTR base = GC_base(p);
     register ptr_t clobbered;
-    register GC_PTR result = GC_debug_malloc(lb, s, i);
+    register GC_PTR result;
     register size_t copy_sz = lb;
     register size_t old_sz;
     register hdr * hhdr;
@@ -394,7 +422,7 @@ GC_PTR p;
     if (p == 0) return(GC_debug_malloc(lb, s, i));
     if (base == 0) {
         GC_err_printf1(
-              "Attempt to free invalid pointer %lx\n", (unsigned long)p);
+              "Attempt to reallocate invalid pointer %lx\n", (unsigned long)p);
         ABORT("realloc(invalid pointer)");
     }
     if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
@@ -419,6 +447,11 @@ GC_PTR p;
       case UNCOLLECTABLE:
        result = GC_debug_malloc_uncollectable(lb, s, i);
        break;
+#    ifdef ATOMIC_UNCOLLECTABLE
+      case AUNCOLLECTABLE:
+       result = GC_debug_malloc_atomic_uncollectable(lb, s, i);
+       break;
+#    endif
       default:
         GC_err_printf0("GC_debug_realloc: encountered bad kind\n");
         ABORT("bad kind");
@@ -432,6 +465,7 @@ GC_PTR p;
     if (old_sz < copy_sz) copy_sz = old_sz;
     if (result == 0) return(0);
     BCOPY(p, result,  copy_sz);
+    GC_debug_free(p);
     return(result);
 }
 
index e555194..d825bf9 100644 (file)
@@ -661,7 +661,7 @@ void GC_finalize_all()
       GC_enqueue_all_finalizers();
       UNLOCK();
       ENABLE_SIGNALS();
-      GC_invoke_finalizers();
+      GC_INVOKE_FINALIZERS();
       DISABLE_SIGNALS();
       LOCK();
     }
@@ -672,9 +672,10 @@ void GC_finalize_all()
 
 /* Invoke finalizers for all objects that are ready to be finalized.   */
 /* Should be called without allocation lock.                           */
-void GC_invoke_finalizers()
+int GC_invoke_finalizers()
 {
     register struct finalizable_object * curr_fo;
+    register int count = 0;
     DCL_LOCK_STATE;
     
     while (GC_finalize_now != 0) {
@@ -695,6 +696,7 @@ void GC_invoke_finalizers()
        (*(curr_fo -> fo_fn))((ptr_t)(curr_fo -> fo_hidden_base),
                              curr_fo -> fo_client_data);
        curr_fo -> fo_client_data = 0;
+       ++count;
 #      ifdef UNDEFINED
            /* This is probably a bad idea.  It throws off accounting if */
            /* nearly all objects are finalizable.  O.w. it shouldn't    */
@@ -702,6 +704,7 @@ void GC_invoke_finalizers()
            GC_free((GC_PTR)curr_fo);
 #      endif
     }
+    return count;
 }
 
 # ifdef __STDC__
diff --git a/gc.h b/gc.h
index 1e00c2f..2303724 100644 (file)
--- a/gc.h
+++ b/gc.h
@@ -473,6 +473,14 @@ GC_API int GC_unregister_disappearing_link GC_PROTO((GC_PTR * /* link */));
 GC_API GC_PTR GC_make_closure GC_PROTO((GC_finalization_proc fn, GC_PTR data));
 GC_API void GC_debug_invoke_finalizer GC_PROTO((GC_PTR obj, GC_PTR data));
 
+GC_API int GC_invoke_finalizers GC_PROTO((void));
+       /* Run finalizers for all objects that are ready to     */
+       /* be finalized.  Return the number of finalizers       */
+       /* that were run.  Normally this is also called         */
+       /* implicitly during some allocations.  If              */
+       /* FINALIZE_ON_DEMAND is defined, it must be called     */
+       /* explicitly.                                          */
+
 /* GC_set_warn_proc can be used to redirect or filter warning messages.        */
 /* p may not be a NULL pointer.                                                */
 typedef void (*GC_warn_proc) GC_PROTO((char *msg, GC_word arg));
@@ -672,14 +680,6 @@ extern void GC_thr_init(); /* Needed for Solaris/X86       */
 # endif
 #endif
 
-#ifdef __WATCOMC__
-  /* Ivan Demakov: Programs compiled by Watcom C with -5r option
-   * crash without this declaration
-   * HB: Could this go into gc_priv.h?
-   */
-  void GC_noop(void*, ...);
-#endif
-
 #ifdef __cplusplus
     }  /* end of extern "C" */
 #endif
index 85cb7cd..645748b 100644 (file)
@@ -32,6 +32,8 @@
 
 #define GC_ALLOC_H
 #define __ALLOC_H      // Prevent inclusion of the default version.  Ugly.
+#define __SGI_STL_ALLOC_H
+#define __SGI_STL_INTERNAL_ALLOC_H
 
 #ifndef __ALLOC
 #   define __ALLOC alloc
@@ -304,8 +306,8 @@ class gc_alloc_template {
        static void * allocate(size_t n) { return GC_malloc(n); }
        static void * ptr_free_allocate(size_t n)
                { return GC_malloc_atomic(n); }
-       static void deallocate(void *p, size_t n) { }
-       static void ptr_free_deallocate(void *p, size_t n) { }
+       static void deallocate(void *, size_t) { }
+       static void ptr_free_deallocate(void *, size_t) { }
 };
 
 typedef gc_alloc_template < 0 > gc_alloc;
@@ -316,8 +318,8 @@ class alloc_template {
        static void * allocate(size_t n) { return GC_malloc_uncollectable(n); }
        static void * ptr_free_allocate(size_t n)
                { return GC_malloc_atomic_uncollectable(n); }
-       static void deallocate(void *p, size_t n) { GC_free(p); }
-       static void ptr_free_deallocate(void *p, size_t n) { GC_free(p); }
+       static void deallocate(void *p, size_t) { GC_free(p); }
+       static void ptr_free_deallocate(void *p, size_t) { GC_free(p); }
 };
 
 typedef alloc_template < 0 > alloc;
index 49a916d..a70032a 100644 (file)
--- a/gc_priv.h
+++ b/gc_priv.h
@@ -57,7 +57,7 @@ typedef GC_signed_word signed_word;
 #   if defined(_SGI_SOURCE) && !defined(_BOOL)
        typedef int bool;
 #   endif
-#   if defined(__SUNPRO_CC) && __SUNPRO_CC <= 0x410
+#   if defined(__SUNPRO_CC) && __SUNPRO_CC <= 0x420
        typedef int bool;
 #   endif
 #   if defined(__cplusplus) && defined(_MSC_VER) && _MSC_VER <= 1020
@@ -174,6 +174,12 @@ typedef char * ptr_t;      /* A generic pointer to which we can add        */
 #   define GATHERSTATS
 #endif
 
+#ifdef FINALIZE_ON_DEMAND
+#   define GC_INVOKE_FINALIZERS()
+#else
+#   define GC_INVOKE_FINALIZERS() (void)GC_invoke_finalizers()
+#endif
+
 #define MERGE_SIZES /* Round up some object sizes, so that fewer distinct */
                    /* free lists are actually maintained.  This applies  */
                    /* only to the top level routines in misc.c, not to   */
@@ -1183,10 +1189,7 @@ extern void (*GC_start_call_back)(/* void */);
 void GC_push_regs();   /* Push register contents onto mark stack.      */
 void GC_remark();      /* Mark from all marked objects.  Used  */
                        /* only if we had to drop something.    */
-void GC_push_one(/*p*/);       /* If p points to an object, mark it    */
-                               /* and push contents on the mark stack  */
-/* Ivan Demakov: Watcom C error'ed without this */
-# if defined(MSWIN32) && defined(__WATCOMC__)
+# if defined(MSWIN32)
   void __cdecl GC_push_one();
 # else
   void GC_push_one(/*p*/);    /* If p points to an object, mark it    */
@@ -1379,8 +1382,6 @@ void GC_finalize();       /* Perform all indicated finalization actions   */
                        /* Unreachable finalizable objects are enqueued */
                        /* for processing by GC_invoke_finalizers.      */
                        /* Invoked with lock.                           */
-void GC_invoke_finalizers();   /* Run eligible finalizers.     */
-                               /* Invoked without lock.        */      
                        
 void GC_add_to_heap(/*p, bytes*/);
                        /* Add a HBLKSIZE aligned chunk to the heap.    */
@@ -1427,7 +1428,12 @@ void GC_print_static_roots();
 void GC_dump();
 
 /* Make arguments appear live to compiler */
-GC_API void GC_noop();
+# ifdef __WATCOMC__
+  void GC_noop(void*, ...);
+# else
+  GC_API void GC_noop();
+# endif
+
 void GC_noop1(/* word arg */);
 
 /* Logging and diagnostic output:      */
index 1e00c2f..2303724 100644 (file)
@@ -473,6 +473,14 @@ GC_API int GC_unregister_disappearing_link GC_PROTO((GC_PTR * /* link */));
 GC_API GC_PTR GC_make_closure GC_PROTO((GC_finalization_proc fn, GC_PTR data));
 GC_API void GC_debug_invoke_finalizer GC_PROTO((GC_PTR obj, GC_PTR data));
 
+GC_API int GC_invoke_finalizers GC_PROTO((void));
+       /* Run finalizers for all objects that are ready to     */
+       /* be finalized.  Return the number of finalizers       */
+       /* that were run.  Normally this is also called         */
+       /* implicitly during some allocations.  If              */
+       /* FINALIZE_ON_DEMAND is defined, it must be called     */
+       /* explicitly.                                          */
+
 /* GC_set_warn_proc can be used to redirect or filter warning messages.        */
 /* p may not be a NULL pointer.                                                */
 typedef void (*GC_warn_proc) GC_PROTO((char *msg, GC_word arg));
@@ -672,14 +680,6 @@ extern void GC_thr_init(); /* Needed for Solaris/X86       */
 # endif
 #endif
 
-#ifdef __WATCOMC__
-  /* Ivan Demakov: Programs compiled by Watcom C with -5r option
-   * crash without this declaration
-   * HB: Could this go into gc_priv.h?
-   */
-  void GC_noop(void*, ...);
-#endif
-
 #ifdef __cplusplus
     }  /* end of extern "C" */
 #endif
index 85cb7cd..645748b 100644 (file)
@@ -32,6 +32,8 @@
 
 #define GC_ALLOC_H
 #define __ALLOC_H      // Prevent inclusion of the default version.  Ugly.
+#define __SGI_STL_ALLOC_H
+#define __SGI_STL_INTERNAL_ALLOC_H
 
 #ifndef __ALLOC
 #   define __ALLOC alloc
@@ -304,8 +306,8 @@ class gc_alloc_template {
        static void * allocate(size_t n) { return GC_malloc(n); }
        static void * ptr_free_allocate(size_t n)
                { return GC_malloc_atomic(n); }
-       static void deallocate(void *p, size_t n) { }
-       static void ptr_free_deallocate(void *p, size_t n) { }
+       static void deallocate(void *, size_t) { }
+       static void ptr_free_deallocate(void *, size_t) { }
 };
 
 typedef gc_alloc_template < 0 > gc_alloc;
@@ -316,8 +318,8 @@ class alloc_template {
        static void * allocate(size_t n) { return GC_malloc_uncollectable(n); }
        static void * ptr_free_allocate(size_t n)
                { return GC_malloc_atomic_uncollectable(n); }
-       static void deallocate(void *p, size_t n) { GC_free(p); }
-       static void ptr_free_deallocate(void *p, size_t n) { GC_free(p); }
+       static void deallocate(void *p, size_t) { GC_free(p); }
+       static void ptr_free_deallocate(void *p, size_t) { GC_free(p); }
 };
 
 typedef alloc_template < 0 > alloc;
index 62492c3..d5d618c 100644 (file)
@@ -1,6 +1,7 @@
 /* 
  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
+ * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.
  *
  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
@@ -11,7 +12,6 @@
  * provided the above notices are retained, and a notice that the code was
  * modified is included with the above copyright notice.
  */
-/* Boehm, October 3, 1995 6:39 pm PDT */
  
 #ifndef CONFIG_H
 
 # endif
 # if defined(mips) || defined(__mips)
 #    define MIPS
-#    if defined(ultrix) || defined(__ultrix)
+#    if defined(ultrix) || defined(__ultrix) || defined(__NetBSD__)
 #      define ULTRIX
 #    else
 #      if defined(_SYSTYPE_SVR4) || defined(SYSTYPE_SVR4) || defined(__SYSTYPE_SVR4__)
-#        define IRIX5
+#        define IRIX5   /* or IRIX 6.X */
 #      else
 #        define RISCOS  /* or IRIX 4.X */
 #      endif
 #    define LINUX
 #    define mach_type_known
 # endif
-# if defined(__alpha)
+# if defined(linux) && defined(powerpc)
+#    define POWERPC
+#    define LINUX
+#    define mach_type_known
+# endif
+# if defined(__alpha) || defined(__alpha__)
 #   define ALPHA
+#   if defined(linux) || defined(__linux__)
+#     define LINUX
+#   else
+#     define OSF1      /* a.k.a Digital Unix */
+#   endif
 #   define mach_type_known
 # endif
 # if defined(_AMIGA)
     /* DGUX defined */
 #   define mach_type_known
 # endif
-# if defined(_MSDOS) && (_M_IX86 == 300) || (_M_IX86 == 400)
+# if (defined(_MSDOS) || defined(_MSC_VER)) && (_M_IX86 >= 300)
 #   define I386
 #   define MSWIN32     /* or Win32s */
 #   define mach_type_known
 # endif
-# if defined(GO32)
+# if defined(__DJGPP__)
 #   define I386
 #   define DJGPP  /* MSDOS running the DJGPP port of GCC */
 #   define mach_type_known
 # endif
+# if defined(__CYGWIN32__)
+#   define I386
+#   define CYGWIN32
+#   define mach_type_known
+# endif
 # if defined(__BORLANDC__)
 #   define I386
 #   define MSWIN32
 #   define mach_type_known
 # endif
+# if defined(_UTS) && !defined(mach_type_known)
+#   define S370
+#   define UTS4
+#   define mach_type_known
+# endif
+/* Ivan Demakov */
+# if defined(__WATCOMC__) && defined(__386__)
+#   define I386
+#   if !defined(OS2) && !defined(MSWIN32) && !defined(DOS4GW)
+#     if defined(__OS2__)
+#       define OS2
+#     else
+#       if defined(__WINDOWS_386__) || defined(__NT__)
+#         define MSWIN32
+#       else
+#         define DOS4GW
+#       endif
+#     endif
+#   endif
+#   define mach_type_known
+# endif
 
 /* Feel free to add more clauses here */
 
                    /*             SPARC      ==> SPARC under SunOS     */
                    /*                  (SUNOS4, SUNOS5,                */
                    /*                   DRSNX variants)                */
-                   /*             ALPHA      ==> DEC Alpha OSF/1       */
+                   /*             ALPHA      ==> DEC Alpha             */
+                   /*                  (OSF1 and LINUX variants)       */
                    /*             M88K       ==> Motorola 88XX0        */
                    /*                  (CX_UX and DGUX)                */
+                   /*             S370       ==> 370-like machine      */
+                   /*                  running Amdahl UTS4             */
 
 
 /*
  *
  * DATASTART is the beginning of the data segment.
  * On UNIX systems, the collector will scan the area between DATASTART
- * and &end for root pointers.
+ * and DATAEND for root pointers.
+ *
+ * DATAEND, if not &end.
+ *
+ * ALIGN_DOUBLE of GC_malloc should return blocks aligned to twice
+ * the pointer size.
  *
  * STACKBOTTOM is the cool end of the stack, which is usually the
  * highest address in the stack.
 #       define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff))
 #       define STACKBOTTOM ((ptr_t) 0xffeffffc)
                              /* empirically determined.  seems to work. */
+#      include <unistd.h>
+#      define GETPAGESIZE() sysconf(_SC_PAGE_SIZE)
 #   endif
 #   ifdef SYSV
 #      define OS_TYPE "SYSV"
                        /* that the stack direction is incorrect.  Two  */
                        /* bytes down from 0x0 should be safe enough.   */
                        /*              --Parag                         */
+#      include <sys/mmu.h>
+#      define GETPAGESIZE() PAGESIZE   /* Is this still right? */
 #   endif
 #   ifdef AMIGA
 #      define OS_TYPE "AMIGA"
                /* STACKBOTTOM and DATASTART handled specially  */
                /* in os_dep.c                                  */
 #      define DATAEND  /* not needed */
+#      define GETPAGESIZE() 4096
 #   endif
 #   ifdef MACOS
 #     ifndef __LOWMEM__
                        /* see os_dep.c for details of global data segments. */
 #     define STACKBOTTOM ((ptr_t) LMGetCurStackBase())
 #     define DATAEND   /* not needed */
+#     define GETPAGESIZE() 4096
 #   endif
 #   ifdef NEXT
 #      define OS_TYPE "NEXT"
 #     define STACKBOTTOM ((ptr_t) LMGetCurStackBase())
 #     define DATAEND  /* not needed */
 #   endif
+#   ifdef LINUX
+#     define OS_TYPE "LINUX"
+#     define STACKBOTTOM ((ptr_t)0x80000000)
+#     define DATASTART GC_data_start
+      extern int _end;
+#     define DATAEND (&_end)
+#   endif
 # endif
 
 # ifdef VAX
 # ifdef SPARC
 #   define MACH_TYPE "SPARC"
 #   define ALIGNMENT 4 /* Required by hardware */
+#   define ALIGN_DOUBLE
     extern int etext;
 #   ifdef SUNOS5
 #      define OS_TYPE "SUNOS5"
        extern char * GC_SysVGetDataStart();
 #       define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, &_etext)
 #      define DATAEND (&_end)
+#      ifndef USE_MMAP
+#          define USE_MMAP
+#      endif
+#       ifdef USE_MMAP
+#         define HEAP_START (ptr_t)0x40000000
+#       else
+#        define HEAP_START DATAEND
+#       endif
 #      define PROC_VDB
 #      define HEURISTIC1
+#      include <unistd.h>
+#       define GETPAGESIZE()  sysconf(_SC_PAGESIZE)
+               /* getpagesize() appeared to be missing from at least one */
+               /* Solaris 5.4 installation.  Weird.                      */
 #   endif
 #   ifdef SUNOS4
 #      define OS_TYPE "SUNOS4"
 #   define ALIGNMENT 4 /* Appears to hold for all "32 bit" compilers   */
                        /* except Borland.  The -a4 option fixes        */
                        /* Borland.                                     */
+                        /* Ivan Demakov: For Watcom the option is -zp4. */
+#   ifndef SMALL_CONFIG
+#     define ALIGN_DOUBLE /* Not strictly necessary, but may give speed   */
+                         /* improvement on Pentiums.                     */
+#   endif
 #   ifdef SEQUENT
 #      define OS_TYPE "SEQUENT"
        extern int etext;
        extern char * GC_SysVGetDataStart();
 #       define DATASTART GC_SysVGetDataStart(0x1000, &etext)
 #      define STACKBOTTOM ((ptr_t)(&_start))
-#      define PROC_VDB
+/** At least in Solaris 2.5, PROC_VDB gives wrong values for dirty bits. */
+/*#    define PROC_VDB*/
+#      define DYNAMIC_LOADING
+#      ifndef USE_MMAP
+#          define USE_MMAP
+#      endif
+#       ifdef USE_MMAP
+#         define HEAP_START (ptr_t)0x40000000
+#       else
+#        define HEAP_START DATAEND
+#       endif
 #   endif
 #   ifdef SCO
 #      define OS_TYPE "SCO"
 #   endif
 #   ifdef LINUX
 #      define OS_TYPE "LINUX"
-       extern int etext;
-#       define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff))
 #      define STACKBOTTOM ((ptr_t)0xc0000000)
 #      define MPROTECT_VDB
+#       ifdef __ELF__
+#            define DYNAMIC_LOADING
+#           ifdef UNDEFINED    /* includes ro data */
+              extern int _etext;
+#              define DATASTART ((ptr_t)((((word) (&_etext)) + 0xfff) & ~0xfff))
+#           endif
+#           include <linux/version.h>
+#           include <features.h>
+#           if LINUX_VERSION_CODE >= 0x20000 && defined(__GLIBC__) && __GLIBC__ >= 2
+                extern int __data_start;
+#               define DATASTART ((ptr_t)(&__data_start))
+#           else
+                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.        */
+                             /* We could use _etext instead, but that  */
+                             /* would include .rodata, which may       */
+                             /* contain large read-only data tables    */
+                             /* that we'd rather not scan.             */
+#           endif
+            extern int _end;
+#           define DATAEND (&_end)
+#      else
+            extern int etext;
+#            define DATASTART ((ptr_t)((((word) (&etext)) + 0xfff) & ~0xfff))
+#       endif
+#   endif
+#   ifdef CYGWIN32
+#       define OS_TYPE "CYGWIN32"
+        extern int _bss_start__;
+#       define DATASTART       ((ptr_t)&_bss_start__)
+        extern int _data_end__;
+#       define DATAEND          ((ptr_t)&_data_end__)
+#      undef STACK_GRAN
+#       define STACK_GRAN 0x10000
+#       define HEURISTIC1
 #   endif
 #   ifdef OS2
 #      define OS_TYPE "OS2"
 #      define OS_TYPE "MSWIN32"
                /* STACKBOTTOM and DATASTART are handled specially in   */
                /* os_dep.c.                                            */
-#      define MPROTECT_VDB
+#       ifndef __WATCOMC__
+#        define MPROTECT_VDB
+#      endif
 #       define DATAEND  /* not needed */
 #   endif
 #   ifdef DJGPP
 #       define OS_TYPE "DJGPP"
+#       include "stubinfo.h"
         extern int etext;
-#       define DATASTART ((ptr_t)(&etext))
-#       define STACKBOTTOM ((ptr_t)0x00080000)
+        extern int _stklen;
+#       define DATASTART ((ptr_t)((((word) (&etext)) + 0x1ff) & ~0x1ff))
+#       define STACKBOTTOM ((ptr_t)((word) _stubinfo + _stubinfo->size \
+                                                     + _stklen))
+               /* This may not be right.  */
 #   endif
 #   ifdef FREEBSD
 #      define OS_TYPE "FREEBSD"
 #      define STACKBOTTOM ((ptr_t)0xc0000000)
 #      define DATAEND  /* not needed */
 #   endif
+#   ifdef DOS4GW
+#     define OS_TYPE "DOS4GW"
+      /* Get_DATASTART, Get_DATAEND, Get_STACKBOTTOM
+       *      Defined in gc-watcom.asm
+       */
+      extern char* Get_DATASTART (void);
+      extern char* Get_DATAEND (void);
+      extern char* Get_STACKBOTTOM (void);
+#     pragma aux Get_DATASTART "*" value [eax];
+#     pragma aux Get_DATAEND "*" value [eax];
+#     pragma aux Get_STACKBOTTOM "*" value [eax];
+#     define DATASTART ((ptr_t) Get_DATASTART())
+#     define STACKBOTTOM ((ptr_t) Get_STACKBOTTOM())
+#     define DATAEND ((ptr_t) Get_DATAEND())
+#   endif
 # endif
 
 # ifdef NS32K
 
 # ifdef MIPS
 #   define MACH_TYPE "MIPS"
-#   define ALIGNMENT 4 /* Required by hardware */
-#   define DATASTART 0x10000000
+#   ifndef IRIX5
+#     define DATASTART (ptr_t)0x10000000
                              /* Could probably be slightly higher since */
-                             /* startup code allocates lots of junk     */
+                             /* startup code allocates lots of stuff.   */
+#   else
+      extern int _fdata;
+#     define DATASTART ((ptr_t)(&_fdata))
+#     ifdef USE_MMAP
+#         define HEAP_START (ptr_t)0x40000000
+#     else
+#        define HEAP_START DATASTART
+#     endif
+                             /* Lowest plausible heap address.         */
+                             /* In the MMAP case, we map there.        */
+                             /* In either case it is used to identify  */
+                             /* heap sections so they're not           */
+                             /* considered as roots.                   */
+#   endif /* IRIX5 */
 #   define HEURISTIC2
+/* #   define STACKBOTTOM ((ptr_t)0x7fff8000)  sometimes also works.  */
 #   ifdef ULTRIX
 #      define OS_TYPE "ULTRIX"
+#       define ALIGNMENT 4
 #   endif
 #   ifdef RISCOS
 #      define OS_TYPE "RISCOS"
+#      define ALIGNMENT 4  /* Required by hardware */
 #   endif
 #   ifdef IRIX5
 #      define OS_TYPE "IRIX5"
-#      define MPROTECT_VDB
-               /* The above is dubious.  Mprotect and signals do work, */
-               /* and dirty bits are implemented under IRIX5.  But,    */
-               /* at least under IRIX5.2, mprotect seems to be so      */
-               /* slow relative to the hardware that incremental       */
-               /* collection is likely to be rarely useful.            */
+#       ifndef IRIX_THREADS
+#          define MPROTECT_VDB
+#       endif
+#       ifdef _MIPS_SZPTR
+#        define CPP_WORDSZ _MIPS_SZPTR
+#        define ALIGNMENT (_MIPS_SZPTR/8)
+#        if CPP_WORDSZ != 64
+#          define ALIGN_DOUBLE
+#        endif
+#      else
+#         define ALIGNMENT 4
+#        define ALIGN_DOUBLE
+#      endif
 #      define DYNAMIC_LOADING
 #   endif
 # endif
 #   define MACH_TYPE "RS6000"
 #   define ALIGNMENT 4
 #   define DATASTART ((ptr_t)0x20000000)
-#   define STACKBOTTOM ((ptr_t)0x2ff80000)
+    extern int errno;
+#   define STACKBOTTOM ((ptr_t)((ulong)&errno + 2*sizeof(int)))
+#   define DYNAMIC_LOADING
+       /* For really old versions of AIX, this may have to be removed. */
 # endif
 
 # ifdef HP_PA
 #   define MACH_TYPE "HP_PA"
 #   define ALIGNMENT 4
+#   define ALIGN_DOUBLE
     extern int __data_start;
 #   define DATASTART ((ptr_t)(&__data_start))
-#   define HEURISTIC2
+#   if 0
+       /* The following appears to work for 7xx systems running HP/UX  */
+       /* 9.xx Furthermore, it might result in much faster             */
+       /* collections than HEURISTIC2, which may involve scanning      */
+       /* segments that directly precede the stack.  It is not the     */
+       /* default, since it may not work on older machine/OS           */
+       /* combinations. (Thanks to Raymond X.T. Nijssen for uncovering */
+       /* this.)                                                       */
+#       define STACKBOTTOM ((ptr_t) 0x7b033000)  /* from /etc/conf/h/param.h */
+#   else
+#       define HEURISTIC2
+#   endif
 #   define STACK_GROWS_UP
+#   define DYNAMIC_LOADING
+#   include <unistd.h>
+#   define GETPAGESIZE() sysconf(_SC_PAGE_SIZE)
+       /* They misspelled the Posix macro?     */
 # endif
 
 # ifdef ALPHA
 #   define MACH_TYPE "ALPHA"
 #   define ALIGNMENT 8
-#   define DATASTART ((ptr_t) 0x140000000)
-#   define HEURISTIC2
+#   ifdef OSF1
+#      define OS_TYPE "OSF1"
+#      define DATASTART ((ptr_t) 0x140000000)
+#      define HEURISTIC2
        /* Normally HEURISTIC2 is too conervative, since                */
        /* the text segment immediately follows the stack.              */
        /* Hence we give an upper pound.                                */
-    extern __start;
-#   define HEURISTIC2_LIMIT ((ptr_t)((word)(&__start) & ~(getpagesize()-1)))
-#   define CPP_WORDSZ 64
-#   define MPROTECT_VDB
-#   define DYNAMIC_LOADING
+       extern __start;
+#      define HEURISTIC2_LIMIT ((ptr_t)((word)(&__start) & ~(getpagesize()-1)))
+#      define CPP_WORDSZ 64
+#      define MPROTECT_VDB
+#      define DYNAMIC_LOADING
+#   endif
+#   ifdef LINUX
+#       define OS_TYPE "LINUX"
+#       define CPP_WORDSZ 64
+#       define STACKBOTTOM ((ptr_t) 0x120000000)
+#       ifdef __ELF__
+            extern int __data_start;
+#           define DATASTART &__data_start
+#           define DYNAMIC_LOADING
+#       else
+#           define DATASTART ((ptr_t) 0x140000000)
+#       endif
+       extern int _end;
+#      define DATAEND (&_end)
+       /* As of 1.3.90, I couldn't find a way to retrieve the correct  */
+       /* fault address from a signal handler.                         */
+       /* Hence MPROTECT_VDB is broken.                                */
+#   endif
 # endif
 
 # ifdef M88K
 #   define MACH_TYPE "M88K"
 #   define ALIGNMENT 4
+#   define ALIGN_DOUBLE
+    extern int etext;
 #   ifdef CX_UX
+#      define OS_TYPE "CX_UX"
 #       define DATASTART ((((word)&etext + 0x3fffff) & ~0x3fffff) + 0x10000)
 #   endif
 #   ifdef  DGUX
+#      define OS_TYPE "DGUX"
        extern char * GC_SysVGetDataStart();
 #       define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, &etext)
 #   endif
 #   define STACKBOTTOM ((char*)0xf0000000) /* determined empirically */
 # endif
 
+# ifdef S370
+#   define MACH_TYPE "S370"
+#   define OS_TYPE "UTS4"
+#   define ALIGNMENT 4 /* Required by hardware */
+    extern int etext;
+       extern int _etext;
+       extern int _end;
+       extern char * GC_SysVGetDataStart();
+#       define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, &_etext)
+#      define DATAEND (&_end)
+#      define HEURISTIC2
+# endif
+
 # ifndef STACK_GROWS_UP
 #   define STACK_GROWS_DOWN
 # endif
 #   define DATAEND (&end)
 # endif
 
-# if defined(SUNOS5) || defined(DRSNX)
+# if defined(SVR4) && !defined(GETPAGESIZE)
+#    include <unistd.h>
+#    define GETPAGESIZE()  sysconf(_SC_PAGESIZE)
+# endif
+
+# ifndef GETPAGESIZE
+#   if defined(SUNOS5) || defined(IRIX5)
+#      include <unistd.h>
+#   endif
+#   define GETPAGESIZE() getpagesize()
+# endif
+
+# if defined(SUNOS5) || defined(DRSNX) || defined(UTS4)
     /* OS has SVR4 generic features.  Probably others also qualify.    */
 #   define SVR4
 # endif
 #   define DEFAULT_VDB
 # endif
 
+# if defined(IRIX_THREADS) && !defined(IRIX5)
+--> inconsistent configuration
+# endif
+# if defined(SOLARIS_THREADS) && !defined(SUNOS5)
+--> inconsistent configuration
+# endif
+# if defined(PCR) || defined(SRC_M3) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || defined(IRIX_THREADS)
+#   define THREADS
+# endif
+
 # if defined(SPARC)
 #   define SAVE_CALL_CHAIN
+#   define ASM_CLEAR_CODE      /* Stack clearing is crucial, and we    */
+                               /* include assembly code to do it well. */
 # endif
 
 # endif
index 49a916d..a70032a 100644 (file)
@@ -57,7 +57,7 @@ typedef GC_signed_word signed_word;
 #   if defined(_SGI_SOURCE) && !defined(_BOOL)
        typedef int bool;
 #   endif
-#   if defined(__SUNPRO_CC) && __SUNPRO_CC <= 0x410
+#   if defined(__SUNPRO_CC) && __SUNPRO_CC <= 0x420
        typedef int bool;
 #   endif
 #   if defined(__cplusplus) && defined(_MSC_VER) && _MSC_VER <= 1020
@@ -174,6 +174,12 @@ typedef char * ptr_t;      /* A generic pointer to which we can add        */
 #   define GATHERSTATS
 #endif
 
+#ifdef FINALIZE_ON_DEMAND
+#   define GC_INVOKE_FINALIZERS()
+#else
+#   define GC_INVOKE_FINALIZERS() (void)GC_invoke_finalizers()
+#endif
+
 #define MERGE_SIZES /* Round up some object sizes, so that fewer distinct */
                    /* free lists are actually maintained.  This applies  */
                    /* only to the top level routines in misc.c, not to   */
@@ -1183,10 +1189,7 @@ extern void (*GC_start_call_back)(/* void */);
 void GC_push_regs();   /* Push register contents onto mark stack.      */
 void GC_remark();      /* Mark from all marked objects.  Used  */
                        /* only if we had to drop something.    */
-void GC_push_one(/*p*/);       /* If p points to an object, mark it    */
-                               /* and push contents on the mark stack  */
-/* Ivan Demakov: Watcom C error'ed without this */
-# if defined(MSWIN32) && defined(__WATCOMC__)
+# if defined(MSWIN32)
   void __cdecl GC_push_one();
 # else
   void GC_push_one(/*p*/);    /* If p points to an object, mark it    */
@@ -1379,8 +1382,6 @@ void GC_finalize();       /* Perform all indicated finalization actions   */
                        /* Unreachable finalizable objects are enqueued */
                        /* for processing by GC_invoke_finalizers.      */
                        /* Invoked with lock.                           */
-void GC_invoke_finalizers();   /* Run eligible finalizers.     */
-                               /* Invoked without lock.        */      
                        
 void GC_add_to_heap(/*p, bytes*/);
                        /* Add a HBLKSIZE aligned chunk to the heap.    */
@@ -1427,7 +1428,12 @@ void GC_print_static_roots();
 void GC_dump();
 
 /* Make arguments appear live to compiler */
-GC_API void GC_noop();
+# ifdef __WATCOMC__
+  void GC_noop(void*, ...);
+# else
+  GC_API void GC_noop();
+# endif
+
 void GC_noop1(/* word arg */);
 
 /* Logging and diagnostic output:      */
index 5e191d1..661a2c0 100644 (file)
@@ -65,6 +65,10 @@ typedef struct GC_Thread_Rep {
                                  /* guaranteed to be dead, but we may  */
                                  /* not yet have registered the join.) */
     pthread_t id;
+    word stop;
+#      define NOT_STOPPED 0
+#      define PLEASE_STOP 1
+#      define STOPPED 2
     word flags;
 #      define FINISHED 1       /* Thread has exited.   */
 #      define DETACHED 2       /* Thread is intended to be detached.   */
@@ -90,7 +94,6 @@ GC_thread GC_lookup_thread(pthread_t id);
 # define SIG_SUSPEND (SIGRTMIN + 6)
 
 pthread_mutex_t GC_suspend_lock = PTHREAD_MUTEX_INITIALIZER;
-volatile unsigned GC_n_stopped = 0;
                                /* Number of threads stopped so far     */
 pthread_cond_t GC_suspend_ack_cv = PTHREAD_COND_INITIALIZER;
 pthread_cond_t GC_continue_cv = PTHREAD_COND_INITIALIZER;
@@ -110,8 +113,13 @@ void GC_suspend_handler(int sig)
     /* of a thread which holds the allocation lock in order    */
     /* to stop the world.  Thus concurrent modification of the */
     /* data structure is impossible.                           */
+    if (PLEASE_STOP != me -> stop) {
+       /* Misdirected signal.  */
+       pthread_mutex_unlock(&GC_suspend_lock);
+       return;
+    }
     me -> stack_ptr = (ptr_t)(&dummy);
-    GC_n_stopped++;
+    me -> stop = STOPPED;
     pthread_cond_signal(&GC_suspend_ack_cv);
     pthread_cond_wait(&GC_continue_cv, &GC_suspend_lock);
     pthread_mutex_unlock(&GC_suspend_lock);
@@ -204,7 +212,8 @@ GC_thread GC_new_thread(pthread_t id)
     result -> id = id;
     result -> next = GC_threads[hv];
     GC_threads[hv] = result;
-    /* result -> flags = 0; */
+    /* result -> flags = 0;     */
+    /* result -> stop = 0;     */
     return(result);
 }
 
@@ -271,21 +280,23 @@ void GC_stop_world()
     pthread_t my_thread = pthread_self();
     register int i;
     register GC_thread p;
-    register int n_live_threads = 0;
     register int result;
+    struct timespec timeout;
     
-    GC_n_stopped = 0;
     for (i = 0; i < THREAD_TABLE_SZ; i++) {
       for (p = GC_threads[i]; p != 0; p = p -> next) {
         if (p -> id != my_thread) {
-            if (p -> flags & FINISHED) continue;
-            n_live_threads++;
+            if (p -> flags & FINISHED) {
+               p -> stop = STOPPED;
+               continue;
+           }
+           p -> stop = PLEASE_STOP;
             result = pthread_kill(p -> id, SIG_SUSPEND);
            /* GC_printf1("Sent signal to 0x%x\n", p -> id); */
            switch(result) {
                 case ESRCH:
                     /* Not really there anymore.  Possible? */
-                    n_live_threads--;
+                    p -> stop = STOPPED;
                     break;
                 case 0:
                     break;
@@ -296,10 +307,25 @@ void GC_stop_world()
       }
     }
     pthread_mutex_lock(&GC_suspend_lock);
-    while(GC_n_stopped < n_live_threads) {
-        /* GC_printf3("\nwaiting:%d %d %d\n", GC_gc_no,
-                       GC_n_stopped, n_live_threads); */
-       pthread_cond_wait(&GC_suspend_ack_cv, &GC_suspend_lock);
+    for (i = 0; i < THREAD_TABLE_SZ; i++) {
+      for (p = GC_threads[i]; p != 0; p = p -> next) {
+        while (p -> id != my_thread && p -> stop != STOPPED) {
+           clock_gettime(CLOCK_REALTIME, &timeout);
+            timeout.tv_nsec += 50000000; /* 50 msecs */
+            if (timeout.tv_nsec >= 1000000000) {
+                timeout.tv_nsec -= 1000000000;
+                ++timeout.tv_sec;
+            }
+            result = pthread_cond_timedwait(&GC_suspend_ack_cv,
+                                           &GC_suspend_lock,
+                                            &timeout);
+            if (result == ETIMEDOUT) {
+                /* Signal was lost or misdirected.  Try again.      */
+                /* Duplicate signals should be benign.              */
+                result = pthread_kill(p -> id, SIG_SUSPEND);
+           }
+       }
+      }
     }
     pthread_mutex_unlock(&GC_suspend_lock);
     /* GC_printf1("World stopped 0x%x\n", pthread_self()); */
@@ -308,7 +334,15 @@ void GC_stop_world()
 /* Caller holds allocation lock.       */
 void GC_start_world()
 {
+    GC_thread p;
+    unsigned i;
+
     /* GC_printf0("World starting\n"); */
+    for (i = 0; i < THREAD_TABLE_SZ; i++) {
+      for (p = GC_threads[i]; p != 0; p = p -> next) {
+       p -> stop = NOT_STOPPED;
+      }
+    }
     pthread_mutex_lock(&GC_suspend_lock);
     /* All other threads are at pthread_cond_wait in signal handler.   */
     /* Otherwise we couldn't have acquired the lock.                   */
index 6b8c092..49e03ce 100644 (file)
--- a/malloc.c
+++ b/malloc.c
@@ -115,7 +115,7 @@ register int k;
     ptr_t result;
     DCL_LOCK_STATE;
 
-    GC_invoke_finalizers();
+    GC_INVOKE_FINALIZERS();
     DISABLE_SIGNALS();
     LOCK();
     result = GC_generic_malloc_inner(lb, k);
index a1fc2f4..598fdfa 100644 (file)
--- a/mallocx.c
+++ b/mallocx.c
@@ -76,7 +76,7 @@ register int k;
     register ptr_t result;
     DCL_LOCK_STATE;
     
-    GC_invoke_finalizers();
+    GC_INVOKE_FINALIZERS();
     DISABLE_SIGNALS();
     LOCK();
     result = GC_generic_malloc_inner_ignore_off_page(lb,k);
@@ -139,7 +139,7 @@ register ptr_t *opp;
 register struct obj_kind * kind = GC_obj_kinds + k;
 DCL_LOCK_STATE;
 
-    GC_invoke_finalizers();
+    GC_INVOKE_FINALIZERS();
     DISABLE_SIGNALS();
     LOCK();
     opp = &(kind -> ok_freelist[lw]);
@@ -192,7 +192,7 @@ DCL_LOCK_STATE;
         return(op);
     }
     lw = ALIGNED_WORDS(lb);
-    GC_invoke_finalizers();
+    GC_INVOKE_FINALIZERS();
     DISABLE_SIGNALS();
     LOCK();
     opp = &(GC_obj_kinds[k].ok_freelist[lw]);
index 8e12d53..35d200d 100644 (file)
@@ -378,8 +378,8 @@ GC_PTR finish;
          return;
       }
       next_index = next - excl_table;
-      for (i = excl_table_entries - 1; i >= next_index; --i) {
-       excl_table[i+1] = excl_table[i];
+      for (i = excl_table_entries; i > next_index; --i) {
+       excl_table[i] = excl_table[i-1];
       }
     } else {
       next_index = excl_table_entries;
index bf7f61a..03c4b98 100644 (file)
@@ -9,6 +9,7 @@
 #   define RAOFF FRAMESZ-SZREG
 #   define GPOFF FRAMESZ-(2*SZREG)
     NESTED(GC_push_regs, FRAMESZ, ra)
+    .mask 0x80000000,-SZREG    # inform debugger of saved ra loc
     move       t0,gp
     SETUP_GPX(t8)
     PTR_SUBU   sp,FRAMESZ
index 3c5ae5a..2ec7905 100644 (file)
--- a/os_dep.c
+++ b/os_dep.c
@@ -14,6 +14,9 @@
 
 # include "gc_priv.h"
 
+# include <stdio.h>
+# include <signal.h>
+
 # if defined(LINUX) && !defined(POWERPC)
 #   include <linux/version.h>
 #   if (LINUX_VERSION_CODE <= 0x10400)
 #     define __KERNEL__
 #     include <asm/signal.h>
 #     undef __KERNEL__
-#   elif (LINUX_VERSION_CODE < 0x20100)
-#     include <asm/sigcontext.h>
+#   else
+      /* Kernels prior to 2.1.1 defined struct sigcontext_struct instead of */
+      /* struct sigcontext.  libc6 (glibc2) uses "struct sigcontext" in     */
+      /* prototypes, so we have to include the top-level sigcontext.h to    */
+      /* make sure the former gets defined to be the latter if appropriate. */
+#     include <features.h>
+#     if 2 <= __GLIBC__
+#       include <sigcontext.h>
+#     else /* not 2 <= __GLIBC__ */
+        /* libc5 doesn't have <sigcontext.h>: go directly with the kernel   */
+        /* one.  Check LINUX_VERSION_CODE to see which we should reference. */
+#       include <asm/sigcontext.h>
+#     endif /* 2 <= __GLIBC__ */
 #   endif
 # endif
 # if !defined(OS2) && !defined(PCR) && !defined(AMIGA) && !defined(MACOS)
@@ -34,8 +48,6 @@
 #      include <unistd.h>
 #   endif
 # endif
-# include <stdio.h>
-# include <signal.h>
 
 /* Blatantly OS dependent routines, except for those that are related  */
 /* dynamic loading.                                                    */
@@ -455,7 +467,7 @@ ptr_t GC_get_stack_base()
        typedef void (*handler)();
 #   endif
 
-#   ifdef SUNOS5SIGS
+#   if defined(SUNOS5SIGS) || defined(IRIX5)
        static struct sigaction oldact;
 #   else
         static handler old_segv_handler, old_bus_handler;
@@ -463,7 +475,7 @@ ptr_t GC_get_stack_base()
     
     void GC_setup_temporary_fault_handler()
     {
-#      ifdef SUNOS5SIGS
+#      if defined(SUNOS5SIGS) || defined(IRIX5)
          struct sigaction      act;
 
          act.sa_handler        = GC_fault_handler;
@@ -475,7 +487,14 @@ ptr_t GC_get_stack_base()
           /* signal mask.                                               */
 
          (void) sigemptyset(&act.sa_mask);
-         (void) sigaction(SIGSEGV, &act, &oldact);
+#        ifdef IRIX_THREADS
+               /* Older versions have a bug related to retrieving and  */
+               /* and setting a handler at the same time.              */
+               (void) sigaction(SIGSEGV, 0, &oldact);
+               (void) sigaction(SIGSEGV, &act, 0);
+#        else
+               (void) sigaction(SIGSEGV, &act, &oldact);
+#        endif /* IRIX_THREADS */
 #      else
          old_segv_handler = signal(SIGSEGV, GC_fault_handler);
 #        ifdef SIGBUS
@@ -486,7 +505,7 @@ ptr_t GC_get_stack_base()
     
     void GC_reset_fault_handler()
     {
-#       ifdef SUNOS5SIGS
+#       if defined(SUNOS5SIGS) || defined(IRIX5)
          (void) sigaction(SIGSEGV, &oldact, 0);
 #       else
          (void) signal(SIGSEGV, old_segv_handler);
@@ -951,14 +970,14 @@ void GC_register_data_segments()
 ptr_t GC_unix_get_mem(bytes)
 word bytes;
 {
-    caddr_t cur_brk = sbrk(0);
+    caddr_t cur_brk = (caddr_t)sbrk(0);
     caddr_t result;
     SBRK_ARG_T lsbs = (word)cur_brk & (GC_page_size-1);
     static caddr_t my_brk_val = 0;
     
     if ((SBRK_ARG_T)bytes < 0) return(0); /* too big */
     if (lsbs != 0) {
-        if(sbrk(GC_page_size - lsbs) == (caddr_t)(-1)) return(0);
+        if((caddr_t)(sbrk(GC_page_size - lsbs)) == (caddr_t)(-1)) return(0);
     }
     if (cur_brk == my_brk_val) {
        /* Use the extra block we allocated last time. */
@@ -1517,7 +1536,7 @@ SIG_PF GC_old_segv_handler;       /* Also old MSWIN32 ACCESS_VIOLATION filter */
             set_pht_entry_from_index(GC_dirty_pages, index);
         }
         UNPROTECT(h, GC_page_size);
-#      if defined(IRIX5) || defined(OSF1) || defined(LINUX)
+#      if defined(OSF1) || defined(LINUX)
            /* These reset the signal handler each time by default. */
            signal(SIGSEGV, (SIG_PF) GC_write_fault_handler);
 #      endif
@@ -1565,10 +1584,15 @@ struct hblk *h;
 
 void GC_dirty_init()
 {
-#if defined(SUNOS5SIGS)
+#if defined(SUNOS5SIGS) || defined(IRIX5)
     struct sigaction   act, oldact;
-    act.sa_sigaction   = GC_write_fault_handler;
-    act.sa_flags       = SA_RESTART | SA_SIGINFO;
+#   ifdef IRIX5
+       act.sa_flags    = SA_RESTART;
+        act.sa_handler  = GC_write_fault_handler;
+#   else
+       act.sa_flags    = SA_RESTART | SA_SIGINFO;
+        act.sa_sigaction = GC_write_fault_handler;
+#   endif
     (void)sigemptyset(&act.sa_mask); 
 #endif
 #   ifdef PRINTSTATS
@@ -1591,7 +1615,7 @@ void GC_dirty_init()
 #      endif
       }
 #   endif
-#   if defined(IRIX5) || defined(OSF1) || defined(SUNOS4) || defined(LINUX)
+#   if defined(OSF1) || defined(SUNOS4) || defined(LINUX)
       GC_old_segv_handler = signal(SIGSEGV, (SIG_PF)GC_write_fault_handler);
       if (GC_old_segv_handler == SIG_IGN) {
         GC_err_printf0("Previously ignored segmentation violation!?");
@@ -1603,8 +1627,13 @@ void GC_dirty_init()
 #      endif
       }
 #   endif
-#   if defined(SUNOS5SIGS)
-      sigaction(SIGSEGV, &act, &oldact);
+#   if defined(SUNOS5SIGS) || defined(IRIX5)
+#     ifdef IRIX_THREADS
+       sigaction(SIGSEGV, 0, &oldact);
+       sigaction(SIGSEGV, &act, 0);
+#     else
+       sigaction(SIGSEGV, &act, &oldact);
+#     endif
       if (oldact.sa_flags & SA_SIGINFO) {
           GC_old_segv_handler = (SIG_PF)(oldact.sa_sigaction);
       } else {
index 6e480ec..516ffaf 100644 (file)
--- a/reclaim.c
+++ b/reclaim.c
@@ -20,7 +20,7 @@ signed_word GC_mem_found = 0;
                        /* Number of words of memory reclaimed     */
 
 # ifdef FIND_LEAK
-static report_leak(p, sz)
+static void report_leak(p, sz)
 ptr_t p;
 word sz;
 {
@@ -40,7 +40,7 @@ word sz;
 
 #   define FOUND_FREE(hblk, word_no) \
       if (abort_if_found) { \
-         report_leak((long)hblk + WORDS_TO_BYTES(word_no), \
+         report_leak((ptr_t)hblk + WORDS_TO_BYTES(word_no), \
                     HDR(hblk) -> hb_sz); \
       }
 # else
index cc72b2d..e5e31d7 100644 (file)
@@ -36,6 +36,7 @@
 # define _CLASSIC_XOPEN_TYPES
 # include <unistd.h>
 # include <errno.h>
+# include "solaris_threads.h"
 
 #undef pthread_join
 #undef pthread_create
@@ -163,7 +164,7 @@ GC_pthread_create(pthread_t *new_thread,
 # else
 
 #ifndef LINT
-  int GC_no_sunOS_threads;
+  int GC_no_sunOS_pthreads;
 #endif
 
 # endif /* SOLARIS_THREADS */
diff --git a/test.c b/test.c
index cdc8b7f..9d2457c 100644 (file)
--- a/test.c
+++ b/test.c
@@ -646,7 +646,7 @@ void typed_test()
 #   endif
     GC_descr d3 = GC_make_descriptor(&bm_large, 32);
     GC_descr d4 = GC_make_descriptor(bm_huge, 320);
-    GC_word * x = GC_malloc_explicitly_typed(2000, d4);
+    GC_word * x = (GC_word *)GC_malloc_explicitly_typed(2000, d4);
     register int i;
     
     old = 0;
@@ -811,7 +811,7 @@ void run_one_test()
     LOCK();
     n_tests++;
     UNLOCK();
-    /* GC_printf1("Finished %x\n", pthread_self());    */
+    /* GC_printf1("Finished %x\n", pthread_self()); */
 }
 
 void check_heap_stats()
@@ -819,6 +819,7 @@ void check_heap_stats()
     unsigned long max_heap_sz;
     register int i;
     int still_live;
+    int late_finalize_count = 0;
     
     if (sizeof(char *) > 4) {
         max_heap_sz = 13000000;
@@ -836,11 +837,18 @@ void check_heap_stats()
       while (GC_collect_a_little()) { }
       for (i = 0; i < 16; i++) {
         GC_gcollect();
+        late_finalize_count += GC_invoke_finalizers();
       }
     (void)GC_printf1("Completed %lu tests\n", (unsigned long)n_tests);
     (void)GC_printf2("Finalized %lu/%lu objects - ",
                     (unsigned long)finalized_count,
                     (unsigned long)finalizable_count);
+#   ifdef FINALIZE_ON_DEMAND
+       if (finalized_count != late_finalize_count) {
+            (void)GC_printf0("Demand finalization error\n");
+           FAIL;
+       }
+#   endif
     if (finalized_count > finalizable_count
         || finalized_count < finalizable_count/2) {
         (void)GC_printf0("finalization is probably broken\n");
@@ -857,8 +865,7 @@ void check_heap_stats()
     i = finalizable_count - finalized_count - still_live;
     if (0 != i) {
         (void)GC_printf2
-            ("%lu disappearing links remain and %lu more objects "
-            "were not finalized\n",
+            ("%lu disappearing links remain and %lu more objects were not finalized\n",
              (unsigned long) still_live, (unsigned long)i);
         if (i > 10) {
            GC_printf0("\tVery suspicious!\n");
@@ -1105,7 +1112,9 @@ main()
     pthread_attr_init(&attr);
     pthread_attr_setstacksize(&attr, 1000000);
     n_tests = 0;
-    GC_enable_incremental();
+#   ifdef MPROTECT_VDB
+       GC_enable_incremental();
+#   endif
     (void) GC_set_warn_proc(warn_proc);
     if ((code = pthread_create(&th1, &attr, thr_run_one_test, 0)) != 0) {
        (void)GC_printf1("Thread 1 creation failed %lu\n", (unsigned long)code);
index 058022c..036795c 100644 (file)
@@ -219,7 +219,11 @@ int main( int argc, char* argv[] ) {
             if (0 == i % 10) {
                 B::Deleting( 1 );
                 delete b;
-                B::Deleting( 0 );}}
+                B::Deleting( 0 );}
+#          ifdef FINALIZE_ON_DEMAND
+             GC_invoke_finalizers();
+#          endif
+           }
 
             /* Make sure the uncollectable As and Bs are still there. */
         for (i = 0; i < 1000; i++) {
@@ -230,7 +234,12 @@ int main( int argc, char* argv[] ) {
             b->Test( i );
             B::Deleting( 1 );
             delete b;
-            B::Deleting( 0 );}
+            B::Deleting( 0 );
+#          ifdef FINALIZE_ON_DEMAND
+                GC_invoke_finalizers();
+#          endif
+
+           }
 
             /* Make sure most of the finalizable Cs, Ds, and Fs have
             gone away. */
index 6bda104..7b3f2c9 100644 (file)
--- a/version.h
+++ b/version.h
@@ -1,6 +1,6 @@
 #define GC_VERSION_MAJOR 4
-#define GC_VERSION_MINOR 12
-#define GC_ALPHA_VERSION GC_NOT_ALPHA
+#define GC_VERSION_MINOR 13
+#define GC_ALPHA_VERSION 1
 
 #   define GC_NOT_ALPHA 0xff