* 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 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.
-/* 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. */
+/* 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. */
- /* 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, other variants) */
- /* 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) */
- /* M88K ==> Motorola 88XX0 */
- /* (CX_UX and DGUX) */
- /* S370 ==> 370-like machine */
- /* running Amdahl UTS4 */
+ /* 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, other variants) */
+ /* 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) */
+ /* M88K ==> Motorola 88XX0 */
+ /* (CX_UX and DGUX) */
+ /* S370 ==> 370-like machine */
+ /* running Amdahl UTS4 */
- /* running LINUX */
- /* ARM32 ==> Intel StrongARM */
- /* 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. */
- /* CRIS ==> Axis Etrax */
- /* M32R ==> Renesas M32R */
+ /* running LINUX */
+ /* ARM32 ==> Intel StrongARM */
+ /* 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. */
+ /* CRIS ==> Axis Etrax */
+ /* M32R ==> Renesas M32R */
* 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
* 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
* For each machine, the following should:
* 1) define STACK_GROWS_UP if the stack grows toward higher addresses, and
* 2) define exactly one of
* For each machine, the following should:
* 1) define STACK_GROWS_UP if the stack grows toward higher addresses, and
* 2) define exactly one of
* 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
* 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
* 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
* 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
- * 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
- * to the nearest plausible page boundary, and use that instead
- * of STACKBOTTOM.
+ * 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.
* 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
* 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
-# define OS_TYPE "OPENBSD"
-# define HEURISTIC2
-# ifdef __ELF__
-# define DATASTART GC_data_start
-# define DYNAMIC_LOADING
-# else
- extern char etext[];
-# define DATASTART ((ptr_t)(etext))
+ /* FIXME: Should we remove this case? */
+# define OS_TYPE "OPENBSD"
+# define HEURISTIC2
+# ifdef __ELF__
+# define DATASTART GC_data_start
+# define DYNAMIC_LOADING
+# else
+ extern char etext[];
+# define DATASTART ((ptr_t)(etext))
-# define OS_TYPE "NETBSD"
-# define HEURISTIC2
-# ifdef __ELF__
-# define DATASTART GC_data_start
-# define DYNAMIC_LOADING
-# else
- extern char etext[];
-# define DATASTART ((ptr_t)(etext))
+# define OS_TYPE "NETBSD"
+# define HEURISTIC2
+# ifdef __ELF__
+# define DATASTART GC_data_start
+# define DYNAMIC_LOADING
+# else
+ extern char etext[];
+# define DATASTART ((ptr_t)(etext))
-# define OS_TYPE "AMIGA"
- /* STACKBOTTOM and DATASTART handled specially */
- /* in os_dep.c */
-# define DATAEND /* not needed */
-# define GETPAGESIZE() 4096
+# define OS_TYPE "AMIGA"
+ /* STACKBOTTOM and DATASTART handled specially */
+ /* in os_dep.c */
+# define DATAEND /* not needed */
+# define GETPAGESIZE() 4096
- /* The performance impact of prefetches is untested */
-# define PREFETCH(x) \
- __asm__ __volatile__ ("dcbt 0,%0" : : "r" ((const void *) (x)))
-# define PREFETCH_FOR_WRITE(x) \
- __asm__ __volatile__ ("dcbtst 0,%0" : : "r" ((const void *) (x)))
+ /* The performance impact of prefetches is untested */
+# define PREFETCH(x) \
+ __asm__ __volatile__ ("dcbt 0,%0" : : "r" ((const void *) (x)))
+# define PREFETCH_FOR_WRITE(x) \
+ __asm__ __volatile__ ("dcbtst 0,%0" : : "r" ((const void *) (x)))
+# ifdef OPENBSD
+# define OS_TYPE "OPENBSD"
+# define ALIGNMENT 4
+# ifdef GC_OPENBSD_THREADS
+# define UTHREAD_SP_OFFSET 268
+# else
+# include <sys/param.h>
+# include <uvm/uvm_extern.h>
+# define STACKBOTTOM USRSTACK
+# endif
+ extern int __data_start[];
+# define DATASTART ((ptr_t)__data_start)
+ extern char _end[];
+# define DATAEND ((ptr_t)(&_end))
+# define DYNAMIC_LOADING
+# endif
- /* 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.
- */
+ /* 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.
+ */
-# define DATAEND (_end)
-# if !defined(USE_MMAP) && defined(REDIRECT_MALLOC)
-# define USE_MMAP
- /* 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
+# 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 */
+ /* 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
-# define PROC_VDB
-/* HEURISTIC1 reportedly no longer works under 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: */
+# define PROC_VDB
+/* HEURISTIC1 reportedly no longer works under 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: */
-# define STACKBOTTOM ((ptr_t) 0xf8000000)
- extern int etext[];
-# define DATASTART ((ptr_t)(etext))
+# ifdef GC_OPENBSD_THREADS
+# define UTHREAD_SP_OFFSET 232
+# else
+# include <sys/param.h>
+# include <uvm/uvm_extern.h>
+# define STACKBOTTOM USRSTACK
+# endif
+ extern int __data_start[];
+# define DATASTART ((ptr_t)__data_start)
+ extern char _end[];
+# define DATAEND ((ptr_t)(&_end))
+# define DYNAMIC_LOADING
-# define OS_TYPE "FREEBSD"
-# define SIG_SUSPEND SIGUSR1
-# define SIG_THR_RESTART SIGUSR2
-# define FREEBSD_STACKBOTTOM
-# ifdef __ELF__
-# define DYNAMIC_LOADING
-# endif
- extern char etext[];
- extern char edata[];
- extern char end[];
-# define NEED_FIND_LIMIT
-# define DATASTART ((ptr_t)(&etext))
-# define DATAEND (GC_find_limit (DATASTART, TRUE))
-# define DATASTART2 ((ptr_t)(&edata))
-# define DATAEND2 ((ptr_t)(&end))
+# define OS_TYPE "FREEBSD"
+# define SIG_SUSPEND SIGUSR1
+# define SIG_THR_RESTART SIGUSR2
+# define FREEBSD_STACKBOTTOM
+# ifdef __ELF__
+# define DYNAMIC_LOADING
+# endif
+ extern char etext[];
+ extern char edata[];
+ extern char end[];
+# define NEED_FIND_LIMIT
+# define DATASTART ((ptr_t)(&etext))
+# define DATAEND (GC_find_limit (DATASTART, TRUE))
+# define DATASTART2 ((ptr_t)(&edata))
+# define DATAEND2 ((ptr_t)(&end))
-# define DATAEND (_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. */
+# 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. */
-/* It appears to be fixed in 2.8 and 2.9. */
-# ifdef SOLARIS25_PROC_VDB_BUG_FIXED
-# define PROC_VDB
-# endif
-# define DYNAMIC_LOADING
-# if !defined(USE_MMAP) && defined(REDIRECT_MALLOC)
-# define USE_MMAP
- /* 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
+/* It appears to be fixed in 2.8 and 2.9. */
+# ifdef SOLARIS25_PROC_VDB_BUG_FIXED
+# define PROC_VDB
+# endif
+# define DYNAMIC_LOADING
+# if !defined(USE_MMAP) && defined(REDIRECT_MALLOC)
+# define USE_MMAP
+ /* 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
-# define OS_TYPE "DGUX"
- 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 STACK_GROWS_DOWN
-# define HEURISTIC2
-# include <unistd.h>
-# define GETPAGESIZE() sysconf(_SC_PAGESIZE)
-# define DYNAMIC_LOADING
-# ifndef USE_MMAP
-# define USE_MMAP
-# endif /* USE_MMAP */
-# define MAP_FAILED (void *) -1
-# ifdef USE_MMAP
-# define HEAP_START (ptr_t)0x40000000
-# else /* USE_MMAP */
-# define HEAP_START DATAEND
-# endif /* USE_MMAP */
+# define OS_TYPE "DGUX"
+ extern int _etext, _end;
+ 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>
+# define GETPAGESIZE() sysconf(_SC_PAGESIZE)
+# define DYNAMIC_LOADING
+# ifndef USE_MMAP
+# define USE_MMAP
+# endif
+# define MAP_FAILED (void *) ((word)-1)
+# ifdef USE_MMAP
+# define HEAP_START (ptr_t)0x40000000
+# else /* USE_MMAP */
+# define HEAP_START DATAEND
+# endif /* USE_MMAP */
- /* STACKBOTTOM is usually 0xc0000000, but this changes with */
- /* different kernel configurations. In particular, systems */
- /* with 2GB physical memory will usually move the user */
- /* address space limit, and hence initial SP to 0x80000000. */
+ /* STACKBOTTOM is usually 0xc0000000, but this changes with */
+ /* different kernel configurations. In particular, systems */
+ /* with 2GB physical memory will usually move the user */
+ /* address space limit, and hence initial SP to 0x80000000. */
-# define MPROTECT_VDB
-# else
- /* We seem to get random errors in incremental mode, */
- /* possibly because Linux threads is itself a malloc client */
- /* and can't deal with the signals. */
-# endif
-# define HEAP_START (ptr_t)0x1000
- /* This encourages mmap to give us low addresses, */
- /* thus allowing the heap to grow to ~3GB */
+# define MPROTECT_VDB
+# else
+ /* We seem to get random errors in incremental mode, */
+ /* possibly because Linux threads is itself a malloc client */
+ /* and can't deal with the signals. */
+# endif
+# define HEAP_START (ptr_t)0x1000
+ /* This encourages mmap to give us low addresses, */
+ /* thus allowing the heap to grow to ~3GB */
- /* 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
- extern int _end[];
-# define DATAEND (_end)
-# else
- extern int etext[];
+ /* 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
+ extern int _end[];
+# define DATAEND (ptr_t)(_end)
+# else
+ extern int etext[];
-# ifdef USE_I686_PREFETCH
- /* FIXME: Thus should use __builtin_prefetch, but we'll leave that */
- /* for the next rtelease. */
-# 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 */
- /* seems to interfere enough with other cache traffic that the net */
- /* result is worse than prefetchnta. */
-# if 0
- /* Using prefetches for write seems to have a slight negative */
- /* impact on performance, at least for a PIII/500. */
-# define PREFETCH_FOR_WRITE(x) \
- __asm__ __volatile__ (" prefetcht0 %0": : "m"(*(char *)(x)))
-# endif
-# endif
-# ifdef USE_3DNOW_PREFETCH
-# define PREFETCH(x) \
- __asm__ __volatile__ (" prefetch %0": : "m"(*(char *)(x)))
-# define PREFETCH_FOR_WRITE(x) \
- __asm__ __volatile__ (" prefetchw %0": : "m"(*(char *)(x)))
-# endif
+# ifdef USE_I686_PREFETCH
+ /* FIXME: Thus should use __builtin_prefetch, but we'll leave that */
+ /* for the next rtelease. */
+# 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. */
+# if 0
+ /* Using prefetches for write seems to have a slight negative */
+ /* impact on performance, at least for a PIII/500. */
+# define PREFETCH_FOR_WRITE(x) \
+ __asm__ __volatile__ (" prefetcht0 %0": : "m"(*(char *)(x)))
+# endif
+# endif
+# ifdef USE_3DNOW_PREFETCH
+# define PREFETCH(x) \
+ __asm__ __volatile__ (" prefetch %0": : "m"(*(char *)(x)))
+# define PREFETCH_FOR_WRITE(x) \
+ __asm__ __volatile__ (" prefetchw %0": : "m"(*(char *)(x)))
+# 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 OS_TYPE "MSWIN32"
+ /* STACKBOTTOM and DATASTART are handled specially in */
+ /* os_dep.c. */
+# define MPROTECT_VDB
+# define GWW_VDB
-# define OS_TYPE "OPENBSD"
+# define OS_TYPE "OPENBSD"
+# ifdef GC_OPENBSD_THREADS
+# define UTHREAD_SP_OFFSET 176
+# else
+# include <sys/param.h>
+# include <uvm/uvm_extern.h>
+# define STACKBOTTOM USRSTACK
+# endif
+ extern int __data_start[];
+# define DATASTART ((ptr_t)__data_start)
+ extern char _end[];
+# define DATAEND ((ptr_t)(&_end))
+# define DYNAMIC_LOADING
-# define OS_TYPE "FREEBSD"
-# ifndef GC_FREEBSD_THREADS
-# define MPROTECT_VDB
-# endif
-# ifdef __GLIBC__
-# define SIG_SUSPEND (32+6)
-# define SIG_THR_RESTART (32+5)
- extern int _end[];
-# define DATAEND (_end)
-# else
-# define SIG_SUSPEND SIGUSR1
-# define SIG_THR_RESTART SIGUSR2
-# endif
-# define FREEBSD_STACKBOTTOM
-# ifdef __ELF__
-# define DYNAMIC_LOADING
-# endif
- extern char etext[];
- extern char * GC_FreeBSDGetDataStart(size_t, ptr_t);
-# define DATASTART GC_FreeBSDGetDataStart(0x1000, (ptr_t)etext)
+# define OS_TYPE "FREEBSD"
+# ifndef GC_FREEBSD_THREADS
+# define MPROTECT_VDB
+# endif
+# ifdef __GLIBC__
+# define SIG_SUSPEND (32+6)
+# define SIG_THR_RESTART (32+5)
+ extern int _end[];
+# define DATAEND (ptr_t)(_end)
+# else
+# define SIG_SUSPEND SIGUSR1
+# define SIG_THR_RESTART SIGUSR2
+# endif
+# define FREEBSD_STACKBOTTOM
+# ifdef __ELF__
+# define DYNAMIC_LOADING
+# endif
+ extern char etext[];
+ char * GC_FreeBSDGetDataStart(size_t, ptr_t);
+# define DATASTART GC_FreeBSDGetDataStart(0x1000, (ptr_t)etext)
- /* 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. */
+ /* 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. */
- /* Lowest plausible heap address. */
- /* In the MMAP case, we map there. */
- /* In either case it is used to identify */
- /* heap sections so they're not */
- /* considered as roots. */
-# define OS_TYPE "IRIX5"
+ /* Lowest plausible heap address. */
+ /* In the MMAP case, we map there. */
+ /* In either case it is used to identify */
+ /* heap sections so they're not */
+ /* considered as roots. */
+# define OS_TYPE "IRIX5"
+# ifdef OPENBSD
+# define OS_TYPE "OPENBSD"
+# define ALIGNMENT 4
+# ifdef GC_OPENBSD_THREADS
+# define UTHREAD_SP_OFFSET 808
+# else
+# include <sys/param.h>
+# include <uvm/uvm_extern.h>
+# define STACKBOTTOM USRSTACK
+# endif
+ extern int _fdata[];
+# define DATASTART ((ptr_t)_fdata)
+ extern char _end[];
+# define DATAEND ((ptr_t)(&_end))
+# define DYNAMIC_LOADING
+# endif
- /* 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.) */
+ /* 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.) */
- /* Gustavo Rodriguez-Rivera suggested changing HEURISTIC2 */
- /* to this. Note that the GC must be initialized before the */
- /* first putenv call. */
- extern char ** environ;
+ /* Gustavo Rodriguez-Rivera suggested changing HEURISTIC2 */
+ /* to this. Note that the GC must be initialized before the */
+ /* first putenv call. */
+ extern char ** environ;
+# ifdef OPENBSD
+# define OS_TYPE "OPENBSD"
+# ifdef GC_OPENBSD_THREADS
+# define UTHREAD_SP_OFFSET 520
+# else
+# include <sys/param.h>
+# include <uvm/uvm_extern.h>
+# define STACKBOTTOM USRSTACK
+# endif
+ extern int __data_start[];
+# define DATASTART ((ptr_t)__data_start)
+ extern char _end[];
+# define DATAEND ((ptr_t)(&_end))
+# define DYNAMIC_LOADING
+# endif
-# define OS_TYPE "OPENBSD"
-# define HEURISTIC2
-# ifdef __ELF__ /* since OpenBSD/Alpha 2.9 */
-# define DATASTART GC_data_start
-# define ELFCLASS32 32
-# define ELFCLASS64 64
-# define ELF_CLASS ELFCLASS64
-# else /* ECOFF, until OpenBSD/Alpha 2.7 */
-# define DATASTART ((ptr_t) 0x140000000)
-# endif
+# define OS_TYPE "OPENBSD"
+# define ELF_CLASS ELFCLASS64
+# ifdef GC_OPENBSD_THREADS
+# define UTHREAD_SP_OFFSET 816
+# else
+# include <sys/param.h>
+# include <uvm/uvm_extern.h>
+# define STACKBOTTOM USRSTACK
+# endif
+ extern int __data_start[];
+# define DATASTART ((ptr_t)__data_start)
+ extern char _end[];
+# define DATAEND ((ptr_t)(&_end))
+# define DYNAMIC_LOADING
-# define SIG_SUSPEND SIGUSR1
-# define SIG_THR_RESTART SIGUSR2
-# define FREEBSD_STACKBOTTOM
-# ifdef __ELF__
-# define DYNAMIC_LOADING
-# endif
+# define SIG_SUSPEND SIGUSR1
+# define SIG_THR_RESTART SIGUSR2
+# define FREEBSD_STACKBOTTOM
+# ifdef __ELF__
+# define DYNAMIC_LOADING
+# endif
- extern char etext[];
- extern char edata[];
- extern char end[];
-# define NEED_FIND_LIMIT
-# define DATASTART ((ptr_t)(&etext))
-# define DATAEND (GC_find_limit (DATASTART, TRUE))
-# define DATASTART2 ((ptr_t)(&edata))
-# define DATAEND2 ((ptr_t)(&end))
+ extern char etext[];
+ extern char edata[];
+ extern char end[];
+# define NEED_FIND_LIMIT
+# define DATASTART ((ptr_t)(&etext))
+# define DATAEND (GC_find_limit (DATASTART, TRUE))
+# define DATASTART2 ((ptr_t)(&edata))
+# define DATAEND2 ((ptr_t)(&end))
-# define OS_TYPE "OSF1"
-# define DATASTART ((ptr_t) 0x140000000)
- extern int _end[];
-# define DATAEND ((ptr_t) &_end)
- extern char ** environ;
- /* 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 conervative, since */
- /* the text segment immediately follows the stack. */
- /* Hence we give an upper pound. */
- /* This is currently unused, since we disabled HEURISTIC2 */
- extern int __start[];
-# define HEURISTIC2_LIMIT ((ptr_t)((word)(__start) & ~(getpagesize()-1)))
-# ifndef GC_OSF1_THREADS
- /* Unresolved signal issues with threads. */
-# define MPROTECT_VDB
+# define OS_TYPE "OSF1"
+# define DATASTART ((ptr_t) 0x140000000)
+ extern int _end[];
+# define DATAEND ((ptr_t) &_end)
+ extern char ** environ;
+ /* 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 */
+ extern int __start[];
+# define HEURISTIC2_LIMIT ((ptr_t)((word)(__start) & ~(getpagesize()-1)))
+# ifndef GC_OSF1_THREADS
+ /* Unresolved signal issues with threads. */
+# define MPROTECT_VDB
- /* Gustavo Rodriguez-Rivera suggested changing HEURISTIC2 */
- /* to this. Note that the GC must be initialized before the */
- /* first putenv call. */
- extern char ** environ;
+ /* Gustavo Rodriguez-Rivera suggested changing HEURISTIC2 */
+ /* to this. Note that the GC must be initialized before the */
+ /* first putenv call. */
+ extern char ** environ;
- /* 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!!! */
+ /* 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!!! */
-# else
- /* In the Intel compiler environment, we seem to end up with */
- /* statically linked executables and an undefined reference */
- /* to _DYNAMIC */
-# endif
-# define MPROTECT_VDB
- /* Requires Linux 2.3.47 or later. */
- extern int _end[];
-# define DATAEND (_end)
+# else
+ /* In the Intel compiler environment, we seem to end up with */
+ /* statically linked executables and an undefined reference */
+ /* to _DYNAMIC */
+# endif
+# define MPROTECT_VDB
+ /* Requires Linux 2.3.47 or later. */
+ extern int _end[];
+# define DATAEND (ptr_t)(_end)
-# ifndef __INTEL_COMPILER
-# define PREFETCH(x) \
- __asm__ (" lfetch [%0]": : "r"(x))
-# define PREFETCH_FOR_WRITE(x) \
- __asm__ (" lfetch.excl [%0]": : "r"(x))
-# define CLEAR_DOUBLE(x) \
- __asm__ (" stf.spill [%0]=f0": : "r"((void *)(x)))
-# else
+# ifndef __INTEL_COMPILER
+# define PREFETCH(x) \
+ __asm__ (" lfetch [%0]": : "r"(x))
+# define PREFETCH_FOR_WRITE(x) \
+ __asm__ (" lfetch.excl [%0]": : "r"(x))
+# define CLEAR_DOUBLE(x) \
+ __asm__ (" stf.spill [%0]=f0": : "r"((void *)(x)))
+# else
-# define PREFETCH(x) \
- __lfetch(__lfhint_none, (x))
-# define PREFETCH_FOR_WRITE(x) \
- __lfetch(__lfhint_nta, (x))
-# define CLEAR_DOUBLE(x) \
- __stf_spill((void *)(x), 0)
-# endif /* __INTEL_COMPILER */
+# define PREFETCH(x) \
+ __lfetch(__lfhint_none, (x))
+# define PREFETCH_FOR_WRITE(x) \
+ __lfetch(__lfhint_nta, (x))
+# define CLEAR_DOUBLE(x) \
+ __stf_spill((void *)(x), 0)
+# endif /* __INTEL_COMPILER */
- /* 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
- extern int _end[];
-# define DATAEND (_end)
-# else
- extern int etext[];
+ /* 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
+ extern int _end[];
+# define DATAEND (ptr_t)(_end)
+# else
+ extern int etext[];
+# 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
+# ifndef USE_MMAP
+# define USE_MMAP
+# endif
+# define USE_MMAP_ANON
+# endif
+# ifdef OPENBSD
+# define ALIGNMENT 4
+# define OS_TYPE "OPENBSD"
+# ifdef GC_OPENBSD_THREADS
+# define UTHREAD_SP_OFFSET 176
+# else
+# include <sys/param.h>
+# include <uvm/uvm_extern.h>
+# define STACKBOTTOM USRSTACK
+# endif
+ extern int __data_start[];
+# define DATASTART ((ptr_t)__data_start)
+ extern char _end[];
+# define DATAEND ((ptr_t)(&_end))
+# define DYNAMIC_LOADING
+# endif
+# ifdef OPENBSD
+# define OS_TYPE "OPENBSD"
+# ifdef GC_OPENBSD_THREADS
+# define UTHREAD_SP_OFFSET 332
+# else
+# include <sys/param.h>
+# include <uvm/uvm_extern.h>
+# define STACKBOTTOM USRSTACK
+# endif
+ extern int __data_start[];
+# define DATASTART ((ptr_t)__data_start)
+ extern char _end[];
+# define DATAEND ((ptr_t)(&_end))
+# define DYNAMIC_LOADING
+# endif
+# ifdef OPENBSD
+# define OS_TYPE "OPENBSD"
+# define ELF_CLASS ELFCLASS64
+# ifdef GC_OPENBSD_THREADS
+# define UTHREAD_SP_OFFSET 400
+# else
+# include <sys/param.h>
+# include <uvm/uvm_extern.h>
+# define STACKBOTTOM USRSTACK
+# endif
+ extern int __data_start[];
+# define DATASTART ((ptr_t)__data_start)
+ extern char _end[];
+# define DATAEND ((ptr_t)(&_end))
+# define DYNAMIC_LOADING
+# endif
-# define MPROTECT_VDB
-# else
- /* We seem to get random errors in incremental mode, */
- /* possibly because Linux threads is itself a malloc client */
- /* and can't deal with the signals. */
-# endif
+# define MPROTECT_VDB
+# else
+ /* We seem to get random errors in incremental mode, */
+ /* possibly because Linux threads is itself a malloc client */
+ /* and can't deal with the signals. */
+# endif
-# define OS_TYPE "FREEBSD"
-# ifndef GC_FREEBSD_THREADS
-# define MPROTECT_VDB
-# endif
-# ifdef __GLIBC__
-# define SIG_SUSPEND (32+6)
-# define SIG_THR_RESTART (32+5)
- extern int _end[];
-# define DATAEND (_end)
-# else
-# define SIG_SUSPEND SIGUSR1
-# define SIG_THR_RESTART SIGUSR2
-# endif
-# define FREEBSD_STACKBOTTOM
-# ifdef __ELF__
-# define DYNAMIC_LOADING
-# endif
- extern char etext[];
- extern char * GC_FreeBSDGetDataStart();
-# define DATASTART GC_FreeBSDGetDataStart(0x1000, &etext)
+# define OS_TYPE "FREEBSD"
+# ifndef GC_FREEBSD_THREADS
+# define MPROTECT_VDB
+# endif
+# ifdef __GLIBC__
+# define SIG_SUSPEND (32+6)
+# define SIG_THR_RESTART (32+5)
+ extern int _end[];
+# define DATAEND (ptr_t)(_end)
+# else
+# define SIG_SUSPEND SIGUSR1
+# define SIG_THR_RESTART SIGUSR2
+# endif
+# define FREEBSD_STACKBOTTOM
+# ifdef __ELF__
+# define DYNAMIC_LOADING
+# endif
+ extern char etext[];
+ ptr_t GC_FreeBSDGetDataStart(size_t max_page_size, ptr_t etext_addr);
+# define DATASTART GC_FreeBSDGetDataStart(0x1000, &etext)
-# define DATAEND (_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. */
-/* Apparently USRSTACK is defined to be USERLIMIT, but in some */
-/* installations that's undefined. We work around this with a */
-/* gross hack: */
+# 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. */
+/* Apparently USRSTACK is defined to be USERLIMIT, but in some */
+/* installations that's undefined. We work around this with a */
+/* gross hack: */
-/* It appears to be fixed in 2.8 and 2.9. */
-# ifdef SOLARIS25_PROC_VDB_BUG_FIXED
-# define PROC_VDB
-# endif
-# define DYNAMIC_LOADING
-# if !defined(USE_MMAP) && defined(REDIRECT_MALLOC)
-# define USE_MMAP
- /* 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
+/* It appears to be fixed in 2.8 and 2.9. */
+# ifdef SOLARIS25_PROC_VDB_BUG_FIXED
+# define PROC_VDB
+# endif
+# define DYNAMIC_LOADING
+# if !defined(USE_MMAP) && defined(REDIRECT_MALLOC)
+# define USE_MMAP
+ /* 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
-# 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 OS_TYPE "MSWIN32"
+ /* STACKBOTTOM and DATASTART are handled specially in */
+ /* os_dep.c. */
+# define MPROTECT_VDB
+# define GWW_VDB
- /* 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. */
+ /* 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. */
- || defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD) \
- || defined(DGUX) || defined(BSD) \
- || defined(AIX) || defined(DARWIN) || defined(OSF1) \
- || defined(HURD)
-# define UNIX_LIKE /* Basic Unix-like system calls work. */
+ || defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD) \
+ || defined(DGUX) || defined(BSD) \
+ || defined(AIX) || defined(DARWIN) || defined(OSF1) \
+ || defined(HURD)
+# define UNIX_LIKE /* Basic Unix-like system calls work. */
-# ifdef SMALL_CONFIG
- /* Presumably not worth the space it takes. */
-# undef PROC_VDB
+# if !defined(STACKBOTTOM) && (defined(ECOS) || defined(NOSYS))
+# error --> undefined STACKBOTTOM
+# endif
+
+# if defined(SMALL_CONFIG) && !defined(GC_DISABLE_INCREMENTAL)
+ /* Presumably not worth the space it takes. */
+# define GC_DISABLE_INCREMENTAL
+# endif
+
+# ifdef GC_DISABLE_INCREMENTAL
+# undef GWW_VDB
-# ifdef PARALLEL_MARK
-# undef MPROTECT_VDB /* For now. */
+# 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 */
- /* 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. */
+ /* 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. */
+# if defined(UNIX_LIKE) && defined(THREADS) && !defined(NO_CANCEL_SAFE)
+ /* 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
+# define IF_CANCEL(x) x
+# else
+# define IF_CANCEL(x)
+# endif
+
+# if (defined(NO_GETENV) || defined(MSWINCE)) && !defined(NO_GETENV_WIN32)
+# define NO_GETENV_WIN32
+# 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
+
- /* 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. */
+ /* 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. */
- /* 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 */
- /* -DREDIRECT_MALLOC. */
- /* GET_MEM() returns a HLKSIZE aligned chunk. */
- /* 0 is taken to mean failure. */
- /* In the case os USE_MMAP, the argument must also be 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. */
+ /* 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() returns a HLKSIZE aligned chunk. */
+ /* 0 is taken to mean failure. */
+ /* In the case os USE_MMAP, the argument must also be 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. */