summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Boehm <boehm@acm.org>1998-02-17 00:00:00 +0000
committerIvan Maidanski <ivmai@mail.ru>2014-05-17 17:36:52 +0400
commitdbd0bc33ea3c51b4d60cee1f1ff41673ccecb1a6 (patch)
tree7e434d7454110f696b1f8d0905ee169ec2806088
parent6d49f3f70f440e85b36067a49a8de52d5099cc43 (diff)
downloadbdwgc-dbd0bc33ea3c51b4d60cee1f1ff41673ccecb1a6.tar.gz
gc4.13alpha1 tarball importgc4_13alpha1
-rw-r--r--Makefile15
-rw-r--r--README31
-rw-r--r--README.sgi9
-rw-r--r--alloc.c4
-rw-r--r--config.h31
-rw-r--r--cord/cordxtra.c6
-rw-r--r--cord/gc.h16
-rw-r--r--dbg_mlc.c38
-rw-r--r--finalize.c7
-rw-r--r--gc.h16
-rw-r--r--gc_alloc.h10
-rw-r--r--gc_priv.h22
-rw-r--r--include/gc.h16
-rw-r--r--include/gc_alloc.h10
-rw-r--r--include/private/config.h313
-rw-r--r--include/private/gc_priv.h22
-rw-r--r--irix_threads.c58
-rw-r--r--malloc.c2
-rw-r--r--mallocx.c6
-rw-r--r--mark_rts.c4
-rw-r--r--mips_sgi_mach_dep.s1
-rw-r--r--os_dep.c63
-rw-r--r--reclaim.c4
-rw-r--r--solaris_pthreads.c3
-rw-r--r--test.c19
-rw-r--r--test_cpp.cc13
-rw-r--r--version.h4
27 files changed, 589 insertions, 154 deletions
diff --git a/Makefile b/Makefile
index 87fcc3f7..8e531188 100644
--- 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 a1d39985..94604cf2 100644
--- 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.
diff --git a/README.sgi b/README.sgi
index 3174e9c9..f21eeb7c 100644
--- a/README.sgi
+++ b/README.sgi
@@ -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 d9584e1e..b7cb6f54 100644
--- 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);
}
diff --git a/config.h b/config.h
index cffbf6e8..d5d618c5 100644
--- a/config.h
+++ b/config.h
@@ -493,6 +493,10 @@
# 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"
@@ -572,15 +576,18 @@
# 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 */
@@ -589,6 +596,7 @@
/* 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
@@ -767,6 +775,7 @@
# define DYNAMIC_LOADING
# include <unistd.h>
# define GETPAGESIZE() sysconf(_SC_PAGE_SIZE)
+ /* They misspelled the Posix macro? */
# endif
# ifdef ALPHA
@@ -852,14 +861,14 @@
# 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
diff --git a/cord/cordxtra.c b/cord/cordxtra.c
index 8566e146..b306fbac 100644
--- a/cord/cordxtra.c
+++ b/cord/cordxtra.c
@@ -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)
diff --git a/cord/gc.h b/cord/gc.h
index 1e00c2f5..23037246 100644
--- 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
diff --git a/dbg_mlc.c b/dbg_mlc.c
index 094614a5..445f123f 100644
--- 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);
}
diff --git a/finalize.c b/finalize.c
index e5551944..d825bf91 100644
--- a/finalize.c
+++ b/finalize.c
@@ -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 1e00c2f5..23037246 100644
--- 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
diff --git a/gc_alloc.h b/gc_alloc.h
index 85cb7cdb..645748b0 100644
--- a/gc_alloc.h
+++ b/gc_alloc.h
@@ -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;
diff --git a/gc_priv.h b/gc_priv.h
index 49a916d0..a70032a8 100644
--- 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: */
diff --git a/include/gc.h b/include/gc.h
index 1e00c2f5..23037246 100644
--- a/include/gc.h
+++ b/include/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
diff --git a/include/gc_alloc.h b/include/gc_alloc.h
index 85cb7cdb..645748b0 100644
--- a/include/gc_alloc.h
+++ b/include/gc_alloc.h
@@ -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;
diff --git a/include/private/config.h b/include/private/config.h
index 62492c3e..d5d618c5 100644
--- a/include/private/config.h
+++ b/include/private/config.h
@@ -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
@@ -49,11 +49,11 @@
# 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
@@ -119,8 +119,18 @@
# 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)
@@ -178,21 +188,47 @@
/* 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 */
@@ -225,9 +261,12 @@
/* 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 */
/*
@@ -249,7 +288,12 @@
*
* 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.
@@ -334,6 +378,8 @@
# 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"
@@ -353,12 +399,15 @@
/* 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__
@@ -368,6 +417,7 @@
/* 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"
@@ -389,6 +439,13 @@
# 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
@@ -417,6 +474,7 @@
# ifdef SPARC
# define MACH_TYPE "SPARC"
# define ALIGNMENT 4 /* Required by hardware */
+# define ALIGN_DOUBLE
extern int etext;
# ifdef SUNOS5
# define OS_TYPE "SUNOS5"
@@ -425,8 +483,20 @@
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"
@@ -463,6 +533,11 @@
# 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;
@@ -475,7 +550,17 @@
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"
@@ -487,10 +572,47 @@
# 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"
@@ -503,14 +625,20 @@
# 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"
@@ -537,6 +665,21 @@
# 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
@@ -553,25 +696,49 @@
# 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
@@ -580,46 +747,102 @@
# 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
@@ -637,7 +860,19 @@
# 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
@@ -680,8 +915,20 @@
# 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
diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h
index 49a916d0..a70032a8 100644
--- a/include/private/gc_priv.h
+++ b/include/private/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: */
diff --git a/irix_threads.c b/irix_threads.c
index 5e191d11..661a2c0c 100644
--- a/irix_threads.c
+++ b/irix_threads.c
@@ -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. */
diff --git a/malloc.c b/malloc.c
index 6b8c0921..49e03cee 100644
--- 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);
diff --git a/mallocx.c b/mallocx.c
index a1fc2f4d..598fdfa6 100644
--- 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]);
diff --git a/mark_rts.c b/mark_rts.c
index 8e12d533..35d200d3 100644
--- a/mark_rts.c
+++ b/mark_rts.c
@@ -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;
diff --git a/mips_sgi_mach_dep.s b/mips_sgi_mach_dep.s
index bf7f61a5..03c4b980 100644
--- a/mips_sgi_mach_dep.s
+++ b/mips_sgi_mach_dep.s
@@ -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
diff --git a/os_dep.c b/os_dep.c
index 3c5ae5aa..2ec79053 100644
--- 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)
@@ -24,8 +27,19 @@
# 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 {
diff --git a/reclaim.c b/reclaim.c
index 6e480ecc..516ffafc 100644
--- 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
diff --git a/solaris_pthreads.c b/solaris_pthreads.c
index cc72b2dc..e5e31d78 100644
--- a/solaris_pthreads.c
+++ b/solaris_pthreads.c
@@ -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 cdc8b7f4..9d2457cd 100644
--- 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);
diff --git a/test_cpp.cc b/test_cpp.cc
index 058022c4..036795c6 100644
--- a/test_cpp.cc
+++ b/test_cpp.cc
@@ -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. */
diff --git a/version.h b/version.h
index 6bda1048..7b3f2c92 100644
--- 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