/*
* Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
* Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
- * Copyright 1996 by Silicon Graphics. All rights reserved.
+ * Copyright 1996-1999 by Silicon Graphics. All rights reserved.
+ * Copyright 1999 by Hewlett-Packard Company. All rights reserved.
+ * Copyright (C) 2007 Free Software Foundation, Inc
*
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
#ifndef _GC_H
# define _GC_H
-# define __GC
-# include <stddef.h>
-#if defined(__CYGWIN32__) && defined(GC_USE_DLL)
-#include "libgc_globals.h"
-#endif
+/*
+ * As this header includes gc_config.h, preprocessor conflicts can occur with
+ * clients that include their own autoconf headers. The following #undef's
+ * work around some likely conflicts.
+ */
-#if defined(_MSC_VER) && defined(_DLL)
-# ifdef GC_BUILD
-# define GC_API __declspec(dllexport)
-# else
-# define GC_API __declspec(dllimport)
+# ifdef PACKAGE_NAME
+# undef PACKAGE_NAME
# endif
-#endif
-
-#if defined(__WATCOMC__) && defined(GC_DLL)
-# ifdef GC_BUILD
-# define GC_API extern __declspec(dllexport)
-# else
-# define GC_API extern __declspec(dllimport)
+# ifdef PACKAGE_BUGREPORT
+# undef PACKAGE_BUGREPORT
+# endif
+# ifdef PACKAGE_STRING
+# undef PACKAGE_STRING
+# endif
+# ifdef PACKAGE_TARNAME
+# undef PACKAGE_TARNAME
+# endif
+# ifdef PACKAGE_VERSION
+# undef PACKAGE_VERSION
# endif
-#endif
-#ifndef GC_API
-#define GC_API extern
-#endif
+# include <gc_config.h>
+# include "gc_config_macros.h"
-# if defined(__STDC__) || defined(__cplusplus)
+# if defined(__STDC__) || defined(__cplusplus) || defined(_AIX)
# define GC_PROTO(args) args
typedef void * GC_PTR;
# define GC_CONST const
extern "C" {
# endif
-
/* Define word and signed_word to be unsigned and signed types of the */
/* size as char * or void *. There seems to be no way to do this */
/* even semi-portably. The following is probably no better/worse */
/* than almost anything else. */
/* The ANSI standard suggests that size_t and ptr_diff_t might be */
-/* better choices. But those appear to have incorrect definitions */
-/* on may systems. Notably "typedef int size_t" seems to be both */
-/* frequent and WRONG. */
-typedef unsigned long GC_word;
-typedef long GC_signed_word;
+/* better choices. But those had incorrect definitions on some older */
+/* systems. Notably "typedef int size_t" is WRONG. */
+#ifndef _WIN64
+ typedef unsigned long GC_word;
+ typedef long GC_signed_word;
+#else
+ /* Win64 isn't really supported yet, but this is the first step. And */
+ /* it might cause error messages to show up in more plausible places. */
+ /* This needs basetsd.h, which is included by windows.h. */
+ typedef ULONG_PTR GC_word;
+ typedef LONG_PTR GC_word;
+#endif
/* Public read-only variables */
GC_API GC_word GC_gc_no;/* Counter incremented per collection. */
/* Includes empty GCs at startup. */
+
+GC_API int GC_parallel; /* GC is parallelized for performance on */
+ /* multiprocessors. Currently set only */
+ /* implicitly if collector is built with */
+ /* -DPARALLEL_MARK and if either: */
+ /* 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 only partially functional, */
+ /* and may not be desirable. */
/* Public R/W variables */
/* deallocated with GC_free. Initial value */
/* is determined by FIND_LEAK macro. */
+GC_API int GC_all_interior_pointers;
+ /* Arrange for pointers to object interiors to */
+ /* be recognized as valid. May not be changed */
+ /* after GC initialization. */
+ /* Initial value is determined by */
+ /* -DALL_INTERIOR_POINTERS. */
+ /* Unless DONT_ADD_BYTE_AT_END is defined, this */
+ /* also affects whether sizes are increased by */
+ /* at least a byte to allow "off the end" */
+ /* pointer recognition. */
+ /* MUST BE 0 or 1. */
+
GC_API int GC_quiet; /* Disable statistics output. Only matters if */
/* collector has been compiled with statistics */
/* enabled. This involves a performance cost, */
GC_API int GC_finalize_on_demand;
/* If nonzero, finalizers will only be run in */
- /* response to an eplit GC_invoke_finalizers */
+ /* response to an explicit GC_invoke_finalizers */
/* call. The default is determined by whether */
/* the FINALIZE_ON_DEMAND macro is defined */
/* when the collector is built. */
/* ordered finalization. Default value is */
/* determined by JAVA_FINALIZATION macro. */
-GC_API int GC_dont_gc; /* Dont collect unless explicitly requested, e.g. */
- /* because it's not safe. */
+GC_API void (* GC_finalizer_notifier) GC_PROTO((void));
+ /* Invoked by the collector when there are */
+ /* objects to be finalized. Invoked at most */
+ /* once per GC cycle. Never invoked unless */
+ /* GC_finalize_on_demand is set. */
+ /* Typically this will notify a finalization */
+ /* thread, which will call GC_invoke_finalizers */
+ /* in response. */
+
+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 */
/* or forced to. */
+GC_API int GC_use_entire_heap;
+ /* Causes the nonincremental collector to use the */
+ /* entire heap before collecting. This was the only */
+ /* option for GC versions < 5.0. This sometimes */
+ /* results in more large block fragmentation, since */
+ /* very larg blocks will tend to get broken up */
+ /* during each GC cycle. It is likely to result in a */
+ /* larger working set, but lower collection */
+ /* frequencies, and hence fewer instructions executed */
+ /* in the collector. */
+
GC_API int GC_full_freq; /* Number of partial collections between */
/* full collections. Matters only if */
/* GC_incremental is set. */
GC_API GC_word GC_non_gc_bytes;
/* Bytes not considered candidates for collection. */
/* Used only to control scheduling of collections. */
+ /* Updated by GC_malloc_uncollectable and GC_free. */
+ /* Wizards only. */
+
+GC_API int GC_no_dls;
+ /* Don't register dynamic library data segments. */
+ /* Wizards only. Should be used only if the */
+ /* application explicitly registers all roots. */
+ /* In Microsoft Windows environments, this will */
+ /* usually also prevent registration of the */
+ /* main data segment as part of the root set. */
GC_API GC_word GC_free_space_divisor;
/* We try to make sure that we allocate at */
/* least N/GC_free_space_divisor bytes between */
/* collections, where N is the heap size plus */
/* a rough estimate of the root set size. */
- /* Initially, GC_free_space_divisor = 4. */
+ /* Initially, GC_free_space_divisor = 3. */
/* Increasing its value will use less space */
/* but more collection time. Decreasing it */
/* will appreciably decrease collection time */
/* automatically. */
/* For multithreaded code, this is the */
/* cold end of the stack for the */
- /* primordial thread. */
+ /* primordial thread. */
+GC_API int GC_dont_precollect; /* Don't collect as part of */
+ /* initialization. Should be set only */
+ /* if the client wants a chance to */
+ /* manually initialize the root set */
+ /* before the first collection. */
+ /* Interferes with blacklisting. */
+ /* Wizards only. */
+
+/* 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));
+
+GC_API unsigned long GC_time_limit;
+ /* If incremental collection is enabled, */
+ /* We try to terminate collections */
+ /* after this many milliseconds. Not a */
+ /* hard time bound. Setting this to */
+ /* GC_TIME_UNLIMITED will essentially */
+ /* disable incremental collection while */
+ /* leaving generational collection */
+ /* enabled. */
+# define GC_TIME_UNLIMITED 999999
+ /* Setting GC_time_limit to this value */
+ /* 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.
+ * For win32 threads, it needs to be called explicitly.
+ */
+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
* will occur after GC_end_stubborn_change has been called on the
* result of GC_malloc_stubborn. GC_malloc_uncollectable allocates an object
* that is scanned for pointers to collectable objects, but is not itself
- * collectable. GC_malloc_uncollectable and GC_free called on the resulting
+ * collectable. The object is scanned even if it does not appear to
+ * be reachable. GC_malloc_uncollectable and GC_free called on the resulting
* object implicitly update GC_non_gc_bytes appropriately.
+ *
+ * Note that the GC_malloc_stubborn support is stubbed out by default
+ * starting in 6.0. GC_malloc_stubborn is an alias for GC_malloc unless
+ * the collector is built with STUBBORN_ALLOC defined.
*/
GC_API GC_PTR GC_malloc GC_PROTO((size_t size_in_bytes));
GC_API GC_PTR GC_malloc_atomic GC_PROTO((size_t size_in_bytes));
/* Return a pointer to the base (lowest address) of an object given */
/* a pointer to a location within the object. */
+/* I.e. map an interior pointer to the corresponding bas pointer. */
+/* Note that with debugging allocation, this returns a pointer to the */
+/* actual base of the object, i.e. the debug information, not to */
+/* the base of the user object. */
/* Return 0 if displaced_pointer doesn't point to within a valid */
/* object. */
+/* Note that a deallocated object in the garbage collected heap */
+/* may be considered valid, even if it has been deallocated with */
+/* GC_free. */
GC_API GC_PTR GC_base GC_PROTO((GC_PTR displaced_pointer));
/* Given a pointer to the base of an object, return its size in bytes. */
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));
/* Return the number of bytes allocated since the last collection. */
GC_API size_t GC_get_bytes_since_gc GC_PROTO((void));
+/* Return the total number of bytes allocated in this process. */
+/* 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 */
/* pointerfree(atomic) or immutable. */
/* 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 */
+/* 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 */
+/* more of the following, or'ed together: */
+#define GC_PROTECTS_POINTER_HEAP 1 /* May protect non-atomic objs. */
+#define GC_PROTECTS_PTRFREE_HEAP 2
+#define GC_PROTECTS_STATIC_DATA 4 /* Curently never. */
+#define GC_PROTECTS_STACK 8 /* Probably impractical. */
+
+#define GC_PROTECTS_NONE 0
+GC_API int GC_incremental_protection_needs GC_PROTO((void));
+
/* Perform some garbage collection work, if appropriate. */
/* Return 0 if there is no more work to be done. */
/* Typically performs an amount of work corresponding roughly */
# define GC_RETURN_ADDR (GC_word)__return_address
#endif
+#if defined(__linux__) || defined(__GLIBC__)
+# include <features.h>
+# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 || __GLIBC__ > 2) \
+ && !defined(__ia64__)
+# ifndef GC_HAVE_BUILTIN_BACKTRACE
+# define GC_HAVE_BUILTIN_BACKTRACE
+# endif
+# endif
+# if defined(__i386__) || defined(__x86_64__)
+# define GC_CAN_SAVE_CALL_STACKS
+# endif
+#endif
+
+#if defined(GC_HAVE_BUILTIN_BACKTRACE) && !defined(GC_CAN_SAVE_CALL_STACKS)
+# define GC_CAN_SAVE_CALL_STACKS
+#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 * descr_string,
- int descr_int
+# define GC_EXTRA_PARAMS GC_word ra, GC_CONST char * s, int i
#else
# define GC_EXTRAS __FILE__, __LINE__
-# define GC_EXTRA_PARAMS GC_CONST char * descr_string, int descr_int
+# define GC_EXTRA_PARAMS GC_CONST char * s, int i
#endif
/* Debugging (annotated) allocation. GC_gcollect will check */
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) \
GC_debug_register_finalizer(p, f, d, of, od)
# define GC_REGISTER_FINALIZER_IGNORE_SELF(p, f, d, of, od) \
GC_debug_register_finalizer_ignore_self(p, f, d, of, od)
+# define GC_REGISTER_FINALIZER_NO_ORDER(p, f, d, of, od) \
+ GC_debug_register_finalizer_no_order(p, f, d, of, od)
+# define GC_REGISTER_FINALIZER_UNREACHABLE(p, f, d, of, od) \
+ GC_debug_register_finalizer_unreachable(p, f, d, of, od)
# define GC_MALLOC_STUBBORN(sz) GC_debug_malloc_stubborn(sz, GC_EXTRAS);
# define GC_CHANGE_STUBBORN(p) GC_debug_change_stubborn(p)
# define GC_END_STUBBORN_CHANGE(p) GC_debug_end_stubborn_change(p)
# 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) \
GC_register_finalizer(p, f, d, of, od)
# define GC_REGISTER_FINALIZER_IGNORE_SELF(p, f, d, of, od) \
GC_register_finalizer_ignore_self(p, f, d, of, od)
+# define GC_REGISTER_FINALIZER_NO_ORDER(p, f, d, of, od) \
+ GC_register_finalizer_no_order(p, f, d, of, od)
+# define GC_REGISTER_FINALIZER_UNREACHABLE(p, f, d, of, od) \
+ GC_register_finalizer_unreachable(p, f, d, of, od)
# define GC_MALLOC_STUBBORN(sz) GC_malloc_stubborn(sz)
# define GC_CHANGE_STUBBORN(p) GC_change_stubborn(p)
# define GC_END_STUBBORN_CHANGE(p) GC_end_stubborn_change(p)
/* Finalization. Some of these primitives are grossly unsafe. */
/* The idea is to make them both cheap, and sufficient to build */
-/* a safer layer, closer to PCedar finalization. */
+/* a safer layer, closer to Modula-3, Java, or PCedar finalization. */
/* The interface represents my conclusions from a long discussion */
/* with Alan Demers, Dan Greene, Carl Hauser, Barry Hayes, */
/* Christian Jacobi, and Russ Atkinson. It's not perfect, and */
/* 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
GC_PROTO((GC_PTR obj, GC_finalization_proc fn, GC_PTR cd,
GC_finalization_proc *ofn, GC_PTR *ocd));
GC_PROTO((GC_PTR obj, GC_finalization_proc fn, GC_PTR cd,
GC_finalization_proc *ofn, GC_PTR *ocd));
+/* Another version of the above. It ignores all cycles. */
+/* It should probably only be used by Java implementations. */
+/* Note that cd will still be viewed as accessible, even if it */
+/* refers to the object itself. */
+GC_API void GC_register_finalizer_no_order
+ GC_PROTO((GC_PTR obj, GC_finalization_proc fn, GC_PTR cd,
+ GC_finalization_proc *ofn, GC_PTR *ocd));
+GC_API void GC_debug_register_finalizer_no_order
+ GC_PROTO((GC_PTR obj, GC_finalization_proc fn, GC_PTR cd,
+ GC_finalization_proc *ofn, GC_PTR *ocd));
+
+/* This is a special finalizer that is useful when an object's */
+/* finalizer must be run when the object is known to be no */
+/* longer reachable, not even from other finalizable objects. */
+/* This can be used in combination with finalizer_no_order so */
+/* as to release resources that must not be released while an */
+/* object can still be brought back to life by other */
+/* finalizers. */
+GC_API void GC_register_finalizer_unreachable
+ GC_PROTO((GC_PTR obj, GC_finalization_proc fn, GC_PTR cd,
+ GC_finalization_proc *ofn, GC_PTR *ocd));
+GC_API void GC_debug_register_finalizer_unreachable
+ GC_PROTO((GC_PTR obj, GC_finalization_proc fn, GC_PTR cd,
+ GC_finalization_proc *ofn, GC_PTR *ocd));
+
/* The following routine may be used to break cycles between */
/* finalizable objects, thus causing cyclic finalizable */
/* objects to be finalized in the correct order. Standard */
/* 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));
GC_API int GC_invoke_finalizers GC_PROTO((void));
/* Run finalizers for all objects that are ready to */
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. cedar-like) finalization facility. It is expected */
+/* (e.g. Java-like) finalization facility. It is expected */
/* that finalization code will arrange for hidden pointers to */
/* disappear. Otherwise objects can be accessed after they */
/* have been collected. */
GC_API GC_PTR GC_call_with_alloc_lock
GC_PROTO((GC_fn_type fn, GC_PTR client_data));
+/* The following routines are primarily intended for use with a */
+/* preprocessor which inserts calls to check C pointer arithmetic. */
+/* They indicate failure by invoking the corresponding _print_proc. */
+
/* Check that p and q point to the same object. */
/* Fail conspicuously if they don't. */
/* Returns the first argument. */
/* Check that if p is a pointer to a heap page, then it points to */
/* a valid displacement within a heap object. */
/* Fail conspicuously if this property does not hold. */
-/* Uninteresting with ALL_INTERIOR_POINTERS. */
+/* Uninteresting with GC_all_interior_pointers. */
/* Always returns its argument. */
GC_API GC_PTR GC_is_valid_displacement GC_PROTO((GC_PTR p));
# ifdef __GNUC__
# define GC_PTR_ADD(x, n) \
GC_PTR_ADD3(x, n, typeof(x))
-# define GC_PRE_INCR(x, n) \
+# define GC_PRE_INCR(x, n) \
GC_PRE_INCR3(x, n, typeof(x))
-# define GC_POST_INCR(x, n) \
+# define GC_POST_INCR(x, n) \
GC_POST_INCR3(x, typeof(x))
# else
/* We can't do this right without typeof, which ANSI */
/* Safer assignment of a pointer to a nonstack location. */
#ifdef GC_DEBUG
-# ifdef __STDC__
+# if defined(__STDC__) || defined(_AIX)
# define GC_PTR_STORE(p, q) \
(*(void **)GC_is_visible(p) = GC_is_valid_displacement(q))
# else
# define GC_PTR_STORE(p, q) *((p) = (q))
#endif
-/* Fynctions called to report pointer checking errors */
+/* Functions called to report pointer checking errors */
GC_API void (*GC_same_obj_print_proc) GC_PROTO((GC_PTR p, GC_PTR q));
GC_API void (*GC_is_valid_displacement_print_proc)
GC_API void (*GC_is_visible_print_proc)
GC_PROTO((GC_PTR p));
-#if defined(_SOLARIS_PTHREADS) && !defined(SOLARIS_THREADS)
-# define SOLARIS_THREADS
-#endif
-
-#ifdef SOLARIS_THREADS
-/* We need to intercept calls to many of the threads primitives, so */
-/* that we can locate thread stacks and stop the world. */
-/* Note also that the collector cannot see thread specific data. */
-/* Thread specific data should generally consist of pointers to */
-/* uncollectable objects, which are deallocated using the destructor */
-/* facility in thr_keycreate. */
-# include <thread.h>
-# include <signal.h>
- int GC_thr_create(void *stack_base, size_t stack_size,
- void *(*start_routine)(void *), void *arg, long flags,
- thread_t *new_thread);
- int GC_thr_join(thread_t wait_for, thread_t *departed, void **status);
- int GC_thr_suspend(thread_t target_thread);
- int GC_thr_continue(thread_t target_thread);
- void * GC_dlopen(const char *path, int mode);
-
-# ifdef _SOLARIS_PTHREADS
-# include <pthread.h>
- extern int GC_pthread_create(pthread_t *new_thread,
- const pthread_attr_t *attr,
- void * (*thread_execp)(void *), void *arg);
- extern int GC_pthread_join(pthread_t wait_for, void **status);
-
-# undef thread_t
-
-# define pthread_join GC_pthread_join
-# define pthread_create GC_pthread_create
-#endif
-
-# define thr_create GC_thr_create
-# define thr_join GC_thr_join
-# define thr_suspend GC_thr_suspend
-# define thr_continue GC_thr_continue
-# define dlopen GC_dlopen
-# endif /* SOLARIS_THREADS */
+/* For pthread support, we generally need to intercept a number of */
+/* thread library calls. We do that here by macro defining them. */
+#if !defined(GC_USE_LD_WRAP) && \
+ (defined(GC_PTHREADS) || defined(GC_SOLARIS_THREADS))
+# include "gc_pthread_redirects.h"
+#endif
-#if defined(IRIX_THREADS) || defined(LINUX_THREADS) || defined(HPUX_THREADS)
-/* We treat these similarly. */
-# include <pthread.h>
-# include <signal.h>
+# if defined(PCR) || defined(GC_SOLARIS_THREADS) || \
+ defined(GC_PTHREADS) || defined(GC_WIN32_THREADS)
+ /* Any flavor of threads except SRC_M3. */
- int GC_pthread_create(pthread_t *new_thread,
- const pthread_attr_t *attr,
- void *(*start_routine)(void *), void *arg);
- int GC_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset);
- int GC_pthread_join(pthread_t thread, void **retval);
+/* Register the current thread as a new thread whose stack(s) should */
+/* be traced by the GC. */
+/* If a platform does not implicitly do so, this must be called before */
+/* a thread can allocate garbage collected memory, or assign pointers */
+/* to the garbage collected heap. Once registered, a thread will be */
+/* stopped during garbage collections. */
+GC_API void GC_register_my_thread GC_PROTO((void));
-# define pthread_create GC_pthread_create
-# define pthread_sigmask GC_pthread_sigmask
-# define pthread_join GC_pthread_join
+/* Register the current thread, with the indicated stack base, as */
+/* a new thread whose stack(s) should be traced by the GC. If a */
+/* platform does not implicitly do so, this must be called before a */
+/* thread can allocate garbage collected memory, or assign pointers */
+/* to the garbage collected heap. Once registered, a thread will be */
+/* stopped during garbage collections. */
+GC_API void GC_unregister_my_thread GC_PROTO((void));
-#endif /* IRIX_THREADS || LINUX_THREADS */
+GC_API GC_PTR GC_get_thread_stack_base GC_PROTO((void));
-# if defined(PCR) || defined(SOLARIS_THREADS) || defined(WIN32_THREADS) || \
- defined(IRIX_THREADS) || defined(LINUX_THREADS) || \
- defined(IRIX_JDK_THREADS) || defined(HPUX_THREADS)
- /* Any flavor of threads except SRC_M3. */
/* This returns a list of objects, linked through their first */
/* word. Its use can greatly reduce lock contention problems, since */
/* the allocation lock can be acquired and released many fewer times. */
/* lb must be large enough to hold the pointer field. */
+/* It is used internally by gc_local_alloc.h, which provides a simpler */
+/* programming interface on Linux. */
GC_PTR GC_malloc_many(size_t lb);
#define GC_NEXT(p) (*(GC_PTR *)(p)) /* Retrieve the next element */
/* in returned list. */
-extern void GC_thr_init(); /* Needed for Solaris/X86 */
+extern void GC_thr_init GC_PROTO((void));/* Needed for Solaris/X86 */
#endif /* THREADS && !SRC_M3 */
-/*
- * If you are planning on putting
- * the collector in a SunOS 5 dynamic library, you need to call GC_INIT()
- * from the statically loaded program section.
- * This circumvents a Solaris 2.X (X<=4) linker bug.
- */
-#if defined(sparc) || defined(__sparc)
+/* Register a callback to control the scanning of dynamic libraries.
+ When the GC scans the static data of a dynamic library, it will
+ first call a user-supplied routine with filename of the library and
+ the address and length of the memory region. This routine should
+ return nonzero if that region should be scanned. */
+GC_API void GC_register_has_static_roots_callback
+ (int (*callback)(const char *, void *, size_t));
+
+
+#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. 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.
+ */
+ GC_API HANDLE WINAPI GC_CreateThread(
+ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress,
+ LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId );
+
+# if defined(_WIN32_WCE)
+ /*
+ * win32_threads.c implements the real WinMain, which will start a new thread
+ * to call GC_WinMain after initializing the garbage collector.
+ */
+ int WINAPI GC_WinMain(
+ HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ LPWSTR lpCmdLine,
+ int nCmdShow );
+
+# ifndef GC_BUILD
+# define WinMain GC_WinMain
+# define CreateThread GC_CreateThread
+# endif
+# endif /* defined(_WIN32_WCE) */
+
+#endif /* defined(GC_WIN32_THREADS) && !cygwin */
+
+ /*
+ * Fully portable code should call GC_INIT() from the main program
+ * before making any other GC_ calls. On most platforms this is a
+ * no-op and the collector self-initializes. But a number of platforms
+ * make that too hard.
+ */
+#if (defined(sparc) || defined(__sparc)) && defined(sun)
+ /*
+ * If you are planning on putting
+ * the collector in a SunOS 5 dynamic library, you need to call GC_INIT()
+ * from the statically loaded program section.
+ * This circumvents a Solaris 2.X (X<=4) linker bug.
+ */
# define GC_INIT() { extern end, etext; \
GC_noop(&end, &etext); }
#else
-# if defined(__CYGWIN32__) && defined(GC_USE_DLL)
+# if defined(__CYGWIN32__) || 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); }
+# ifdef __CYGWIN32__
+ extern int _data_start__[];
+ extern int _data_end__[];
+ extern int _bss_start__[];
+ extern int _bss_end__[];
+# define GC_MAX(x,y) ((x) > (y) ? (x) : (y))
+# define GC_MIN(x,y) ((x) < (y) ? (x) : (y))
+# define GC_DATASTART ((GC_PTR) GC_MIN(_data_start__, _bss_start__))
+# define GC_DATAEND ((GC_PTR) GC_MAX(_data_end__, _bss_end__))
+# ifdef GC_DLL
+# define GC_INIT() { GC_add_roots(GC_DATASTART, GC_DATAEND); }
+# else
+# define GC_INIT()
+# endif
+# endif
+# if defined(_AIX)
+ extern int _data[], _end[];
+# define GC_DATASTART ((GC_PTR)((ulong)_data))
+# define GC_DATAEND ((GC_PTR)((ulong)_end))
+# define GC_INIT() { GC_add_roots(GC_DATASTART, GC_DATAEND); }
+# endif
# else
+# if defined(__APPLE__) && defined(__MACH__) || defined(GC_WIN32_THREADS)
+# define GC_INIT() { GC_init(); }
+# else
# define GC_INIT()
-# endif
-#endif
+# endif /* !__MACH && !GC_WIN32_THREADS */
+# endif /* !AIX && !cygwin */
+#endif /* !sparc */
-#if (defined(_MSDOS) || defined(_MSC_VER)) && (_M_IX86 >= 300) \
- || defined(_WIN32)
+#if !defined(_WIN32_WCE) \
+ && ((defined(_MSDOS) || defined(_MSC_VER)) && (_M_IX86 >= 300) \
+ || defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__CYGWIN__))
/* win32S may not free all resources on process exit. */
/* This explicitly deallocates the heap. */
GC_API void GC_win32_free_heap ();
#endif
+#if ( defined(_AMIGA) && !defined(GC_AMIGA_MAKINGLIB) )
+ /* Allocation really goes through GC_amiga_allocwrapper_do */
+# include "gc_amiga_redirects.h"
+#endif
+
+#if defined(GC_REDIRECT_TO_LOCAL) && !defined(GC_LOCAL_ALLOC_H)
+# include "gc_local_alloc.h"
+#endif
+
#ifdef __cplusplus
} /* end of extern "C" */
#endif
+/* External thread suspension support. These functions do not implement
+ * suspension counts or any other higher-level abstraction. Threads which
+ * have been suspended numerous times will resume with the very first call
+ * to GC_resume_thread.
+ */
+#if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
+ && !defined(GC_WIN32_THREADS) && !defined(GC_DARWIN_THREADS)
+GC_API void GC_suspend_thread GC_PROTO((pthread_t));
+GC_API void GC_resume_thread GC_PROTO((pthread_t));
+GC_API int GC_is_thread_suspended GC_PROTO((pthread_t));
+#endif
#endif /* _GC_H */