# 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
# define SEQUENT
# define mach_type_known
# endif
-# if (defined(sun) || defined(__sun)) && (defined(i386) || defined(__i386__))
+# if defined(sun) && (defined(i386) || defined(__i386__))
# define I386
# define SOLARIS
# define mach_type_known
# endif
-# if (defined(sun) || defined(__sun)) && defined(__amd64)
+# if defined(sun) && defined(__amd64)
# define X86_64
# define SOLARIS
# define mach_type_known
# 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
# 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)
# 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
* 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
* 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"
*
/* 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))
# define DYNAMIC_LOADING
# define SEARCH_FOR_DATA_START
extern int _end[];
-# define DATAEND (_end)
+# define DATAEND (ptr_t)(_end)
# endif
# ifdef DARWIN
# define OS_TYPE "DARWIN"
# 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 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
extern int _end[];
extern ptr_t GC_SysVGetDataStart(size_t, ptr_t);
# define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext)
-# define DATAEND (_end)
+# 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
# endif
extern int _end[];
extern int _etext[];
-# define DATAEND (_end)
+# define DATAEND (ptr_t)(_end)
# define SVR4
extern ptr_t GC_SysVGetDataStart(size_t, ptr_t);
# ifdef __arch64__
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 */
/* 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
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 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 */
/* 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"
# define OS_TYPE "MSWIN32"
/* STACKBOTTOM and DATASTART are handled specially in */
/* os_dep.c. */
-# if !defined(__WATCOMC__)
-# define MPROTECT_VDB
- /* We also avoided doing this in the past with GC_WIN32_THREADS */
- /* Hopefully that's fixed. */
-# endif
-# if _MSC_VER >= 1300 /* .NET, i.e. > VisualStudio 6 */
-# define GWW_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
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 "LINUX"
# define DYNAMIC_LOADING
extern int _end[];
-# define DATAEND (_end)
-# define SEARCH_FOR_DATA_START
+# define DATAEND (ptr_t)(_end)
+ extern int __data_start[];
+# define DATASTART ((ptr_t)(__data_start))
# define CPP_WORDSZ _MIPS_SZPTR
# define ALIGNMENT (_MIPS_SZPTR/8)
# if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 2 || __GLIBC__ > 2
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 DYNAMIC_LOADING
# define SEARCH_FOR_DATA_START
extern int _end[];
-# define DATAEND (&_end)
+# define DATAEND (ptr_t)(&_end)
# endif /* LINUX */
# endif /* HP_PA */
/* 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. */
# 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
# define CPP_WORDSZ 32 /* Is this possible? */
# endif
# define ALIGNMENT 8
-# define STRTOULL _strtoui64
# endif
# endif
extern int _end[];
extern ptr_t GC_SysVGetDataStart(size_t, ptr_t);
# define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext)
-# define DATAEND (_end)
+# define DATAEND (ptr_t)(_end)
# define HEURISTIC2
# endif
# endif
# define OS_TYPE "LINUX"
# define LINUX_STACKBOTTOM
# define DYNAMIC_LOADING
-# define SEARCH_FOR_DATA_START
- extern int _end[];
-# define DATAEND (_end)
+ extern int __data_start[];
+# define DATASTART ((ptr_t)(__data_start))
+ extern int _end[];
+# define DATAEND (ptr_t)(_end)
# define CACHE_LINE_SIZE 256
# define GETPAGESIZE() 4096
# endif
# 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 LINUX_STACKBOTTOM
# define SEARCH_FOR_DATA_START
extern int _end[];
-# define DATAEND (_end)
+# define DATAEND (ptr_t)(_end)
# endif
# ifdef SH
# 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 DYNAMIC_LOADING
# define SEARCH_FOR_DATA_START
extern int _end[];
-# define DATAEND (_end)
+# define DATAEND (ptr_t)(_end)
# endif
# endif
# 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))
# 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 OS_TYPE "MSWIN32"
/* STACKBOTTOM and DATASTART are handled specially in */
/* os_dep.c. */
-# if !defined(__WATCOMC__)
-# define MPROTECT_VDB
- /* We also avoided doing this in the past with GC_WIN32_THREADS */
- /* Hopefully that's fixed. */
-# endif
-# if _MSC_VER >= 1300 /* .NET, i.e. > VisualStudio 6 */
-# define GWW_VDB
-# endif
+# define MPROTECT_VDB
+# define GWW_VDB
# define DATAEND /* not needed */
# endif
# endif
# ifndef DATAEND
extern int end[];
-# define DATAEND (end)
+# define DATAEND (ptr_t)(end)
# endif
# if defined(SVR4) && !defined(GETPAGESIZE)
# 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(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
# define CACHE_LINE_SIZE 32 /* Wild guess */
# endif
+# 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 */
# 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. */
# 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)
/* 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. */
/* does. */
struct hblk; /* See gc_priv.h. */
# if defined(PCR)
- char * real_malloc();
+ char * real_malloc(size_t bytes);
# define GET_MEM(bytes) HBLKPTR(real_malloc((size_t)bytes + GC_page_size) \
+ GC_page_size-1)
# elif defined(OS2)
# define GET_MEM(bytes) HBLKPTR((size_t) calloc(1, (size_t)bytes + GC_page_size) \
+ GC_page_size-1)
# elif defined(MSWIN32)
- extern ptr_t GC_win32_get_mem();
+ 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)
NewPtrClear(bytes + GC_page_size) + GC_page_size-1)
# endif
# elif defined(MSWINCE)
- extern ptr_t GC_wince_get_mem();
+ 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);
GC_amiga_get_mem((size_t)bytes + GC_page_size) \
+ GC_page_size-1)
# else
- extern ptr_t GC_unix_get_mem();
+ ptr_t GC_unix_get_mem(GC_word bytes);
# define GET_MEM(bytes) (struct hblk *)GC_unix_get_mem(bytes)
# endif