diff options
author | jsturm <jsturm@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-07-28 04:18:23 +0000 |
---|---|---|
committer | jsturm <jsturm@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-07-28 04:18:23 +0000 |
commit | 341281013a7334da0896c950d9c254e42692c479 (patch) | |
tree | 827bf34dcb0c2786d314e5fa136528e5a4feb6f7 /boehm-gc/include | |
parent | 975f1a7b2a8b2194905616d3fb05653329a2afce (diff) | |
download | gcc-341281013a7334da0896c950d9c254e42692c479.tar.gz |
Import GC 6.3alpha1.
* BCC_MAKEFILE: Merge with GC 6.3alpha1 release.
* ChangeLog: Likewise.
* Makefile.am: Likewise.
* Makefile.direct: Likewise.
* Makefile.dj: Likewise.
* allchblk.c: Likewise.
* alloc.c: Likewise.
* backgraph.c: Likewise.
* configure.host: Likewise.
* configure.in: Likewise.
* dbg_mlc.c: Likewise.
* dyn_load.c: Likewise.
* finalize.c: Likewise.
* gc_cpp.cc: Likewise.
* gc_dlopen.c: Likewise.
* gcj_mlc.c: Likewise.
* if_mach.c: Likewise.
* mach_dep.c: Likewise.
* malloc.c: Likewise.
* mallocx.c: Likewise.
* mark.c: Likewise.
* mark_rts.c: Likewise.
* misc.c: Likewise.
* os_dep.c: Likewise.
* ptr_chck.c: Likewise.
* reclaim.c: Likewise.
* solaris_pthreads.c: Likewise.
* solaris_threads.c: Likewise.
* sparc_mach_dep.S: Likewise.
* threadlibs.c: Likewise.
* typd_mlc.c: Likewise.
* version.h: Likewise.
* win32_threads.c: Likewise.
* Mac_files/MacOS_Test_config.h: Likewise.
* Mac_files/MacOS_config.h: Likewise.
* cord/cordbscs.c: Likewise.
* cord/cordprnt.c: Likewise.
* cord/de_win.c: Likewise.
* doc/README: Likewise.
* doc/README.MacOSX: Likewise.
* doc/README.changes: Likewise.
* doc/README.environment: Likewise.
* doc/README.ews4800: Likewise.
* doc/README.linux: Likewise.
* doc/README.macros: Likewise.
* doc/README.win32: Likewise.
* doc/debugging.html: Likewise.
* doc/gcdescr.html: Likewise.
* doc/tree.html: Likewise.
* include/Makefile.in: Likewise.
* include/gc.h: Likewise.
* include/gc_cpp.h: Likewise.
* include/gc_local_alloc.h: Likewise.
* include/gc_mark.h: Likewise.
* include/gc_pthread_redirects.h: Likewise.
* include/gc_typed.h: Likewise.
* include/new_gc_alloc.h: Likewise.
* include/private/dbg_mlc.h: Likewise.
* include/private/gc_hdrs.h: Likewise.
* include/private/gc_locks.h: Likewise.
* include/private/gc_pmark.h: Likewise.
* include/private/gc_priv.h: Likewise.
* include/private/gcconfig.h: Likewise.
* include/private/solaris_threads.h: Likewise.
* include/private/specific.h: Likewise.
* tests/test.c: Likewise.
* tests/test_cpp.cc: Likewise.
* configure: Rebuild.
* Makefile.in: Rebuild.
* mips_sgi_mach_dep.s: Add.
* alpha_mach_dep.s: Remove.
* irix_threads.c: Remove.
* linux_threads.c: Remove.
* mips_sgi_mach_dep.S: Remove.
* missing: Remove.
* powerpc_macosx_mach_dep.s: Remove.
* doc/Makefile.am: Remove.
* doc/Makefile.in: Remove.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@69880 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'boehm-gc/include')
-rw-r--r-- | boehm-gc/include/Makefile.in | 11 | ||||
-rw-r--r-- | boehm-gc/include/gc.h | 236 | ||||
-rw-r--r-- | boehm-gc/include/gc_cpp.h | 72 | ||||
-rw-r--r-- | boehm-gc/include/gc_local_alloc.h | 3 | ||||
-rw-r--r-- | boehm-gc/include/gc_mark.h | 4 | ||||
-rw-r--r-- | boehm-gc/include/gc_pthread_redirects.h | 17 | ||||
-rw-r--r-- | boehm-gc/include/gc_typed.h | 32 | ||||
-rw-r--r-- | boehm-gc/include/new_gc_alloc.h | 8 | ||||
-rw-r--r-- | boehm-gc/include/private/dbg_mlc.h | 10 | ||||
-rw-r--r-- | boehm-gc/include/private/gc_hdrs.h | 2 | ||||
-rw-r--r-- | boehm-gc/include/private/gc_locks.h | 245 | ||||
-rw-r--r-- | boehm-gc/include/private/gc_pmark.h | 39 | ||||
-rw-r--r-- | boehm-gc/include/private/gc_priv.h | 166 | ||||
-rw-r--r-- | boehm-gc/include/private/gcconfig.h | 509 | ||||
-rw-r--r-- | boehm-gc/include/private/solaris_threads.h | 3 | ||||
-rw-r--r-- | boehm-gc/include/private/specific.h | 2 |
16 files changed, 896 insertions, 463 deletions
diff --git a/boehm-gc/include/Makefile.in b/boehm-gc/include/Makefile.in index 65bd34e2e33..94ece1a258a 100644 --- a/boehm-gc/include/Makefile.in +++ b/boehm-gc/include/Makefile.in @@ -1,6 +1,6 @@ -# Makefile.in generated automatically by automake 1.4 from Makefile.am +# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am -# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -66,9 +66,11 @@ target_triplet = @target@ AR = @AR@ AS = @AS@ CC = @CC@ +CFLAGS = @CFLAGS@ CPP = @CPP@ CXX = @CXX@ CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ CXXINCLUDES = @CXXINCLUDES@ DLLTOOL = @DLLTOOL@ EXEEXT = @EXEEXT@ @@ -89,10 +91,15 @@ RANLIB = @RANLIB@ STRIP = @STRIP@ THREADLIBS = @THREADLIBS@ VERSION = @VERSION@ +addincludes = @addincludes@ +addlibs = @addlibs@ addobjs = @addobjs@ +addtests = @addtests@ gc_basedir = @gc_basedir@ mkinstalldirs = @mkinstalldirs@ target_all = @target_all@ +toolexecdir = @toolexecdir@ +toolexeclibdir = @toolexeclibdir@ AUTOMAKE_OPTIONS = foreign diff --git a/boehm-gc/include/gc.h b/boehm-gc/include/gc.h index 69075b0669e..d49cd9d60b1 100644 --- a/boehm-gc/include/gc.h +++ b/boehm-gc/include/gc.h @@ -30,91 +30,7 @@ # define _GC_H -/* - * Some tests for old macros. These violate our namespace rules and will - * disappear shortly. Use the GC_ names. - */ -#if defined(SOLARIS_THREADS) || defined(_SOLARIS_THREADS) -# define GC_SOLARIS_THREADS -#endif -#if defined(_SOLARIS_PTHREADS) -# define GC_SOLARIS_PTHREADS -#endif -#if defined(IRIX_THREADS) -# define GC_IRIX_THREADS -#endif -#if defined(HPUX_THREADS) -# define GC_HPUX_THREADS -#endif -#if defined(OSF1_THREADS) -# define GC_OSF1_THREADS -#endif -#if defined(LINUX_THREADS) -# define GC_LINUX_THREADS -#endif -#if defined(WIN32_THREADS) -# define GC_WIN32_THREADS -#endif -#if defined(USE_LD_WRAP) -# define GC_USE_LD_WRAP -#endif - -#if !defined(_REENTRANT) && (defined(GC_SOLARIS_THREADS) \ - || defined(GC_SOLARIS_PTHREADS) \ - || defined(GC_HPUX_THREADS) \ - || defined(GC_LINUX_THREADS)) -# define _REENTRANT - /* Better late than never. This fails if system headers that */ - /* depend on this were previously included. */ -#endif - -#if defined(GC_SOLARIS_PTHREADS) && !defined(GC_SOLARIS_THREADS) -# define GC_SOLARIS_THREADS -#endif - -# if defined(GC_SOLARIS_PTHREADS) || defined(GC_FREEBSD_THREADS) || \ - defined(GC_IRIX_THREADS) || defined(GC_LINUX_THREADS) || \ - defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) -# define GC_PTHREADS -# endif - -# define __GC -# include <stddef.h> -# ifdef _WIN32_WCE -/* Yet more kluges for WinCE */ -# include <stdlib.h> /* size_t is defined here */ - typedef long ptrdiff_t; /* ptrdiff_t is not defined */ -# endif - -#if defined(__MINGW32__) &&defined(_DLL) && !defined(GC_NOT_DLL) -# ifdef GC_BUILD -# define GC_API __declspec(dllexport) -# else -# define GC_API __declspec(dllimport) -# endif -#endif - -#if (defined(__DMC__) || defined(_MSC_VER)) \ - && (defined(_DLL) && !defined(GC_NOT_DLL) \ - || defined(GC_DLL)) -# ifdef GC_BUILD -# define GC_API extern __declspec(dllexport) -# else -# define GC_API __declspec(dllimport) -# endif -#endif - -#if defined(__WATCOMC__) && defined(GC_DLL) -# ifdef GC_BUILD -# define GC_API extern __declspec(dllexport) -# else -# define GC_API extern __declspec(dllimport) -# endif -#endif - -#ifndef GC_API -#define GC_API extern -#endif +# include "gc_config_macros.h" # if defined(__STDC__) || defined(__cplusplus) # define GC_PROTO(args) args @@ -154,7 +70,7 @@ GC_API int GC_parallel; /* GC is parallelized for performance on */ /* Env variable GC_NPROC is set to > 1, or */ /* GC_NPROC is not set and this is an MP. */ /* If GC_parallel is set, incremental */ - /* collection is aonly partially functional, */ + /* collection is only partially functional, */ /* and may not be desirable. */ @@ -215,8 +131,14 @@ GC_API void (* GC_finalizer_notifier)(); /* thread, which will call GC_invoke_finalizers */ /* in response. */ -GC_API int GC_dont_gc; /* Dont collect unless explicitly requested, e.g. */ - /* because it's not safe. */ +GC_API int GC_dont_gc; /* != 0 ==> Dont collect. In versions 6.2a1+, */ + /* this overrides explicit GC_gcollect() calls. */ + /* Used as a counter, so that nested enabling */ + /* and disabling work correctly. Should */ + /* normally be updated with GC_enable() and */ + /* GC_disable() calls. */ + /* Direct assignment to GC_dont_gc is */ + /* deprecated. */ GC_API int GC_dont_expand; /* Dont expand heap unless explicitly requested */ @@ -316,9 +238,18 @@ GC_API unsigned long GC_time_limit; /* enabled. */ # define GC_TIME_UNLIMITED 999999 /* Setting GC_time_limit to this value */ - /* will disable the "pause time exceeded */ + /* will disable the "pause time exceeded"*/ /* tests. */ +/* Public procedures */ + +/* Initialize the collector. This is only required when using thread-local + * allocation, since unlike the regular allocation routines, GC_local_malloc + * is not self-initializing. If you use GC_local_malloc you should arrange + * to call this somehow (e.g. from a constructor) before doing any allocation. + */ +GC_API void GC_init GC_PROTO((void)); + /* * general purpose allocation routines, with roughly malloc calling conv. * The atomic versions promise that no relevant pointers are contained @@ -419,17 +350,21 @@ GC_API void GC_clear_roots GC_PROTO((void)); GC_API void GC_add_roots GC_PROTO((char * low_address, char * high_address_plus_1)); +/* Remove a root segment. Wizards only. */ +GC_API void GC_remove_roots GC_PROTO((char * low_address, + char * high_address_plus_1)); + /* Add a displacement to the set of those considered valid by the */ /* collector. GC_register_displacement(n) means that if p was returned */ /* by GC_malloc, then (char *)p + n will be considered to be a valid */ -/* pointer to n. N must be small and less than the size of p. */ +/* pointer to p. N must be small and less than the size of p. */ /* (All pointers to the interior of objects from the stack are */ /* considered valid in any case. This applies to heap objects and */ /* static data.) */ /* Preferably, this should be called before any other GC procedures. */ /* Calling it later adds to the probability of excess memory */ /* retention. */ -/* This is a no-op if the collector was compiled with recognition of */ +/* This is a no-op if the collector has recognition of */ /* arbitrary interior pointers enabled, which is now the default. */ GC_API void GC_register_displacement GC_PROTO((GC_word n)); @@ -464,9 +399,18 @@ GC_API size_t GC_get_free_bytes GC_PROTO((void)); GC_API size_t GC_get_bytes_since_gc GC_PROTO((void)); /* Return the total number of bytes allocated in this process. */ -/* Never decreases. */ +/* Never decreases, except due to wrapping. */ GC_API size_t GC_get_total_bytes GC_PROTO((void)); +/* Disable garbage collection. Even GC_gcollect calls will be */ +/* ineffective. */ +GC_API void GC_disable GC_PROTO((void)); + +/* Reenable garbage collection. GC_disable() and GC_enable() calls */ +/* nest. Garbage collection is enabled if the number of calls to both */ +/* both functions is equal. */ +GC_API void GC_enable GC_PROTO((void)); + /* Enable incremental/generational collection. */ /* Not advisable unless dirty bits are */ /* available or most heap objects are */ @@ -474,7 +418,11 @@ GC_API size_t GC_get_total_bytes GC_PROTO((void)); /* Don't use in leak finding mode. */ /* Ignored if GC_dont_gc is true. */ /* Only the generational piece of this is */ -/* functional if GC_parallel is TRUE. */ +/* functional if GC_parallel is TRUE */ +/* or if GC_time_limit is GC_TIME_UNLIMITED. */ +/* Causes GC_local_gcj_malloc() to revert to */ +/* locked allocation. Must be called */ +/* before any GC_local_gcj_malloc() calls. */ GC_API void GC_enable_incremental GC_PROTO((void)); /* Does incremental mode write-protect pages? Returns zero or */ @@ -518,6 +466,42 @@ GC_API GC_PTR GC_malloc_atomic_ignore_off_page GC_PROTO((size_t lb)); # define GC_RETURN_ADDR (GC_word)__return_address #endif +#ifdef __linux__ +# include <features.h> +# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 || __GLIBC__ > 2) \ + && !defined(__ia64__) +# define GC_HAVE_BUILTIN_BACKTRACE +# define GC_CAN_SAVE_CALL_STACKS +# endif +# if defined(__i386__) || defined(__x86_64__) +# define GC_CAN_SAVE_CALL_STACKS +# endif +#endif + +#if defined(__sparc__) +# define GC_CAN_SAVE_CALL_STACKS +#endif + +/* If we're on an a platform on which we can't save call stacks, but */ +/* gcc is normally used, we go ahead and define GC_ADD_CALLER. */ +/* We make this decision independent of whether gcc is actually being */ +/* used, in order to keep the interface consistent, and allow mixing */ +/* of compilers. */ +/* This may also be desirable if it is possible but expensive to */ +/* retrieve the call chain. */ +#if (defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__) \ + || defined(__FreeBSD__)) & !defined(GC_CAN_SAVE_CALL_STACKS) +# define GC_ADD_CALLER +# if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) + /* gcc knows how to retrieve return address, but we don't know */ + /* how to generate call stacks. */ +# define GC_RETURN_ADDR (GC_word)__builtin_return_address(0) +# else + /* Just pass 0 for gcc compatibility. */ +# define GC_RETURN_ADDR 0 +# endif +#endif + #ifdef GC_ADD_CALLER # define GC_EXTRAS GC_RETURN_ADDR, __FILE__, __LINE__ # define GC_EXTRA_PARAMS GC_word ra, GC_CONST char * s, int i @@ -536,18 +520,42 @@ GC_API GC_PTR GC_debug_malloc_uncollectable GC_PROTO((size_t size_in_bytes, GC_EXTRA_PARAMS)); GC_API GC_PTR GC_debug_malloc_stubborn GC_PROTO((size_t size_in_bytes, GC_EXTRA_PARAMS)); +GC_API GC_PTR GC_debug_malloc_ignore_off_page + GC_PROTO((size_t size_in_bytes, GC_EXTRA_PARAMS)); +GC_API GC_PTR GC_debug_malloc_atomic_ignore_off_page + GC_PROTO((size_t size_in_bytes, GC_EXTRA_PARAMS)); GC_API void GC_debug_free GC_PROTO((GC_PTR object_addr)); GC_API GC_PTR GC_debug_realloc GC_PROTO((GC_PTR old_object, size_t new_size_in_bytes, GC_EXTRA_PARAMS)); - GC_API void GC_debug_change_stubborn GC_PROTO((GC_PTR)); GC_API void GC_debug_end_stubborn_change GC_PROTO((GC_PTR)); + +/* Routines that allocate objects with debug information (like the */ +/* above), but just fill in dummy file and line number information. */ +/* Thus they can serve as drop-in malloc/realloc replacements. This */ +/* can be useful for two reasons: */ +/* 1) It allows the collector to be built with DBG_HDRS_ALL defined */ +/* even if some allocation calls come from 3rd party libraries */ +/* that can't be recompiled. */ +/* 2) On some platforms, the file and line information is redundant, */ +/* since it can be reconstructed from a stack trace. On such */ +/* platforms it may be more convenient not to recompile, e.g. for */ +/* leak detection. This can be accomplished by instructing the */ +/* linker to replace malloc/realloc with these. */ +GC_API GC_PTR GC_debug_malloc_replacement GC_PROTO((size_t size_in_bytes)); +GC_API GC_PTR GC_debug_realloc_replacement + GC_PROTO((GC_PTR object_addr, size_t size_in_bytes)); + # ifdef GC_DEBUG # define GC_MALLOC(sz) GC_debug_malloc(sz, GC_EXTRAS) # define GC_MALLOC_ATOMIC(sz) GC_debug_malloc_atomic(sz, GC_EXTRAS) -# define GC_MALLOC_UNCOLLECTABLE(sz) GC_debug_malloc_uncollectable(sz, \ - GC_EXTRAS) +# define GC_MALLOC_UNCOLLECTABLE(sz) \ + GC_debug_malloc_uncollectable(sz, GC_EXTRAS) +# define GC_MALLOC_IGNORE_OFF_PAGE(sz) \ + GC_debug_malloc_ignore_off_page(sz, GC_EXTRAS) +# define GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(sz) \ + GC_debug_malloc_atomic_ignore_off_page(sz, GC_EXTRAS) # define GC_REALLOC(old, sz) GC_debug_realloc(old, sz, GC_EXTRAS) # define GC_FREE(p) GC_debug_free(p) # define GC_REGISTER_FINALIZER(p, f, d, of, od) \ @@ -566,6 +574,10 @@ GC_API void GC_debug_end_stubborn_change GC_PROTO((GC_PTR)); # define GC_MALLOC(sz) GC_malloc(sz) # define GC_MALLOC_ATOMIC(sz) GC_malloc_atomic(sz) # define GC_MALLOC_UNCOLLECTABLE(sz) GC_malloc_uncollectable(sz) +# define GC_MALLOC_IGNORE_OFF_PAGE(sz) \ + GC_malloc_ignore_off_page(sz) +# define GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(sz) \ + GC_malloc_atomic_ignore_off_page(sz) # define GC_REALLOC(old, sz) GC_realloc(old, sz) # define GC_FREE(p) GC_free(p) # define GC_REGISTER_FINALIZER(p, f, d, of, od) \ @@ -644,7 +656,8 @@ GC_API void GC_debug_register_finalizer /* itself. There is a stylistic argument that this is wrong, */ /* but it's unavoidable for C++, since the compiler may */ /* silently introduce these. It's also benign in that specific */ -/* case. */ +/* case. And it helps if finalizable objects are split to */ +/* avoid cycles. */ /* Note that cd will still be viewed as accessible, even if it */ /* refers to the object itself. */ GC_API void GC_register_finalizer_ignore_self @@ -717,11 +730,6 @@ GC_API int GC_unregister_disappearing_link GC_PROTO((GC_PTR * /* link */)); /* Undoes a registration by either of the above two */ /* routines. */ -/* Auxiliary fns to make finalization work correctly with displaced */ -/* pointers introduced by the debugging allocators. */ -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)); - /* Returns !=0 if GC_invoke_finalizers has something to do. */ GC_API int GC_should_invoke_finalizers GC_PROTO((void)); @@ -738,6 +746,10 @@ GC_API int GC_invoke_finalizers GC_PROTO((void)); typedef void (*GC_warn_proc) GC_PROTO((char *msg, GC_word arg)); GC_API GC_warn_proc GC_set_warn_proc GC_PROTO((GC_warn_proc p)); /* Returns old warning procedure. */ + +GC_API GC_word GC_set_free_space_divisor GC_PROTO((GC_word value)); + /* Set free_space_divisor. See above for definition. */ + /* Returns old value. */ /* The following is intended to be used by a higher level */ /* (e.g. Java-like) finalization facility. It is expected */ @@ -873,14 +885,17 @@ extern void GC_thr_init(); /* Needed for Solaris/X86 */ #endif /* THREADS && !SRC_M3 */ -#if defined(GC_WIN32_THREADS) +#if defined(GC_WIN32_THREADS) && !defined(__CYGWIN32__) && !defined(__CYGWIN__) # include <windows.h> /* * All threads must be created using GC_CreateThread, so that they will be - * recorded in the thread table. + * recorded in the thread table. For backwards compatibility, this is not + * technically true if the GC is built as a dynamic library, since it can + * and does then use DllMain to keep track of thread creations. But new code + * should be built to call GC_CreateThread. */ - HANDLE WINAPI GC_CreateThread( + GC_API HANDLE GC_CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId ); @@ -902,7 +917,7 @@ extern void GC_thr_init(); /* Needed for Solaris/X86 */ # endif # endif /* defined(_WIN32_WCE) */ -#endif /* defined(GC_WIN32_THREADS) */ +#endif /* defined(GC_WIN32_THREADS) && !cygwin */ /* * If you are planning on putting @@ -914,13 +929,18 @@ extern void GC_thr_init(); /* Needed for Solaris/X86 */ # define GC_INIT() { extern end, etext; \ GC_noop(&end, &etext); } #else -# if (defined(__CYGWIN32__) && defined(GC_USE_DLL)) || defined (_AIX) +# if defined(__CYGWIN32__) && defined(GC_DLL) || defined (_AIX) /* - * Similarly gnu-win32 DLLs need explicit initialization + * Similarly gnu-win32 DLLs need explicit initialization from + * the main program, as does AIX. */ # define GC_INIT() { GC_add_roots(DATASTART, DATAEND); } # else +# if defined(__APPLE__) && defined(__MACH__) +# define GC_INIT() { GC_init(); } +# else # define GC_INIT() +# endif # endif #endif diff --git a/boehm-gc/include/gc_cpp.h b/boehm-gc/include/gc_cpp.h index ceb73f50a65..d789a3731e3 100644 --- a/boehm-gc/include/gc_cpp.h +++ b/boehm-gc/include/gc_cpp.h @@ -134,7 +134,9 @@ by UseGC. GC is an alias for UseGC, unless GC_NAME_CONFLICT is defined. #include "gc.h" #ifndef THINK_CPLUS -#define _cdecl +# define GC_cdecl +#else +# define GC_cdecl _cdecl #endif #if ! defined( GC_NO_OPERATOR_NEW_ARRAY ) \ @@ -159,12 +161,22 @@ enum GCPlacement {UseGC, class gc {public: inline void* operator new( size_t size ); inline void* operator new( size_t size, GCPlacement gcp ); + inline void* operator new( size_t size, void *p ); + /* Must be redefined here, since the other overloadings */ + /* hide the global definition. */ inline void operator delete( void* obj ); +# ifndef __BORLANDC__ /* Confuses the Borland compiler. */ + inline void operator delete( void*, void* ); +# endif #ifdef GC_OPERATOR_NEW_ARRAY inline void* operator new[]( size_t size ); inline void* operator new[]( size_t size, GCPlacement gcp ); + inline void* operator new[]( size_t size, void *p ); inline void operator delete[]( void* obj ); +# ifndef __BORLANDC__ + inline void gc::operator delete[]( void*, void* ); +# endif #endif /* GC_OPERATOR_NEW_ARRAY */ }; /* @@ -176,7 +188,7 @@ class gc_cleanup: virtual public gc {public: inline gc_cleanup(); inline virtual ~gc_cleanup(); private: - inline static void _cdecl cleanup( void* obj, void* clientData );}; + inline static void GC_cdecl cleanup( void* obj, void* clientData );}; /* Instances of classes derived from "gc_cleanup" will be allocated in the collected heap by default. When the collector discovers an @@ -211,7 +223,6 @@ inline void* operator new( classes derived from "gc_cleanup" or containing members derived from "gc_cleanup". */ -#ifdef GC_OPERATOR_NEW_ARRAY #ifdef _MSC_VER /** This ensures that the system default operator new[] doesn't get @@ -220,42 +231,24 @@ inline void* operator new( * There seems to be really redirect new in this environment without * including this everywhere. */ - inline void *operator new[]( size_t size ) - { - return GC_MALLOC_UNCOLLECTABLE( size ); - } - - inline void operator delete[](void* obj) - { - GC_FREE(obj); - }; - - inline void* operator new( size_t size) - { - return GC_MALLOC_UNCOLLECTABLE( size); - }; + void *operator new[]( size_t size ); + + void operator delete[](void* obj); - inline void operator delete(void* obj) - { - GC_FREE(obj); - }; + void* operator new( size_t size); + void operator delete(void* obj); -// This new operator is used by VC++ in case of Debug builds ! - inline void* operator new( size_t size, + // This new operator is used by VC++ in case of Debug builds ! + void* operator new( size_t size, int ,//nBlockUse, const char * szFileName, - int nLine - ) { -# ifndef GC_DEBUG - return GC_malloc_uncollectable( size ); -# else - return GC_debug_malloc_uncollectable(size, szFileName, nLine); -# endif - } - + int nLine ); #endif /* _MSC_VER */ + +#ifdef GC_OPERATOR_NEW_ARRAY + inline void* operator new[]( size_t size, GCPlacement gcp, @@ -283,9 +276,15 @@ inline void* gc::operator new( size_t size, GCPlacement gcp ) { else return GC_MALLOC_UNCOLLECTABLE( size );} +inline void* gc::operator new( size_t size, void *p ) { + return p;} + inline void gc::operator delete( void* obj ) { GC_FREE( obj );} +#ifndef __BORLANDC__ + inline void gc::operator delete( void*, void* ) {} +#endif #ifdef GC_OPERATOR_NEW_ARRAY @@ -295,14 +294,21 @@ inline void* gc::operator new[]( size_t size ) { inline void* gc::operator new[]( size_t size, GCPlacement gcp ) { return gc::operator new( size, gcp );} +inline void* gc::operator new[]( size_t size, void *p ) { + return p;} + inline void gc::operator delete[]( void* obj ) { gc::operator delete( obj );} + +#ifndef __BORLANDC__ + inline void gc::operator delete[]( void*, void* ) {} +#endif #endif /* GC_OPERATOR_NEW_ARRAY */ inline gc_cleanup::~gc_cleanup() { - GC_REGISTER_FINALIZER_IGNORE_SELF( GC_base(this), 0, 0, 0, 0 );} + GC_register_finalizer_ignore_self( GC_base(this), 0, 0, 0, 0 );} inline void gc_cleanup::cleanup( void* obj, void* displ ) { ((gc_cleanup*) ((char*) obj + (ptrdiff_t) displ))->~gc_cleanup();} diff --git a/boehm-gc/include/gc_local_alloc.h b/boehm-gc/include/gc_local_alloc.h index 1e58730cfe8..88e29e9a11f 100644 --- a/boehm-gc/include/gc_local_alloc.h +++ b/boehm-gc/include/gc_local_alloc.h @@ -33,6 +33,9 @@ * -DTHREAD_LOCAL_ALLOC, which is currently supported only on Linux. * * The debugging allocators use standard, not thread-local allocation. + * + * These routines normally require an explicit call to GC_init(), though + * that may be done from a constructor function. */ #ifndef GC_LOCAL_ALLOC_H diff --git a/boehm-gc/include/gc_mark.h b/boehm-gc/include/gc_mark.h index 0856d16fdae..9ddba2ca527 100644 --- a/boehm-gc/include/gc_mark.h +++ b/boehm-gc/include/gc_mark.h @@ -129,7 +129,9 @@ extern GC_PTR GC_greatest_plausible_heap_addr; /* be reserved for exceptional cases. That will ensure that */ /* performance of this call is not extremely performance critical. */ /* (Otherwise we would need to inline GC_mark_and_push completely, */ -/* which would tie the client code to a fixed colllector version.) */ +/* which would tie the client code to a fixed collector version.) */ +/* Note that mark procedures should explicitly call FIXUP_POINTER() */ +/* if required. */ struct GC_ms_entry *GC_mark_and_push GC_PROTO((GC_PTR obj, struct GC_ms_entry * mark_stack_ptr, diff --git a/boehm-gc/include/gc_pthread_redirects.h b/boehm-gc/include/gc_pthread_redirects.h index 47284fbc97a..842518cfcc4 100644 --- a/boehm-gc/include/gc_pthread_redirects.h +++ b/boehm-gc/include/gc_pthread_redirects.h @@ -52,15 +52,30 @@ int GC_pthread_create(pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); +#ifndef GC_DARWIN_THREADS int GC_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset); +#endif int GC_pthread_join(pthread_t thread, void **retval); int GC_pthread_detach(pthread_t thread); +#if defined(GC_OSF1_THREADS) \ + && defined(_PTHREAD_USE_MANGLED_NAMES_) && !defined(_PTHREAD_USE_PTDNAM_) +/* Unless the compiler supports #pragma extern_prefix, the Tru64 UNIX + <pthread.h> redefines some POSIX thread functions to use mangled names. + If so, undef them before redefining. */ +# undef pthread_create +# undef pthread_join +# undef pthread_detach +#endif + # define pthread_create GC_pthread_create -# define pthread_sigmask GC_pthread_sigmask # define pthread_join GC_pthread_join # define pthread_detach GC_pthread_detach + +#ifndef GC_DARWIN_THREADS +# define pthread_sigmask GC_pthread_sigmask # define dlopen GC_dlopen +#endif #endif /* GC_xxxxx_THREADS */ diff --git a/boehm-gc/include/gc_typed.h b/boehm-gc/include/gc_typed.h index 2e0598f204c..905734b8da0 100644 --- a/boehm-gc/include/gc_typed.h +++ b/boehm-gc/include/gc_typed.h @@ -29,14 +29,21 @@ # include "gc.h" # endif +#ifdef __cplusplus + extern "C" { +#endif typedef GC_word * GC_bitmap; /* The least significant bit of the first word is one if */ /* the first word in the object may be a pointer. */ +# define GC_WORDSZ (8*sizeof(GC_word)) # define GC_get_bit(bm, index) \ - (((bm)[divWORDSZ(index)] >> modWORDSZ(index)) & 1) + (((bm)[index/GC_WORDSZ] >> (index%GC_WORDSZ)) & 1) # define GC_set_bit(bm, index) \ - (bm)[divWORDSZ(index)] |= (word)1 << modWORDSZ(index) + (bm)[index/GC_WORDSZ] |= ((GC_word)1 << (index%GC_WORDSZ)) +# define GC_WORD_OFFSET(t, f) (offsetof(t,f)/sizeof(GC_word)) +# define GC_WORD_LEN(t) (sizeof(t)/ sizeof(GC_word)) +# define GC_BITMAP_SIZE(t) ((GC_WORD_LEN(t) + GC_WORDSZ-1)/GC_WORDSZ) typedef GC_word GC_descr; @@ -57,6 +64,16 @@ GC_API GC_descr GC_make_descriptor GC_PROTO((GC_bitmap bm, size_t len)); /* is intended to be called once per type, not once */ /* per allocation. */ +/* It is possible to generate a descriptor for a C type T with */ +/* word aligned pointer fields f1, f2, ... as follows: */ +/* */ +/* GC_descr T_descr; */ +/* GC_word T_bitmap[GC_BITMAP_SIZE(T)] = {0}; */ +/* GC_set_bit(T_bitmap, GC_WORD_OFFSET(T,f1)); */ +/* GC_set_bit(T_bitmap, GC_WORD_OFFSET(T,f2)); */ +/* ... */ +/* T_descr = GC_make_descriptor(T_bitmap, GC_WORD_LEN(T)); */ + GC_API GC_PTR GC_malloc_explicitly_typed GC_PROTO((size_t size_in_bytes, GC_descr d)); /* Allocate an object whose layout is described by d. */ @@ -79,15 +96,18 @@ GC_API GC_PTR GC_calloc_explicitly_typed /* Returned object is cleared. */ #ifdef GC_DEBUG -# define GC_MALLOC_EXPLICTLY_TYPED(bytes, d) GC_MALLOC(bytes) -# define GC_CALLOC_EXPLICTLY_TYPED(n, bytes, d) GC_MALLOC(n*bytes) +# define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) GC_MALLOC(bytes) +# define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) GC_MALLOC(n*bytes) #else -# define GC_MALLOC_EXPLICTLY_TYPED(bytes, d) \ +# define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) \ GC_malloc_explicitly_typed(bytes, d) -# define GC_CALLOC_EXPLICTLY_TYPED(n, bytes, d) \ +# define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) \ GC_calloc_explicitly_typed(n, bytes, d) #endif /* !GC_DEBUG */ +#ifdef __cplusplus + } /* matches extern "C" */ +#endif #endif /* _GC_TYPED_H */ diff --git a/boehm-gc/include/new_gc_alloc.h b/boehm-gc/include/new_gc_alloc.h index aad9446543e..20a2fabf83c 100644 --- a/boehm-gc/include/new_gc_alloc.h +++ b/boehm-gc/include/new_gc_alloc.h @@ -64,6 +64,14 @@ #endif #endif +/* A hack to deal with gcc 3.1. If you are using gcc3.1 and later, */ +/* you should probably really use gc_allocator.h instead. */ +#if defined (__GNUC__) && \ + (__GNUC > 3 || (__GNUC__ == 3 && (__GNUC_MINOR__ >= 1))) +# define simple_alloc __simple_alloc +#endif + + #define GC_ALLOC_H diff --git a/boehm-gc/include/private/dbg_mlc.h b/boehm-gc/include/private/dbg_mlc.h index 5378835811c..e2003e6c44f 100644 --- a/boehm-gc/include/private/dbg_mlc.h +++ b/boehm-gc/include/private/dbg_mlc.h @@ -115,16 +115,24 @@ typedef struct { #ifdef SHORT_DBG_HDRS # define DEBUG_BYTES (sizeof (oh)) +# define UNCOLLECTABLE_DEBUG_BYTES DEBUG_BYTES #else /* Add space for END_FLAG, but use any extra space that was already */ /* added to catch off-the-end pointers. */ -# define DEBUG_BYTES (sizeof (oh) + sizeof (word) - EXTRA_BYTES) + /* For uncollectable objects, the extra byte is not added. */ +# define UNCOLLECTABLE_DEBUG_BYTES (sizeof (oh) + sizeof (word)) +# define DEBUG_BYTES (UNCOLLECTABLE_DEBUG_BYTES - EXTRA_BYTES) #endif #define USR_PTR_FROM_BASE(p) ((ptr_t)(p) + sizeof(oh)) /* Round bytes to words without adding extra byte at end. */ #define SIMPLE_ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1) - 1) +/* ADD_CALL_CHAIN stores a (partial) call chain into an object */ +/* header. It may be called with or without the allocation */ +/* lock. */ +/* PRINT_CALL_CHAIN prints the call chain stored in an object */ +/* to stderr. It requires that we do not hold the lock. */ #ifdef SAVE_CALL_CHAIN # define ADD_CALL_CHAIN(base, ra) GC_save_callers(((oh *)(base)) -> oh_ci) # define PRINT_CALL_CHAIN(base) GC_print_callers(((oh *)(base)) -> oh_ci) diff --git a/boehm-gc/include/private/gc_hdrs.h b/boehm-gc/include/private/gc_hdrs.h index dd615455f3b..96749ab1bf0 100644 --- a/boehm-gc/include/private/gc_hdrs.h +++ b/boehm-gc/include/private/gc_hdrs.h @@ -70,7 +70,7 @@ extern hdr * GC_invalid_header; /* header for an imaginary block */ #define ADVANCE(p, hhdr, source) \ { \ hdr * new_hdr = GC_invalid_header; \ - p = GC_FIND_START(p, hhdr, &new_hdr, (word)source); \ + p = GC_find_start(p, hhdr, &new_hdr); \ hhdr = new_hdr; \ } diff --git a/boehm-gc/include/private/gc_locks.h b/boehm-gc/include/private/gc_locks.h index 9b91ada917a..775176b3151 100644 --- a/boehm-gc/include/private/gc_locks.h +++ b/boehm-gc/include/private/gc_locks.h @@ -141,23 +141,24 @@ # if defined(POWERPC) inline static int GC_test_and_set(volatile unsigned int *addr) { int oldval; - int temp = 1; // locked value + int temp = 1; /* locked value */ __asm__ __volatile__( - "1:\tlwarx %0,0,%3\n" // load and reserve - "\tcmpwi %0, 0\n" // if load is - "\tbne 2f\n" // non-zero, return already set - "\tstwcx. %2,0,%1\n" // else store conditional - "\tbne- 1b\n" // retry if lost reservation - "2:\t\n" // oldval is zero if we set + "1:\tlwarx %0,0,%3\n" /* load and reserve */ + "\tcmpwi %0, 0\n" /* if load is */ + "\tbne 2f\n" /* non-zero, return already set */ + "\tstwcx. %2,0,%1\n" /* else store conditional */ + "\tbne- 1b\n" /* retry if lost reservation */ + "\tsync\n" /* import barrier */ + "2:\t\n" /* oldval is zero if we set */ : "=&r"(oldval), "=p"(addr) : "r"(temp), "1"(addr) - : "memory"); - return (int)oldval; + : "cr0","memory"); + return oldval; } # define GC_TEST_AND_SET_DEFINED inline static void GC_clear(volatile unsigned int *addr) { - __asm__ __volatile__("eieio" ::: "memory"); + __asm__ __volatile__("eieio" : : : "memory"); *(addr) = 0; } # define GC_CLEAR_DEFINED @@ -174,12 +175,18 @@ " bne %2,2f\n" " xor %0,%3,%0\n" " stl_c %0,%1\n" +# ifdef __ELF__ " beq %0,3f\n" +# else + " beq %0,1b\n" +# endif " mb\n" "2:\n" +# ifdef __ELF__ ".section .text2,\"ax\"\n" "3: br 1b\n" ".previous" +# endif :"=&r" (temp), "=m" (*addr), "=&r" (oldvalue) :"Ir" (1), "m" (*addr) :"memory"); @@ -187,8 +194,11 @@ return oldvalue; } # define GC_TEST_AND_SET_DEFINED - /* Should probably also define GC_clear, since it needs */ - /* a memory barrier ?? */ + inline static void GC_clear(volatile unsigned int *addr) { + __asm__ __volatile__("mb" : : : "memory"); + *(addr) = 0; + } +# define GC_CLEAR_DEFINED # endif /* ALPHA */ # ifdef ARM32 inline static int GC_test_and_set(volatile unsigned int *addr) { @@ -206,22 +216,30 @@ # define GC_TEST_AND_SET_DEFINED # endif /* ARM32 */ # ifdef S390 - inline static int GC_test_and_set(volatile unsigned int *addr) { - int ret; - __asm__ __volatile__ ( - " l %0,0(%2)\n" - "0: cs %0,%1,0(%2)\n" - " jl 0b" - : "=&d" (ret) - : "d" (1), "a" (addr) - : "cc", "memory"); - return ret; - } + inline static int GC_test_and_set(volatile unsigned int *addr) { + int ret; + __asm__ __volatile__ ( + " l %0,0(%2)\n" + "0: cs %0,%1,0(%2)\n" + " jl 0b" + : "=&d" (ret) + : "d" (1), "a" (addr) + : "cc", "memory"); + return ret; + } # endif # endif /* __GNUC__ */ # if (defined(ALPHA) && !defined(__GNUC__)) -# define GC_test_and_set(addr) __cxx_test_and_set_atomic(addr, 1) +# ifndef OSF1 + --> We currently assume that if gcc is not used, we are + --> running under Tru64. +# endif +# include <machine/builtins.h> +# include <c_asm.h> +# define GC_test_and_set(addr) __ATOMIC_EXCH_LONG(addr, 1) # define GC_TEST_AND_SET_DEFINED +# define GC_clear(addr) { asm("mb"); *(volatile unsigned *)addr = 0; } +# define GC_CLEAR_DEFINED # endif # if defined(MSWIN32) # define GC_test_and_set(addr) InterlockedExchange((LPLONG)addr,1) @@ -234,14 +252,51 @@ # define GC_TEST_AND_SET_DEFINED # elif __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) \ || !defined(_COMPILER_VERSION) || _COMPILER_VERSION < 700 -# define GC_test_and_set(addr) test_and_set(addr, 1) +# ifdef __GNUC__ +# define GC_test_and_set(addr) _test_and_set((void *)addr,1) +# else +# define GC_test_and_set(addr) test_and_set((void *)addr,1) +# endif # else -# define GC_test_and_set(addr) __test_and_set(addr,1) +# define GC_test_and_set(addr) __test_and_set32((void *)addr,1) # define GC_clear(addr) __lock_release(addr); # define GC_CLEAR_DEFINED # endif # define GC_TEST_AND_SET_DEFINED # endif /* MIPS */ +# if defined(_AIX) +# include <sys/atomic_op.h> +# if (defined(_POWER) || defined(_POWERPC)) +# if defined(__GNUC__) + inline static void GC_memsync() { + __asm__ __volatile__ ("sync" : : : "memory"); + } +# else +# ifndef inline +# define inline __inline +# endif +# pragma mc_func GC_memsync { \ + "7c0004ac" /* sync (same opcode used for dcs)*/ \ + } +# endif +# else +# error dont know how to memsync +# endif + inline static int GC_test_and_set(volatile unsigned int * addr) { + int oldvalue = 0; + if (compare_and_swap((void *)addr, &oldvalue, 1)) { + GC_memsync(); + return 0; + } else return 1; + } +# define GC_TEST_AND_SET_DEFINED + inline static void GC_clear(volatile unsigned int *addr) { + GC_memsync(); + *(addr) = 0; + } +# define GC_CLEAR_DEFINED + +# endif # if 0 /* defined(HP_PA) */ /* The official recommendation seems to be to not use ldcw from */ /* user mode. Since multithreaded incremental collection doesn't */ @@ -275,7 +330,7 @@ # endif # if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \ - && !defined(GC_IRIX_THREADS) + && !defined(GC_IRIX_THREADS) && !defined(GC_WIN32_THREADS) # define NO_THREAD (pthread_t)(-1) # include <pthread.h> # if defined(PARALLEL_MARK) @@ -306,12 +361,12 @@ { char result; __asm__ __volatile__("lock; cmpxchgl %2, %0; setz %1" - : "=m"(*(addr)), "=r"(result) - : "r" (new_val), "0"(*(addr)), "a"(old) : "memory"); + : "+m"(*(addr)), "=r"(result) + : "r" (new_val), "a"(old) : "memory"); return (GC_bool) result; } # endif /* !GENERIC_COMPARE_AND_SWAP */ - inline static void GC_memory_write_barrier() + inline static void GC_memory_barrier() { /* We believe the processor ensures at least processor */ /* consistent ordering. Thus a compiler barrier */ @@ -319,6 +374,37 @@ __asm__ __volatile__("" : : : "memory"); } # endif /* I386 */ + +# if defined(POWERPC) +# if !defined(GENERIC_COMPARE_AND_SWAP) + /* Returns TRUE if the comparison succeeded. */ + inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr, + GC_word old, GC_word new_val) + { + int result, dummy; + __asm__ __volatile__( + "1:\tlwarx %0,0,%5\n" + "\tcmpw %0,%4\n" + "\tbne 2f\n" + "\tstwcx. %3,0,%2\n" + "\tbne- 1b\n" + "\tsync\n" + "\tli %1, 1\n" + "\tb 3f\n" + "2:\tli %1, 0\n" + "3:\t\n" + : "=&r" (dummy), "=r" (result), "=p" (addr) + : "r" (new_val), "r" (old), "2"(addr) + : "cr0","memory"); + return (GC_bool) result; + } +# endif /* !GENERIC_COMPARE_AND_SWAP */ + inline static void GC_memory_barrier() + { + __asm__ __volatile__("sync" : : : "memory"); + } +# endif /* POWERPC */ + # if defined(IA64) # if !defined(GENERIC_COMPARE_AND_SWAP) inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr, @@ -330,31 +416,71 @@ # endif /* !GENERIC_COMPARE_AND_SWAP */ # if 0 /* Shouldn't be needed; we use volatile stores instead. */ - inline static void GC_memory_write_barrier() + inline static void GC_memory_barrier() { __sync_synchronize (); } # endif /* 0 */ # endif /* IA64 */ +# if defined(ALPHA) +# if !defined(GENERIC_COMPARE_AND_SWAP) +# if defined(__GNUC__) + inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr, + GC_word old, GC_word new_val) + { + unsigned long was_equal; + unsigned long temp; + + __asm__ __volatile__( + "1: ldq_l %0,%1\n" + " cmpeq %0,%4,%2\n" + " mov %3,%0\n" + " beq %2,2f\n" + " stq_c %0,%1\n" + " beq %0,1b\n" + "2:\n" + " mb\n" + :"=&r" (temp), "=m" (*addr), "=&r" (was_equal) + : "r" (new_val), "Ir" (old) + :"memory"); + return was_equal; + } +# else /* !__GNUC__ */ + inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr, + GC_word old, GC_word new_val) + { + return __CMP_STORE_QUAD(addr, old, new_val, addr); + } +# endif /* !__GNUC__ */ +# endif /* !GENERIC_COMPARE_AND_SWAP */ +# ifdef __GNUC__ + inline static void GC_memory_barrier() + { + __asm__ __volatile__("mb" : : : "memory"); + } +# else +# define GC_memory_barrier() asm("mb") +# endif /* !__GNUC__ */ +# endif /* ALPHA */ # if defined(S390) # if !defined(GENERIC_COMPARE_AND_SWAP) - inline static GC_bool GC_compare_and_exchange(volatile C_word *addr, - GC_word old, GC_word new_val) - { - int retval; - __asm__ __volatile__ ( -# ifndef __s390x__ - " cs %1,%2,0(%3)\n" -# else - " csg %1,%2,0(%3)\n" -# endif - " ipm %0\n" - " srl %0,28\n" - : "=&d" (retval), "+d" (old) - : "d" (new_val), "a" (addr) - : "cc", "memory"); - return retval == 0; - } + inline static GC_bool GC_compare_and_exchange(volatile C_word *addr, + GC_word old, GC_word new_val) + { + int retval; + __asm__ __volatile__ ( +# ifndef __s390x__ + " cs %1,%2,0(%3)\n" +# else + " csg %1,%2,0(%3)\n" +# endif + " ipm %0\n" + " srl %0,28\n" + : "=&d" (retval), "+d" (old) + : "d" (new_val), "a" (addr) + : "cc", "memory"); + return retval == 0; + } # endif # endif # if !defined(GENERIC_COMPARE_AND_SWAP) @@ -427,8 +553,12 @@ { GC_ASSERT(I_HOLD_LOCK()); UNSET_LOCK_HOLDER(); \ pthread_mutex_unlock(&GC_allocate_ml); } # else /* !GC_ASSERTIONS */ +# if defined(NO_PTHREAD_TRYLOCK) +# define LOCK() GC_lock(); +# else /* !defined(NO_PTHREAD_TRYLOCK) */ # define LOCK() \ { if (0 != pthread_mutex_trylock(&GC_allocate_ml)) GC_lock(); } +# endif # define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml) # endif /* !GC_ASSERTIONS */ # endif /* USE_PTHREAD_LOCKS */ @@ -450,7 +580,7 @@ /* on Irix anymore. */ # include <mutex.h> - extern unsigned long GC_allocate_lock; + extern volatile unsigned int GC_allocate_lock; /* This is not a mutex because mutexes that obey the (optional) */ /* POSIX scheduling rules are subject to convoys in high contention */ /* applications. This is basically a spin lock. */ @@ -471,11 +601,18 @@ } # define EXIT_GC() GC_collecting = 0; # endif /* GC_IRIX_THREADS */ -# ifdef GC_WIN32_THREADS -# include <windows.h> - GC_API CRITICAL_SECTION GC_allocate_ml; -# define LOCK() EnterCriticalSection(&GC_allocate_ml); -# define UNLOCK() LeaveCriticalSection(&GC_allocate_ml); +# if defined(GC_WIN32_THREADS) +# if defined(GC_PTHREADS) +# include <pthread.h> + extern pthread_mutex_t GC_allocate_ml; +# define LOCK() pthread_mutex_lock(&GC_allocate_ml) +# define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml) +# else +# include <windows.h> + GC_API CRITICAL_SECTION GC_allocate_ml; +# define LOCK() EnterCriticalSection(&GC_allocate_ml); +# define UNLOCK() LeaveCriticalSection(&GC_allocate_ml); +# endif # endif # ifndef SET_LOCK_HOLDER # define SET_LOCK_HOLDER() diff --git a/boehm-gc/include/private/gc_pmark.h b/boehm-gc/include/private/gc_pmark.h index 872065702f0..c109738203a 100644 --- a/boehm-gc/include/private/gc_pmark.h +++ b/boehm-gc/include/private/gc_pmark.h @@ -137,7 +137,7 @@ extern mse * GC_mark_stack; #ifdef __STDC__ # ifdef PRINT_BLACK_LIST ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p, - ptr_t source); + word source); # else ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p); # endif @@ -145,7 +145,7 @@ extern mse * GC_mark_stack; ptr_t GC_find_start(); #endif -mse *GC_signal_mark_stack_overflow(mse *msp); +mse * GC_signal_mark_stack_overflow GC_PROTO((mse *msp)); # ifdef GATHERSTATS # define ADD_TO_ATOMIC(sz) GC_atomic_in_use += (sz) @@ -174,14 +174,6 @@ mse *GC_signal_mark_stack_overflow(mse *msp); } \ } -#ifdef PRINT_BLACK_LIST -# define GC_FIND_START(current, hhdr, new_hdr_p, source) \ - GC_find_start(current, hhdr, new_hdr_p, source) -#else -# define GC_FIND_START(current, hhdr, new_hdr_p, source) \ - GC_find_start(current, hhdr, new_hdr_p) -#endif - /* Push the contents of current onto the mark stack if it is a valid */ /* ptr to a currently unmarked object. Mark it. */ /* If we assumed a standard-conforming compiler, we could probably */ @@ -195,8 +187,7 @@ mse *GC_signal_mark_stack_overflow(mse *msp); GET_HDR(my_current, my_hhdr); \ if (IS_FORWARDING_ADDR_OR_NIL(my_hhdr)) { \ hdr * new_hdr = GC_invalid_header; \ - my_current = GC_FIND_START(my_current, my_hhdr, \ - &new_hdr, (word)source); \ + my_current = GC_find_start(my_current, my_hhdr, &new_hdr); \ my_hhdr = new_hdr; \ } \ PUSH_CONTENTS_HDR(my_current, mark_stack_top, mark_stack_limit, \ @@ -290,21 +281,39 @@ exit_label: ; \ /* * Push a single value onto mark stack. Mark from the object pointed to by p. + * Invoke FIXUP_POINTER(p) before any further processing. * P is considered valid even if it is an interior pointer. * Previously marked objects are not pushed. Hence we make progress even * if the mark stack overflows. */ -# define GC_PUSH_ONE_STACK(p, source) \ - if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \ + +# if NEED_FIXUP_POINTER + /* Try both the raw version and the fixed up one. */ +# define GC_PUSH_ONE_STACK(p, source) \ + if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \ && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \ PUSH_ONE_CHECKED_STACK(p, source); \ - } + } \ + FIXUP_POINTER(p); \ + if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \ + && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \ + PUSH_ONE_CHECKED_STACK(p, source); \ + } +# else /* !NEED_FIXUP_POINTER */ +# define GC_PUSH_ONE_STACK(p, source) \ + if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \ + && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \ + PUSH_ONE_CHECKED_STACK(p, source); \ + } +# endif + /* * As above, but interior pointer recognition as for * normal for heap pointers. */ # define GC_PUSH_ONE_HEAP(p,source) \ + FIXUP_POINTER(p); \ if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \ && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \ GC_mark_stack_top = GC_mark_and_push( \ diff --git a/boehm-gc/include/private/gc_priv.h b/boehm-gc/include/private/gc_priv.h index b09c4840945..ffa398b308b 100644 --- a/boehm-gc/include/private/gc_priv.h +++ b/boehm-gc/include/private/gc_priv.h @@ -30,14 +30,20 @@ # define BSD_TIME #endif +#ifdef DGUX +# include <sys/types.h> +# include <sys/time.h> +# include <sys/resource.h> +#endif /* DGUX */ + #ifdef BSD_TIME # include <sys/types.h> # include <sys/time.h> # include <sys/resource.h> #endif /* BSD_TIME */ -# ifndef GC_H -# include "gc.h" +# ifndef _GC_H +# include "../gc.h" # endif # ifndef GC_MARK_H @@ -206,11 +212,10 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ #endif #if defined(GC_GCJ_SUPPORT) && ALIGNMENT < 8 && !defined(ALIGN_DOUBLE) - /* GCJ's Hashtable synchronization code requires 64-bit alignment. */ + /* GCJ's Hashtable synchronization code requires 64-bit alignment. */ # define ALIGN_DOUBLE #endif - /* ALIGN_DOUBLE requires MERGE_SIZES at present. */ # if defined(ALIGN_DOUBLE) && !defined(MERGE_SIZES) # define MERGE_SIZES @@ -347,7 +352,8 @@ void GC_print_callers GC_PROTO((struct callinfo info[NFRAMES])); # include <string.h> # define BCOPY_EXISTS # endif -# if defined(MACOSX) +# if defined(DARWIN) +# include <string.h> # define BCOPY_EXISTS # endif @@ -360,68 +366,6 @@ void GC_print_callers GC_PROTO((struct callinfo info[NFRAMES])); # define BZERO(x,n) bzero((char *)(x),(int)(n)) # endif -/* HBLKSIZE aligned allocation. 0 is taken to mean failure */ -/* space is assumed to be cleared. */ -/* In the case os USE_MMAP, the argument must also be a */ -/* physical page size. */ -/* GET_MEM is currently not assumed to retrieve 0 filled space, */ -/* though we should perhaps take advantage of the case in which */ -/* does. */ -struct hblk; /* See below. */ -# ifdef PCR - char * real_malloc(); -# define GET_MEM(bytes) HBLKPTR(real_malloc((size_t)bytes + GC_page_size) \ - + GC_page_size-1) -# else -# ifdef OS2 - void * os2_alloc(size_t bytes); -# define GET_MEM(bytes) HBLKPTR((ptr_t)os2_alloc((size_t)bytes \ - + GC_page_size) \ - + GC_page_size-1) -# else -# if defined(NEXT) || defined(MACOSX) || defined(DOS4GW) || \ - (defined(AMIGA) && !defined(GC_AMIGA_FASTALLOC)) || \ - (defined(SUNOS5) && !defined(USE_MMAP)) -# define GET_MEM(bytes) HBLKPTR((size_t) \ - calloc(1, (size_t)bytes + GC_page_size) \ - + GC_page_size-1) -# else -# ifdef MSWIN32 - extern ptr_t GC_win32_get_mem(); -# define GET_MEM(bytes) (struct hblk *)GC_win32_get_mem(bytes) -# else -# ifdef MACOS -# if defined(USE_TEMPORARY_MEMORY) - extern Ptr GC_MacTemporaryNewPtr(size_t size, - Boolean clearMemory); -# define GET_MEM(bytes) HBLKPTR( \ - GC_MacTemporaryNewPtr(bytes + GC_page_size, true) \ - + GC_page_size-1) -# else -# define GET_MEM(bytes) HBLKPTR( \ - NewPtrClear(bytes + GC_page_size) + GC_page_size-1) -# endif -# else -# ifdef MSWINCE - extern ptr_t GC_wince_get_mem(); -# define GET_MEM(bytes) (struct hblk *)GC_wince_get_mem(bytes) -# else -# if defined(AMIGA) && defined(GC_AMIGA_FASTALLOC) - extern void *GC_amiga_get_mem(size_t size); - define GET_MEM(bytes) HBLKPTR((size_t) \ - GC_amiga_get_mem((size_t)bytes + GC_page_size) \ - + GC_page_size-1) -# else - extern ptr_t GC_unix_get_mem(); -# define GET_MEM(bytes) (struct hblk *)GC_unix_get_mem(bytes) -# endif -# endif -# endif -# endif -# endif -# endif -# endif - /* Delay any interrupts or signals that may abort this thread. Data */ /* structures are in a consistent state outside this pair of calls. */ /* ANSI C allows both to be empty (though the standard isn't very */ @@ -486,7 +430,7 @@ struct hblk; /* See below. */ # ifdef SMALL_CONFIG # define ABORT(msg) abort(); # else - GC_API void GC_abort(); + GC_API void GC_abort GC_PROTO((GC_CONST char * msg)); # define ABORT(msg) GC_abort(msg); # endif # endif @@ -646,9 +590,10 @@ extern GC_warn_proc GC_current_warn_proc; */ # ifdef LARGE_CONFIG -# define LOG_PHT_ENTRIES 19 /* Collisions likely at 512K blocks, */ - /* which is >= 2GB. Each table takes */ - /* 64KB. */ +# define LOG_PHT_ENTRIES 20 /* Collisions likely at 1M blocks, */ + /* which is >= 4GB. Each table takes */ + /* 128KB, some of which may never be */ + /* touched. */ # else # ifdef SMALL_CONFIG # define LOG_PHT_ENTRIES 14 /* Collisions are likely if heap grows */ @@ -656,7 +601,7 @@ extern GC_warn_proc GC_current_warn_proc; /* Each hash table occupies 2K bytes. */ # else /* default "medium" configuration */ # define LOG_PHT_ENTRIES 16 /* Collisions are likely if heap grows */ - /* to more than 16K hblks >= 256MB. */ + /* to more than 64K hblks >= 256MB. */ /* Each hash table occupies 8K bytes. */ # endif # endif @@ -897,6 +842,10 @@ struct _GC_arrays { word _mem_freed; /* Number of explicitly deallocated words of memory */ /* since last collection. */ + word _finalizer_mem_freed; + /* Words of memory explicitly deallocated while */ + /* finalizers were running. Used to approximate mem. */ + /* explicitly deallocated by finalizers. */ ptr_t _scratch_end_ptr; ptr_t _scratch_last_end_ptr; /* Used by headers.c, and can easily appear to point to */ @@ -957,7 +906,7 @@ struct _GC_arrays { /* OFFSET_TOO_BIG if the value j would be too */ /* large to fit in the entry. (Note that the */ /* size of these entries matters, both for */ - /* space consumption and for cache utilization. */ + /* space consumption and for cache utilization.) */ # define OFFSET_TOO_BIG 0xfe # define OBJ_INVALID 0xff # define MAP_ENTRY(map, bytes) (map)[bytes] @@ -1067,6 +1016,7 @@ GC_API GC_FAR struct _GC_arrays GC_arrays; # define GC_words_finalized GC_arrays._words_finalized # define GC_non_gc_bytes_at_gc GC_arrays._non_gc_bytes_at_gc # define GC_mem_freed GC_arrays._mem_freed +# define GC_finalizer_mem_freed GC_arrays._finalizer_mem_freed # define GC_scratch_end_ptr GC_arrays._scratch_end_ptr # define GC_scratch_last_end_ptr GC_arrays._scratch_last_end_ptr # define GC_mark_procs GC_arrays._mark_procs @@ -1201,17 +1151,19 @@ extern struct hblk * GC_hblkfreelist[]; /* header structure associated with */ /* block. */ -extern GC_bool GC_is_initialized; /* GC_init() has been run. */ - extern GC_bool GC_objects_are_marked; /* There are marked objects in */ /* the heap. */ #ifndef SMALL_CONFIG extern GC_bool GC_incremental; /* Using incremental/generational collection. */ +# define TRUE_INCREMENTAL \ + (GC_incremental && GC_time_limit != GC_TIME_UNLIMITED) + /* True incremental, not just generational, mode */ #else # define GC_incremental FALSE /* Hopefully allow optimizer to remove some code. */ +# define TRUE_INCREMENTAL FALSE #endif extern GC_bool GC_dirty_maintained; @@ -1229,6 +1181,10 @@ extern long GC_large_alloc_warn_interval; extern long GC_large_alloc_warn_suppressed; /* Number of warnings suppressed so far. */ +#ifdef THREADS + extern GC_bool GC_world_stopped; +#endif + /* Operations */ # ifndef abs # define abs(x) ((x) < 0? (-(x)) : (x)) @@ -1403,6 +1359,11 @@ extern void (*GC_start_call_back) GC_PROTO((void)); # else void GC_push_regs GC_PROTO((void)); # endif +# if defined(SPARC) || defined(IA64) + /* Cause all stacked registers to be saved in memory. Return a */ + /* pointer to the top of the corresponding memory stack. */ + word GC_save_regs_in_stack GC_PROTO((void)); +# endif /* Push register contents onto mark stack. */ /* If NURSERY is defined, the default push */ /* action can be overridden with GC_push_proc */ @@ -1452,6 +1413,7 @@ void GC_set_fl_marks GC_PROTO((ptr_t p)); /* Set all mark bits associated with */ /* a free list. */ void GC_add_roots_inner GC_PROTO((char * b, char * e, GC_bool tmp)); +void GC_remove_roots_inner GC_PROTO((char * b, char * e)); GC_bool GC_is_static_root GC_PROTO((ptr_t p)); /* Is the address p in one of the registered static */ /* root sections? */ @@ -1462,11 +1424,10 @@ GC_bool GC_is_tmp_root GC_PROTO((ptr_t p)); # endif void GC_register_dynamic_libraries GC_PROTO((void)); /* Add dynamic library data sections to the root set. */ - GC_bool GC_register_main_static_data GC_PROTO((void)); - /* We need to register the main data segment. Returns */ - /* TRUE unless this is done implicitly as part of */ - /* dynamic library registration. */ + /* We need to register the main data segment. Returns */ + /* TRUE unless this is done implicitly as part of */ + /* dynamic library registration. */ /* Machine dependent startup routines */ ptr_t GC_get_stack_base GC_PROTO((void)); /* Cold end of stack */ @@ -1624,6 +1585,8 @@ GC_bool GC_collect_or_expand GC_PROTO(( \ /* until the blocks are available or */ /* until it fails by returning FALSE. */ +extern GC_bool GC_is_initialized; /* GC_init() has been run. */ + #if defined(MSWIN32) || defined(MSWINCE) void GC_deinit GC_PROTO((void)); /* Free any resources allocated by */ @@ -1665,6 +1628,8 @@ ptr_t GC_allocobj GC_PROTO((word sz, int kind)); /* Make the indicated */ /* free list nonempty, and return its */ /* head. */ + +void GC_free_inner(GC_PTR p); void GC_init_headers GC_PROTO((void)); struct hblkhdr * GC_install_header GC_PROTO((struct hblk *h)); @@ -1694,6 +1659,12 @@ void GC_notify_or_invoke_finalizers GC_PROTO((void)); /* Call *GC_finalizer_notifier if there are */ /* finalizers to be run, and we haven't called */ /* this procedure yet this GC cycle. */ + +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)); + /* Auxiliary fns to make finalization work */ + /* correctly with displaced pointers introduced */ + /* by the debugging allocators. */ void GC_add_to_heap GC_PROTO((struct hblk *p, word bytes)); /* Add a HBLKSIZE aligned chunk to the heap. */ @@ -1704,16 +1675,36 @@ void GC_print_obj GC_PROTO((ptr_t p)); /* description of the object to stderr. */ extern void (*GC_check_heap) GC_PROTO((void)); /* Check that all objects in the heap with */ - /* debugging info are intact. Print */ - /* descriptions of any that are not. */ + /* debugging info are intact. */ + /* Add any that are not to GC_smashed list. */ +extern void (*GC_print_all_smashed) GC_PROTO((void)); + /* Print GC_smashed if it's not empty. */ + /* Clear GC_smashed list. */ +extern void GC_print_all_errors GC_PROTO((void)); + /* Print smashed and leaked objects, if any. */ + /* Clear the lists of such objects. */ extern void (*GC_print_heap_obj) GC_PROTO((ptr_t p)); /* If possible print s followed by a more */ /* detailed description of the object */ /* referred to by p. */ +#if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG) + void GC_print_address_map GC_PROTO((void)); + /* Print an address map of the process. */ +#endif +extern GC_bool GC_have_errors; /* We saw a smashed or leaked object. */ + /* Call error printing routine */ + /* occasionally. */ extern GC_bool GC_print_stats; /* Produce at least some logging output */ /* Set from environment variable. */ +#ifndef NO_DEBUGGING + extern GC_bool GC_dump_regularly; /* Generate regular debugging dumps. */ +# define COND_DUMP if (GC_dump_regularly) GC_dump(); +#else +# define COND_DUMP +#endif + /* Macros used for collector internal allocation. */ /* These assume the collector lock is held. */ #ifdef DBG_HDRS_ALL @@ -1785,6 +1776,7 @@ void GC_print_block_list GC_PROTO((void)); void GC_print_hblkfreelist GC_PROTO((void)); void GC_print_heap_sects GC_PROTO((void)); void GC_print_static_roots GC_PROTO((void)); +void GC_print_finalization_stats GC_PROTO((void)); void GC_dump GC_PROTO((void)); #ifdef KEEP_BACK_PTRS @@ -1866,6 +1858,16 @@ void GC_err_puts GC_PROTO((GC_CONST char *s)); # define GC_ASSERT(expr) # endif +/* Check a compile time assertion at compile time. The error */ +/* message for failure is a bit baroque, but ... */ +#if defined(mips) && !defined(__GNUC__) +/* DOB: MIPSPro C gets an internal error taking the sizeof an array type. + This code works correctly (ugliness is to avoid "unused var" warnings) */ +# define GC_STATIC_ASSERT(expr) do { if (0) { char j[(expr)? 1 : -1]; j[0]='\0'; j[0]=j[0]; } } while(0) +#else +# define GC_STATIC_ASSERT(expr) sizeof(char[(expr)? 1 : -1]) +#endif + # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC) /* We need additional synchronization facilities from the thread */ /* support. We believe these are less performance critical */ @@ -1911,7 +1913,7 @@ void GC_err_puts GC_PROTO((GC_CONST char *s)); /* in Linux glibc, but it's not exported.) Thus we continue to use */ /* the same hard-coded signals we've always used. */ # if !defined(SIG_SUSPEND) -# if defined(GC_LINUX_THREADS) +# if defined(GC_LINUX_THREADS) || defined(GC_DGUX386_THREADS) # if defined(SPARC) && !defined(SIGPWR) /* SPARC/Linux doesn't properly define SIGPWR in <signal.h>. * It is aliased to SIGLOST in asm/signal.h, though. */ diff --git a/boehm-gc/include/private/gcconfig.h b/boehm-gc/include/private/gcconfig.h index 809887f8219..29dab213815 100644 --- a/boehm-gc/include/private/gcconfig.h +++ b/boehm-gc/include/private/gcconfig.h @@ -13,11 +13,25 @@ * provided the above notices are retained, and a notice that the code was * modified is included with the above copyright notice. */ + +/* + * This header is private to the gc. It is almost always included from + * gc_priv.h. However it is possible to include it by itself if just the + * configuration macros are needed. In that + * case, a few declarations relying on types declared in gc_priv.h will be + * omitted. + */ #ifndef GCCONFIG_H # define GCCONFIG_H +# ifndef GC_PRIVATE_H + /* Fake ptr_t declaration, just to avoid compilation errors. */ + /* This avoids many instances if "ifndef GC_PRIVATE_H" below. */ + typedef struct GC_undefined_struct * ptr_t; +# endif + /* Machine dependent parameters. Some tuning parameters can be found */ /* near the top of gc_private.h. */ @@ -25,7 +39,9 @@ /* First a unified test for Linux: */ # if defined(linux) || defined(__linux__) +# ifndef LINUX # define LINUX +# endif # endif /* And one for NetBSD: */ @@ -44,9 +60,9 @@ # endif /* Determine the machine type: */ -# if defined(__arm__) || defined(__thumb__) +# if defined(__XSCALE__) # define ARM32 -# if !defined(LINUX) && !defined(NETBSD) +# if !defined(LINUX) # define NOSYS # define mach_type_known # endif @@ -69,7 +85,7 @@ # define SPARC # define mach_type_known # endif -# if defined(NETBSD) && defined(m68k) +# if defined(NETBSD) && (defined(m68k) || defined(__m68k__)) # define M68K # define mach_type_known # endif @@ -77,7 +93,7 @@ # define POWERPC # define mach_type_known # endif -# if defined(NETBSD) && defined(__arm__) +# if defined(NETBSD) && (defined(__arm32__) || defined(__arm__)) # define ARM32 # define mach_type_known # endif @@ -90,6 +106,10 @@ # endif # define mach_type_known # endif +# if defined(__NetBSD__) && defined(__vax__) +# define VAX +# define mach_type_known +# endif # if defined(mips) || defined(__mips) || defined(_mips) # define MIPS # if defined(nec_ews) || defined(_nec_ews) @@ -109,6 +129,13 @@ # endif /* !LINUX */ # define mach_type_known # endif +# if defined(DGUX) && (defined(i386) || defined(__i386__)) +# define I386 +# ifndef _USING_DGUX +# define _USING_DGUX +# endif +# define mach_type_known +# endif # if defined(sequent) && (defined(i386) || defined(__i386__)) # define I386 # define SEQUENT @@ -198,7 +225,11 @@ # define IA64 # define mach_type_known # endif -# if defined(LINUX) && (defined(powerpc) || defined(__powerpc__)) +# if defined(LINUX) && defined(__arm__) +# define ARM32 +# define mach_type_known +# endif +# if defined(LINUX) && (defined(powerpc) || defined(__powerpc__) || defined(powerpc64) || defined(__powerpc64__)) # define POWERPC # define mach_type_known # endif @@ -237,19 +268,19 @@ # define MACOS # define mach_type_known # endif -# if defined(__MWERKS__) && defined(__powerc) +# if defined(__MWERKS__) && defined(__powerc) && !defined(__MACH__) # define POWERPC # define MACOS # define mach_type_known # endif # if defined(macosx) || \ defined(__APPLE__) && defined(__MACH__) && defined(__ppc__) -# define MACOSX +# define DARWIN # define POWERPC # define mach_type_known # endif # if defined(__APPLE__) && defined(__MACH__) && defined(__i386__) -# define MACOSX +# define DARWIN # define I386 --> Not really supported, but at least we recognize it. # endif @@ -291,7 +322,7 @@ # define CX_UX # define mach_type_known # endif -# if defined(DGUX) +# if defined(DGUX) && defined(m88k) # define M88K /* DGUX defined */ # define mach_type_known @@ -419,17 +450,18 @@ /* (CX_UX and DGUX) */ /* S370 ==> 370-like machine */ /* running Amdahl UTS4 */ - /* S390 ==> 390-like machine */ - /* running LINUX */ + /* S390 ==> 390-like machine */ + /* running LINUX */ /* ARM32 ==> Intel StrongARM */ /* IA64 ==> Intel IPF */ /* (e.g. Itanium) */ /* (LINUX and HPUX) */ - /* IA64_32 ==> IA64 w/32 bit ABI */ - /* (HPUX) */ /* SH ==> Hitachi SuperH */ /* (LINUX & MSWINCE) */ /* X86_64 ==> AMD x86-64 */ + /* POWERPC ==> IBM/Apple PowerPC */ + /* (MACOS(<=9),DARWIN(incl.MACOSX),*/ + /* LINUX, NETBSD, NOSYS variants) */ /* @@ -450,7 +482,12 @@ * defining it to be 1 will always work, but perform poorly. * * DATASTART is the beginning of the data segment. - * On UNIX systems, the collector will scan the area between DATASTART + * On some platforms SEARCH_FOR_DATA_START is defined. + * SEARCH_FOR_DATASTART will cause GC_data_start to + * be set to an address determined by accessing data backwards from _end + * until an unmapped page is found. DATASTART will be defined to be + * GC_data_start. + * On UNIX-like systems, the collector will scan the area between DATASTART * and DATAEND for root pointers. * * DATAEND, if not `end' where `end' is defined as ``extern int end[];''. @@ -470,8 +507,13 @@ * 1) define STACK_GROWS_UP if the stack grows toward higher addresses, and * 2) define exactly one of * STACKBOTTOM (should be defined to be an expression) + * LINUX_STACKBOTTOM * HEURISTIC1 * HEURISTIC2 + * If STACKBOTTOM is defined, then it's value will be used directly as the + * stack base. If LINUX_STACKBOTTOM is defined, then it will be determined + * with a method appropriate for most Linux systems. Currently we look + * first for __libc_stack_end, and if that fails read it from /proc. * If either of the last two macros are defined, then STACKBOTTOM is computed * during collector startup using one of the following two heuristics: * HEURISTIC1: Take an address inside GC_init's frame, and round it up to @@ -536,6 +578,9 @@ * An architecture may also define CLEAR_DOUBLE(x) to be a fast way to * clear the two words at GC_malloc-aligned address x. By default, * word stores of 0 are used instead. + * + * HEAP_START may be defined as the initial address hint for mmap-based + * allocation. */ /* If we are using a recent version of gcc, we can use __builtin_unwind_init() @@ -560,18 +605,25 @@ # ifdef NETBSD # define OS_TYPE "NETBSD" # define HEURISTIC2 - extern char etext[]; -# define DATASTART ((ptr_t)(etext)) +# ifdef __ELF__ +# define DATASTART GC_data_start +# define DYNAMIC_LOADING +# else + extern char etext[]; +# define DATASTART ((ptr_t)(etext)) +# endif # endif # ifdef LINUX # define OS_TYPE "LINUX" # define STACKBOTTOM ((ptr_t)0xf0000000) +# define USE_GENERIC_PUSH_REGS + /* We never got around to the assembly version. */ /* # define MPROTECT_VDB - Reported to not work 9/17/01 */ # ifdef __ELF__ # define DYNAMIC_LOADING # include <features.h> # if defined(__GLIBC__)&& __GLIBC__>=2 -# define LINUX_DATA_START +# define SEARCH_FOR_DATA_START # else /* !GLIBC2 */ extern char **__environ; # define DATASTART ((ptr_t)(&__environ)) @@ -666,26 +718,49 @@ # define DATAEND /* not needed */ # endif # ifdef LINUX -# define ALIGNMENT 4 /* Guess. Can someone verify? */ +# if (defined (powerpc64) || defined(__powerpc64__)) +# define ALIGNMENT 8 +# define CPP_WORDSZ 64 +# else +# define ALIGNMENT 4 /* Guess. Can someone verify? */ /* This was 2, but that didn't sound right. */ +# endif # define OS_TYPE "LINUX" -# define DYNAMIC_LOADING + /* HEURISTIC1 has been reliably reported to fail for a 32-bit */ + /* executable on a 64 bit kernel. */ # define LINUX_STACKBOTTOM - /* Stack usually starts at 0x80000000 */ -# define LINUX_DATA_START +# define DYNAMIC_LOADING +# define SEARCH_FOR_DATA_START extern int _end[]; # define DATAEND (_end) # endif -# ifdef MACOSX - /* There are reasons to suspect this may not be reliable. */ +# ifdef DARWIN # define ALIGNMENT 4 -# define OS_TYPE "MACOSX" +# define OS_TYPE "DARWIN" +# define DYNAMIC_LOADING + /* XXX: see get_end(3), get_etext() and get_end() should not be used. + These aren't used when dyld support is enabled (it is by default) */ # define DATASTART ((ptr_t) get_etext()) +# define DATAEND ((ptr_t) get_end()) # define STACKBOTTOM ((ptr_t) 0xc0000000) -# define DATAEND /* not needed */ -# undef MPROTECT_VDB +# define USE_MMAP +# define USE_MMAP_ANON +# define USE_ASM_PUSH_REGS + /* This is potentially buggy. It needs more testing. See the comments in + os_dep.c */ +# define MPROTECT_VDB # include <unistd.h> # define GETPAGESIZE() getpagesize() +# if defined(USE_PPC_PREFETCH) && defined(__GNUC__) + /* The performance impact of prefetches is untested */ +# define PREFETCH(x) \ + __asm__ __volatile__ ("dcbt 0,%0" : : "r" ((const void *) (x))) +# define PREFETCH_FOR_WRITE(x) \ + __asm__ __volatile__ ("dcbtst 0,%0" : : "r" ((const void *) (x))) +# endif + /* There seems to be some issues with trylock hanging on darwin. This + should be looked into some more */ +# define NO_PTHREAD_TRYLOCK # endif # ifdef NETBSD # define ALIGNMENT 4 @@ -746,8 +821,8 @@ # define OS_TYPE "SUNOS5" extern int _etext[]; extern int _end[]; - extern char * GC_SysVGetDataStart(); -# define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, _etext) + extern ptr_t GC_SysVGetDataStart(); +# define DATASTART GC_SysVGetDataStart(0x10000, _etext) # define DATAEND (_end) # if !defined(USE_MMAP) && defined(REDIRECT_MALLOC) # define USE_MMAP @@ -801,9 +876,9 @@ # endif # ifdef DRSNX # define OS_TYPE "DRSNX" - extern char * GC_SysVGetDataStart(); + extern ptr_t GC_SysVGetDataStart(); extern int etext[]; -# define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, etext) +# define DATASTART GC_SysVGetDataStart(0x10000, etext) # define MPROTECT_VDB # define STACKBOTTOM ((ptr_t) 0xdfff0000) # define DYNAMIC_LOADING @@ -819,13 +894,14 @@ extern int _etext[]; # define DATAEND (_end) # define SVR4 + extern ptr_t GC_SysVGetDataStart(); # ifdef __arch64__ +# define DATASTART GC_SysVGetDataStart(0x100000, _etext) /* libc_stack_end is not set reliably for sparc64 */ -# define STACKBOTTOM ((ptr_t) 0x80000000000) -# define DATASTART (ptr_t)GC_SysVGetDataStart(0x100000, _etext) +# define STACKBOTTOM ((ptr_t) 0x80000000000ULL) # else -# define LINUX_STACKBOTTOM -# define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, _etext) +# define DATASTART GC_SysVGetDataStart(0x10000, _etext) +# define LINUX_STACKBOTTOM # endif # endif # ifdef OPENBSD @@ -876,7 +952,7 @@ # ifdef SUNOS5 # define OS_TYPE "SUNOS5" extern int _etext[], _end[]; - extern char * GC_SysVGetDataStart(); + extern ptr_t GC_SysVGetDataStart(); # define DATASTART GC_SysVGetDataStart(0x1000, _etext) # define DATAEND (_end) /* # define STACKBOTTOM ((ptr_t)(_start)) worked through 2.7, */ @@ -921,6 +997,28 @@ # define DYNAMIC_LOADING # define ELF_CLASS ELFCLASS32 # endif +# ifdef DGUX +# define OS_TYPE "DGUX" + extern int _etext, _end; + extern ptr_t GC_SysVGetDataStart(); +# define DATASTART GC_SysVGetDataStart(0x1000, &_etext) +# define DATAEND (&_end) +# define STACK_GROWS_DOWN +# define HEURISTIC2 +# include <unistd.h> +# define GETPAGESIZE() sysconf(_SC_PAGESIZE) +# define DYNAMIC_LOADING +# ifndef USE_MMAP +# define USE_MMAP +# endif /* USE_MMAP */ +# define MAP_FAILED (void *) -1 +# ifdef USE_MMAP +# define HEAP_START (ptr_t)0x40000000 +# else /* USE_MMAP */ +# define HEAP_START DATAEND +# endif /* USE_MMAP */ +# endif /* DGUX */ + # ifdef LINUX # ifndef __GNUC__ /* The Intel compiler doesn't like inline assembly */ @@ -944,6 +1042,9 @@ /* possibly because Linux threads is itself a malloc client */ /* and can't deal with the signals. */ # endif +# define HEAP_START 0x1000 + /* This encourages mmap to give us low addresses, */ + /* thus allowing the heap to grow to ~3GB */ # ifdef __ELF__ # define DYNAMIC_LOADING # ifdef UNDEFINED /* includes ro data */ @@ -952,7 +1053,7 @@ # endif # include <features.h> # if defined(__GLIBC__) && __GLIBC__ >= 2 -# define LINUX_DATA_START +# define SEARCH_FOR_DATA_START # else extern char **__environ; # define DATASTART ((ptr_t)(&__environ)) @@ -1006,8 +1107,12 @@ /* DATAEND = _data_end__ */ /* To get it right for both, we take the */ /* minumum/maximum of the two. */ +# ifndef MAX # define MAX(x,y) ((x) > (y) ? (x) : (y)) +# endif +# ifndef MIN # define MIN(x,y) ((x) < (y) ? (x) : (y)) +# endif # define DATASTART ((ptr_t) MIN(_data_start__, _bss_start__)) # define DATAEND ((ptr_t) MAX(_data_end__, _bss_end__)) # undef STACK_GRAN @@ -1061,16 +1166,9 @@ # ifdef __ELF__ # define DYNAMIC_LOADING # endif -/* Handle unmapped hole i386*-*-freebsd[45]* may put between etext and edata. */ extern char etext[]; - extern char edata[]; - extern char end[]; -# define NEED_FIND_LIMIT -# define DATASTART ((ptr_t)(etext)) -# define MIN(x,y) ((x) < (y) ? (x) : (y)) -# define DATAEND (MIN (GC_find_limit (DATASTART, TRUE), DATASTART2)) -# define DATASTART2 ((ptr_t)(edata)) -# define DATAEND2 ((ptr_t)(end)) + extern char * GC_FreeBSDGetDataStart(); +# define DATASTART GC_FreeBSDGetDataStart(0x1000, &etext) # endif # ifdef NETBSD # define OS_TYPE "NETBSD" @@ -1149,7 +1247,11 @@ # define DATASTART ((ptr_t)(__data_start)) # define ALIGNMENT 4 # define USE_GENERIC_PUSH_REGS -# define LINUX_STACKBOTTOM +# if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 2 || __GLIBC__ > 2 +# define LINUX_STACKBOTTOM +# else +# define STACKBOTTOM 0x80000000 +# endif # endif /* Linux */ # ifdef EWS4800 # define HEURISTIC2 @@ -1203,7 +1305,8 @@ /* heap sections so they're not */ /* considered as roots. */ # define OS_TYPE "IRIX5" -# define MPROTECT_VDB +/*# define MPROTECT_VDB DOB: this should work, but there is evidence */ +/* of recent breakage. */ # ifdef _MIPS_SZPTR # define CPP_WORDSZ _MIPS_SZPTR # define ALIGNMENT (_MIPS_SZPTR/8) @@ -1226,28 +1329,46 @@ # define ALIGNMENT 4 # define HEURISTIC2 # define USE_GENERIC_PUSH_REGS - extern int _fdata[]; -# define DATASTART ((ptr_t)(_fdata)) - extern int _end[]; -# define DATAEND ((ptr_t)(_end)) -# define DYNAMIC_LOADING +# ifdef __ELF__ + extern int etext[]; +# define DATASTART GC_data_start +# define NEED_FIND_LIMIT +# define DYNAMIC_LOADING +# else +# define DATASTART ((ptr_t) 0x10000000) +# define STACKBOTTOM ((ptr_t) 0x7ffff000) +# endif /* _ELF_ */ # endif # endif # ifdef RS6000 # define MACH_TYPE "RS6000" +# ifdef ALIGNMENT +# undef ALIGNMENT +# endif +# ifdef IA64 +# undef IA64 /* DOB: some AIX installs stupidly define IA64 in /usr/include/sys/systemcfg.h */ +# endif # ifdef __64BIT__ # define ALIGNMENT 8 # define CPP_WORDSZ 64 +# define STACKBOTTOM ((ptr_t)0x1000000000000000) # else # define ALIGNMENT 4 # define CPP_WORDSZ 32 -# endif +# define STACKBOTTOM ((ptr_t)((ulong)&errno)) +# endif + /* From AIX linker man page: + _text Specifies the first location of the program. + _etext Specifies the first location after the program. + _data Specifies the first location of the data. + _edata Specifies the first location after the initialized data + _end or end Specifies the first location after all data. + */ extern int _data[], _end[]; # define DATASTART ((ptr_t)((ulong)_data)) # define DATAEND ((ptr_t)((ulong)_end)) extern int errno; -# define STACKBOTTOM ((ptr_t)((ulong)&errno)) # define USE_GENERIC_PUSH_REGS # define DYNAMIC_LOADING /* For really old versions of AIX, this may have to be removed. */ @@ -1311,15 +1432,23 @@ # define OS_TYPE "LINUX" # define LINUX_STACKBOTTOM # define DYNAMIC_LOADING -# define LINUX_DATA_START +# define SEARCH_FOR_DATA_START extern int _end[]; -# define DATAEND (_end) +# define DATAEND (&_end) # endif /* LINUX */ # endif /* HP_PA */ # ifdef ALPHA # define MACH_TYPE "ALPHA" # define ALIGNMENT 8 +# define CPP_WORDSZ 64 +# ifndef LINUX +# define USE_GENERIC_PUSH_REGS + /* Gcc and probably the DEC/Compaq compiler spill pointers to preserved */ + /* fp registers in some cases when the target is a 21264. The assembly */ + /* code doesn't handle that yet, and version dependencies make that a */ + /* bit tricky. Do the easy thing for now. */ +# endif # ifdef NETBSD # define OS_TYPE "NETBSD" # define HEURISTIC2 @@ -1327,13 +1456,11 @@ # define ELFCLASS32 32 # define ELFCLASS64 64 # define ELF_CLASS ELFCLASS64 -# define CPP_WORDSZ 64 # define DYNAMIC_LOADING # endif # ifdef OPENBSD # define OS_TYPE "OPENBSD" # define HEURISTIC2 -# define CPP_WORDSZ 64 # ifdef __ELF__ /* since OpenBSD/Alpha 2.9 */ # define DATASTART GC_data_start # define ELFCLASS32 32 @@ -1357,17 +1484,16 @@ extern char edata[]; extern char end[]; # define NEED_FIND_LIMIT -# define DATASTART ((ptr_t)(etext)) +# define DATASTART ((ptr_t)(&etext)) # define DATAEND (GC_find_limit (DATASTART, TRUE)) -# define DATASTART2 ((ptr_t)(edata)) -# define DATAEND2 ((ptr_t)(end)) -# define CPP_WORDSZ 64 +# define DATASTART2 ((ptr_t)(&edata)) +# define DATAEND2 ((ptr_t)(&end)) # endif # ifdef OSF1 # define OS_TYPE "OSF1" # define DATASTART ((ptr_t) 0x140000000) extern int _end[]; -# define DATAEND ((ptr_t) _end) +# define DATAEND ((ptr_t) &_end) extern char ** environ; /* round up from the value of environ to the nearest page boundary */ /* Probably breaks if putenv is called before collector */ @@ -1378,19 +1504,19 @@ /* the text segment immediately follows the stack. */ /* Hence we give an upper pound. */ /* This is currently unused, since we disabled HEURISTIC2 */ - extern int __start[]; + extern int __start[]; # define HEURISTIC2_LIMIT ((ptr_t)((word)(__start) & ~(getpagesize()-1))) -# define CPP_WORDSZ 64 -# define MPROTECT_VDB +# ifndef GC_OSF1_THREADS + /* Unresolved signal issues with threads. */ +# define MPROTECT_VDB +# endif # define DYNAMIC_LOADING # endif # ifdef LINUX # define OS_TYPE "LINUX" -# define CPP_WORDSZ 64 # define STACKBOTTOM ((ptr_t) 0x120000000) # ifdef __ELF__ # define SEARCH_FOR_DATA_START -# define DATASTART GC_data_start # define DYNAMIC_LOADING # else # define DATASTART ((ptr_t) 0x140000000) @@ -1468,7 +1594,6 @@ extern char * GC_register_stackbottom; # define BACKING_STORE_BASE ((ptr_t)GC_register_stackbottom) # define SEARCH_FOR_DATA_START -# define DATASTART GC_data_start # ifdef __GNUC__ # define DYNAMIC_LOADING # else @@ -1502,23 +1627,25 @@ # endif # ifdef DGUX # define OS_TYPE "DGUX" - extern char * GC_SysVGetDataStart(); -# define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, etext) + extern ptr_t GC_SysVGetDataStart(); +# define DATASTART GC_SysVGetDataStart(0x10000, etext) # endif # define STACKBOTTOM ((char*)0xf0000000) /* determined empirically */ # endif # ifdef S370 + /* If this still works, and if anyone cares, this should probably */ + /* be moved to the S390 category. */ # define MACH_TYPE "S370" # define ALIGNMENT 4 /* Required by hardware */ # define USE_GENERIC_PUSH_REGS # ifdef UTS4 # define OS_TYPE "UTS4" - extern int etext[]; + extern int etext[]; extern int _etext[]; extern int _end[]; - extern char * GC_SysVGetDataStart(); -# define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, _etext) + extern ptr_t GC_SysVGetDataStart(); +# define DATASTART GC_SysVGetDataStart(0x10000, _etext) # define DATAEND (_end) # define HEURISTIC2 # endif @@ -1528,23 +1655,23 @@ # define MACH_TYPE "S390" # define USE_GENERIC_PUSH_REGS # ifndef __s390x__ -# define ALIGNMENT 4 -# define CPP_WORDSZ 32 +# define ALIGNMENT 4 +# define CPP_WORDSZ 32 # else -# define ALIGNMENT 8 -# define CPP_WORDSZ 64 -# define HBLKSIZE 4096 +# define ALIGNMENT 8 +# define CPP_WORDSZ 64 +# define HBLKSIZE 4096 # endif # ifdef LINUX # define OS_TYPE "LINUX" # define LINUX_STACKBOTTOM # define DYNAMIC_LOADING - extern int __data_start[]; + extern int __data_start[]; # define DATASTART ((ptr_t)(__data_start)) - extern int _end[]; -# define DATAEND (_end) -# define CACHE_LINE_SIZE 256 -# define GETPAGESIZE() 4096 + extern int _end[]; +# define DATAEND (_end) +# define CACHE_LINE_SIZE 256 +# define GETPAGESIZE() 4096 # endif # endif @@ -1562,13 +1689,8 @@ # ifdef NETBSD # define OS_TYPE "NETBSD" # define HEURISTIC2 -# ifdef __ELF__ -# define DATASTART GC_data_start -# define DYNAMIC_LOADING -# else - extern char etext[]; -# define DATASTART ((ptr_t)(etext)) -# endif + extern char etext[]; +# define DATASTART ((ptr_t)(etext)) # define USE_GENERIC_PUSH_REGS # endif # ifdef LINUX @@ -1581,7 +1703,7 @@ # define DYNAMIC_LOADING # include <features.h> # if defined(__GLIBC__) && __GLIBC__ >= 2 -# define LINUX_DATA_START +# define SEARCH_FOR_DATA_START # else extern char **__environ; # define DATASTART ((ptr_t)(&__environ)) @@ -1628,7 +1750,7 @@ # define STACKBOTTOM ((ptr_t) 0x7c000000) # define USE_GENERIC_PUSH_REGS # define DYNAMIC_LOADING -# define LINUX_DATA_START +# define SEARCH_FOR_DATA_START extern int _end[]; # define DATAEND (_end) # endif @@ -1645,7 +1767,9 @@ # define MACH_TYPE "X86_64" # define ALIGNMENT 8 # define CPP_WORDSZ 64 -# define HBLKSIZE 4096 +# ifndef HBLKSIZE +# define HBLKSIZE 4096 +# endif # define CACHE_LINE_SIZE 64 # define USE_GENERIC_PUSH_REGS # ifdef LINUX @@ -1665,7 +1789,7 @@ # define DATASTART ((ptr_t)((((word) (_etext)) + 0xfff) & ~0xfff)) # endif # include <features.h> -# define LINUX_DATA_START +# define SEARCH_FOR_DATA_START extern int _end[]; # define DATAEND (_end) # else @@ -1679,19 +1803,6 @@ # endif # endif -#ifdef LINUX_DATA_START - /* Some Linux distributions arrange to define __data_start. Some */ - /* define data_start as a weak symbol. The latter is technically */ - /* broken, since the user program may define data_start, in which */ - /* case we lose. Nonetheless, we try both, prefering __data_start. */ - /* We assume gcc. */ -# pragma weak __data_start - extern int __data_start[]; -# pragma weak data_start - extern int data_start[]; -# define DATASTART ((ptr_t)(__data_start != 0? __data_start : data_start)) -#endif - #if defined(LINUX) && defined(REDIRECT_MALLOC) /* Rld appears to allocate some memory with its own allocator, and */ /* some through malloc, which might be redirected. To make this */ @@ -1730,15 +1841,15 @@ # endif # if defined(SUNOS5) || defined(DRSNX) || defined(UTS4) - /* OS has SVR4 generic features. Probably others also qualify. */ + /* OS has SVR4 generic features. Probably others also qualify. */ # define SVR4 # endif # if defined(SUNOS5) || defined(DRSNX) - /* OS has SUNOS5 style semi-undocumented interface to dynamic */ - /* loader. */ + /* OS has SUNOS5 style semi-undocumented interface to dynamic */ + /* loader. */ # define SUNOS5DL - /* OS has SUNOS5 style signal handlers. */ + /* OS has SUNOS5 style signal handlers. */ # define SUNOS5SIGS # endif @@ -1747,13 +1858,14 @@ # endif # if defined(SVR4) || defined(LINUX) || defined(IRIX) || defined(HPUX) \ - || defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD) \ - || defined(BSD) || defined(_AIX) || defined(MACOSX) || defined(OSF1) + || defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD) \ + || defined(DGUX) || defined(BSD) \ + || defined(_AIX) || defined(DARWIN) || defined(OSF1) # define UNIX_LIKE /* Basic Unix-like system calls work. */ # endif # if CPP_WORDSZ != 32 && CPP_WORDSZ != 64 - -> bad word size + -> bad word size # endif # ifdef PCR @@ -1767,13 +1879,13 @@ # endif # ifdef SRC_M3 -/* Postponed for now. */ + /* Postponed for now. */ # undef PROC_VDB # undef MPROTECT_VDB # endif # ifdef SMALL_CONFIG -/* Presumably not worth the space it takes. */ + /* Presumably not worth the space it takes. */ # undef PROC_VDB # undef MPROTECT_VDB # endif @@ -1813,49 +1925,50 @@ /* platforms as well, though it should be avoided in win32. */ # endif /* LINUX */ -# if defined(SEARCH_FOR_DATA_START) && defined(GC_PRIVATE_H) +# if defined(SEARCH_FOR_DATA_START) extern ptr_t GC_data_start; +# define DATASTART GC_data_start # endif # ifndef CLEAR_DOUBLE # define CLEAR_DOUBLE(x) \ - ((word*)x)[0] = 0; \ - ((word*)x)[1] = 0; + ((word*)x)[0] = 0; \ + ((word*)x)[1] = 0; # endif /* CLEAR_DOUBLE */ -/* Internally we use GC_SOLARIS_THREADS to test for either old or pthreads. */ + /* Internally we use GC_SOLARIS_THREADS to test for either old or pthreads. */ # if defined(GC_SOLARIS_PTHREADS) && !defined(GC_SOLARIS_THREADS) # define GC_SOLARIS_THREADS # endif # if defined(GC_IRIX_THREADS) && !defined(IRIX5) ---> inconsistent configuration + --> inconsistent configuration # endif # if defined(GC_LINUX_THREADS) && !defined(LINUX) ---> inconsistent configuration + --> inconsistent configuration # endif # if defined(GC_SOLARIS_THREADS) && !defined(SUNOS5) ---> inconsistent configuration + --> inconsistent configuration # endif # if defined(GC_HPUX_THREADS) && !defined(HPUX) ---> inconsistent configuration + --> inconsistent configuration +# endif +# if defined(GC_AIX_THREADS) && !defined(_AIX) + --> inconsistent configuration # endif -# if defined(GC_WIN32_THREADS) && !defined(MSWIN32) - /* Ideally CYGWIN32 should work, in addition to MSWIN32. I suspect */ - /* the necessary code is mostly there, but nobody has actually made */ - /* sure the right combination of pieces is compiled in, etc. */ ---> inconsistent configuration +# if defined(GC_WIN32_THREADS) && !defined(MSWIN32) && !defined(CYGWIN32) + --> inconsistent configuration # endif # if defined(PCR) || defined(SRC_M3) || \ - defined(GC_SOLARIS_THREADS) || defined(GC_WIN32_THREADS) || \ - defined(GC_PTHREADS) + defined(GC_SOLARIS_THREADS) || defined(GC_WIN32_THREADS) || \ + defined(GC_PTHREADS) # define THREADS # endif -# if defined(HP_PA) || defined(M88K) || defined(POWERPC) && !defined(MACOSX) \ - || defined(LINT) || defined(MSWINCE) \ - || (defined(I386) && defined(__LCC__)) +# if defined(HP_PA) || defined(M88K) || defined(POWERPC) && !defined(DARWIN) \ + || defined(LINT) || defined(MSWINCE) || defined(ARM32) \ + || (defined(I386) && defined(__LCC__)) /* Use setjmp based hack to mark from callee-save registers. */ /* The define should move to the individual platform */ /* descriptions. */ @@ -1867,36 +1980,26 @@ /* include assembly code to do it well. */ # endif -/* Can we save call chain in objects for debugging? */ -/* SET NFRAMES (# of saved frames) and NARGS (#of args for each frame) */ -/* to reasonable values for the platform. */ -/* Set SAVE_CALL_CHAIN if we can. SAVE_CALL_COUNT can be specified at */ -/* build time, though we feel free to adjust it slightly. */ -/* Define NEED_CALLINFO if we either save the call stack or */ -/* GC_ADD_CALLER is defined. */ -#ifdef LINUX -# include <features.h> -# if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 || __GLIBC__ > 2 -# define HAVE_BUILTIN_BACKTRACE -# endif -#endif + /* Can we save call chain in objects for debugging? */ + /* SET NFRAMES (# of saved frames) and NARGS (#of args for each */ + /* frame) to reasonable values for the platform. */ + /* Set SAVE_CALL_CHAIN if we can. SAVE_CALL_COUNT can be specified */ + /* at build time, though we feel free to adjust it slightly. */ + /* Define NEED_CALLINFO if we either save the call stack or */ + /* GC_ADD_CALLER is defined. */ + /* GC_CAN_SAVE_CALL_STACKS is set in gc.h. */ #if defined(SPARC) -# define CAN_SAVE_CALL_STACKS # define CAN_SAVE_CALL_ARGS #endif #if (defined(I386) || defined(X86_64)) && defined(LINUX) - /* SAVE_CALL_CHAIN is supported if the code is compiled to save */ - /* frame pointers by default, i.e. no -fomit-frame-pointer flag. */ -# define CAN_SAVE_CALL_STACKS + /* SAVE_CALL_CHAIN is supported if the code is compiled to save */ + /* frame pointers by default, i.e. no -fomit-frame-pointer flag. */ # define CAN_SAVE_CALL_ARGS #endif -#if defined(HAVE_BUILTIN_BACKTRACE) && !defined(CAN_SAVE_CALL_STACKS) -# define CAN_SAVE_CALL_STACKS -#endif # if defined(SAVE_CALL_COUNT) && !defined(GC_ADD_CALLER) \ - && defined(CAN_SAVE_CALL_STACKS) + && defined(GC_CAN_SAVE_CALL_STACKS) # define SAVE_CALL_CHAIN # endif # ifdef SAVE_CALL_CHAIN @@ -1909,7 +2012,7 @@ # ifdef SAVE_CALL_CHAIN # ifndef SAVE_CALL_COUNT # define NFRAMES 6 /* Number of frames to save. Even for */ - /* alignment reasons. */ + /* alignment reasons. */ # else # define NFRAMES ((SAVE_CALL_COUNT + 1) & ~1) # endif @@ -1925,4 +2028,96 @@ # define DBG_HDRS_ALL # endif +# if defined(POINTER_MASK) && !defined(POINTER_SHIFT) +# define POINTER_SHIFT 0 +# endif + +# if defined(POINTER_SHIFT) && !defined(POINTER_MASK) +# define POINTER_MASK ((GC_word)(-1)) +# endif + +# if !defined(FIXUP_POINTER) && defined(POINTER_MASK) +# define FIXUP_POINTER(p) (p) = ((p) & (POINTER_MASK) << POINTER_SHIFT) +# endif + +# if defined(FIXUP_POINTER) +# define NEED_FIXUP_POINTER 1 +# else +# define NEED_FIXUP_POINTER 0 +# define FIXUP_POINTER(p) +# endif + +#ifdef GC_PRIVATE_H + /* This relies on some type definitions from gc_priv.h, from */ + /* where it's normally included. */ + /* */ + /* How to get heap memory from the OS: */ + /* Note that sbrk()-like allocation is preferred, since it */ + /* usually makes it possible to merge consecutively allocated */ + /* chunks. It also avoids unintented recursion with */ + /* -DREDIRECT_MALLOC. */ + /* GET_MEM() returns a HLKSIZE aligned chunk. */ + /* 0 is taken to mean failure. */ + /* In the case os USE_MMAP, the argument must also be a */ + /* physical page size. */ + /* GET_MEM is currently not assumed to retrieve 0 filled space, */ + /* though we should perhaps take advantage of the case in which */ + /* does. */ + struct hblk; /* See gc_priv.h. */ +# ifdef PCR + char * real_malloc(); +# define GET_MEM(bytes) HBLKPTR(real_malloc((size_t)bytes + GC_page_size) \ + + GC_page_size-1) +# else +# ifdef OS2 + void * os2_alloc(size_t bytes); +# define GET_MEM(bytes) HBLKPTR((ptr_t)os2_alloc((size_t)bytes \ + + GC_page_size) \ + + GC_page_size-1) +# else +# if defined(NEXT) || defined(DOS4GW) || \ + (defined(AMIGA) && !defined(GC_AMIGA_FASTALLOC)) || \ + (defined(SUNOS5) && !defined(USE_MMAP)) +# define GET_MEM(bytes) HBLKPTR((size_t) \ + calloc(1, (size_t)bytes + GC_page_size) \ + + GC_page_size-1) +# else +# ifdef MSWIN32 + extern ptr_t GC_win32_get_mem(); +# define GET_MEM(bytes) (struct hblk *)GC_win32_get_mem(bytes) +# else +# ifdef MACOS +# if defined(USE_TEMPORARY_MEMORY) + extern Ptr GC_MacTemporaryNewPtr(size_t size, + Boolean clearMemory); +# define GET_MEM(bytes) HBLKPTR( \ + GC_MacTemporaryNewPtr(bytes + GC_page_size, true) \ + + GC_page_size-1) +# else +# define GET_MEM(bytes) HBLKPTR( \ + NewPtrClear(bytes + GC_page_size) + GC_page_size-1) +# endif +# else +# ifdef MSWINCE + extern ptr_t GC_wince_get_mem(); +# define GET_MEM(bytes) (struct hblk *)GC_wince_get_mem(bytes) +# else +# if defined(AMIGA) && defined(GC_AMIGA_FASTALLOC) + extern void *GC_amiga_get_mem(size_t size); +# define GET_MEM(bytes) HBLKPTR((size_t) \ + GC_amiga_get_mem((size_t)bytes + GC_page_size) \ + + GC_page_size-1) +# else + extern ptr_t GC_unix_get_mem(); +# define GET_MEM(bytes) (struct hblk *)GC_unix_get_mem(bytes) +# endif +# endif +# endif +# endif +# endif +# endif +# endif + +#endif /* GC_PRIVATE_H */ + # endif /* GCCONFIG_H */ diff --git a/boehm-gc/include/private/solaris_threads.h b/boehm-gc/include/private/solaris_threads.h index 1464bc14fd7..7d49c2987e0 100644 --- a/boehm-gc/include/private/solaris_threads.h +++ b/boehm-gc/include/private/solaris_threads.h @@ -16,7 +16,8 @@ # define DETACHED 2 /* Thread is intended to be detached. */ # define CLIENT_OWNS_STACK 4 /* Stack was supplied by client. */ -# define SUSPENDED 8 /* Currently suspended. */ +# define SUSPNDED 8 /* Currently suspended. */ + /* SUSPENDED is used insystem header. */ ptr_t stack; size_t stack_size; cond_t join_cv; diff --git a/boehm-gc/include/private/specific.h b/boehm-gc/include/private/specific.h index 399f84f58d6..a0e6ae0ebc1 100644 --- a/boehm-gc/include/private/specific.h +++ b/boehm-gc/include/private/specific.h @@ -85,7 +85,7 @@ static __inline__ void * PREFIXED(getspecific) (tsd * key) { unsigned hash_val = CACHE_HASH(qtid); tse * volatile * entry_ptr = key -> cache + hash_val; tse * entry = *entry_ptr; /* Must be loaded only once. */ - if (entry -> qtid == qtid) { + if (EXPECT(entry -> qtid == qtid, 1)) { GC_ASSERT(entry -> thread == pthread_self()); return entry -> value; } |