/* * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996 by Silicon Graphics. All rights reserved. * Copyright (c) 2000-2004 Hewlett-Packard Development Company, L.P. * Copyright (c) 2009-2021 Ivan Maidanski * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. * * Permission is hereby granted to use or copy this program * for any purpose, provided the above notices are retained on all copies. * Permission to modify the code and to distribute modified code is granted, * provided the above notices are retained, and a notice that the code was * modified is included with the above copyright notice.
*/
/* * This header is private to the gc. It is almost always included from * gc_priv.h. However it is possible to include it by itself if just the * configuration macros are needed. In that * case, a few declarations relying on types declared in gc_priv.h will be * omitted.
*/
#if !defined(sony_news) # include <stddef.h> /* For size_t, etc. */ #endif
/* Note: Only wrap our own declarations, and not the included headers. */ /* In this case, wrap our entire file, but temporarily unwrap/rewrap */ /* around #includes. Types and macros do not need such wrapping, only */ /* the declared global data and functions. */ #ifdef __cplusplus # define EXTERN_C_BEGIN extern"C" { # define EXTERN_C_END } /* extern "C" */ #else # define EXTERN_C_BEGIN /* empty */ # define EXTERN_C_END /* empty */ #endif
#ifdef LINT2 /* A macro (based on a tricky expression) to prevent false warnings */ /* like "Array compared to 0", "Comparison of identical expressions", */ /* "Untrusted loop bound" output by some static code analysis tools. */ /* The argument should not be a literal value. The result is */ /* converted to word type. (Actually, GC_word is used instead of */ /* word type as the latter might be undefined at the place of use.) */ # define COVERT_DATAFLOW(w) (~(GC_word)(w)^(~(GC_word)0)) #else # define COVERT_DATAFLOW(w) ((GC_word)(w)) #endif
/* Machine dependent parameters. Some tuning parameters can be found */ /* near the top of gc_private.h. */
/* Machine specific parts contributed by various people. See README file. */
#ifdefined(__ANDROID__) && !defined(HOST_ANDROID) /* __ANDROID__ macro is defined by Android NDK gcc. */ # define HOST_ANDROID 1 #endif
/* First a unified test for Linux: */ # if (defined(linux) || defined(__linux__) || defined(HOST_ANDROID)) \
&& !defined(LINUX) && !defined(__native_client__) # define LINUX # endif
/* And one for NetBSD: */ # ifdefined(__NetBSD__) # define NETBSD # endif
/* And one for OpenBSD: */ # ifdefined(__OpenBSD__) # define OPENBSD # endif
/* And one for FreeBSD: */ # if (defined(__FreeBSD__) || defined(__DragonFly__) \
|| defined(__FreeBSD_kernel__)) && !defined(FREEBSD) \
&& !defined(GC_NO_FREEBSD) /* Orbis compiler defines __FreeBSD__ */ # define FREEBSD # endif
/* And one for Darwin: */ # ifdefined(macosx) || (defined(__APPLE__) && defined(__MACH__)) # define DARWIN
EXTERN_C_END # include <TargetConditionals.h>
EXTERN_C_BEGIN # endif
/* Or manually define the machine type here. A machine type is */ /* characterized by the architecture. Some */ /* machine types are further subdivided by OS. */ /* 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 */ # if !defined(mach_type_known) && !defined(CPPCHECK) # error The collector has not been ported to this machine/OS combination # endif /* Mapping is: M68K ==> Motorola 680X0 */ /* (NEXT, and SYSV (A/UX), */ /* MACOS and AMIGA variants) */ /* I386 ==> Intel 386 */ /* (SEQUENT, OS2, SCO, LINUX, NETBSD, */ /* FREEBSD, THREE86BSD, MSWIN32, */ /* BSDI, SOLARIS, NEXT and others) */ /* NS32K ==> Encore Multimax */ /* MIPS ==> R2000 through R14K */ /* (many variants) */ /* VAX ==> DEC VAX */ /* (BSD, ULTRIX variants) */ /* HP_PA ==> HP9000/700 & /800 */ /* HP/UX, LINUX */ /* SPARC ==> SPARC v7/v8/v9 */ /* (SOLARIS, LINUX, DRSNX variants) */ /* ALPHA ==> DEC Alpha */ /* (OSF1 and LINUX variants) */ /* LOONGARCH ==> Loongson LoongArch */ /* (LINUX 32- and 64-bit variants) */ /* M88K ==> Motorola 88XX0 */ /* (CX_UX and DGUX) */ /* S370 ==> 370-like machine */ /* running Amdahl UTS4 */ /* S390 ==> 390-like machine */ /* running LINUX */ /* AARCH64 ==> ARM AArch64 */ /* (LP64 and ILP32 variants) */ /* E2K ==> Elbrus 2000 */ /* running LINUX */ /* ARM32 ==> Intel StrongARM */ /* (many variants) */ /* IA64 ==> Intel IPF */ /* (e.g. Itanium) */ /* (LINUX and HPUX) */ /* SH ==> Hitachi SuperH */ /* (LINUX & MSWINCE) */ /* X86_64 ==> AMD x86-64 */ /* POWERPC ==> IBM/Apple PowerPC */ /* (MACOS(<=9),DARWIN(incl.MACOSX),*/ /* LINUX, NETBSD, AIX, NOSYS */ /* variants) */ /* Handles 32 and 64-bit variants. */ /* ARC ==> Synopsys ARC */ /* AVR32 ==> Atmel RISC 32-bit */ /* CRIS ==> Axis Etrax */ /* M32R ==> Renesas M32R */ /* NIOS2 ==> Altera NIOS2 */ /* HEXAGON ==> Qualcomm Hexagon */ /* OR1K ==> OpenRISC/or1k */ /* RISCV ==> RISC-V 32/64-bit */ /* TILEPRO ==> Tilera TILEPro */ /* TILEGX ==> Tilera TILE-Gx */
/* * 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 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 * 32 bit pointers should use CPP_WORDSZ of 32, not 64. Default is 32.) * * MACH_TYPE is a string representation of the machine type. * OS_TYPE is analogous for the OS. * * ALIGNMENT is the largest N, such that * all pointer are guaranteed to be aligned on N byte boundaries. * defining it to be 1 will always work, but perform poorly. * * DATASTART is the beginning of the data segment. * On some platforms SEARCH_FOR_DATA_START is defined. * The latter will cause GC_data_start to * be set to an address determined by accessing data backwards from _end * until an unmapped page is found. DATASTART will be defined to be * GC_data_start. * On UNIX-like systems, the collector will scan the area between DATASTART * and DATAEND for root pointers. * * DATAEND, if not "end", where "end" is defined as "extern int end[]". * RTH suggests gaining access to linker script synth'd values with * this idiom instead of "&end", where "end" is defined as "extern int end". * Otherwise, "GCC will assume these are in .sdata/.sbss" and it will, e.g., * cause failures on alpha*-*-* with -msmall-data or -fpic or mips-*-* * without any special options. * * STACKBOTTOM is the cold 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. * For each machine, the following should: * 1) define STACK_GROWS_UP if the stack grows toward higher addresses, and * 2) define exactly one of * STACKBOTTOM (should be defined to be an expression) * LINUX_STACKBOTTOM * HEURISTIC1 * HEURISTIC2 * If STACKBOTTOM is defined, then its value will be used directly (as the * stack bottom). 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 (currently only if 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 * the next multiple of STACK_GRAN. * 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 signaled. Round that * to the nearest plausible page boundary, and use that instead * of STACKBOTTOM. * * Gustavo Rodriguez-Rivera points out that on most (all?) Unix machines, * the value of environ is a pointer that can serve as STACKBOTTOM. * I expect that HEURISTIC2 can be replaced by this approach, which * interferes far less with debugging. However it has the disadvantage * that it's confused by a putenv call before the collector is initialized. * This could be dealt with by intercepting putenv ... * * If no expression for STACKBOTTOM can be found, and neither of the above * heuristics are usable, the collector can still be used with all of the above * undefined, provided one of the following is done: * 1) GC_mark_roots can be changed to somehow mark from the correct stack(s) * without reference to STACKBOTTOM. This is appropriate for use in * conjunction with thread packages, since there will be multiple stacks. * (Allocating thread stacks in the heap, and treating them as ordinary * heap data objects is also possible as a last resort. However, this is * likely to introduce significant amounts of excess storage retention * unless the dead parts of the thread stacks are periodically cleared.) * 2) Client code may set GC_stackbottom before calling any GC_ routines. * If the author of the client code controls the main program, this is * 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 (provided real_main() is not inlined by the compiler): * * #include "gc.h" * * main(argc, argv, envp) * int argc; * char **argv, **envp; * { * volatile int dummy; * * GC_stackbottom = (ptr_t)(&dummy); * return(real_main(argc, argv, envp)); * } * * * Each architecture may also define the style of virtual dirty bit * implementation to be used: * GWW_VDB: Use win32 GetWriteWatch primitive. * MPROTECT_VDB: Write protect the heap and catch faults. * PROC_VDB: Use the SVR4 /proc primitives to read dirty bits. * SOFT_VDB: Use the Linux /proc primitives to track 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 dyn_load.c * defined GC_register_dynamic_libraries() for the architecture. * * An architecture may define PREFETCH(x) to preload the cache with *x. * This defaults to GCC built-in operation (or a no-op for other compilers). * * GC_PREFETCH_FOR_WRITE(x) is used if *x is about to be written. * * An architecture may also define CLEAR_DOUBLE(x) to be a fast way to * clear the two words at GC_malloc-aligned address x. By default, * word stores of 0 are used instead. * * HEAP_START may be defined as the initial address hint for mmap-based * allocation.
*/
/* If available, we can use __builtin_unwind_init() to push the */ /* relevant registers onto the stack. */ # if GC_GNUC_PREREQ(2, 8) \
&& !GC_GNUC_PREREQ(11, 0) /* broken at least in 11.2.0 on cygwin64 */ \
&& !defined(__INTEL_COMPILER) && !defined(__PATHCC__) \
&& !defined(__FUJITSU) /* for FX10 system */ \
&& !(defined(POWERPC) && defined(DARWIN)) /* for MacOS X 10.3.9 */ \
&& !defined(E2K) && !defined(RTEMS) \
&& !defined(__ARMCC_VERSION) /* does not exist in armcc gnu emu */ \
&& (!defined(__clang__) \
|| GC_CLANG_PREREQ(8, 0) /* was no-op in clang-3 at least */) # define HAVE_BUILTIN_UNWIND_INIT # endif
/* The common OS-specific definitions (should be applicable to */ /* all (or most, at least) supported architectures). */
# ifdef DARWIN # define OS_TYPE "DARWIN" # define DYNAMIC_LOADING /* TODO: 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 USE_MMAP_ANON
EXTERN_C_END # include <unistd.h>
EXTERN_C_BEGIN # define GETPAGESIZE() (unsigned)getpagesize() /* There seems to be some issues with trylock hanging on darwin. */ /* TODO: This should be looked into some more. */ # define NO_PTHREAD_TRYLOCK # endif /* DARWIN */
# ifdef SOLARIS # define OS_TYPE "SOLARIS" externint _etext[], _end[];
ptr_t GC_SysVGetDataStart(size_t, ptr_t); # define DATASTART_IS_FUNC # define DATAEND ((ptr_t)(_end)) # if !defined(USE_MMAP) && defined(REDIRECT_MALLOC) # define USE_MMAP 1 /* Otherwise we now use calloc. Mmap may result in the */ /* heap interleaved with thread stacks, which can result in */ /* excessive blacklisting. Sbrk is unusable since it */ /* doesn't interact correctly with the system malloc. */ # endif # ifdef USE_MMAP # define HEAP_START (ptr_t)0x40000000 # else # define HEAP_START DATAEND # endif # ifndef GC_THREADS # define MPROTECT_VDB # endif # define DYNAMIC_LOADING /* Define STACKBOTTOM as (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. */ /* HEURISTIC1 reportedly no longer works under Solaris 2.7. */ /* HEURISTIC2 probably works, but this appears to be preferable.*/ /* Apparently USRSTACK is defined to be USERLIMIT, but in some */ /* installations that's undefined. We work around this with a */ /* gross hack: */
EXTERN_C_END # include <sys/vmparam.h> # include <unistd.h>
EXTERN_C_BEGIN # ifdef USERLIMIT /* This should work everywhere, but doesn't. */ # define STACKBOTTOM ((ptr_t)USRSTACK) # else # define HEURISTIC2 # endif # endif /* SOLARIS */
# ifdef VAX # define MACH_TYPE "VAX" # define ALIGNMENT 4 /* Pointers are longword aligned by 4.2 C compiler */ externchar etext[]; # define DATASTART ((ptr_t)(etext)) # ifdef BSD # define OS_TYPE "BSD" # define HEURISTIC1 /* HEURISTIC2 may be OK, but it's hard to test. */ # endif # ifdef ULTRIX # define OS_TYPE "ULTRIX" # define STACKBOTTOM ((ptr_t)0x7fffc800) # endif # endif
# ifdef SPARC # define MACH_TYPE "SPARC" # ifdefined(__arch64__) || defined(__sparcv9) # define ALIGNMENT 8 # define CPP_WORDSZ 64 # define ELF_CLASS ELFCLASS64 # else # define ALIGNMENT 4 /* Required by hardware */ # define CPP_WORDSZ 32 # endif /* 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 DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext) # define PROC_VDB # define GETPAGESIZE() (unsigned)sysconf(_SC_PAGESIZE) /* getpagesize() appeared to be missing from at least */ /* one Solaris 5.4 installation. Weird. */ # endif # ifdef DRSNX # define OS_TYPE "DRSNX" externint etext[];
ptr_t GC_SysVGetDataStart(size_t, ptr_t); # define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)etext) # define DATASTART_IS_FUNC # define MPROTECT_VDB # define STACKBOTTOM ((ptr_t)0xdfff0000) # define DYNAMIC_LOADING # endif # ifdef LINUX # if !defined(__ELF__) && !defined(CPPCHECK) # error Linux SPARC a.out not supported # endif # define SVR4 externint _etext[];
ptr_t GC_SysVGetDataStart(size_t, ptr_t); # ifdef __arch64__ # define DATASTART GC_SysVGetDataStart(0x100000, (ptr_t)_etext) # else # define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext) # endif # define DATASTART_IS_FUNC # endif # ifdef OPENBSD /* Nothing specific. */ # endif # ifdef NETBSD /* Nothing specific. */ # endif # ifdef FREEBSD externchar etext[]; externchar edata[]; # if !defined(CPPCHECK) externchar end[]; # endif # define NEED_FIND_LIMIT # define DATASTART ((ptr_t)(&etext)) void * GC_find_limit(void *, int); # define DATAEND (ptr_t)GC_find_limit(DATASTART, TRUE) # define DATAEND_IS_FUNC # define GC_HAVE_DATAREGION2 # define DATASTART2 ((ptr_t)(&edata)) # define DATAEND2 ((ptr_t)(&end)) # endif # endif
# ifdef I386 # define MACH_TYPE "I386" # if (defined(__LP64__) || defined(_WIN64)) && !defined(CPPCHECK) # error This should be handled as X86_64 # else # define CPP_WORDSZ 32 # define ALIGNMENT 4 /* Appears to hold for all "32 bit" compilers */ /* except Borland. The -a4 option fixes */ /* Borland. For Watcom the option is -zp4. */ # endif # ifdef SEQUENT # define OS_TYPE "SEQUENT" externint etext[]; # define DATASTART ((ptr_t)((((word)(etext)) + 0xfff) & ~0xfff)) # define STACKBOTTOM ((ptr_t)0x3ffff000) # endif # ifdef EMSCRIPTEN # define OS_TYPE "EMSCRIPTEN" # define DATASTART (ptr_t)ALIGNMENT # define DATAEND (ptr_t)ALIGNMENT # define USE_MMAP_ANON /* avoid /dev/zero, not supported */ # define STACK_GROWS_DOWN # endif # ifdefined(__QNX__) # define OS_TYPE "QNX" # define SA_RESTART 0 # define HEURISTIC1 externchar etext[]; externint _end[]; # define DATASTART ((ptr_t)etext) # define DATAEND ((ptr_t)_end) # endif # ifdef HAIKU externint etext[]; # define DATASTART ((ptr_t)((((word)(etext)) + 0xfff) & ~0xfff)) # endif # ifdef SOLARIS # define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)_etext) /* 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 # define PROC_VDB # endif # endif # ifdef SCO # define OS_TYPE "SCO" externint etext[]; # define DATASTART ((ptr_t)((((word)(etext)) + 0x3fffff) & ~0x3fffff) \
+ ((word)(etext) & 0xfff)) # define STACKBOTTOM ((ptr_t)0x7ffffffc) # endif # ifdef SCO_ELF # define OS_TYPE "SCO_ELF" externint etext[]; # define DATASTART ((ptr_t)(etext)) # define STACKBOTTOM ((ptr_t)0x08048000) # define DYNAMIC_LOADING # define ELF_CLASS ELFCLASS32 # endif # ifdef DGUX # define OS_TYPE "DGUX" externint _etext, _end;
ptr_t GC_SysVGetDataStart(size_t, ptr_t); # define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)(&_etext)) # define DATASTART_IS_FUNC # define DATAEND ((ptr_t)(&_end)) # define STACK_GROWS_DOWN # define HEURISTIC2
EXTERN_C_END # include <unistd.h>
EXTERN_C_BEGIN # define GETPAGESIZE() (unsigned)sysconf(_SC_PAGESIZE) # define DYNAMIC_LOADING # ifndef USE_MMAP # define USE_MMAP 1 # endif # define MAP_FAILED (void *) ((word)-1) # define HEAP_START (ptr_t)0x40000000 # endif /* DGUX */ # ifdef LINUX # if !defined(REDIRECT_MALLOC) # define MPROTECT_VDB # else /* We seem to get random errors in the incremental mode, */ /* possibly because the Linux threads implementation */ /* itself is a malloc client and cannot deal with the */ /* signals. fread() uses malloc too. */ # endif # define HEAP_START (ptr_t)0x1000 /* This encourages mmap to give us low addresses, */ /* thus allowing the heap to grow to ~3 GB. */ # ifdef __ELF__ # ifdefined(__GLIBC__) && __GLIBC__ >= 2 \
|| defined(HOST_ANDROID) || defined(HOST_TIZEN) # define SEARCH_FOR_DATA_START # else externchar **__environ; # define DATASTART ((ptr_t)(&__environ)) /* hideous kludge: __environ is the first */ /* word in crt0.o, and delimits the start */ /* of the data segment, no matter which */ /* ld options were passed through. */ /* We could use _etext instead, but that */ /* would include .rodata, which may */ /* contain large read-only data tables */ /* that we'd rather not scan. */ # endif # if !defined(GC_NO_SIGSETJMP) && (defined(HOST_TIZEN) \
|| (defined(HOST_ANDROID) \
&& !(GC_GNUC_PREREQ(4, 8) || GC_CLANG_PREREQ(3, 2) \
|| __ANDROID_API__ >= 18))) /* Older Android NDK releases lack sigsetjmp in x86 libc */ /* (setjmp is used instead to find data_start). The bug */ /* is fixed in Android NDK r8e (so, ok to use sigsetjmp */ /* if gcc4.8+, clang3.2+ or Android API level 18+). */ # define GC_NO_SIGSETJMP 1 # endif # else externint etext[]; # define DATASTART ((ptr_t)((((word)(etext)) + 0xfff) & ~0xfff)) # endif # ifdef USE_I686_PREFETCH # define PREFETCH(x) \
__asm__ __volatile__ ("prefetchnta %0" : : "m"(*(char *)(x))) /* Empirically prefetcht0 is much more effective at reducing */ /* 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. */ # ifdef FORCE_WRITE_PREFETCH /* Using prefetches for write seems to have a slight negative */ /* impact on performance, at least for a PIII/500. */ # define GC_PREFETCH_FOR_WRITE(x) \
__asm__ __volatile__ ("prefetcht0 %0" : : "m"(*(char *)(x))) # else # define GC_NO_PREFETCH_FOR_WRITE # endif # elif defined(USE_3DNOW_PREFETCH) # define PREFETCH(x) \
__asm__ __volatile__ ("prefetch %0" : : "m"(*(char *)(x))) # define GC_PREFETCH_FOR_WRITE(x) \
__asm__ __volatile__ ("prefetchw %0" : : "m"(*(char *)(x))) # endif # ifdefined(__GLIBC__) && !defined(__UCLIBC__) \
&& !defined(GLIBC_TSX_BUG_FIXED) /* Workaround lock elision implementation for some glibc. */ # define GLIBC_2_19_TSX_BUG
EXTERN_C_END # include <gnu/libc-version.h> /* for gnu_get_libc_version() */
EXTERN_C_BEGIN # endif # ifndef SOFT_VDB # define SOFT_VDB # endif # endif # ifdef CYGWIN32 # define WOW64_THREAD_CONTEXT_WORKAROUND # define DATASTART ((ptr_t)GC_DATASTART) /* From gc.h */ # define DATAEND ((ptr_t)GC_DATAEND) # ifndef USE_WINALLOC # /* MPROTECT_VDB does not work, it leads to a spurious exit. */ # ifdef USE_MMAP # define NEED_FIND_LIMIT # endif # endif # endif # ifdef INTERIX # define OS_TYPE "INTERIX" externint _data_start__[]; externint _bss_end__[]; # define DATASTART ((ptr_t)_data_start__) # define DATAEND ((ptr_t)_bss_end__) # define STACKBOTTOM ({ ptr_t rv; \
__asm__ __volatile__ ("movl %%fs:4, %%eax" \
: "=a" (rv)); \
rv; }) # define USE_MMAP_ANON # endif # ifdef OS2 # define OS_TYPE "OS2" /* STACKBOTTOM and DATASTART are handled specially in */ /* os_dep.c. OS2 actually has the right */ /* system call! */ # define DATAEND /* not needed */ # endif # ifdef MSWIN32 # define WOW64_THREAD_CONTEXT_WORKAROUND # define RETRY_GET_THREAD_CONTEXT # define MPROTECT_VDB # endif # ifdef MSWINCE /* Nothing specific. */ # endif # ifdef DJGPP # define OS_TYPE "DJGPP"
EXTERN_C_END # include "stubinfo.h"
EXTERN_C_BEGIN externint etext[]; externint _stklen; externint __djgpp_stack_limit; # define DATASTART ((ptr_t)((((word)(etext)) + 0x1ff) & ~0x1ff)) /* #define STACKBOTTOM ((ptr_t)((word)_stubinfo+_stubinfo->size+_stklen)) */ # define STACKBOTTOM ((ptr_t)((word)__djgpp_stack_limit + _stklen)) /* This may not be right. */ # endif # ifdef OPENBSD /* Nothing specific. */ # endif # ifdef FREEBSD # ifdef __GLIBC__ externint _end[]; # define DATAEND ((ptr_t)(_end)) # endif # endif # ifdef NETBSD /* Nothing specific. */ # endif # ifdef THREE86BSD # define OS_TYPE "THREE86BSD" # define HEURISTIC2 externchar etext[]; # define DATASTART ((ptr_t)(etext)) # endif # ifdef BSDI # define OS_TYPE "BSDI" # define HEURISTIC2 externchar etext[]; # define DATASTART ((ptr_t)(etext)) # endif # ifdef NEXT # define STACKBOTTOM ((ptr_t)0xc0000000) # endif # ifdef RTEMS # define OS_TYPE "RTEMS"
EXTERN_C_END # include <sys/unistd.h>
EXTERN_C_BEGIN externint etext[]; void *rtems_get_stack_bottom(void); # define InitStackBottom rtems_get_stack_bottom() # define DATASTART ((ptr_t)etext) # define STACKBOTTOM ((ptr_t)InitStackBottom) # endif # ifdef DOS4GW # define OS_TYPE "DOS4GW" externlong __nullarea; externchar _end; externchar *_STACKTOP; /* Depending on calling conventions Watcom C either precedes */ /* 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 STACKBOTTOM ((ptr_t)_STACKTOP) /* confused? me too. */ # define DATASTART ((ptr_t)(&__nullarea)) # define DATAEND ((ptr_t)(&_end)) # endif # ifdef HURD # define OS_TYPE "HURD" # define STACK_GROWS_DOWN # define HEURISTIC2 # define SEARCH_FOR_DATA_START externint _end[]; # define DATAEND ((ptr_t)(_end)) /* # define MPROTECT_VDB Not quite working yet? */ # define DYNAMIC_LOADING # define USE_MMAP_ANON # endif # ifdef DARWIN # define DARWIN_DONT_PARSE_STACK 1 # define STACKBOTTOM ((ptr_t)0xc0000000) # define MPROTECT_VDB # if TARGET_OS_IPHONE && !defined(NO_DYLD_BIND_FULLY_IMAGE) /* iPhone/iPad simulator */ # define NO_DYLD_BIND_FULLY_IMAGE # endif # endif /* DARWIN */ # endif
# ifdef NS32K # define MACH_TYPE "NS32K" # define ALIGNMENT 4 externchar **environ; # define DATASTART ((ptr_t)(&environ)) /* hideous kludge: environ is the first */ /* word in crt0.o, and delimits the start */ /* of the data segment, no matter which */ /* ld options were passed through. */ # define STACKBOTTOM ((ptr_t)0xfffff000) /* for Encore */ # endif
# ifdef HP_PA # define MACH_TYPE "HP_PA" # ifdef __LP64__ # define CPP_WORDSZ 64 # define ALIGNMENT 8 # else # define CPP_WORDSZ 32 # define ALIGNMENT 4 # endif # define STACK_GROWS_UP # ifdef HPUX # ifndef GC_THREADS # define MPROTECT_VDB # endif # ifdef USE_HPUX_FIXED_STACKBOTTOM /* The following appears to work for 7xx systems running HP/UX */ /* 9.xx. Furthermore, it might result in much faster */ /* collections than HEURISTIC2, which may involve scanning */ /* segments that directly precede the stack. It is not the */ /* default, since it may not work on older machine/OS */ /* combinations. (Thanks to Raymond X.T. Nijssen for uncovering */ /* this.) */ /* This technique also doesn't work with HP/UX 11.xx. The */ /* stack size is settable using the kernel maxssiz variable, */ /* and in 11.23 and latter, the size can be set dynamically. */ /* It also doesn't handle SHMEM_MAGIC binaries which have */ /* stack and data in the first quadrant. */ # define STACKBOTTOM ((ptr_t)0x7b033000) /* from /etc/conf/h/param.h */ # elif defined(USE_ENVIRON_POINTER) /* Gustavo Rodriguez-Rivera suggested changing HEURISTIC2 */ /* to this. Note that the GC must be initialized before the */ /* first putenv call. Unfortunately, some clients do not obey. */ externchar ** environ; # define STACKBOTTOM ((ptr_t)environ) # elif !defined(HEURISTIC2) /* This uses pst_vm_status support. */ # define HPUX_MAIN_STACKBOTTOM # define NEED_FIND_LIMIT # endif # ifndef __GNUC__ # define PREFETCH(x) do { \ registerlong addr = (long)(x); \
(void) _asm ("LDW", 0, 0, addr, 0); \
} while (0) # endif # endif /* HPUX */ # ifdef LINUX # define SEARCH_FOR_DATA_START # endif # ifdef OPENBSD /* Nothing specific. */ # endif # endif /* HP_PA */
# ifdef ALPHA # define MACH_TYPE "ALPHA" # define ALIGNMENT 8 # define CPP_WORDSZ 64 # ifdef NETBSD # define ELFCLASS32 32 # define ELFCLASS64 64 # define ELF_CLASS ELFCLASS64 # endif # ifdef OPENBSD /* Nothing specific. */ # endif # ifdef FREEBSD /* MPROTECT_VDB is not yet supported at all on FreeBSD/alpha. */ /* Handle unmapped hole alpha*-*-freebsd[45]* puts between etext and edata. */ externchar etext[]; externchar edata[]; # if !defined(CPPCHECK) externchar end[]; # endif # define NEED_FIND_LIMIT # define DATASTART ((ptr_t)(&etext)) void * GC_find_limit(void *, int); # define DATAEND (ptr_t)GC_find_limit(DATASTART, TRUE) # define DATAEND_IS_FUNC # define GC_HAVE_DATAREGION2 # define DATASTART2 ((ptr_t)(&edata)) # define DATAEND2 ((ptr_t)(&end)) # endif # ifdef OSF1 # define OS_TYPE "OSF1" # define DATASTART ((ptr_t)0x140000000) externint _end[]; # define DATAEND ((ptr_t)(&_end)) externchar ** environ;
EXTERN_C_END # include <unistd.h>
EXTERN_C_BEGIN /* round up from the value of environ to the nearest page boundary */ /* Probably breaks if putenv is called before collector */ /* initialization. */ # define STACKBOTTOM ((ptr_t)(((word)(environ) | (getpagesize()-1))+1)) /* # define HEURISTIC2 */ /* Normally HEURISTIC2 is too conservative, since */ /* the text segment immediately follows the stack. */
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.