From dbd0bc33ea3c51b4d60cee1f1ff41673ccecb1a6 Mon Sep 17 00:00:00 2001 From: Hans Boehm Date: Tue, 17 Feb 1998 00:00:00 +0000 Subject: [PATCH] gc4.13alpha1 tarball import --- Makefile | 15 ++- README | 31 ++++- README.sgi | 9 ++ alloc.c | 4 +- config.h | 31 +++-- cord/cordxtra.c | 6 +- cord/gc.h | 16 +-- dbg_mlc.c | 38 +++++- finalize.c | 7 +- gc.h | 16 +-- gc_alloc.h | 10 +- gc_priv.h | 22 ++-- include/gc.h | 16 +-- include/gc_alloc.h | 10 +- include/private/config.h | 313 +++++++++++++++++++++++++++++++++++++++++----- include/private/gc_priv.h | 22 ++-- irix_threads.c | 58 +++++++-- malloc.c | 2 +- mallocx.c | 6 +- mark_rts.c | 4 +- mips_sgi_mach_dep.s | 1 + os_dep.c | 63 +++++++--- reclaim.c | 4 +- solaris_pthreads.c | 3 +- test.c | 19 ++- test_cpp.cc | 13 +- version.h | 4 +- 27 files changed, 589 insertions(+), 154 deletions(-) diff --git a/Makefile b/Makefile index 87fcc3f..8e53118 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 a1d3998..94604cf 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 3174e9c..f21eeb7 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 d9584e1..b7cb6f5 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 cffbf6e..d5d618c 100644 --- a/config.h +++ b/config.h @@ -493,6 +493,10 @@ # endif # define PROC_VDB # define HEURISTIC1 +# include +# 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 +# include +# 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 # 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 - int - GC_getpagesize() - { - return sysconf(_SC_PAGESIZE); - } +# include +# define GETPAGESIZE() sysconf(_SC_PAGESIZE) # endif + # ifndef GETPAGESIZE +# if defined(SUNOS5) || defined(IRIX5) +# include +# endif # define GETPAGESIZE() getpagesize() # endif diff --git a/cord/cordxtra.c b/cord/cordxtra.c index 8566e14..b306fba 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 1e00c2f..2303724 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 094614a..445f123 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 e555194..d825bf9 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 1e00c2f..2303724 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 85cb7cd..645748b 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 49a916d..a70032a 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 1e00c2f..2303724 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 85cb7cd..645748b 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 62492c3..d5d618c 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 +# 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 +# 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 +# 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 +# include +# 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 +# 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 +# define GETPAGESIZE() sysconf(_SC_PAGESIZE) +# endif + +# ifndef GETPAGESIZE +# if defined(SUNOS5) || defined(IRIX5) +# include +# 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 49a916d..a70032a 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 5e191d1..661a2c0 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 6b8c092..49e03ce 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 a1fc2f4..598fdfa 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 8e12d53..35d200d 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 bf7f61a..03c4b98 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 3c5ae5a..2ec7905 100644 --- a/os_dep.c +++ b/os_dep.c @@ -14,6 +14,9 @@ # include "gc_priv.h" +# include +# include + # if defined(LINUX) && !defined(POWERPC) # include # if (LINUX_VERSION_CODE <= 0x10400) @@ -24,8 +27,19 @@ # define __KERNEL__ # include # undef __KERNEL__ -# elif (LINUX_VERSION_CODE < 0x20100) -# include +# 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 +# if 2 <= __GLIBC__ +# include +# else /* not 2 <= __GLIBC__ */ + /* libc5 doesn't have : go directly with the kernel */ + /* one. Check LINUX_VERSION_CODE to see which we should reference. */ +# include +# endif /* 2 <= __GLIBC__ */ # endif # endif # if !defined(OS2) && !defined(PCR) && !defined(AMIGA) && !defined(MACOS) @@ -34,8 +48,6 @@ # include # endif # endif -# include -# include /* 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 6e480ec..516ffaf 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 cc72b2d..e5e31d7 100644 --- a/solaris_pthreads.c +++ b/solaris_pthreads.c @@ -36,6 +36,7 @@ # define _CLASSIC_XOPEN_TYPES # include # include +# 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 --- 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 058022c..036795c 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 6bda104..7b3f2c9 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 -- 2.7.4