#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
/* 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. */ /* Hence we give an upper pound. */ /* This is currently unused, since we disabled HEURISTIC2 */ externint __start[]; # define HEURISTIC2_LIMIT ((ptr_t)((word)(__start) & ~(getpagesize()-1))) # ifndef GC_OSF1_THREADS /* Unresolved signal issues with threads. */ # define MPROTECT_VDB # endif # define DYNAMIC_LOADING # endif # ifdef LINUX # ifdef __ELF__ # define SEARCH_FOR_DATA_START # else # define DATASTART ((ptr_t)0x140000000) externint _end[]; # define DATAEND ((ptr_t)(_end)) # endif # if !defined(REDIRECT_MALLOC) # define MPROTECT_VDB /* Has only been superficially tested. May not */ /* work on all versions. */ # endif # endif # endif /* ALPHA */
# ifdef IA64 # define MACH_TYPE "IA64" # ifdef HPUX # ifdef _ILP32 # define CPP_WORDSZ 32 /* Requires 8 byte alignment for malloc */ # define ALIGNMENT 4 # else # if !defined(_LP64) && !defined(CPPCHECK) # error Unknown ABI # endif # define CPP_WORDSZ 64 /* Requires 16 byte alignment for malloc */ # define ALIGNMENT 8 # endif /* Note that the GC must be initialized before the 1st putenv call. */ externchar ** environ; # define STACKBOTTOM ((ptr_t)environ) # define HPUX_STACKBOTTOM /* The following was empirically determined, and is probably */ /* not very robust. */ /* Note that the backing store base seems to be at a nice */ /* address minus one page. */ # define BACKING_STORE_DISPLACEMENT 0x1000000 # define BACKING_STORE_ALIGNMENT 0x1000 extern ptr_t GC_register_stackbottom; # define BACKING_STORE_BASE GC_register_stackbottom /* Known to be wrong for recent HP/UX versions!!! */ # endif # ifdef LINUX # define CPP_WORDSZ 64 # define ALIGNMENT 8 /* The following works on NUE and older kernels: */ /* define STACKBOTTOM ((ptr_t)0xa000000000000000l) */ /* TODO: LINUX_STACKBOTTOM does not work on NUE. */ /* We also need the base address of the register stack */ /* backing store. */ extern ptr_t GC_register_stackbottom; # define BACKING_STORE_BASE GC_register_stackbottom # define SEARCH_FOR_DATA_START # ifdef __GNUC__ # define DYNAMIC_LOADING # else /* In the Intel compiler environment, we seem to end up with */ /* statically linked executables and an undefined reference */ /* to _DYNAMIC */ # endif # if !defined(REDIRECT_MALLOC) # define MPROTECT_VDB /* Requires Linux 2.3.47 or later. */ # endif # ifdef __GNUC__ # ifndef __INTEL_COMPILER # define PREFETCH(x) \
__asm__ (" lfetch [%0]": : "r"(x)) # define GC_PREFETCH_FOR_WRITE(x) \
__asm__ (" lfetch.excl [%0]": : "r"(x)) # define CLEAR_DOUBLE(x) \
__asm__ (" stf.spill [%0]=f0": : "r"((void *)(x))) # else
EXTERN_C_END # include <ia64intrin.h>
EXTERN_C_BEGIN # define PREFETCH(x) __lfetch(__lfhint_none, (x)) # define GC_PREFETCH_FOR_WRITE(x) __lfetch(__lfhint_nta, (x)) # define CLEAR_DOUBLE(x) __stf_spill((void *)(x), 0) # endif /* __INTEL_COMPILER */ # endif # endif # ifdef MSWIN32 /* FIXME: This is a very partial guess. There is no port, yet. */ # ifdefined(_WIN64) # define CPP_WORDSZ 64 # else # define CPP_WORDSZ 32/* Is this possible? */ # endif # define ALIGNMENT 8 # endif # endif
#ifdefined(LINUX_STACKBOTTOM) && defined(NO_PROC_STAT) \
&& !defined(USE_LIBC_PRIVATES) /* This combination will fail, since we have no way to get */ /* the stack bottom. Use HEURISTIC2 instead. */ # undef LINUX_STACKBOTTOM # define HEURISTIC2 /* This may still fail on some architectures like IA64. */ /* We tried ... */ #endif
#ifdefined(USE_MMAP_ANON) && !defined(USE_MMAP) # define USE_MMAP 1 #elif (defined(LINUX) || defined(OPENBSD)) && defined(USE_MMAP) /* The kernel may do a somewhat better job merging mappings etc. */ /* with anonymous mappings. */ # define USE_MMAP_ANON #endif
#ifdefined(GC_LINUX_THREADS) && defined(REDIRECT_MALLOC) \
&& !defined(USE_PROC_FOR_LIBRARIES) /* 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
#ifdefined(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(NO_MARKER_SPECIAL_SIGMASK) \
&& (defined(NACL) || defined(GC_WIN32_PTHREADS)) /* Either there is no pthread_sigmask(), or GC marker thread cannot */ /* steal and drop user signal calls. */ # define NO_MARKER_SPECIAL_SIGMASK #endif
#ifdef GC_NETBSD_THREADS # define SIGRTMIN 33 # define SIGRTMAX 63 /* It seems to be necessary to wait until threads have restarted. */ /* But it is unclear why that is the case. */ # define GC_NETBSD_THREADS_WORKAROUND #endif
#ifdef GC_OPENBSD_THREADS
EXTERN_C_END # include <sys/param.h>
EXTERN_C_BEGIN /* Prior to 5.2 release, OpenBSD had user threads and required */ /* special handling. */ # if OpenBSD < 201211 # define GC_OPENBSD_UTHREADS 1 # endif #endif/* GC_OPENBSD_THREADS */
/* Xbox One (DURANGO) may not need to be this aggressive, but the */
/* default is likely too lax under heavy allocation pressure. */
/* The platform does not have a virtual paging system, so it does not */
/* have a large virtual address space that a standard x64 platform has. */
#if defined(USE_MUNMAP) && !defined(MUNMAP_THRESHOLD) \
&& (defined(SN_TARGET_PS3) \
|| defined(SN_TARGET_PSP2) || defined(MSWIN_XBOX1))
# define MUNMAP_THRESHOLD 2
#endif
#if defined(USE_MUNMAP) && defined(COUNT_UNMAPPED_REGIONS) \
&& !defined(GC_UNMAPPED_REGIONS_SOFT_LIMIT)
/* The default limit of vm.max_map_count on Linux is ~65530. */
/* There is approximately one mapped region to every unmapped region. */
/* Therefore if we aim to use up to half of vm.max_map_count for the */
/* GC (leaving half for the rest of the process) then the number of */
/* unmapped regions should be one quarter of vm.max_map_count. */
# if defined(__DragonFly__)
# define GC_UNMAPPED_REGIONS_SOFT_LIMIT (1000000 / 4)
# else
# define GC_UNMAPPED_REGIONS_SOFT_LIMIT 16384
# endif
#endif
#if defined(BASE_ATOMIC_OPS_EMULATED)
/* GC_write_fault_handler() cannot use lock-based atomic primitives */
/* as this could lead to a deadlock. */
# undef MPROTECT_VDB
#endif
#if defined(USE_PROC_FOR_LIBRARIES) && defined(GC_LINUX_THREADS)
/* Incremental GC based on mprotect is incompatible with /proc roots. */
# undef MPROTECT_VDB
#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 */
/* call GC_register_dynamic_libraries before stopping the world. */
/* For performance reasons, this may be beneficial on other */
/* platforms as well, though it should be avoided in win32. */
#endif /* LINUX */
#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(MSWIN32) || defined(MSWINCE)) && !defined(__GNUC__)) \
|| (defined(MSWIN32) && defined(I386)) /* for Win98 */ \
|| (defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS))) \
&& !defined(NO_CRT) && !defined(NO_WRAP_MARK_SOME)
/* Under rare conditions, we may end up marking from nonexistent */
/* memory. Hence we need to be prepared to recover by running */
/* GC_mark_some with a suitable handler in place. */
/* TODO: Probably replace __GNUC__ above with ndef GC_PTHREADS. */
/* FIXME: Should we really need it for WinCE? If yes then */
/* WRAP_MARK_SOME should be also defined for CeGCC which requires */
/* CPU/OS-specific code in mark_ex_handler and GC_mark_some (for */
/* manual stack unwinding and exception handler installation). */
# define WRAP_MARK_SOME
#endif
#if defined(PARALLEL_MARK) && !defined(DEFAULT_STACK_MAYBE_SMALL) \
&& (defined(HPUX) || defined(GC_DGUX386_THREADS) \
|| defined(NO_GETCONTEXT) /* e.g. musl */)
/* TODO: Test default stack size in configure. */
# define DEFAULT_STACK_MAYBE_SMALL
#endif
#ifdef PARALLEL_MARK
/* The minimum stack size for a marker thread. */
# define MIN_STACK_SIZE (8 * HBLKSIZE * sizeof(word))
#endif
#if defined(HOST_ANDROID) && !defined(THREADS) \
&& !defined(USE_GET_STACKBASE_FOR_MAIN)
/* Always use pthread_attr_getstack on Android ("-lpthread" option is */
/* not needed to be specified manually) since GC_linux_main_stack_base */
/* causes app crash if invoked inside Dalvik VM. */
# define USE_GET_STACKBASE_FOR_MAIN
#endif
#if defined(UNIX_LIKE) && defined(THREADS) && !defined(NO_CANCEL_SAFE) \
&& !defined(HOST_ANDROID)
/* Make the code cancellation-safe. This basically means that we */
/* ensure that cancellation requests are ignored while we are in */
/* the collector. This applies only to Posix deferred cancellation; */
/* we don't handle Posix asynchronous cancellation. */
/* Note that this only works if pthread_setcancelstate is */
/* async-signal-safe, at least in the absence of asynchronous */
/* cancellation. This appears to be true for the glibc version, */
/* though it is not documented. Without that assumption, there */
/* seems to be no way to safely wait in a signal handler, which */
/* we need to do for thread suspension. */
/* Also note that little other code appears to be cancellation-safe. */
/* Hence it may make sense to turn this off for performance. */
# define CANCEL_SAFE
#endif
#if !defined(MSGBOX_ON_ERROR) && !defined(NO_MSGBOX_ON_ERROR) \
&& !defined(SMALL_CONFIG) && defined(MSWIN32) \
&& !defined(MSWINRT_FLAVOR) && !defined(MSWIN_XBOX1)
/* Show Windows message box with "OK" button on a GC fatal error. */
/* Client application is terminated once the user clicks the button. */
# define MSGBOX_ON_ERROR
#endif
#if defined(SPARC)
# define ASM_CLEAR_CODE /* Stack clearing is crucial, and we */
/* include assembly code to do it well. */
#endif
/* Can we save call chain in objects for debugging? */
/* SET NFRAMES (# of saved frames) and NARGS (#of args for each */
/* frame) to reasonable values for the platform. */
/* Set SAVE_CALL_CHAIN if we can. SAVE_CALL_COUNT can be specified */
/* at build time, though we feel free to adjust it slightly. */
/* Define NEED_CALLINFO if we either save the call stack or */
/* GC_ADD_CALLER is defined. */
/* GC_CAN_SAVE_CALL_STACKS is set in gc.h. */
#if defined(SPARC)
# define CAN_SAVE_CALL_ARGS
#endif
#if (defined(I386) || defined(X86_64)) \
&& (defined(LINUX) || defined(__GLIBC__))
/* SAVE_CALL_CHAIN is supported if the code is compiled to save */
/* frame pointers by default, i.e. no -fomit-frame-pointer flag. */
# define CAN_SAVE_CALL_ARGS
#endif
#if defined(SAVE_CALL_COUNT) && !defined(GC_ADD_CALLER) \
&& defined(GC_CAN_SAVE_CALL_STACKS)
# define SAVE_CALL_CHAIN
#endif
#ifdef SAVE_CALL_CHAIN
# if defined(SAVE_CALL_NARGS) && defined(CAN_SAVE_CALL_ARGS)
# define NARGS SAVE_CALL_NARGS
# else
# define NARGS 0 /* Number of arguments to save for each call. */
# endif
#endif
#ifdef SAVE_CALL_CHAIN
# if !defined(SAVE_CALL_COUNT) || defined(CPPCHECK)
# define NFRAMES 6 /* Number of frames to save. Even for */
/* alignment reasons. */
# else
# define NFRAMES ((SAVE_CALL_COUNT + 1) & ~1)
# endif
# define NEED_CALLINFO
#endif /* SAVE_CALL_CHAIN */
#ifdef GC_ADD_CALLER
# define NFRAMES 1
# define NARGS 0
# define NEED_CALLINFO
#endif
/* Some static sanity tests. */
#if !defined(CPPCHECK)
# 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 defined
# endif
# if !defined(STACK_GROWS_UP) && !defined(STACK_GROWS_DOWN)
# error One of STACK_GROWS_UP and STACK_GROWS_DOWN should be defined
# endif
# if defined(REDIRECT_MALLOC) && defined(THREADS) && !defined(LINUX) \
&& !defined(REDIRECT_MALLOC_IN_HEADER)
# error REDIRECT_MALLOC with THREADS works at most on Linux
# endif
#endif /* !CPPCHECK */
#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 unintended recursion with */
/* REDIRECT_MALLOC macro defined. */
/* GET_MEM() argument should be of size_t type and have */
/* no side-effect. GET_MEM() returns HBLKSIZE-aligned chunk; */
/* 0 is taken to mean failure. */
/* In case of MMAP_SUPPORTED, the argument must also be */
/* a multiple of a physical page size. */
/* GET_MEM is currently not assumed to retrieve 0 filled space, */
/* though we should perhaps take advantage of the case in which */
/* does. */
struct hblk; /* See gc_priv.h. */
# if defined(PCR)
char * real_malloc(size_t bytes);
# define GET_MEM(bytes) HBLKPTR(real_malloc(SIZET_SAT_ADD(bytes, \
GC_page_size)) \
+ GC_page_size-1)
# elif defined(OS2)
void * os2_alloc(size_t bytes);
# define GET_MEM(bytes) HBLKPTR((ptr_t)os2_alloc( \
SIZET_SAT_ADD(bytes, \
GC_page_size)) \
+ GC_page_size-1)
# elif defined(NEXT) || defined(DOS4GW) || defined(NONSTOP) \
|| (defined(AMIGA) && !defined(GC_AMIGA_FASTALLOC)) \
|| (defined(SOLARIS) && !defined(USE_MMAP)) || defined(RTEMS) \
|| defined(__CC_ARM)
# define GET_MEM(bytes) HBLKPTR((size_t)calloc(1, \
SIZET_SAT_ADD(bytes, \
GC_page_size)) \
+ GC_page_size - 1)
# elif defined(MSWIN_XBOX1)
ptr_t GC_durango_get_mem(size_t bytes);
# define GET_MEM(bytes) (struct hblk *)GC_durango_get_mem(bytes)
# elif defined(MSWIN32) || defined(CYGWIN32)
ptr_t GC_win32_get_mem(size_t bytes);
# define GET_MEM(bytes) (struct hblk *)GC_win32_get_mem(bytes)
# elif defined(MACOS)
# if defined(USE_TEMPORARY_MEMORY)
Ptr GC_MacTemporaryNewPtr(size_t size, Boolean clearMemory);
# define GET_MEM(bytes) HBLKPTR(GC_MacTemporaryNewPtr( \
SIZET_SAT_ADD(bytes, \
GC_page_size), true) \
+ GC_page_size-1)
# else
# define GET_MEM(bytes) HBLKPTR(NewPtrClear(SIZET_SAT_ADD(bytes, \
GC_page_size)) \
+ GC_page_size-1)
# endif
# elif defined(MSWINCE)
ptr_t GC_wince_get_mem(size_t bytes);
# define GET_MEM(bytes) (struct hblk *)GC_wince_get_mem(bytes)
# elif defined(AMIGA) && defined(GC_AMIGA_FASTALLOC)
void *GC_amiga_get_mem(size_t bytes);
# define GET_MEM(bytes) HBLKPTR((size_t)GC_amiga_get_mem( \
SIZET_SAT_ADD(bytes, \
GC_page_size)) \
+ GC_page_size-1)
# elif defined(PLATFORM_GETMEM)
void *platform_get_mem(size_t bytes);
# define GET_MEM(bytes) (struct hblk*)platform_get_mem(bytes)
# elif defined(SN_TARGET_PS3)
void *ps3_get_mem(size_t bytes);
# define GET_MEM(bytes) (struct hblk*)ps3_get_mem(bytes)
# elif defined(SN_TARGET_PSP2)
void *psp2_get_mem(size_t bytes);
# define GET_MEM(bytes) (struct hblk*)psp2_get_mem(bytes)
# elif defined(NINTENDO_SWITCH)
void *switch_get_mem(size_t bytes);
# define GET_MEM(bytes) (struct hblk*)switch_get_mem(bytes)
# elif defined(HAIKU)
ptr_t GC_haiku_get_mem(size_t bytes);
# define GET_MEM(bytes) (struct hblk*)GC_haiku_get_mem(bytes)
# elif defined(EMSCRIPTEN_TINY)
void *emmalloc_memalign(size_t alignment, size_t size);
# define GET_MEM(bytes) (struct hblk*)emmalloc_memalign(GC_page_size, bytes)
# else
ptr_t GC_unix_get_mem(size_t bytes);
# define GET_MEM(bytes) (struct hblk *)GC_unix_get_mem(bytes)
# endif
#endif /* GC_PRIVATE_H */
EXTERN_C_END
#endif /* GCCONFIG_H */
Messung V0.5 in Prozent
¤ 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.0.69Bemerkung:
(vorverarbeitet am 2026-09-11)
¤
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.