/* 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;
+# include <stddef.h> /* For size_t etc. */
# endif
/* Machine dependent parameters. Some tuning parameters can be found */
/* And one for FreeBSD: */
# if (defined(__FreeBSD__) || defined(__DragonFly__) || \
- defined(__FreeBSD_kernel__)) && !defined(FREEBSD)
+ defined(__FreeBSD_kernel__)) && !defined(FREEBSD)
# define FREEBSD
# endif
+/* And one for Darwin: */
+# if defined(macosx) || (defined(__APPLE__) && defined(__MACH__))
+# define DARWIN
+# endif
+
/* Determine the machine type: */
# if defined(__arm__) || defined(__thumb__)
# define ARM32
-# if !defined(LINUX) && !defined(NETBSD)
+# if !defined(LINUX) && !defined(NETBSD) && !defined(DARWIN)
# define NOSYS
# define mach_type_known
# endif
# endif
# if defined(sun) && defined(mc68000)
-# define M68K
-# define SUNOS4
-# define mach_type_known
+# error SUNOS4 no longer supported
# endif
# if defined(hp9000s300)
-# define M68K
-# define HP
-# define mach_type_known
+# error M68K based HP machines no longer supported.
# endif
# if defined(OPENBSD) && defined(m68k)
# define M68K
# if defined(ultrix) || defined(__ultrix)
# define ULTRIX
# else
-# if defined(_SYSTYPE_SVR4) || defined(SYSTYPE_SVR4) \
- || defined(__SYSTYPE_SVR4__)
-# define IRIX5 /* or IRIX 6.X */
-# else
-# define RISCOS /* or IRIX 4.X */
-# endif
+# define IRIX5 /* or IRIX 6.X */
# endif
# endif /* !LINUX */
# if defined(__NetBSD__) && defined(__MIPSEL__)
# endif
# if defined(sun) && (defined(i386) || defined(__i386__))
# define I386
-# define SUNOS5
+# define SOLARIS
# define mach_type_known
# endif
# if defined(sun) && defined(__amd64)
# define mach_type_known
# endif
# if defined(ibm032)
-# define RT
-# define mach_type_known
+# error IBM PC/RT no longer supported.
# endif
# if defined(sun) && (defined(sparc) || defined(__sparc))
# define SPARC
/* Test for SunOS 5.x */
# include <errno.h>
-# ifdef ECHRNG
-# define SUNOS5
-# else
-# define SUNOS4
-# endif
+# define SOLARIS
# define mach_type_known
# endif
# if defined(sparc) && defined(unix) && !defined(sun) && !defined(linux) \
# define mach_type_known
# endif
# if defined(_IBMR2)
-# define RS6000
+# define POWERPC
+# define AIX
# define mach_type_known
# endif
# if defined(__NetBSD__) && defined(__sparc__)
# define mach_type_known
# endif
# if defined(_AUX_SOURCE)
-# define M68K
-# define SYSV
-# define mach_type_known
+# error A/UX no longer supported
# endif
# if defined(_PA_RISC1_0) || defined(_PA_RISC1_1) || defined(_PA_RISC2_0) \
|| defined(hppa) || defined(__hppa__)
# endif
# define mach_type_known
# endif
-# if defined(__ia64) && defined(_HPUX_SOURCE)
+# if defined(__ia64) && (defined(_HPUX_SOURCE) || defined(__HP_aCC))
# define IA64
# ifndef HPUX
# define HPUX
# define MACOS
# define mach_type_known
# endif
-# if defined(macosx) || (defined(__APPLE__) && defined(__MACH__))
-# define DARWIN
+# if defined(DARWIN)
# if defined(__ppc__) || defined(__ppc64__)
# define POWERPC
# define mach_type_known
-# endif
-# if defined(__i386__)
+# elif defined(__x86_64__)
+# define X86_64
+# define mach_type_known
+# elif defined(__i386__)
# define I386
# define mach_type_known
+# elif defined(__arm__)
+# define ARM32
+# define mach_type_known
+# define DARWIN_DONT_PARSE_STACK
# endif
# endif
# if defined(NeXT) && defined(mc68000)
# define I386
# define mach_type_known
# endif
+# if defined(FREEBSD) && defined(__x86_64__)
+# define X86_64
+# define mach_type_known
+# endif
# if defined(__NetBSD__) && (defined(i386) || defined(__i386__))
# define I386
# define mach_type_known
# if defined(FREEBSD) && defined(__sparc__)
# define SPARC
# define mach_type_known
-#endif
+# endif
# if defined(bsdi) && (defined(i386) || defined(__i386__))
# define I386
# define BSDI
# else
# if (defined(_MSDOS) || defined(_MSC_VER)) && (_M_IX86 >= 300) \
|| defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__CYGWIN__)
-# define I386
-# define MSWIN32 /* or Win32s */
+# if defined(__LP64__) || defined(_WIN64)
+# define X86_64
+# else
+# define I386
+# endif
+# define MSWIN32 /* or Win64 */
# define mach_type_known
# endif
# if defined(_MSC_VER) && defined(_M_IA64)
# define IA64
# define MSWIN32 /* Really win64, but we don't treat 64-bit */
- /* variants as a differnt platform. */
+ /* variants as a different platform. */
# endif
# endif
# if defined(__DJGPP__)
# define CYGWIN32
# define mach_type_known
# endif
-# if defined(__MINGW32__)
+# if defined(__MINGW32__) && !defined(mach_type_known)
# define I386
# define MSWIN32
# define mach_type_known
# define mach_type_known
# endif
# if defined(__pj__)
-# define PJ
-# define mach_type_known
+# error PicoJava no longer supported
+ /* The implementation had problems, and I haven't heard of users */
+ /* in ages. If you want it resurrected, let me know. */
# endif
# if defined(__embedded__) && defined(PPC)
# define POWERPC
/* Or manually define the machine type here. A machine type is */
/* characterized by the architecture. Some */
/* machine types are further subdivided by OS. */
-/* the macros ULTRIX, RISCOS, and BSD to distinguish. */
-/* Note that SGI IRIX is treated identically to RISCOS. */
+/* Macros such as LINUX, FREEBSD, etc. distinguish them. */
/* SYSV on an M68K actually means A/UX. */
/* The distinction in these cases is usually the stack starting address */
# ifndef mach_type_known
- --> unknown machine type
+# error "The collector has not been ported to this machine/OS combination."
# endif
/* Mapping is: M68K ==> Motorola 680X0 */
- /* (SUNOS4,HP,NEXT, and SYSV (A/UX), */
+ /* (NEXT, and SYSV (A/UX), */
/* MACOS and AMIGA variants) */
/* I386 ==> Intel 386 */
/* (SEQUENT, OS2, SCO, LINUX, NETBSD, */
/* FREEBSD, THREE86BSD, MSWIN32, */
- /* BSDI,SUNOS5, NEXT, other variants) */
+ /* BSDI,SOLARIS, NEXT, other variants) */
/* NS32K ==> Encore Multimax */
- /* MIPS ==> R2000 through R14K */
+ /* MIPS ==> R2000 through R14K */
/* (many variants) */
/* VAX ==> DEC VAX */
/* (BSD, ULTRIX variants) */
- /* RS6000 ==> IBM RS/6000 AIX3.X */
- /* RT ==> IBM PC/RT */
/* HP_PA ==> HP9000/700 & /800 */
/* HP/UX, LINUX */
/* SPARC ==> SPARC v7/v8/v9 */
- /* (SUNOS4, SUNOS5, LINUX, */
- /* DRSNX variants) */
+ /* (SOLARIS, LINUX, DRSNX variants) */
/* ALPHA ==> DEC Alpha */
/* (OSF1 and LINUX variants) */
/* M88K ==> Motorola 88XX0 */
/* X86_64 ==> AMD x86-64 */
/* POWERPC ==> IBM/Apple PowerPC */
/* (MACOS(<=9),DARWIN(incl.MACOSX),*/
- /* LINUX, NETBSD, NOSYS variants) */
+ /* LINUX, NETBSD, AIX, NOSYS */
+ /* variants) */
/* Handles 32 and 64-bit variants. */
- /* AIX should be handled here, but */
- /* that's called an RS6000. */
/* CRIS ==> Axis Etrax */
/* M32R ==> Renesas M32R */
* For each architecture and OS, the following need to be defined:
*
* CPP_WORDSZ is a simple integer constant representing the word size.
- * in bits. We assume byte addressibility, where a byte has 8 bits.
+ * in bits. We assume byte addressability, where a byte has 8 bits.
* We also assume CPP_WORDSZ is either 32 or 64.
* (We care about the length of pointers, not hardware
* bus widths. Thus a 64 bit processor with a C compiler that uses
* cause failures on alpha*-*-* with ``-msmall-data or -fpic'' or mips-*-*
* without any special options.
*
- * ALIGN_DOUBLE of GC_malloc should return blocks aligned to twice
- * the pointer size.
- *
* STACKBOTTOM is the cool end of the stack, which is usually the
* highest address in the stack.
* Under PCR or OS/2, we have other ways of finding thread stacks.
* 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.
+ * first for __libc_stack_end (currently only id USE_LIBC_PRIVATES is
+ * defined), and if that fails read it from /proc. (If USE_LIBC_PRIVATES
+ * is not defined and NO_PROC_STAT is defined, we revert to HEURISTIC2.)
* 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
* HEURISTIC2: Take an address inside GC_init's frame, increment it repeatedly
* in small steps (decrement if STACK_GROWS_UP), and read the value
* at each location. Remember the value when the first
- * Segmentation violation or Bus error is signalled. Round that
+ * Segmentation violation or Bus error is signaled. Round that
* to the nearest plausible page boundary, and use that instead
* of STACKBOTTOM.
*
* easily accomplished by introducing a new main program, setting
* GC_stackbottom to the address of a local variable, and then calling
* the original main program. The new main program would read something
- * like:
+ * like (provided real_main() is not inlined by the compiler):
*
* # include "gc_private.h"
*
* Each architecture may also define the style of virtual dirty bit
* implementation to be used:
* MPROTECT_VDB: Write protect the heap and catch faults.
+ * GWW_VDB: Use win32 GetWriteWatch primitive.
* PROC_VDB: Use the SVR4 /proc primitives to read dirty bits.
*
+ * The first and second one may be combined, in which case a runtime
+ * selection will be made, based on GetWriteWatch availability.
+ *
* An architecture may define DYNAMIC_LOADING if dynamic_load.c
* defined GC_register_dynamic_libraries() for the architecture.
*
*/
/* If we are using a recent version of gcc, we can use __builtin_unwind_init()
- * to push the relevant registers onto the stack. This generally makes
- * USE_GENERIC_PUSH_REGS the preferred approach for marking from registers.
+ * to push the relevant registers onto the stack.
*/
# if defined(__GNUC__) && ((__GNUC__ >= 3) || \
(__GNUC__ == 2 && __GNUC_MINOR__ >= 8)) \
- && !defined(__INTEL_COMPILER) \
- && !defined(__PATHCC__)
+ && !defined(__INTEL_COMPILER) && !defined(__PATHCC__)
# define HAVE_BUILTIN_UNWIND_INIT
# endif
extern char etext[];
# define DATASTART ((ptr_t)(etext))
# endif
-# define USE_GENERIC_PUSH_REGS
# endif
# ifdef NETBSD
# define OS_TYPE "NETBSD"
extern char etext[];
# define DATASTART ((ptr_t)(etext))
# endif
-# define USE_GENERIC_PUSH_REGS
# 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 */
+# define LINUX_STACKBOTTOM
+# define MPROTECT_VDB
# ifdef __ELF__
# define DYNAMIC_LOADING
# include <features.h>
/* that we'd rather not scan. */
# endif /* !GLIBC2 */
extern int _end[];
-# define DATAEND (_end)
+# define DATAEND (ptr_t)(_end)
# else
extern int etext[];
# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff))
# endif
# endif
-# ifdef SUNOS4
-# define OS_TYPE "SUNOS4"
- extern char etext[];
-# define DATASTART ((ptr_t)((((word) (etext)) + 0x1ffff) & ~0x1ffff))
-# define HEURISTIC1 /* differs */
-# define DYNAMIC_LOADING
-# endif
-# ifdef HP
-# define OS_TYPE "HP"
- extern char etext[];
-# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff))
-# define STACKBOTTOM ((ptr_t) 0xffeffffc)
- /* empirically determined. seems to work. */
-# include <unistd.h>
-# define GETPAGESIZE() sysconf(_SC_PAGE_SIZE)
-# endif
-# ifdef SYSV
-# define OS_TYPE "SYSV"
- extern etext[];
-# define DATASTART ((ptr_t)((((word) (etext)) + 0x3fffff) \
- & ~0x3fffff) \
- +((word)etext & 0x1fff))
- /* This only works for shared-text binaries with magic number 0413.
- The other sorts of SysV binaries put the data at the end of the text,
- in which case the default of etext would work. Unfortunately,
- handling both would require having the magic-number available.
- -- Parag
- */
-# define STACKBOTTOM ((ptr_t)0xFFFFFFFE)
- /* The stack starts at the top of memory, but */
- /* 0x0 cannot be used as setjump_test complains */
- /* that the stack direction is incorrect. Two */
- /* bytes down from 0x0 should be safe enough. */
- /* --Parag */
-# include <sys/mmu.h>
-# define GETPAGESIZE() PAGESIZE /* Is this still right? */
-# endif
# ifdef AMIGA
# define OS_TYPE "AMIGA"
/* STACKBOTTOM and DATASTART handled specially */
# define DYNAMIC_LOADING
# define SEARCH_FOR_DATA_START
extern int _end[];
-# define DATAEND (_end)
+# define DATAEND (ptr_t)(_end)
# endif
# ifdef DARWIN
-# ifdef __ppc64__
+# define OS_TYPE "DARWIN"
+# define DYNAMIC_LOADING
+# if defined(__ppc64__)
# define ALIGNMENT 8
# define CPP_WORDSZ 64
+# define STACKBOTTOM ((ptr_t) 0x7fff5fc00000)
+# define CACHE_LINE_SIZE 64
+# ifndef HBLKSIZE
+# define HBLKSIZE 4096
+# endif
# else
# define ALIGNMENT 4
+# define STACKBOTTOM ((ptr_t) 0xc0000000)
# endif
-# 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) */
+ 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 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. It relies on threads to track writes. */
# ifdef GC_DARWIN_THREADS
-/* # define MPROTECT_VDB -- diabled for now. May work for some apps. */
+# define MPROTECT_VDB
# endif
# include <unistd.h>
# define GETPAGESIZE() getpagesize()
__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 */
+ should be looked into some more */
# define NO_PTHREAD_TRYLOCK
# endif
# ifdef FREEBSD
# define DYNAMIC_LOADING
# endif
extern char etext[];
- extern char * GC_FreeBSDGetDataStart();
+ ptr_t GC_FreeBSDGetDataStart(size_t max_page_size, ptr_t etext_addr);
# define DATASTART GC_FreeBSDGetDataStart(0x1000, &etext)
# endif
# ifdef NETBSD
# define DATASTART GC_data_start
# define DYNAMIC_LOADING
# endif
+# ifdef AIX
+# define OS_TYPE "AIX"
+# undef ALIGNMENT /* in case it's defined */
+# 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
+# define STACKBOTTOM ((ptr_t)((ulong)&errno))
+# endif
+# define USE_MMAP
+# define USE_MMAP_ANON
+ /* 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 DYNAMIC_LOADING
+ /* For really old versions of AIX, this may have to be removed. */
+# endif
+
# ifdef NOSYS
# define ALIGNMENT 4
# define OS_TYPE "NOSYS"
extern void __end[], __dso_handle[];
# define DATASTART (__dso_handle) /* OK, that's ugly. */
-# define DATAEND (__end)
+# define DATAEND (ptr_t)(__end)
/* Stack starts at 0xE0000000 for the simulator. */
# undef STACK_GRAN
# define STACK_GRAN 0x10000000
# endif
# endif
-# ifdef RT
-# define MACH_TYPE "RT"
-# define ALIGNMENT 4
-# define DATASTART ((ptr_t) 0x10000000)
-# define STACKBOTTOM ((ptr_t) 0x1fffd800)
-# endif
-
# ifdef SPARC
# define MACH_TYPE "SPARC"
# if defined(__arch64__) || defined(__sparcv9)
# define ALIGNMENT 4 /* Required by hardware */
# define CPP_WORDSZ 32
# endif
-# define ALIGN_DOUBLE
-# ifdef SUNOS5
-# define OS_TYPE "SUNOS5"
+ /* Don't define USE_ASM_PUSH_REGS. We do use an asm helper, but */
+ /* not to push the registers on the mark stack. */
+# ifdef SOLARIS
+# define OS_TYPE "SOLARIS"
extern int _etext[];
extern int _end[];
- extern ptr_t GC_SysVGetDataStart();
-# define DATASTART GC_SysVGetDataStart(0x10000, _etext)
-# define DATAEND (_end)
+ extern ptr_t GC_SysVGetDataStart(size_t, ptr_t);
+# define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext)
+# define DATAEND (ptr_t)(_end)
# if !defined(USE_MMAP) && defined(REDIRECT_MALLOC)
# define USE_MMAP
/* Otherwise we now use calloc. Mmap may result in the */
# include <sys/vmparam.h>
# ifdef USERLIMIT
/* This should work everywhere, but doesn't. */
-# define STACKBOTTOM USRSTACK
+# define STACKBOTTOM ((ptr_t) USRSTACK)
# else
# define HEURISTIC2
# endif
/* Solaris 5.4 installation. Weird. */
# define DYNAMIC_LOADING
# endif
-# ifdef SUNOS4
-# define OS_TYPE "SUNOS4"
- /* [If you have a weak stomach, don't read this.] */
- /* We would like to use: */
-/* # define DATASTART ((ptr_t)((((word) (etext)) + 0x1fff) & ~0x1fff)) */
- /* This fails occasionally, due to an ancient, but very */
- /* persistent ld bug. etext is set 32 bytes too high. */
- /* We instead read the text segment size from the a.out */
- /* header, which happens to be mapped into our address space */
- /* at the start of the text segment. The detective work here */
- /* was done by Robert Ehrlich, Manuel Serrano, and Bernard */
- /* Serpette of INRIA. */
- /* This assumes ZMAGIC, i.e. demand-loadable executables. */
-# define TEXTSTART 0x2000
-# define DATASTART ((ptr_t)(*(int *)(TEXTSTART+0x4)+TEXTSTART))
-# define MPROTECT_VDB
-# define HEURISTIC1
-# define DYNAMIC_LOADING
-# endif
# ifdef DRSNX
# define OS_TYPE "DRSNX"
- extern ptr_t GC_SysVGetDataStart();
+ extern ptr_t GC_SysVGetDataStart(size_t, ptr_t);
extern int etext[];
-# define DATASTART GC_SysVGetDataStart(0x10000, etext)
+# define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)etext)
# define MPROTECT_VDB
# define STACKBOTTOM ((ptr_t) 0xdfff0000)
# define DYNAMIC_LOADING
# endif
extern int _end[];
extern int _etext[];
-# define DATAEND (_end)
+# define DATAEND (ptr_t)(_end)
# define SVR4
- extern ptr_t GC_SysVGetDataStart();
+ extern ptr_t GC_SysVGetDataStart(size_t, ptr_t);
# ifdef __arch64__
-# define DATASTART GC_SysVGetDataStart(0x100000, _etext)
+# define DATASTART GC_SysVGetDataStart(0x100000, (ptr_t)_etext)
# else
-# define DATASTART GC_SysVGetDataStart(0x10000, _etext)
+# define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext)
# endif
# define LINUX_STACKBOTTOM
# endif
# ifdef I386
# define MACH_TYPE "I386"
# if defined(__LP64__) || defined(_WIN64)
-# define CPP_WORDSZ 64
-# define ALIGNMENT 8
+# error This should be handled as X86_64
# else
# define CPP_WORDSZ 32
# define ALIGNMENT 4
/* Borland. */
/* Ivan Demakov: For Watcom the option is -zp4. */
# endif
-# ifndef SMALL_CONFIG
-# define ALIGN_DOUBLE /* Not strictly necessary, but may give speed */
- /* improvement on Pentiums. */
-# endif
-# ifdef HAVE_BUILTIN_UNWIND_INIT
-# define USE_GENERIC_PUSH_REGS
-# endif
# ifdef SEQUENT
# define OS_TYPE "SEQUENT"
extern int etext[];
extern int etext[];
# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff))
# endif
-# ifdef SUNOS5
-# define OS_TYPE "SUNOS5"
+# ifdef SOLARIS
+# define OS_TYPE "SOLARIS"
extern int _etext[], _end[];
- extern ptr_t GC_SysVGetDataStart();
-# define DATASTART GC_SysVGetDataStart(0x1000, _etext)
-# define DATAEND (_end)
+ extern ptr_t GC_SysVGetDataStart(size_t, ptr_t);
+# define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)_etext)
+# define DATAEND (ptr_t)(_end)
/* # define STACKBOTTOM ((ptr_t)(_start)) worked through 2.7, */
/* but reportedly breaks under 2.8. It appears that the stack */
/* base is a property of the executable, so this should not break */
/* old executables. */
/* HEURISTIC2 probably works, but this appears to be preferable. */
# include <sys/vm.h>
-# define STACKBOTTOM USRSTACK
+# define STACKBOTTOM ((ptr_t) USRSTACK)
/* At least in Solaris 2.5, PROC_VDB gives wrong values for dirty bits. */
/* It appears to be fixed in 2.8 and 2.9. */
# ifdef SOLARIS25_PROC_VDB_BUG_FIXED
# ifdef DGUX
# define OS_TYPE "DGUX"
extern int _etext, _end;
- extern ptr_t GC_SysVGetDataStart();
-# define DATASTART GC_SysVGetDataStart(0x1000, &_etext)
-# define DATAEND (&_end)
+ extern ptr_t GC_SysVGetDataStart(size_t, ptr_t);
+# define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)(&_etext))
+# define DATAEND (ptr_t)(&_end)
# define STACK_GROWS_DOWN
# define HEURISTIC2
# include <unistd.h>
# ifndef USE_MMAP
# define USE_MMAP
# endif /* USE_MMAP */
-# define MAP_FAILED (void *) -1
+# define MAP_FAILED (void *) ((word)-1)
# ifdef USE_MMAP
# define HEAP_START (ptr_t)0x40000000
# else /* USE_MMAP */
# endif /* DGUX */
# ifdef LINUX
-# ifndef __GNUC__
- /* The Intel compiler doesn't like inline assembly */
-# define USE_GENERIC_PUSH_REGS
-# endif
# define OS_TYPE "LINUX"
# define LINUX_STACKBOTTOM
# if 0
/* that we'd rather not scan. */
# endif
extern int _end[];
-# define DATAEND (_end)
+# define DATAEND (ptr_t)(_end)
# else
extern int etext[];
# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff))
# define PREFETCH(x) \
__asm__ __volatile__ (" prefetchnta %0": : "m"(*(char *)(x)))
/* Empirically prefetcht0 is much more effective at reducing */
- /* cache miss stalls for the targetted load instructions. But it */
+ /* cache miss stalls for the targeted load instructions. But it */
/* seems to interfere enough with other cache traffic that the net */
/* result is worse than prefetchnta. */
# if 0
# undef STACK_GRAN
# define STACK_GRAN 0x10000
# define HEURISTIC1
+# ifdef USE_MMAP
+# define NEED_FIND_LIMIT
+# define USE_MMAP_ANON
+# endif
# endif
# ifdef OS2
# define OS_TYPE "OS2"
/* os_dep.c. OS2 actually has the right */
/* system call! */
# define DATAEND /* not needed */
-# define USE_GENERIC_PUSH_REGS
# endif
# ifdef MSWIN32
# define OS_TYPE "MSWIN32"
/* STACKBOTTOM and DATASTART are handled specially in */
/* os_dep.c. */
-# ifndef __WATCOMC__
-# define MPROTECT_VDB
-# endif
+# define MPROTECT_VDB
+# define GWW_VDB
# define DATAEND /* not needed */
# endif
# ifdef MSWINCE
# define SIG_SUSPEND (32+6)
# define SIG_THR_RESTART (32+5)
extern int _end[];
-# define DATAEND (_end)
+# define DATAEND (ptr_t)(_end)
# else
# define SIG_SUSPEND SIGUSR1
# define SIG_THR_RESTART SIGUSR2
# define DYNAMIC_LOADING
# endif
extern char etext[];
- extern char * GC_FreeBSDGetDataStart();
-# define DATASTART GC_FreeBSDGetDataStart(0x1000, &etext)
+ extern char * GC_FreeBSDGetDataStart(size_t, ptr_t);
+# define DATASTART GC_FreeBSDGetDataStart(0x1000, (ptr_t)etext)
# endif
# ifdef NETBSD
# define OS_TYPE "NETBSD"
extern char _end;
extern char *_STACKTOP;
/* Depending on calling conventions Watcom C either precedes
- or does not precedes with undescore names of C-variables.
+ or does not precedes with underscore names of C-variables.
Make sure startup code variables always have the same names. */
#pragma aux __nullarea "*";
#pragma aux _end "*";
# define OS_TYPE "HURD"
# define STACK_GROWS_DOWN
# define HEURISTIC2
- extern int __data_start[];
-# define DATASTART ( (ptr_t) (__data_start))
- extern int _end[];
-# define DATAEND ( (ptr_t) (_end))
+# define SIG_SUSPEND SIGUSR1
+# define SIG_THR_RESTART SIGUSR2
+# define SEARCH_FOR_DATA_START
+ extern int _end[];
+# define DATAEND ((ptr_t) (_end))
/* # define MPROTECT_VDB Not quite working yet? */
# define DYNAMIC_LOADING
# endif
# define DARWIN_DONT_PARSE_STACK
# 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) */
+ 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 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. It relies on threads to track writes. */
# ifdef GC_DARWIN_THREADS
-/* # define MPROTECT_VDB -- disabled for now. May work for some apps. */
+# define MPROTECT_VDB
# endif
# include <unistd.h>
# define GETPAGESIZE() getpagesize()
/* There seems to be some issues with trylock hanging on darwin. This
- should be looked into some more */
+ should be looked into some more */
# define NO_PTHREAD_TRYLOCK
# endif /* DARWIN */
# endif
# ifdef MIPS
# define MACH_TYPE "MIPS"
# ifdef LINUX
- /* This was developed for a linuxce style platform. Probably */
- /* needs to be tweaked for workstation class machines. */
# define OS_TYPE "LINUX"
# define DYNAMIC_LOADING
extern int _end[];
-# define DATAEND (_end)
+# define DATAEND (ptr_t)(_end)
extern int __data_start[];
# define DATASTART ((ptr_t)(__data_start))
-# define ALIGNMENT 4
-# define USE_GENERIC_PUSH_REGS
+# define CPP_WORDSZ _MIPS_SZPTR
+# define ALIGNMENT (_MIPS_SZPTR/8)
# if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 2 || __GLIBC__ > 2
-# define LINUX_STACKBOTTOM
+# define LINUX_STACKBOTTOM
# else
-# define STACKBOTTOM 0x80000000
+# define STACKBOTTOM ((ptr_t)0x7fff8000)
# endif
# endif /* Linux */
# ifdef EWS4800
extern int _DYNAMIC_LINKING[], _gp[];
# define DATASTART ((ptr_t)((((word)etext + 0x3ffff) & ~0x3ffff) \
+ ((word)etext & 0xffff)))
-# define DATAEND (edata)
+# define DATAEND (ptr_t)(edata)
# define DATASTART2 (_DYNAMIC_LINKING \
? (ptr_t)(((word)_gp + 0x8000 + 0x3ffff) & ~0x3ffff) \
: (ptr_t)edata)
-# define DATAEND2 (end)
+# define DATAEND2 (ptr_t)(end)
# define ALIGNMENT 4
# endif
# define OS_TYPE "EWS4800"
-# define USE_GENERIC_PUSH_REGS 1
# endif
# ifdef ULTRIX
# define HEURISTIC2
# define OS_TYPE "ULTRIX"
# define ALIGNMENT 4
# endif
-# ifdef RISCOS
-# define HEURISTIC2
-# define DATASTART (ptr_t)0x10000000
-# define OS_TYPE "RISCOS"
-# define ALIGNMENT 4 /* Required by hardware */
-# endif
# ifdef IRIX5
# define HEURISTIC2
extern int _fdata[];
# ifdef _MIPS_SZPTR
# define CPP_WORDSZ _MIPS_SZPTR
# define ALIGNMENT (_MIPS_SZPTR/8)
-# if CPP_WORDSZ != 64
-# define ALIGN_DOUBLE
-# endif
# else
# define ALIGNMENT 4
-# define ALIGN_DOUBLE
# endif
# define DYNAMIC_LOADING
# endif
# define OS_TYPE "NETBSD"
# define ALIGNMENT 4
# define HEURISTIC2
-# define USE_GENERIC_PUSH_REGS
# ifdef __ELF__
extern int etext[];
# define DATASTART GC_data_start
# define OS_TYPE "NONSTOP"
# define ALIGNMENT 4
# define DATASTART ((ptr_t) 0x08000000)
- extern int _end[];
-# define DATAEND (_end)
+ extern char **environ;
+# define DATAEND ((ptr_t)(environ - 0x10))
# define STACKBOTTOM ((ptr_t) 0x4fffffff)
-# define USE_GENERIC_PUSH_REGS
-# 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
-# define STACKBOTTOM ((ptr_t)((ulong)&errno))
# endif
-# define USE_MMAP
-# define USE_MMAP_ANON
- /* 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 USE_GENERIC_PUSH_REGS
-# define DYNAMIC_LOADING
- /* For really old versions of AIX, this may have to be removed. */
# endif
# ifdef HP_PA
# else
# define CPP_WORDSZ 32
# define ALIGNMENT 4
-# define ALIGN_DOUBLE
# endif
# if !defined(GC_HPUX_THREADS) && !defined(GC_LINUX_THREADS)
# ifndef LINUX /* For now. */
# define MPROTECT_VDB
# endif
# else
-# define GENERIC_COMPARE_AND_SWAP
- /* No compare-and-swap instruction. Use pthread mutexes */
- /* when we absolutely have to. */
# ifdef PARALLEL_MARK
# define USE_MARK_BYTES
/* Minimize compare-and-swap usage. */
# define DYNAMIC_LOADING
# define SEARCH_FOR_DATA_START
extern int _end[];
-# define DATAEND (&_end)
+# define DATAEND (ptr_t)(&_end)
# endif /* LINUX */
# endif /* HP_PA */
# 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
/* initialization. */
# define STACKBOTTOM ((ptr_t)(((word)(environ) | (getpagesize()-1))+1))
/* # define HEURISTIC2 */
- /* Normally HEURISTIC2 is too conervative, since */
+ /* Normally HEURISTIC2 is too conservative, since */
/* the text segment immediately follows the stack. */
/* Hence we give an upper pound. */
/* This is currently unused, since we disabled HEURISTIC2 */
# define DATASTART ((ptr_t) 0x140000000)
# endif
extern int _end[];
-# define DATAEND (_end)
+# define DATAEND (ptr_t)(_end)
# define MPROTECT_VDB
/* Has only been superficially tested. May not */
/* work on all versions. */
# ifdef IA64
# define MACH_TYPE "IA64"
-# define USE_GENERIC_PUSH_REGS
- /* We need to get preserved registers in addition to register */
- /* windows. That's easiest to do with setjmp. */
-# ifdef PARALLEL_MARK
-# define USE_MARK_BYTES
- /* Compare-and-exchange is too expensive to use for */
- /* setting mark bits. */
-# endif
# ifdef HPUX
# ifdef _ILP32
# define CPP_WORDSZ 32
-# define ALIGN_DOUBLE
/* Requires 8 byte alignment for malloc */
# define ALIGNMENT 4
# else
---> unknown ABI
# endif
# define CPP_WORDSZ 64
-# define ALIGN_DOUBLE
/* Requires 16 byte alignment for malloc */
# define ALIGNMENT 8
# endif
# endif
# ifdef LINUX
# define CPP_WORDSZ 64
-# define ALIGN_DOUBLE
- /* Requires 16 byte alignment for malloc */
# define ALIGNMENT 8
# define OS_TYPE "LINUX"
/* The following works on NUE and older kernels: */
# define MPROTECT_VDB
/* Requires Linux 2.3.47 or later. */
extern int _end[];
-# define DATAEND (_end)
+# define DATAEND (ptr_t)(_end)
# ifdef __GNUC__
# ifndef __INTEL_COMPILER
# define PREFETCH(x) \
__lfetch(__lfhint_nta, (x))
# define CLEAR_DOUBLE(x) \
__stf_spill((void *)(x), 0)
-# endif /* __INTEL_COMPILER */
+# endif // __INTEL_COMPILER
# endif
# endif
# ifdef MSWIN32
# ifdef M88K
# define MACH_TYPE "M88K"
# define ALIGNMENT 4
-# define ALIGN_DOUBLE
extern int etext[];
# ifdef CX_UX
# define OS_TYPE "CX_UX"
# endif
# ifdef DGUX
# define OS_TYPE "DGUX"
- extern ptr_t GC_SysVGetDataStart();
-# define DATASTART GC_SysVGetDataStart(0x10000, etext)
+ extern ptr_t GC_SysVGetDataStart(size_t, ptr_t);
+# define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)etext)
# endif
# define STACKBOTTOM ((char*)0xf0000000) /* determined empirically */
# endif
/* 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 _end[];
- extern ptr_t GC_SysVGetDataStart();
-# define DATASTART GC_SysVGetDataStart(0x10000, _etext)
-# define DATAEND (_end)
+ extern ptr_t GC_SysVGetDataStart(size_t, ptr_t);
+# define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext)
+# define DATAEND (ptr_t)(_end)
# define HEURISTIC2
# endif
# endif
# ifdef S390
# 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
-# endif
+# define ALIGNMENT 8
+# define CPP_WORDSZ 64
# ifndef HBLKSIZE
# define HBLKSIZE 4096
# endif
+# endif
# ifdef LINUX
# define OS_TYPE "LINUX"
# define LINUX_STACKBOTTOM
extern int __data_start[];
# define DATASTART ((ptr_t)(__data_start))
extern int _end[];
-# define DATAEND (_end)
+# define DATAEND (ptr_t)(_end)
# define CACHE_LINE_SIZE 256
# define GETPAGESIZE() 4096
# endif
# endif
-# if defined(PJ)
-# define ALIGNMENT 4
- extern int _etext[];
-# define DATASTART ((ptr_t)(_etext))
-# define HEURISTIC1
-# endif
-
# ifdef ARM32
# define CPP_WORDSZ 32
# define MACH_TYPE "ARM32"
extern char etext[];
# define DATASTART ((ptr_t)(etext))
# endif
-# define USE_GENERIC_PUSH_REGS
# endif
# ifdef LINUX
# define OS_TYPE "LINUX"
# define LINUX_STACKBOTTOM
# undef STACK_GRAN
# define STACK_GRAN 0x10000000
-# define USE_GENERIC_PUSH_REGS
# ifdef __ELF__
# define DYNAMIC_LOADING
# include <features.h>
-# if defined(__GLIBC__) && __GLIBC__ >= 2
+# if defined(__GLIBC__) && __GLIBC__ >= 2 \
+ || defined(PLATFORM_ANDROID)
# define SEARCH_FOR_DATA_START
# else
extern char **__environ;
/* that we'd rather not scan. */
# endif
extern int _end[];
-# define DATAEND (_end)
+# define DATAEND (ptr_t)(_end)
# else
extern int etext[];
# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff))
# define OS_TYPE "MSWINCE"
# define DATAEND /* not needed */
# endif
+# ifdef DARWIN
+ /* iPhone */
+# define OS_TYPE "DARWIN"
+# define DATASTART ((ptr_t) get_etext())
+# define DATAEND ((ptr_t) get_end())
+/* #define STACKBOTTOM ((ptr_t) 0x30000000) */ /* FIXME: Is this needed? */
+# define HEURISTIC1
+# define USE_MMAP
+# define USE_MMAP_ANON
+# endif
# ifdef NOSYS
/* __data_start is usually defined in the target linker script. */
extern int __data_start[];
# define DATASTART (ptr_t)(__data_start)
-# define USE_GENERIC_PUSH_REGS
/* __stack_base__ is set in newlib/libc/sys/arm/crt0.S */
extern void *__stack_base__;
# define STACKBOTTOM ((ptr_t) (__stack_base__))
# define OS_TYPE "LINUX"
# define DYNAMIC_LOADING
# define LINUX_STACKBOTTOM
-# define USE_GENERIC_PUSH_REGS
# define SEARCH_FOR_DATA_START
extern int _end[];
-# define DATAEND (_end)
+# define DATAEND (ptr_t)(_end)
# endif
# ifdef SH
# ifdef LINUX
# define OS_TYPE "LINUX"
# define LINUX_STACKBOTTOM
-# define USE_GENERIC_PUSH_REGS
# define DYNAMIC_LOADING
# define SEARCH_FOR_DATA_START
extern int _end[];
-# define DATAEND (_end)
+# define DATAEND (ptr_t)(_end)
# endif
# ifdef NETBSD
# define OS_TYPE "NETBSD"
# define HEURISTIC2
# define DATASTART GC_data_start
-# define USE_GENERIC_PUSH_REGS
# define DYNAMIC_LOADING
# endif
# endif
# define LINUX_STACKBOTTOM
# undef STACK_GRAN
# define STACK_GRAN 0x10000000
-# define USE_GENERIC_PUSH_REGS
# define DYNAMIC_LOADING
# define SEARCH_FOR_DATA_START
extern int _end[];
-# define DATAEND (_end)
+# define DATAEND (ptr_t)(_end)
# endif
# endif
# define HBLKSIZE 4096
# endif
# define CACHE_LINE_SIZE 64
-# define USE_GENERIC_PUSH_REGS
# ifdef LINUX
# define OS_TYPE "LINUX"
# define LINUX_STACKBOTTOM
# include <features.h>
# define SEARCH_FOR_DATA_START
extern int _end[];
-# define DATAEND (_end)
+# define DATAEND (ptr_t)(_end)
# else
extern int etext[];
# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff))
# endif
-# if defined(__GNUC__) && __GNUC >= 3
+# if defined(__GNUC__) && __GNUC__ >= 3
# define PREFETCH(x) __builtin_prefetch((x), 0, 0)
# define PREFETCH_FOR_WRITE(x) __builtin_prefetch((x), 1)
# endif
# endif
+# ifdef DARWIN
+# define OS_TYPE "DARWIN"
+# define DARWIN_DONT_PARSE_STACK
+# 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) 0x7fff5fc00000)
+# define USE_MMAP
+# define USE_MMAP_ANON
+# ifdef GC_DARWIN_THREADS
+# define MPROTECT_VDB
+# endif
+# include <unistd.h>
+# define GETPAGESIZE() getpagesize()
+ /* There seems to be some issues with trylock hanging on darwin. This
+ should be looked into some more */
+# define NO_PTHREAD_TRYLOCK
+# endif
# ifdef FREEBSD
# define OS_TYPE "FREEBSD"
# ifndef GC_FREEBSD_THREADS
# define SIG_SUSPEND (32+6)
# define SIG_THR_RESTART (32+5)
extern int _end[];
-# define DATAEND (_end)
+# define DATAEND (ptr_t)(_end)
# else
# define SIG_SUSPEND SIGUSR1
# define SIG_THR_RESTART SIGUSR2
# define DYNAMIC_LOADING
# endif
extern char etext[];
- extern char * GC_FreeBSDGetDataStart();
+ ptr_t GC_FreeBSDGetDataStart(size_t max_page_size, ptr_t etext_addr);
# define DATASTART GC_FreeBSDGetDataStart(0x1000, &etext)
# endif
# ifdef NETBSD
extern int _etext[], _end[];
extern ptr_t GC_SysVGetDataStart(size_t, ptr_t);
# define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)_etext)
-# define DATAEND (_end)
+# define DATAEND (ptr_t)(_end)
/* # define STACKBOTTOM ((ptr_t)(_start)) worked through 2.7, */
/* but reportedly breaks under 2.8. It appears that the stack */
/* base is a property of the executable, so this should not break */
# include <sys/vmparam.h>
# ifdef USERLIMIT
/* This should work everywhere, but doesn't. */
-# define STACKBOTTOM USRSTACK
+# define STACKBOTTOM ((ptr_t) USRSTACK)
# else
# define HEURISTIC2
# endif
# define HEAP_START DATAEND
# endif
# endif
+# ifdef MSWIN32
+# define OS_TYPE "MSWIN32"
+ /* STACKBOTTOM and DATASTART are handled specially in */
+ /* os_dep.c. */
+# define MPROTECT_VDB
+# define GWW_VDB
+# define DATAEND /* not needed */
+# endif
# endif
+#if defined(LINUX_STACKBOTTOM) && defined(NO_PROC_STAT) \
+ && !defined(USE_LIBC_PRIVATES)
+ /* This combination will fail, since we have no way to get */
+ /* the stack base. Use HEURISTIC2 instead. */
+# undef LINUX_STACKBOTTOM
+# define HEURISTIC2
+ /* This may still fail on some architectures like IA64. */
+ /* We tried ... */
+#endif
+
#if defined(LINUX) && defined(USE_MMAP)
/* The kernel may do a somewhat better job merging mappings etc. */
/* with anonymous mappings. */
# define USE_MMAP_ANON
#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 */
- /* work with collectable memory, we have to scan memory allocated */
- /* by rld's internal malloc. */
+#if defined(GC_LINUX_THREADS) && defined(REDIRECT_MALLOC)
+ /* Nptl allocates thread stacks with mmap, which is fine. But it */
+ /* keeps a cache of thread stacks. Thread stacks contain the */
+ /* thread control blocks. These in turn contain a pointer to */
+ /* (sizeof (void *) from the beginning of) the dtv for thread-local */
+ /* storage, which is calloc allocated. If we don't scan the cached */
+ /* thread stacks, we appear to lose the dtv. This tends to */
+ /* result in something that looks like a bogus dtv count, which */
+ /* tends to result in a memset call on a block that is way too */
+ /* large. Sometimes we're lucky and the process just dies ... */
+ /* There seems to be a similar issue with some other memory */
+ /* allocated by the dynamic loader. */
+ /* This should be avoidable by either: */
+ /* - Defining USE_PROC_FOR_LIBRARIES here. */
+ /* That performs very poorly, precisely because we end up */
+ /* scanning cached stacks. */
+ /* - Have calloc look at its callers. */
+ /* In spite of the fact that it is gross and disgusting. */
+ /* In fact neither seems to suffice, probably in part because */
+ /* even with USE_PROC_FOR_LIBRARIES, we don't scan parts of stack */
+ /* segments that appear to be out of bounds. Thus we actually */
+ /* do both, which seems to yield the best results. */
+
# define USE_PROC_FOR_LIBRARIES
#endif
-
+
# ifndef STACK_GROWS_UP
# define STACK_GROWS_DOWN
# endif
# ifndef DATAEND
extern int end[];
-# define DATAEND (end)
+# define DATAEND (ptr_t)(end)
# endif
# if defined(SVR4) && !defined(GETPAGESIZE)
# endif
# ifndef GETPAGESIZE
-# if defined(SUNOS5) || defined(IRIX5)
+# if defined(SOLARIS) || defined(IRIX5) || defined(LINUX) \
+ || defined(NETBSD) || defined(FREEBSD) || defined(HPUX)
# include <unistd.h>
# endif
# define GETPAGESIZE() getpagesize()
# endif
-# if defined(SUNOS5) || defined(DRSNX) || defined(UTS4)
- /* OS has SVR4 generic features. Probably others also qualify. */
+# if defined(SOLARIS) || defined(DRSNX) || defined(UTS4)
+ /* 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. */
-# define SUNOS5DL
- /* OS has SUNOS5 style signal handlers. */
+# if defined(SOLARIS) || defined(DRSNX)
+ /* OS has SOLARIS style semi-undocumented interface */
+ /* to dynamic loader. */
+# define SOLARISDL
+ /* OS has SOLARIS style signal handlers. */
# define SUNOS5SIGS
# endif
# if defined(SVR4) || defined(LINUX) || defined(IRIX5) || defined(HPUX) \
|| defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD) \
- || defined(DGUX) || defined(BSD) || defined(SUNOS4) \
- || defined(_AIX) || defined(DARWIN) || defined(OSF1)
+ || defined(DGUX) || defined(BSD) \
+ || defined(AIX) || defined(DARWIN) || defined(OSF1) \
+ || defined(HURD)
# define UNIX_LIKE /* Basic Unix-like system calls work. */
# endif
# define PCR_VDB
# endif
-# ifdef SRC_M3
- /* Postponed for now. */
-# undef PROC_VDB
-# undef MPROTECT_VDB
-# endif
-
# ifdef SMALL_CONFIG
/* Presumably not worth the space it takes. */
# undef PROC_VDB
# endif
# ifdef USE_MUNMAP
+ /* FIXME: Remove this undef if possible. */
# undef MPROTECT_VDB /* Can't deal with address space holes. */
# endif
-# ifdef PARALLEL_MARK
+# if defined(PARALLEL_MARK)
+ /* FIXME: Remove this undef if possible. */
# undef MPROTECT_VDB /* For now. */
# endif
-# if !defined(PCR_VDB) && !defined(PROC_VDB) && !defined(MPROTECT_VDB)
+# if defined(MPROTECT_VDB) && defined(GC_PREFER_MPROTECT_VDB)
+ /* Choose MPROTECT_VDB manually (if multiple strategies available). */
+# undef PCR_VDB
+# undef PROC_VDB
+ /* #undef GWW_VDB - handled in os_dep.c */
+# endif
+
+# if !defined(PCR_VDB) && !defined(PROC_VDB) && !defined(MPROTECT_VDB) \
+ && !defined(GWW_VDB)
# define DEFAULT_VDB
# endif
# define CACHE_LINE_SIZE 32 /* Wild guess */
# endif
-# if defined(LINUX) || defined(__GLIBC__)
+# ifndef STATIC
+# ifndef NO_DEBUGGING
+# define STATIC /* ignore to aid profiling and possibly debugging */
+# else
+# define STATIC static
+# endif
+# endif
+
+# if defined(LINUX) || defined(HURD) || defined(__GLIBC__)
# define REGISTER_LIBRARIES_EARLY
/* We sometimes use dl_iterate_phdr, which may acquire an internal */
/* lock. This isn't safe after the world has stopped. So we must */
((word*)x)[1] = 0;
# endif /* CLEAR_DOUBLE */
- /* 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
+# if defined(GC_LINUX_THREADS) && defined(REDIRECT_MALLOC) \
+ && !defined(INCLUDE_LINUX_THREAD_DESCR)
+ /* Will not work, since libc and the dynamic loader use thread */
+ /* locals, sometimes as the only reference. */
+# define INCLUDE_LINUX_THREAD_DESCR
# endif
# if defined(GC_IRIX_THREADS) && !defined(IRIX5)
# if defined(GC_NETBSD_THREADS) && !defined(NETBSD)
--> inconsistent configuration
# endif
-# if defined(GC_SOLARIS_THREADS) && !defined(SUNOS5)
+# if defined(GC_FREEBSD_THREADS) && !defined(FREEBSD)
+ --> inconsistent configuration
+# endif
+# if defined(GC_SOLARIS_THREADS) && !defined(SOLARIS)
--> inconsistent configuration
# endif
# if defined(GC_HPUX_THREADS) && !defined(HPUX)
# if defined(GC_AIX_THREADS) && !defined(_AIX)
--> inconsistent configuration
# endif
+# if defined(GC_GNU_THREADS) && !defined(HURD)
+ --> inconsistent configuration
+# endif
# 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)
+# if defined(PCR) || defined(GC_WIN32_THREADS) || defined(GC_PTHREADS)
# define THREADS
# endif
-# if defined(HP_PA) || defined(M88K) \
- || defined(POWERPC) && !defined(DARWIN) \
- || defined(LINT) || defined(MSWINCE) || defined(ARM32) || defined(CRIS) \
- || (defined(I386) && defined(__LCC__))
- /* Use setjmp based hack to mark from callee-save registers. */
- /* The define should move to the individual platform */
- /* descriptions. */
-# define USE_GENERIC_PUSH_REGS
+# if !defined(USE_MARK_BITS) && !defined(USE_MARK_BYTES)
+# if defined(THREADS) && defined(PARALLEL_MARK)
+# define USE_MARK_BYTES
+# else
+# define USE_MARK_BITS
+# endif
# endif
# if defined(MSWINCE)
# define NO_GETENV
# endif
+# ifndef STRTOULL
+# if defined(_WIN64) && !defined(__GNUC__)
+# define STRTOULL _strtoui64
+# elif defined(_LLP64) || defined(__LLP64__) || defined(_WIN64)
+# define STRTOULL strtoull
+# else
+ /* strtoul() fits since sizeof(long) >= sizeof(word). */
+# define STRTOULL strtoul
+# endif
+# endif
+
# if defined(SPARC)
# define ASM_CLEAR_CODE /* Stack clearing is crucial, and we */
/* include assembly code to do it well. */
# 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
# endif
# if !defined(FIXUP_POINTER) && defined(POINTER_MASK)
-# define FIXUP_POINTER(p) (p) = ((p) & (POINTER_MASK) << POINTER_SHIFT)
+# define FIXUP_POINTER(p) (p = ((p) & POINTER_MASK) << POINTER_SHIFT)
# endif
# if defined(FIXUP_POINTER)
# define FIXUP_POINTER(p)
# endif
+# if !defined(MARK_BIT_PER_GRANULE) && !defined(MARK_BIT_PER_OBJ)
+# define MARK_BIT_PER_GRANULE /* Usually faster */
+# endif
+
+/* Some static sanity tests. */
+# if defined(MARK_BIT_PER_GRANULE) && defined(MARK_BIT_PER_OBJ)
+# error Define only one of MARK_BIT_PER_GRANULE and MARK_BIT_PER_OBJ.
+# endif
+
+# if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN)
+# error "Only one of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd."
+# endif
+# if !defined(STACK_GROWS_UP) && !defined(STACK_GROWS_DOWN)
+# error "One of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd."
+# endif
+
+# if defined(REDIRECT_MALLOC) && defined(THREADS) && !defined(LINUX)
+# error "REDIRECT_MALLOC with THREADS works at most on Linux."
+# 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 */
+ /* chunks. It also avoids unintended recursion with */
/* -DREDIRECT_MALLOC. */
/* GET_MEM() returns a HLKSIZE aligned chunk. */
/* 0 is taken to mean failure. */
/* though we should perhaps take advantage of the case in which */
/* does. */
struct hblk; /* See gc_priv.h. */
-# ifdef PCR
- char * real_malloc();
+# if defined(PCR)
+ char * real_malloc(size_t bytes);
# 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 \
+# elif defined(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(NONSTOP) || \
+# elif defined(NEXT) || defined(DOS4GW) || defined(NONSTOP) || \
(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( \
+ (defined(SOLARIS) && !defined(USE_MMAP))
+# define GET_MEM(bytes) HBLKPTR((size_t) calloc(1, (size_t)bytes + GC_page_size) \
+ + GC_page_size-1)
+# elif defined(MSWIN32)
+ ptr_t GC_win32_get_mem(GC_word bytes);
+# define GET_MEM(bytes) (struct hblk *)GC_win32_get_mem(bytes)
+# elif defined(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( \
+# 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) \
+# endif
+# elif defined(MSWINCE)
+ ptr_t GC_wince_get_mem(GC_word bytes);
+# define GET_MEM(bytes) (struct hblk *)GC_wince_get_mem(bytes)
+# elif 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
+# else
+ ptr_t GC_unix_get_mem(GC_word bytes);
+# define GET_MEM(bytes) (struct hblk *)GC_unix_get_mem(bytes)
# endif
#endif /* GC_PRIVATE_H */
-#if defined(_AIX) && !defined(__GNUC__) && !defined(__STDC__)
- /* IBMs xlc compiler doesn't appear to follow the convention of */
- /* defining __STDC__ to be zero in extended mode. */
-# define __STDC__ 0
-#endif
-
# endif /* GCCONFIG_H */