aboutsummaryrefslogtreecommitdiff
path: root/boehm-gc/include
diff options
context:
space:
mode:
authorJeff Sturm <jsturm@one-point.com>2003-07-28 04:18:23 +0000
committerJeff Sturm <jsturm@gcc.gnu.org>2003-07-28 04:18:23 +0000
commit30c3de1ffb2daa8b2b8281bcece806793c4d4803 (patch)
tree827bf34dcb0c2786d314e5fa136528e5a4feb6f7 /boehm-gc/include
parent1cb1de7ead03894075ea7392879654d3d968f044 (diff)
downloadgcc-30c3de1ffb2daa8b2b8281bcece806793c4d4803.zip
gcc-30c3de1ffb2daa8b2b8281bcece806793c4d4803.tar.gz
gcc-30c3de1ffb2daa8b2b8281bcece806793c4d4803.tar.bz2
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. From-SVN: r69880
Diffstat (limited to 'boehm-gc/include')
-rw-r--r--boehm-gc/include/Makefile.in11
-rw-r--r--boehm-gc/include/gc.h236
-rw-r--r--boehm-gc/include/gc_cpp.h72
-rw-r--r--boehm-gc/include/gc_local_alloc.h3
-rw-r--r--boehm-gc/include/gc_mark.h4
-rw-r--r--boehm-gc/include/gc_pthread_redirects.h17
-rw-r--r--boehm-gc/include/gc_typed.h32
-rw-r--r--boehm-gc/include/new_gc_alloc.h8
-rw-r--r--boehm-gc/include/private/dbg_mlc.h10
-rw-r--r--boehm-gc/include/private/gc_hdrs.h2
-rw-r--r--boehm-gc/include/private/gc_locks.h245
-rw-r--r--boehm-gc/include/private/gc_pmark.h39
-rw-r--r--boehm-gc/include/private/gc_priv.h166
-rw-r--r--boehm-gc/include/private/gcconfig.h509
-rw-r--r--boehm-gc/include/private/solaris_threads.h3
-rw-r--r--boehm-gc/include/private/specific.h2
16 files changed, 896 insertions, 463 deletions
diff --git a/boehm-gc/include/Makefile.in b/boehm-gc/include/Makefile.in
index 65bd34e..94ece1a 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 69075b0..d49cd9d 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 ceb73f5..d789a37 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 1e58730..88e29e9 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 0856d16..9ddba2c 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 47284fb..842518c 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 2e0598f..905734b 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 aad9446..20a2fab 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 5378835..e2003e6 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 dd61545..96749ab 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 9b91ada..775176b 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 8720657..c109738 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 b09c484..ffa398b 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 809887f..29dab21 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 1464bc1..7d49c29 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 399f84f..a0e6ae0 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;
}