gcconfig.h raw

   1  /*
   2   * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
   3   * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
   4   * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.
   5   * Copyright (c) 2000-2004 Hewlett-Packard Development Company, L.P.
   6   * Copyright (c) 2009-2022 Ivan Maidanski
   7   *
   8   * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
   9   * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  10   *
  11   * Permission is hereby granted to use or copy this program
  12   * for any purpose, provided the above notices are retained on all copies.
  13   * Permission to modify the code and to distribute modified code is granted,
  14   * provided the above notices are retained, and a notice that the code was
  15   * modified is included with the above copyright notice.
  16   */
  17  
  18  /*
  19   * This header is private to the collector.  It is almost always
  20   * included from `gc_priv.h` file.  However it is possible to include
  21   * it by itself if just the configuration macros are needed.  In that
  22   * case, a few declarations relying on types declared in `gc_priv.h`
  23   * file will be omitted.
  24   */
  25  
  26  #ifndef GCCONFIG_H
  27  #define GCCONFIG_H
  28  
  29  #ifndef GC_H
  30  #  ifdef HAVE_CONFIG_H
  31  #    include "config.h"
  32  #  endif
  33  #  include "gc/gc.h"
  34  #endif
  35  
  36  #ifdef CPPCHECK
  37  #  undef CLOCKS_PER_SEC
  38  #  undef FIXUP_POINTER
  39  #  undef POINTER_MASK
  40  #  undef POINTER_SHIFT
  41  #  undef REDIRECT_REALLOC
  42  #  undef _MAX_PATH
  43  #endif
  44  
  45  #ifndef PTR_T_DEFINED
  46  typedef char *ptr_t;
  47  #  define PTR_T_DEFINED
  48  #endif
  49  
  50  #if !defined(sony_news)
  51  #  include <stddef.h> /*< for `size_t`, etc. */
  52  #endif
  53  
  54  /*
  55   * Note: only wrap our own declarations, and not the included headers;
  56   * in this case, wrap our entire file, but temporarily unwrap/rewrap
  57   * around `#include` entities; macros do not need such wrapping.
  58   */
  59  #ifdef __cplusplus
  60  #  define EXTERN_C_BEGIN extern "C" {
  61  #  define EXTERN_C_END } /* extern "C" */
  62  #else
  63  #  define EXTERN_C_BEGIN
  64  #  define EXTERN_C_END
  65  #endif
  66  
  67  EXTERN_C_BEGIN
  68  
  69  /* Convenient internal macro to test version of Clang. */
  70  #if defined(__clang__) && defined(__clang_major__)
  71  #  define GC_CLANG_PREREQ(major, minor) \
  72      ((__clang_major__ << 8) + __clang_minor__ >= ((major) << 8) + (minor))
  73  #  define GC_CLANG_PREREQ_FULL(major, minor, patchlevel)          \
  74      (GC_CLANG_PREREQ(major, (minor) + 1)                          \
  75       || (__clang_major__ == (major) && __clang_minor__ == (minor) \
  76           && __clang_patchlevel__ >= (patchlevel)))
  77  #else
  78  #  define GC_CLANG_PREREQ(major, minor) 0 /*< `FALSE` */
  79  #  define GC_CLANG_PREREQ_FULL(major, minor, patchlevel) 0
  80  #endif
  81  
  82  /*
  83   * Machine-dependent parameters.  Some tuning parameters can be found
  84   * near the top of `gc_priv.h` file.
  85   */
  86  
  87  /* Machine-specific parts contributed by various people.  See `README` file. */
  88  
  89  #if defined(__ANDROID__) && !defined(HOST_ANDROID)
  90  /* A Linux-based OS.  `__ANDROID__` macro is defined by Android NDK gcc. */
  91  #  define HOST_ANDROID 1
  92  #endif
  93  
  94  #if defined(TIZEN) && !defined(HOST_TIZEN)
  95  /* A Linux-based OS. */
  96  #  define HOST_TIZEN 1
  97  #endif
  98  
  99  #if defined(__SYMBIAN32__) && !defined(SYMBIAN)
 100  #  define SYMBIAN
 101  #  ifdef __WINS__
 102  #    pragma data_seg(".data2")
 103  #  endif
 104  #endif
 105  
 106  /* First a unified test for Linux. */
 107  #if (defined(linux) || defined(__linux__) || defined(HOST_ANDROID) \
 108       || defined(HOST_TIZEN))                                       \
 109      && !defined(LINUX) && !defined(__native_client__)
 110  #  define LINUX
 111  #endif
 112  
 113  /* And one for NetBSD. */
 114  #if defined(__NetBSD__)
 115  #  define NETBSD
 116  #endif
 117  
 118  /* And one for OpenBSD. */
 119  #if defined(__OpenBSD__)
 120  #  define OPENBSD
 121  #endif
 122  
 123  /* And one for FreeBSD. */
 124  #if (defined(__FreeBSD__) || defined(__DragonFly__) \
 125       || defined(__FreeBSD_kernel__))                \
 126      && !defined(FREEBSD)                            \
 127      && !defined(GC_NO_FREEBSD) /*< Orbis compiler defines `__FreeBSD__` */
 128  #  define FREEBSD
 129  #endif
 130  
 131  #if defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD)
 132  #  define ANY_BSD
 133  #endif
 134  
 135  #if defined(__COSMOPOLITAN__)
 136  #  define COSMO
 137  #endif
 138  
 139  #if defined(__EMBOX__)
 140  #  define EMBOX
 141  #endif
 142  
 143  #if defined(__KOS__)
 144  #  define KOS
 145  #endif
 146  
 147  #if defined(__QNX__) && !defined(QNX)
 148  #  define QNX
 149  #endif
 150  
 151  #if defined(__serenity__)
 152  #  define SERENITY
 153  #endif
 154  
 155  /* And one for Darwin. */
 156  #if defined(macosx) || (defined(__APPLE__) && defined(__MACH__))
 157  #  define DARWIN
 158  EXTERN_C_END
 159  #  include <TargetConditionals.h>
 160  EXTERN_C_BEGIN
 161  #endif
 162  
 163  /* Determine the machine type. */
 164  #if defined(__native_client__)
 165  #  define NACL
 166  #  if !defined(__portable_native_client__) && !defined(__arm__)
 167  #    define I386
 168  #    define mach_type_known
 169  #  else
 170  /* Here we will rely upon arch-specific defines. */
 171  #  endif
 172  #endif
 173  #if defined(__aarch64__) && !defined(ANY_BSD) && !defined(COSMO) \
 174      && !defined(DARWIN) && !defined(LINUX) && !defined(KOS)      \
 175      && !defined(NN_BUILD_TARGET_PLATFORM_NX) && !defined(QNX)    \
 176      && !defined(SERENITY) && !defined(_WIN32)
 177  #  define AARCH64
 178  #  define NOSYS
 179  #  define mach_type_known
 180  #endif
 181  #if defined(__arm) || defined(__arm__) || defined(__thumb__)
 182  #  define ARM32
 183  #  if defined(NACL) || defined(SYMBIAN)
 184  #    define mach_type_known
 185  #  elif !defined(ANY_BSD) && !defined(DARWIN) && !defined(LINUX)             \
 186        && !defined(QNX) && !defined(NN_PLATFORM_CTR)                          \
 187        && !defined(SN_TARGET_PSP2) && !defined(_WIN32) && !defined(__CEGCC__) \
 188        && !defined(GC_NO_NOSYS)
 189  #    define NOSYS
 190  #    define mach_type_known
 191  #  endif
 192  #endif
 193  #if defined(__riscv) && !defined(ANY_BSD) && !defined(LINUX)
 194  #  define RISCV
 195  #  define NOSYS
 196  #  define mach_type_known
 197  #endif
 198  #if defined(vax) || defined(__vax__)
 199  #  define VAX
 200  #  ifdef ultrix
 201  #    define ULTRIX
 202  #  else
 203  #    define BSD
 204  #  endif
 205  #  define mach_type_known
 206  #endif
 207  #if defined(NETBSD) && defined(__vax__)
 208  #  define VAX
 209  #  define mach_type_known
 210  #endif
 211  #if (defined(mips) || defined(__mips) || defined(_mips)) \
 212      && !defined(__TANDEM) && !defined(ANY_BSD) && !defined(LINUX)
 213  #  define MIPS
 214  #  if defined(nec_ews) || defined(_nec_ews)
 215  #    define EWS4800
 216  #    define mach_type_known
 217  #  elif defined(ultrix) || defined(__ultrix)
 218  #    define ULTRIX
 219  #    define mach_type_known
 220  #  elif !defined(_WIN32_WCE) && !defined(__CEGCC__) && !defined(__MINGW32CE__)
 221  #    define IRIX5 /*< or Irix 6.x */
 222  #    define mach_type_known
 223  #  endif /* !MSWINCE */
 224  #endif
 225  #if defined(DGUX) && (defined(i386) || defined(__i386__))
 226  #  define I386
 227  #  ifndef _USING_DGUX
 228  #    define _USING_DGUX
 229  #  endif
 230  #  define mach_type_known
 231  #endif
 232  #if defined(sequent) && (defined(i386) || defined(__i386__))
 233  #  define I386
 234  #  define SEQUENT
 235  #  define mach_type_known
 236  #endif
 237  #if (defined(sun) || defined(__sun)) && (defined(i386) || defined(__i386__))
 238  #  define I386
 239  #  define SOLARIS
 240  #  define mach_type_known
 241  #endif
 242  #if (defined(sun) || defined(__sun)) && defined(__amd64)
 243  #  define X86_64
 244  #  define SOLARIS
 245  #  define mach_type_known
 246  #endif
 247  #if (defined(__OS2__) || defined(__EMX__)) && defined(__32BIT__)
 248  #  define I386
 249  #  define OS2
 250  #  define mach_type_known
 251  #endif
 252  #if (defined(sun) || defined(__sun)) && (defined(sparc) || defined(__sparc))
 253  /* SunOS 5.x */
 254  EXTERN_C_END
 255  #  include <errno.h>
 256  EXTERN_C_BEGIN
 257  #  define SPARC
 258  #  define SOLARIS
 259  #  define mach_type_known
 260  #elif defined(sparc) && defined(unix) && !defined(sun) && !defined(linux) \
 261      && !defined(ANY_BSD)
 262  #  define SPARC
 263  #  define DRSNX
 264  #  define mach_type_known
 265  #endif
 266  #if defined(_IBMR2) /* `&& defined(_AIX)` */
 267  #  define POWERPC
 268  #  define AIX
 269  #  define mach_type_known
 270  #endif
 271  #if defined(_M_XENIX) && defined(_M_SYSV) && defined(_M_I386)
 272  /* TODO: The above test may need refinement. */
 273  #  define I386
 274  #  if defined(_SCO_ELF)
 275  #    define SCO_ELF
 276  #  else
 277  #    define SCO
 278  #  endif
 279  #  define mach_type_known
 280  #endif
 281  #if defined(_PA_RISC1_0) || defined(_PA_RISC1_1) || defined(_PA_RISC2_0) \
 282      || defined(hppa) || defined(__hppa__)
 283  #  define HP_PA
 284  #  if !defined(LINUX) && !defined(HPUX) && !defined(OPENBSD)
 285  #    define HPUX
 286  #  endif
 287  #  define mach_type_known
 288  #endif
 289  #if defined(__ia64) && (defined(_HPUX_SOURCE) || defined(__HP_aCC))
 290  #  define IA64
 291  #  ifndef HPUX
 292  #    define HPUX
 293  #  endif
 294  #  define mach_type_known
 295  #endif
 296  #if (defined(__BEOS__) || defined(__HAIKU__)) && defined(_X86_)
 297  #  define I386
 298  #  define HAIKU
 299  #  define mach_type_known
 300  #endif
 301  #if defined(__HAIKU__) && (defined(__amd64__) || defined(__x86_64__))
 302  #  define X86_64
 303  #  define HAIKU
 304  #  define mach_type_known
 305  #endif
 306  #if defined(__alpha) || defined(__alpha__)
 307  #  define ALPHA
 308  #  if !defined(ANY_BSD) && !defined(LINUX)
 309  #    define OSF1 /*< Compaq Tru64 UNIX (Digital UNIX) */
 310  #  endif
 311  #  define mach_type_known
 312  #endif
 313  #if defined(__rtems__) && (defined(i386) || defined(__i386__))
 314  #  define I386
 315  #  define RTEMS
 316  #  define mach_type_known
 317  #endif
 318  #if defined(NeXT) && defined(mc68000)
 319  #  define M68K
 320  #  define NEXT
 321  #  define mach_type_known
 322  #endif
 323  #if defined(NeXT) && (defined(i386) || defined(__i386__))
 324  #  define I386
 325  #  define NEXT
 326  #  define mach_type_known
 327  #endif
 328  #if defined(bsdi) && (defined(i386) || defined(__i386__))
 329  #  define I386
 330  #  define BSDI
 331  #  define mach_type_known
 332  #endif
 333  #if defined(__386BSD__) && !defined(mach_type_known)
 334  #  define I386
 335  #  define THREE86BSD
 336  #  define mach_type_known
 337  #endif
 338  #if defined(_CX_UX) && defined(_M88K)
 339  #  define M88K
 340  #  define CX_UX
 341  #  define mach_type_known
 342  #endif
 343  #if defined(DGUX) && defined(m88k)
 344  #  define M88K
 345  /* `DGUX` macro is already defined. */
 346  #  define mach_type_known
 347  #endif
 348  #if defined(_WIN32_WCE) || defined(__CEGCC__) || defined(__MINGW32CE__)
 349  /*
 350   * `SH3`, `SH4`, `MIPS` macros are already defined for the corresponding
 351   * architectures.
 352   */
 353  #  if defined(SH3) || defined(SH4)
 354  #    define SH
 355  #  endif
 356  #  if defined(x86) || defined(__i386__)
 357  #    define I386
 358  #  endif
 359  #  if defined(_M_ARM) || defined(ARM) || defined(_ARM_)
 360  #    define ARM32
 361  #  endif
 362  #  define MSWINCE
 363  #  define mach_type_known
 364  #else
 365  #  if ((defined(_MSDOS) || defined(_MSC_VER)) && (_M_IX86 >= 300))          \
 366        || (defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__CYGWIN__) \
 367            && !defined(__INTERIX) && !defined(SYMBIAN))                      \
 368        || defined(__MINGW32__)
 369  #    if defined(__LP64__) || defined(_M_X64)
 370  #      define X86_64
 371  #    elif defined(_M_ARM)
 372  #      define ARM32
 373  #    elif defined(_M_ARM64)
 374  #      define AARCH64
 375  #    else /* _M_IX86 */
 376  #      define I386
 377  #    endif
 378  #    ifdef _XBOX_ONE
 379  #      define MSWIN_XBOX1
 380  #    else
 381  #      ifndef MSWIN32
 382  #        define MSWIN32 /*< or Win64 */
 383  #      endif
 384  #      if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
 385  #        define MSWINRT_FLAVOR
 386  #      endif
 387  #    endif
 388  #    define mach_type_known
 389  #  endif
 390  #  if defined(_MSC_VER) && defined(_M_IA64)
 391  #    define IA64
 392  /*
 393   * Really Win64, but we do not treat 64-bit variants as a different
 394   * platform.
 395   */
 396  #    define MSWIN32
 397  #  endif
 398  #endif /* !_WIN32_WCE && !__CEGCC__ && !__MINGW32CE__ */
 399  #if defined(__DJGPP__)
 400  #  define I386
 401  #  ifndef DJGPP
 402  /* MSDOS running the DJGPP port of gcc. */
 403  #    define DJGPP
 404  #  endif
 405  #  define mach_type_known
 406  #endif
 407  #if defined(__CYGWIN32__) || defined(__CYGWIN__)
 408  #  if defined(__LP64__)
 409  #    define X86_64
 410  #  else
 411  #    define I386
 412  #  endif
 413  #  define CYGWIN32
 414  #  define mach_type_known
 415  #endif /* __CYGWIN__ */
 416  #if defined(__INTERIX)
 417  #  define I386
 418  #  define INTERIX
 419  #  define mach_type_known
 420  #endif
 421  #if defined(_UTS) && !defined(mach_type_known)
 422  #  define S370
 423  #  define UTS4
 424  #  define mach_type_known
 425  #endif
 426  #if defined(__embedded__) && defined(PPC)
 427  #  define POWERPC
 428  #  define NOSYS
 429  #  define mach_type_known
 430  #endif
 431  #if defined(__WATCOMC__) && defined(__386__)
 432  #  define I386
 433  #  if !defined(OS2) && !defined(MSWIN32) && !defined(DOS4GW)
 434  #    if defined(__OS2__)
 435  #      define OS2
 436  #    elif defined(__WINDOWS_386__) || defined(__NT__)
 437  #      define MSWIN32
 438  #    else
 439  #      define DOS4GW
 440  #    endif
 441  #  endif
 442  #  define mach_type_known
 443  #endif /* __WATCOMC__ && __386__ */
 444  #if defined(__GNU__) && defined(__i386__)
 445  /* The Debian Hurd running on generic PC. */
 446  #  define HURD
 447  #  define I386
 448  #  define mach_type_known
 449  #endif
 450  #if defined(__GNU__) && defined(__x86_64__)
 451  #  define HURD
 452  #  define X86_64
 453  #  define mach_type_known
 454  #endif
 455  #if defined(__TANDEM)
 456  /* Nonstop S-series. */
 457  /* FIXME: Should recognize Integrity series? */
 458  #  define MIPS
 459  #  define NONSTOP
 460  #  define mach_type_known
 461  #endif
 462  #if defined(__tile__) && defined(LINUX)
 463  #  ifdef __tilegx__
 464  #    define TILEGX
 465  #  else
 466  #    define TILEPRO
 467  #  endif
 468  #  define mach_type_known
 469  #endif
 470  #if defined(NN_BUILD_TARGET_PLATFORM_NX)
 471  #  define AARCH64
 472  #  define NINTENDO_SWITCH
 473  #  define mach_type_known
 474  #endif
 475  #if defined(__EMSCRIPTEN__) || defined(EMSCRIPTEN)
 476  #  define WEBASSEMBLY
 477  #  ifndef EMSCRIPTEN
 478  #    define EMSCRIPTEN
 479  #  endif
 480  #  define mach_type_known
 481  #endif
 482  #if defined(__wasi__)
 483  /* The WebAssembly System Interface (WASI). */
 484  #  define WEBASSEMBLY
 485  #  define WASI
 486  #  define mach_type_known
 487  #endif
 488  
 489  #if defined(__aarch64__)                                      \
 490      && (defined(ANY_BSD) || defined(COSMO) || defined(DARWIN) \
 491          || defined(LINUX) || defined(KOS) || defined(QNX)     \
 492          || defined(SERENITY))
 493  #  define AARCH64
 494  #  define mach_type_known
 495  #elif defined(__arc__) && defined(LINUX)
 496  #  define ARC
 497  #  define mach_type_known
 498  #elif (defined(__arm) || defined(__arm__) || defined(__arm32__)               \
 499         || defined(__ARM__))                                                   \
 500      && (defined(ANY_BSD) || defined(DARWIN) || defined(LINUX) || defined(QNX) \
 501          || defined(NN_PLATFORM_CTR) || defined(SN_TARGET_PSP2))
 502  #  define ARM32
 503  #  define mach_type_known
 504  #elif defined(__avr32__) && defined(LINUX)
 505  #  define AVR32
 506  #  define mach_type_known
 507  #elif defined(__cris__) && defined(LINUX)
 508  #  ifndef CRIS
 509  #    define CRIS
 510  #  endif
 511  #  define mach_type_known
 512  #elif defined(__e2k__) && defined(LINUX)
 513  #  define E2K
 514  #  define mach_type_known
 515  #elif defined(__hexagon__) && defined(LINUX)
 516  #  define HEXAGON
 517  #  define mach_type_known
 518  #elif (defined(__i386__) || defined(i386) || defined(__X86__)) \
 519      && (defined(ANY_BSD) || defined(DARWIN) || defined(EMBOX)  \
 520          || defined(LINUX) || defined(QNX) || defined(SERENITY))
 521  #  define I386
 522  #  define mach_type_known
 523  #elif (defined(__ia64) || defined(__ia64__)) && defined(LINUX)
 524  #  define IA64
 525  #  define mach_type_known
 526  #elif defined(__loongarch__) && defined(LINUX)
 527  #  define LOONGARCH
 528  #  define mach_type_known
 529  #elif defined(__m32r__) && defined(LINUX)
 530  #  define M32R
 531  #  define mach_type_known
 532  #elif ((defined(__m68k__) || defined(m68k))      \
 533         && (defined(NETBSD) || defined(OPENBSD))) \
 534      || (defined(__mc68000__) && defined(LINUX))
 535  #  define M68K
 536  #  define mach_type_known
 537  #elif (defined(__mips) || defined(_mips) || defined(mips)) \
 538      && (defined(ANY_BSD) || defined(LINUX))
 539  #  define MIPS
 540  #  define mach_type_known
 541  #elif (defined(__NIOS2__) || defined(__NIOS2) || defined(__nios2__)) \
 542      && defined(LINUX)
 543  #  define NIOS2 /*< Altera NIOS2 */
 544  #  define mach_type_known
 545  #elif defined(__or1k__) && defined(LINUX)
 546  #  define OR1K /*< OpenRISC (or1k) */
 547  #  define mach_type_known
 548  #elif (defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__) \
 549         || defined(__ppc64__) || defined(powerpc) || defined(powerpc64))   \
 550      && (defined(ANY_BSD) || defined(DARWIN) || defined(LINUX))
 551  #  define POWERPC
 552  #  define mach_type_known
 553  #elif defined(__riscv) && (defined(ANY_BSD) || defined(LINUX))
 554  #  define RISCV
 555  #  define mach_type_known
 556  #elif defined(__s390__) && defined(LINUX)
 557  #  define S390
 558  #  define mach_type_known
 559  #elif defined(__sh__) \
 560      && (defined(LINUX) || defined(NETBSD) || defined(OPENBSD))
 561  #  define SH
 562  #  define mach_type_known
 563  #elif (defined(__sparc) || defined(sparc)) \
 564      && (defined(ANY_BSD) || defined(LINUX))
 565  #  define SPARC
 566  #  define mach_type_known
 567  #elif defined(__sw_64__) && defined(LINUX)
 568  #  define SW_64
 569  #  define mach_type_known
 570  #elif (defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) \
 571         || defined(__X86_64__))                                        \
 572      && (defined(ANY_BSD) || defined(COSMO) || defined(DARWIN)         \
 573          || defined(LINUX) || defined(QNX) || defined(SERENITY))
 574  #  define X86_64
 575  #  define mach_type_known
 576  #endif
 577  
 578  /*
 579   * Feel free to add more clauses here.  Or manually define the machine
 580   * type here.  A machine type is characterized by the architecture.
 581   * Some machine types are further subdivided by OS.  Macros such as
 582   * `LINUX`, `FREEBSD`, etc. distinguish them.  The distinction in these
 583   * cases is usually the stack starting address.
 584   */
 585  
 586  #if !defined(mach_type_known) && !defined(CPPCHECK)
 587  #  error The collector has not been ported to this machine/OS combination
 588  #endif
 589  
 590  /*
 591   * The CPU architecture mapping is:
 592   *   - `AARCH64`: ARM AArch64 ILP32/64-bit (running `COSMO` environment,
 593   *     `DARWIN` (OS X or iOS), `KOS`, `LINUX`, `MSWIN32`, `NETBSD`,
 594   *     `NINTENDO_SWITCH`, `NOSYS` environment, `OPENBSD`, `QNX`, `SERENITY`);
 595   *   - `ALPHA`: DEC Alpha (running `FREEBSD`, `LINUX`, `NETBSD`, `OPENBSD`,
 596   *     `OSF1`);
 597   *   - `ARC`: Synopsys ARC (running `LINUX`);
 598   *   - `ARM32`: ARMv7 (running `DARWIN` (iOS), `FREEBSD`, `LINUX`, `MSWIN32`,
 599   *     `MSWINCE`, `NETBSD`, `NN_PLATFORM_CTR`, `NOSYS` environment,
 600   *     `OPENBSD`, `QNX`, `SN_TARGET_PSP2`, `SYMBIAN`);
 601   *   - `AVR32`: Atmel RISC (running `LINUX`);
 602   *   - `CRIS`: Axis Etrax (running `LINUX`);
 603   *   - `E2K`: Elbrus 2000 32/64-bit (running `LINUX`);
 604   *   - `HEXAGON`: Qualcomm Hexagon (running `LINUX`);
 605   *   - `HP_PA`: HP9000/700 and HP9000/800 32/64-bit (running `HPUX`, `LINUX`,
 606   *     `OPENBSD`);
 607   *   - `I386`: Intel 486/586/686 (running `BSDI`, `CYGWIN32` environment,
 608   *     `DARWIN` (macOS), `DGUX`, `DJGPP` environment, `DOS4GW` environment,
 609   *     `EMBOX`, `FREEBSD`, `HAIKU`, `HURD`, `INTERIX`, `LINUX`, `MSWIN32`,
 610   *     `MSWINCE`, `NACL` environment, `NETBSD`, `NEXT`, `OPENBSD`, `OS2`,
 611   *     `QNX`, `RTEMS`, `SCO`, `SCO_ELF`, `SEQUENT`, `SERENITY`, `SOLARIS`,
 612   *     `THREE86BSD`);
 613   *   - `IA64`: Intel IPF, e.g. Itanium 32/64-bit (running `HPUX`, `LINUX`,
 614   *     `MSWIN32`);
 615   *   - `LOONGARCH`: Loongson LoongArch 32/64-bit (running `LINUX`);
 616   *   - `M32R`: Renesas M32R (running `LINUX`);
 617   *   - `M68K`: Motorola 680x0 (running `LINUX`, `NETBSD`, `NEXT`, `OPENBSD`);
 618   *   - `M88K`: Motorola 88xx0 (running `CX_UX`, `DGUX`);
 619   *   - `MIPS`: R2000+ 32/64-bit (running `EWS4800`, `FREEBSD`, `IRIX5`,
 620   *     `LINUX`, `MSWINCE`, `NETBSD`, `NONSTOP`, `OPENBSD`, `ULTRIX`);
 621   *   - `NIOS2`: Altera NIOS2 (running `LINUX`);
 622   *   - `OR1K`: OpenRISC/or1k (running `LINUX`);
 623   *   - `POWERPC`: IBM/Apple PowerPC 32/64-bit (running `AIX`, `DARWIN`,
 624   *     `FREEBSD`, `LINUX`, `NETBSD`, `NOSYS` environment, `OPENBSD`,
 625   *     `SN_TARGET_PS3`);
 626   *   - `RISCV`: RISC-V 32/64-bit (running `FREEBSD`, `LINUX`, `NETBSD`,
 627   *     `NOSYS` environment, `OPENBSD`);
 628   *   - `S370`: A 370-like machine (running `UTS4`);
 629   *   - `S390`: A 390-like machine 32/64-bit (running `LINUX`);
 630   *   - `SH`: Hitachi SuperH (running `LINUX`, `MSWINCE`, `NETBSD`,
 631   *     `OPENBSD`);
 632   *   - `SH4`: Hitachi SH4 (running `MSWINCE`);
 633   *   - `SPARC`: SPARC v7/v8/v9 32/64-bit (running `DRSNX`, `FREEBSD`,
 634   *     `LINUX`, `NETBSD`, `OPENBSD`, `SOLARIS`);
 635   *   - `SW_64`: Sunway/Shenwei (running `LINUX`);
 636   *   - `TILEGX`: Tilera TILE-Gx 32/64-bit (running `LINUX`);
 637   *   - `TILEPRO`: Tilera TILEPro (running `LINUX`);
 638   *   - `VAX`: DEC VAX (running `BSD`, `ULTRIX`);
 639   *   - `WEBASSEMBLY`: WebAssembly/Wasm (running `EMSCRIPTEN` environment,
 640   *     `WASI` environment);
 641   *   - `X86_64`: AMD x86-64 ILP32/64-bit (running `COSMO` environment,
 642   *     `CYGWIN32` environment, `DARWIN` (macOS), `FREEBSD`, `HAIKU`,
 643   *     `HURD`, `LINUX`, `MSWIN32`, `MSWIN_XBOX1`, `NETBSD`, `OPENBSD`,
 644   *     `PLATFORM_GETMEM` environment, `QNX`, `SERENITY`, `SOLARIS`).
 645   */
 646  
 647  /*
 648   * For each architecture and OS, the following need to be defined:
 649   *
 650   * `CPP_WORDSZ` is a simple integer constant representing the word size
 651   * in bits.  We assume byte addressability, where a byte has 8 bits.
 652   * We also assume `CPP_WORDSZ` is either 32 or 64.
 653   * (We care about the length of a pointer address, not hardware
 654   * bus widths.  Thus a 64-bit processor with a C compiler that uses
 655   * 32-bit pointers should use `CPP_WORDSZ` of 32, not 64.)
 656   *
 657   * `CPP_PTRSZ` is the pointer size in bits.  For most of the supported
 658   * targets, it is equal to `CPP_WORDSZ`.
 659   *
 660   * `MACH_TYPE` is a string representation of the machine type.
 661   * `OS_TYPE` is analogous for the OS.
 662   *
 663   * `ALIGNMENT` is the largest `n`, such that all pointer are guaranteed
 664   * to be aligned on `n`-byte boundary.  Defining it to be 1 will always
 665   * work, but will perform poorly.  Should not be larger than size of
 666   * a pointer.
 667   *
 668   * `DATASTART` is the beginning of the data segment.  On some platforms
 669   * `SEARCH_FOR_DATA_START` is defined.  The latter will cause
 670   * `GC_data_start` to be set to an address determined by accessing data
 671   * backwards from `_end` until an unmapped page is found.  `DATASTART` will
 672   * be defined to be `GC_data_start`.   On UNIX-like systems, the collector
 673   * will scan the area between `DATASTART` and `DATAEND` for root pointers.
 674   *
 675   * `DATAEND`, if not `end`, where `end` is defined as `extern int end[]`.
 676   * RTH suggests gaining access to linker script synth'd values with
 677   * this idiom instead of `&end`, where `end` is defined as `extern int end`.
 678   * Otherwise, "gcc will assume these are in .sdata/.sbss" and it will, e.g.,
 679   * cause failures on `alpha*-*-*` with `-msmall-data` or `-fpic` or
 680   * `mips-*-*` without any special options.
 681   *
 682   * `STACKBOTTOM` is the cold end of the stack, which is usually the
 683   * highest address in the stack.
 684   * Under OS/2, we have other ways of finding thread stacks.
 685   * For each machine, the following should:
 686   *   1. Define `STACK_GROWS_UP` if the stack grows toward higher addresses;
 687   *   2. Define exactly one of
 688   *      - `STACKBOTTOM` (should be defined to be an expression),
 689   *      - `HEURISTIC1`,
 690   *      - `SPECIFIC_MAIN_STACKBOTTOM`,
 691   *      - `HEURISTIC2`.
 692   *
 693   * If `STACKBOTTOM` is defined, then its value will be used directly (as
 694   * the stack bottom).  If `SPECIFIC_MAIN_STACKBOTTOM` is defined, then it
 695   * will be determined with a specific method appropriate for the operating
 696   * system.  Currently we look first for `__libc_stack_end` (currently only
 697   * if `USE_LIBC_PRIVATES` is defined), and if that fails, read it from
 698   * `/proc` pseudo-file.  (If `USE_LIBC_PRIVATES` is not defined and
 699   * `NO_PROC_STAT` is defined, we revert to `HEURISTIC2`.)
 700   * If either of the last two macros are defined, then `STACKBOTTOM` is
 701   * computed during collector startup using one of the following two
 702   * heuristics:
 703   *   - `HEURISTIC1`: Take an address inside `GC_init`'s frame, and round it
 704   *     up to the next multiple of `STACK_GRAN`;
 705   *   - `HEURISTIC2`: Take an address inside `GC_init`'s frame, increment it
 706   *     repeatedly in small steps (decrement if `STACK_GROWS_UP`), and read
 707   *     the value at each location, remember the value when the first
 708   *     Segmentation violation or Bus error is signaled, round that to the
 709   *     nearest plausible page boundary, and use that instead of
 710   *     `STACKBOTTOM`.
 711   *
 712   * Gustavo Rodriguez-Rivera points out that on most (all?) UNIX machines,
 713   * the value of `environ` is a pointer that can serve as `STACKBOTTOM`.
 714   * I expect that `HEURISTIC2` can be replaced by this approach, which
 715   * interferes far less with debugging.  However it has the disadvantage that
 716   * it is confused by a `putenv()` call before the collector is initialized.
 717   * This could be dealt with by intercepting `putenv()`...
 718   *
 719   * If no expression for `STACKBOTTOM` can be found, and neither of the above
 720   * heuristics are usable, the collector can still be used with all of the
 721   * above undefined, provided one of the following is done:
 722   *   1. `GC_mark_roots` can be changed to somehow mark from the correct
 723   *      stack(s) without reference to `STACKBOTTOM`.  This is appropriate for
 724   *      use in conjunction with thread packages, since there will be multiple
 725   *      stacks.  (Allocating thread stacks in the heap, and treating them as
 726   *      ordinary heap data objects is also possible as a last resort.
 727   *      However, this is likely to introduce significant amounts of excess
 728   *      storage retention unless the dead parts of the thread stacks are
 729   *      periodically cleared.)
 730   *   2. Client code may set `GC_stackbottom` before calling any `GC_`
 731   *      routines.  If the author of the client code owns the main program,
 732   *      this could be accomplished by introducing a new `main` function,
 733   *      calling `GC_call_with_gc_active()` which sets `GC_stackbottom` and
 734   *      then calls the original (real) `main` function.
 735   *
 736   * Each architecture may also define the style of virtual dirty bit
 737   * implementation to be used:
 738   *   - `GWW_VDB`: use Win32 `GetWriteWatch` primitive;
 739   *   - `MPROTECT_VDB`: write-protect the heap and catch faults;
 740   *   - `PROC_VDB`: use the SVR4 `/proc` primitives to read dirty bits;
 741   *   - `SOFT_VDB`: use the Linux `/proc` primitives to track dirty bits.
 742   *
 743   * The first and second one may be combined, in which case a runtime
 744   * selection will be made, based on `GetWriteWatch` availability.
 745   *
 746   * An architecture may define `DYNAMIC_LOADING` if `dyn_load.c` file
 747   * implements `GC_register_dynamic_libraries()` for the architecture.
 748   *
 749   * An architecture may define `PREFETCH(x)` to preload the cache with `*x`.
 750   * This defaults to gcc built-in operation (or a no-op for other compilers).
 751   *
 752   * `GC_PREFETCH_FOR_WRITE(x)` is used if `*x` is about to be written.
 753   *
 754   * An architecture may also define `CLEAR_DOUBLE(x)` to be a fast way to
 755   * clear 2 pointers at `GC_malloc`-aligned address `x`.  The default
 756   * implementation is just to store two `NULL` pointers.
 757   *
 758   * `HEAP_START` may be defined as the initial address hint for `mmap`-based
 759   * allocation.
 760   */
 761  
 762  #ifdef LINUX
 763  /* TODO: FreeBSD too? */
 764  EXTERN_C_END
 765  #  include <features.h> /*< for `__GLIBC__` and `__GLIBC_MINOR__`, at least */
 766  EXTERN_C_BEGIN
 767  #endif
 768  
 769  /* Convenient internal macro to test `glibc` version (if compiled against). */
 770  #if defined(__GLIBC__) && defined(__GLIBC_MINOR__)
 771  #  define GC_GLIBC_PREREQ(major, minor) \
 772      ((__GLIBC__ << 8) + __GLIBC_MINOR__ >= ((major) << 8) + (minor))
 773  #else
 774  #  define GC_GLIBC_PREREQ(major, minor) 0 /*< `FALSE` */
 775  #endif
 776  
 777  /*
 778   * Align a `ptr_t` pointer down/up to a given boundary.  The latter should
 779   * be a power of two.
 780   */
 781  #if GC_CLANG_PREREQ(11, 0)
 782  #  define PTR_ALIGN_DOWN(p, b) __builtin_align_down(p, b)
 783  #  if defined(DARWIN) && defined(GC_SINGLE_OBJ_BUILD) && GC_CLANG_PREREQ(17, 0)
 784  /* Workaround a crash in Apple clang-17. */
 785  /* TODO: Disable for later clang versions when the bug is fixed. */
 786  #    define PTR_ALIGN_UP(p, b) \
 787        ((ptr_t)__builtin_align_up((GC_uintptr_t)(p), b))
 788  #  else
 789  #    define PTR_ALIGN_UP(p, b) __builtin_align_up(p, b)
 790  #  endif
 791  #else
 792  #  define PTR_ALIGN_DOWN(p, b) \
 793      ((ptr_t)((GC_uintptr_t)(p) & ~((GC_uintptr_t)(b) - (GC_uintptr_t)1)))
 794  #  define PTR_ALIGN_UP(p, b)                                           \
 795      ((ptr_t)(((GC_uintptr_t)(p) + (GC_uintptr_t)(b) - (GC_uintptr_t)1) \
 796               & ~((GC_uintptr_t)(b) - (GC_uintptr_t)1)))
 797  #endif
 798  
 799  /*
 800   * If available, we can use `__builtin_unwind_init()` to push the relevant
 801   * registers onto the stack.
 802   */
 803  #if GC_GNUC_PREREQ(2, 8)                                                   \
 804      && !GC_GNUC_PREREQ(11, 0) /*< broken at least in 11.2.0 on cygwin64 */ \
 805      && !defined(__INTEL_COMPILER) && !defined(__PATHCC__)                  \
 806      && !defined(__FUJITSU)                    /*< for FX10 system */       \
 807      && !(defined(POWERPC) && defined(DARWIN)) /*< for MacOS X 10.3.9 */    \
 808      && !defined(E2K) && !defined(RTEMS)                                    \
 809      && !defined(__ARMCC_VERSION) /*< does not exist in armcc gnu emu */    \
 810      && !(defined(__clang__)                                                \
 811           && defined(__ARM_ARCH_5TE__) /* clang-19 emits `vpush`/`vpop` */) \
 812      && (!defined(__clang__)                                                \
 813          || GC_CLANG_PREREQ(8, 0) /* was no-op in clang-3 at least */)
 814  #  define HAVE_BUILTIN_UNWIND_INIT
 815  #endif
 816  
 817  #if (defined(__CC_ARM) || defined(CX_UX) || defined(DJGPP) || defined(EMBOX) \
 818       || defined(EWS4800) || defined(LINUX) || defined(OS2) || defined(RTEMS) \
 819       || defined(UTS4) || defined(MSWIN32) || defined(MSWINCE)                \
 820       || (defined(NOSYS) && defined(RISCV)))                                  \
 821      && !defined(NO_UNDERSCORE_SETJMP)
 822  #  define NO_UNDERSCORE_SETJMP
 823  #endif
 824  
 825  /*
 826   * The common OS-specific definitions.  Should be applicable to all
 827   * (or most, at least) supported architectures.
 828   */
 829  
 830  #ifdef CYGWIN32
 831  #  define OS_TYPE "CYGWIN32"
 832  #  define RETRY_GET_THREAD_CONTEXT
 833  #  ifdef USE_WINALLOC
 834  #    define GWW_VDB
 835  #  elif defined(USE_MMAP)
 836  #    define USE_MMAP_ANON
 837  #  endif
 838  #endif /* CYGWIN32 */
 839  
 840  #ifdef COSMO
 841  #  define OS_TYPE "COSMO"
 842  #  ifndef USE_GET_STACKBASE_FOR_MAIN
 843  #    define USE_GET_STACKBASE_FOR_MAIN
 844  #  endif
 845  extern int __data_start[] __attribute__((__weak__));
 846  #  define DATASTART ((ptr_t)__data_start)
 847  extern int _end[];
 848  #  define DATAEND ((ptr_t)_end)
 849  #  define USE_MMAP_ANON
 850  #  ifndef HAVE_CLOCK_GETTIME
 851  #    define HAVE_CLOCK_GETTIME 1
 852  #  endif
 853  #  ifndef HAVE_PTHREAD_SETNAME_NP_WITH_TID
 854  /* Normally should be defined by `configure`, etc. */
 855  #    define HAVE_PTHREAD_SETNAME_NP_WITH_TID 1
 856  #  endif
 857  #  if !defined(GC_THREADS) || defined(NO_HANDLE_FORK) \
 858        || defined(GC_NO_CAN_CALL_ATFORK)
 859  #    define MPROTECT_VDB
 860  /* FIXME: Otherwise `gctest` crashes in child process. */
 861  #  endif
 862  /* FIXME: A deadlock occurs in markers, thus disabled for now. */
 863  #  undef PARALLEL_MARK
 864  #endif /* COSMO */
 865  
 866  #ifdef DARWIN
 867  #  define OS_TYPE "DARWIN"
 868  #  define DYNAMIC_LOADING
 869  /*
 870   * TODO: See `get_end(3)`, `get_etext` and `get_end` should not be used.
 871   * These are not used when `dyld` support is enabled (it is the default).
 872   */
 873  #  define DATASTART ((ptr_t)get_etext())
 874  #  define DATAEND ((ptr_t)get_end())
 875  #  define USE_MMAP_ANON
 876  /* There seems to be some issues with try-lock hanging on Darwin. */
 877  /* TODO: This should be looked into some more. */
 878  #  define NO_PTHREAD_TRYLOCK
 879  #  ifndef TARGET_OS_XR
 880  #    define TARGET_OS_XR 0
 881  #  endif
 882  #  ifndef TARGET_OS_VISION
 883  #    define TARGET_OS_VISION 0
 884  #  endif
 885  #endif /* DARWIN */
 886  
 887  #ifdef EMBOX
 888  #  define OS_TYPE "EMBOX"
 889  extern int _modules_data_start[], _apps_bss_end[];
 890  #  define DATASTART ((ptr_t)_modules_data_start)
 891  #  define DATAEND ((ptr_t)_apps_bss_end)
 892  /*
 893   * Note: the designated area might be quite large (several dozens of MBs)
 894   * as it includes `.data` and `.bss` of all apps and modules of the built
 895   * binary image.
 896   */
 897  #endif /* EMBOX */
 898  
 899  #ifdef FREEBSD
 900  #  define OS_TYPE "FREEBSD"
 901  #  define SPECIFIC_MAIN_STACKBOTTOM
 902  #  ifdef __ELF__
 903  #    define DYNAMIC_LOADING
 904  #  endif
 905  #  ifndef USE_MMAP
 906  /* `sbrk()` is not available. */
 907  #    define USE_MMAP 1
 908  #  endif
 909  #  if !defined(ALPHA) && !defined(SPARC)
 910  extern char etext[];
 911  #    define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)etext)
 912  #    define DATASTART_USES_XGETDATASTART
 913  #    ifndef REDIRECT_MALLOC
 914  #      define MPROTECT_VDB
 915  #    else
 916  /* Similar as on Linux, `fread()` might use `malloc()`. */
 917  #    endif
 918  #  endif
 919  #endif /* FREEBSD */
 920  
 921  #ifdef HAIKU
 922  #  define OS_TYPE "HAIKU"
 923  #  define DYNAMIC_LOADING
 924  /* Note: `DATASTART` is not used really, see `GC_register_main_static_data`. */
 925  extern int etext[];
 926  #  define DATASTART PTR_ALIGN_UP((ptr_t)etext, 0x1000)
 927  #  ifndef USE_GET_STACKBASE_FOR_MAIN
 928  #    define USE_GET_STACKBASE_FOR_MAIN
 929  #  endif
 930  #  define USE_MMAP_ANON
 931  /*
 932   * On Haiku R1, at least, `pthreads` locks never spin but always call
 933   * into the kernel if the lock cannot be acquired with a simple atomic
 934   * operation.  (Up to 5x overall performance improvement of the
 935   * collector is observed by forcing use of spin locks.)
 936   */
 937  #  ifndef USE_SPIN_LOCK
 938  #    define USE_SPIN_LOCK
 939  #  endif
 940  /*
 941   * TODO: `MPROTECT_VDB` is not working correctly on anything other than
 942   * recent nightly Haiku OS builds (as of Nov 2024), and also it is
 943   * considerably slower than regular collecting, so do not enable it for now.
 944   */
 945  EXTERN_C_END
 946  #  include <OS.h>
 947  EXTERN_C_BEGIN
 948  #  define GETPAGESIZE() (unsigned)B_PAGE_SIZE
 949  #  ifndef HAVE_CLOCK_GETTIME
 950  #    define HAVE_CLOCK_GETTIME 1
 951  #  endif
 952  #endif /* HAIKU */
 953  
 954  #ifdef HPUX
 955  #  define OS_TYPE "HPUX"
 956  extern int __data_start[];
 957  #  define DATASTART ((ptr_t)__data_start)
 958  #  ifdef USE_MMAP
 959  #    define USE_MMAP_ANON
 960  #  endif
 961  #  define DYNAMIC_LOADING
 962  #  define GETPAGESIZE() (unsigned)sysconf(_SC_PAGE_SIZE)
 963  #endif /* HPUX */
 964  
 965  #ifdef HURD
 966  #  define OS_TYPE "HURD"
 967  #  define HEURISTIC2
 968  #  define SEARCH_FOR_DATA_START
 969  extern int _end[];
 970  #  define DATAEND ((ptr_t)_end)
 971  /* TODO: `MPROTECT_VDB` is not quite working yet? */
 972  #  define DYNAMIC_LOADING
 973  #  define USE_MMAP_ANON
 974  #endif /* HURD */
 975  
 976  #ifdef LINUX
 977  #  define OS_TYPE "LINUX"
 978  #  if defined(FORCE_MPROTECT_BEFORE_MADVISE) || defined(PREFER_MMAP_PROT_NONE)
 979  #    define COUNT_UNMAPPED_REGIONS
 980  #  endif
 981  #  define RETRY_TKILL_ON_EAGAIN
 982  #  if !defined(MIPS) && !defined(POWERPC)
 983  #    define SPECIFIC_MAIN_STACKBOTTOM
 984  #  endif
 985  #  if defined(__ELF__) && !defined(IA64)
 986  #    define DYNAMIC_LOADING
 987  #  endif
 988  #  if defined(__ELF__) && !defined(ARC) && !defined(RISCV) && !defined(S390) \
 989        && !defined(TILEGX) && !defined(TILEPRO)
 990  extern int _end[];
 991  #    define DATAEND ((ptr_t)_end)
 992  #  endif
 993  #  if !defined(REDIRECT_MALLOC) && !defined(E2K)
 994  /* Requires Linux 2.3.47 or later. */
 995  #    define MPROTECT_VDB
 996  #  else
 997  /*
 998   * We seem to get random errors in the incremental mode, possibly because
 999   * the Linux threads implementation itself is a `malloc` client and cannot
1000   * deal with the signals.  `fread()` uses `malloc()` too.
1001   * In case of e2k, unless `-fsemi-spec-ld` (or `-O0`) option is passed
1002   * to gcc (both when compiling the collector library and the client),
1003   * a semi-speculative optimization may lead to `SIGILL` (with `ILL_ILLOPN`
1004   * `si_code`) instead of `SIGSEGV`.
1005   */
1006  #  endif
1007  #endif /* LINUX */
1008  
1009  #ifdef KOS
1010  #  define OS_TYPE "KOS"
1011  #  ifndef USE_GET_STACKBASE_FOR_MAIN
1012  /* Note: this requires `-lpthread` option. */
1013  #    define USE_GET_STACKBASE_FOR_MAIN
1014  #  endif
1015  extern int __data_start[];
1016  #  define DATASTART ((ptr_t)__data_start)
1017  #endif /* KOS */
1018  
1019  #ifdef MSWIN32
1020  #  define OS_TYPE "MSWIN32"
1021  /* `STACKBOTTOM` and `DATASTART` are handled specially in `os_dep.c` file. */
1022  #  if !defined(CPPCHECK)
1023  #    define DATAEND /*< not needed */
1024  #  endif
1025  #  if defined(USE_GLOBAL_ALLOC) && !defined(MSWINRT_FLAVOR)
1026  /* Cannot pass `MEM_WRITE_WATCH` to `GlobalAlloc()`. */
1027  #  else
1028  #    define GWW_VDB
1029  #  endif
1030  #endif
1031  
1032  #ifdef MSWINCE
1033  #  define OS_TYPE "MSWINCE"
1034  #  if !defined(CPPCHECK)
1035  #    define DATAEND /*< not needed */
1036  #  endif
1037  #endif
1038  
1039  #ifdef NACL
1040  #  define OS_TYPE "NACL"
1041  #  if defined(__GLIBC__)
1042  #    define DYNAMIC_LOADING
1043  #  endif
1044  #  define DATASTART MAKE_CPTR(0x10020000)
1045  extern int _end[];
1046  #  define DATAEND ((ptr_t)_end)
1047  #  define STACK_GRAN 0x10000
1048  #  define HEURISTIC1
1049  #  define NO_PTHREAD_GETATTR_NP
1050  #  define USE_MMAP_ANON
1051  /* FIXME: Not real page size. */
1052  #  define GETPAGESIZE() 65536
1053  #  define MAX_NACL_GC_THREADS 1024
1054  #endif /* NACL */
1055  
1056  #ifdef NETBSD
1057  #  define OS_TYPE "NETBSD"
1058  #  define HEURISTIC2
1059  #  ifdef __ELF__
1060  #    define SEARCH_FOR_DATA_START
1061  #    define DYNAMIC_LOADING
1062  #  elif !defined(MIPS)
1063  /* TODO: Probably do not exclude it. */
1064  extern char etext[];
1065  #    define DATASTART ((ptr_t)etext)
1066  #  endif
1067  #  define MPROTECT_VDB
1068  #endif /* NETBSD */
1069  
1070  #ifdef NEXT
1071  #  define OS_TYPE "NEXT"
1072  #  define DATASTART ((ptr_t)get_etext())
1073  #  define DATAEND /*< not needed */
1074  #  undef USE_MUNMAP
1075  #endif
1076  
1077  #ifdef OPENBSD
1078  #  define OS_TYPE "OPENBSD"
1079  #  ifndef GC_THREADS
1080  #    define HEURISTIC2
1081  #  endif
1082  #  ifdef __ELF__
1083  extern int __data_start[], _end[];
1084  #    define DATASTART ((ptr_t)__data_start)
1085  #    define DATAEND ((ptr_t)_end)
1086  #    define DYNAMIC_LOADING
1087  #  else
1088  extern char etext[];
1089  #    define DATASTART ((ptr_t)etext)
1090  #  endif
1091  #  define MPROTECT_VDB
1092  #endif /* OPENBSD */
1093  
1094  #ifdef QNX
1095  #  define OS_TYPE "QNX"
1096  #  define SA_RESTART 0
1097  #  ifndef SPECIFIC_MAIN_STACKBOTTOM
1098  /* TODO: This is not used by default. */
1099  #    define STACK_GRAN 0x1000000
1100  #    define HEURISTIC1
1101  #  endif
1102  extern char etext[];
1103  #  define DATASTART ((ptr_t)etext)
1104  extern int _end[];
1105  #  define DATAEND ((ptr_t)_end)
1106  #endif /* QNX */
1107  
1108  #ifdef SERENITY
1109  #  define OS_TYPE "SERENITY"
1110  extern int etext[], _end[];
1111  #  define DATASTART PTR_ALIGN_UP((ptr_t)etext, 0x1000)
1112  #  define DATAEND ((ptr_t)_end)
1113  #  define DYNAMIC_LOADING
1114  /* TODO: Enable `mprotect`-based VDB. */
1115  #  define USE_MMAP_ANON
1116  #endif /* SERENITY */
1117  
1118  #ifdef SOLARIS
1119  #  define OS_TYPE "SOLARIS"
1120  extern int _end[];
1121  #  define DATAEND ((ptr_t)_end)
1122  #  if !defined(USE_MMAP) && defined(REDIRECT_MALLOC)
1123  #    define USE_MMAP 1
1124  /*
1125   * Otherwise we now use `calloc()`.  `mmap()` may result in the heap
1126   * interleaved with thread stacks, which can result in excessive
1127   * black-listing.  `sbrk()` is unusable since it does not interact
1128   * correctly with the system `malloc()`.
1129   */
1130  #  endif
1131  #  ifdef USE_MMAP
1132  #    define HEAP_START ((word)0x40000000)
1133  #  else
1134  #    define HEAP_START ADDR(DATAEND)
1135  #  endif
1136  #  ifndef GC_THREADS
1137  #    define MPROTECT_VDB
1138  #  endif
1139  #  define DYNAMIC_LOADING
1140  /*
1141   * Define `STACKBOTTOM` as `(ptr_t)_start` worked through 2.7, but
1142   * reportedly breaks under 2.8.  It appears that the stack base is
1143   * a property of the executable, so this should not break old executables.
1144   * `HEURISTIC1` reportedly no longer works under Solaris 2.7.
1145   * `HEURISTIC2` probably works, but this appears to be preferable.
1146   * Apparently `USRSTACK` is defined to be `USERLIMIT`, but in some
1147   * installations that is undefined.  We work around this with a gross hack.
1148   */
1149  EXTERN_C_END
1150  #  include <sys/vmparam.h>
1151  EXTERN_C_BEGIN
1152  #  ifdef USERLIMIT
1153  /* This should work everywhere, but does not. */
1154  #    define STACKBOTTOM ((ptr_t)USRSTACK)
1155  #  else
1156  #    define HEURISTIC2
1157  #  endif
1158  #endif /* SOLARIS */
1159  
1160  #ifdef SYMBIAN
1161  #  define OS_TYPE "SYMBIAN"
1162  #  define DATASTART ((ptr_t)ALIGNMENT) /*< cannot be `NULL` */
1163  #  define DATAEND ((ptr_t)ALIGNMENT)
1164  #  ifndef USE_MMAP
1165  /* `sbrk()` is not available. */
1166  #    define USE_MMAP 1
1167  #  endif
1168  #endif /* SYMBIAN */
1169  
1170  /*
1171   * Below are the definitions specific to each supported architecture
1172   * and OS, grouped by the former.
1173   */
1174  
1175  #ifdef M68K
1176  #  define MACH_TYPE "M68K"
1177  #  define CPP_WORDSZ 32
1178  #  define ALIGNMENT 2 /*< not 4 */
1179  #  ifdef OPENBSD
1180  /* Nothing specific. */
1181  #  endif
1182  #  ifdef NETBSD
1183  /* Nothing specific. */
1184  #  endif
1185  #  ifdef LINUX
1186  #    ifdef __ELF__
1187  #      if GC_GLIBC_PREREQ(2, 0)
1188  #        define SEARCH_FOR_DATA_START
1189  #      else
1190  /*
1191   * Hideous kludge: `__environ` is the first word in platform `crt0.o` file,
1192   * and delimits the start of the data segment, no matter which `ld` options
1193   * were passed through.  We could use `_etext` instead, but that would
1194   * include `.rodata`, which may contain large read-only data tables that
1195   * we would rather not scan.
1196   */
1197  extern char **__environ;
1198  #        define DATASTART ((ptr_t)(&__environ))
1199  #      endif
1200  #    else
1201  extern int etext[];
1202  #      define DATASTART PTR_ALIGN_UP((ptr_t)etext, 0x1000)
1203  #    endif
1204  #  endif
1205  #  ifdef NEXT
1206  #    define STACKBOTTOM MAKE_CPTR(0x4000000)
1207  #  endif
1208  #endif
1209  
1210  #ifdef POWERPC
1211  #  define MACH_TYPE "POWERPC"
1212  #  ifdef LINUX
1213  #    if defined(__powerpc64__)
1214  #      define CPP_WORDSZ 64
1215  #      ifndef HBLKSIZE
1216  #        define HBLKSIZE 4096
1217  #      endif
1218  #    else
1219  #      define CPP_WORDSZ 32
1220  #    endif
1221  /*
1222   * `HEURISTIC1` has been reliably reported to fail for a 32-bit executable
1223   * on a 64-bit kernel.
1224   */
1225  #    if defined(__bg__)
1226  /*
1227   * The Linux Compute Node Kernel (used on BlueGene systems) does not
1228   * support the `SPECIFIC_MAIN_STACKBOTTOM` way.
1229   */
1230  #      define HEURISTIC2
1231  #      define NO_PTHREAD_GETATTR_NP
1232  #    else
1233  #      define SPECIFIC_MAIN_STACKBOTTOM
1234  #    endif
1235  #    define SEARCH_FOR_DATA_START
1236  #    ifndef SOFT_VDB
1237  #      define SOFT_VDB
1238  #    endif
1239  #  endif
1240  #  ifdef DARWIN
1241  #    if defined(__ppc64__)
1242  #      define CPP_WORDSZ 64
1243  #      define STACKBOTTOM MAKE_CPTR(0x7fff5fc00000)
1244  #      define CACHE_LINE_SIZE 64
1245  #      ifndef HBLKSIZE
1246  #        define HBLKSIZE 4096
1247  #      endif
1248  #    else
1249  #      define CPP_WORDSZ 32
1250  #      define STACKBOTTOM MAKE_CPTR(0xc0000000)
1251  #    endif
1252  #    define MPROTECT_VDB
1253  #    if defined(USE_PPC_PREFETCH) && defined(__GNUC__)
1254  /* The performance impact of prefetches is untested. */
1255  #      define PREFETCH(x) \
1256          __asm__ __volatile__("dcbt 0,%0" : : "r"((const void *)(x)))
1257  #      define GC_PREFETCH_FOR_WRITE(x) \
1258          __asm__ __volatile__("dcbtst 0,%0" : : "r"((const void *)(x)))
1259  #    endif
1260  #  endif
1261  #  ifdef OPENBSD
1262  #    if defined(__powerpc64__)
1263  #      define CPP_WORDSZ 64
1264  #    else
1265  #      define CPP_WORDSZ 32
1266  #    endif
1267  #  endif
1268  #  ifdef FREEBSD
1269  #    if defined(__powerpc64__)
1270  #      define CPP_WORDSZ 64
1271  #      ifndef HBLKSIZE
1272  #        define HBLKSIZE 4096
1273  #      endif
1274  #    else
1275  #      define CPP_WORDSZ 32
1276  #    endif
1277  #  endif
1278  #  ifdef NETBSD
1279  #    define CPP_WORDSZ 32
1280  #  endif
1281  #  ifdef SN_TARGET_PS3
1282  #    define OS_TYPE "SN_TARGET_PS3"
1283  #    define CPP_WORDSZ 32
1284  #    define NO_GETENV
1285  extern int _end[], __bss_start;
1286  #    define DATASTART ((ptr_t)__bss_start)
1287  #    define DATAEND ((ptr_t)_end)
1288  #    define STACKBOTTOM ((ptr_t)ps3_get_stack_bottom())
1289  void *ps3_get_mem(size_t lb);
1290  #    define GET_MEM(lb) ps3_get_mem(lb)
1291  /*
1292   * The current `LOCK()` implementation for PS3 explicitly uses
1293   * `pthread_mutex_lock()` for some reason.
1294   */
1295  #    define NO_PTHREAD_TRYLOCK
1296  #  endif
1297  #  ifdef AIX
1298  #    define OS_TYPE "AIX"
1299  #    undef ALIGNMENT /*< in case it is defined */
1300  #    undef IA64
1301  /*
1302   * DOB: some AIX installs stupidly define `IA64` in platform
1303   * `sys/systemcfg.h` file.
1304   */
1305  #    ifdef __64BIT__
1306  #      define CPP_WORDSZ 64
1307  #      define STACKBOTTOM MAKE_CPTR(0x1000000000000000)
1308  #    else
1309  #      define CPP_WORDSZ 32
1310  extern int errno;
1311  #      define STACKBOTTOM ((ptr_t)(&errno))
1312  #    endif
1313  #    define USE_MMAP_ANON
1314  /*
1315   * From AIX linker man page:
1316   *   - `_text` specifies the first location of the program;
1317   *   - `_etext` specifies the first location after the program;
1318   *   - `_data` specifies the first location of the data;
1319   *   - `_edata` specifies the first location after the initialized data;
1320   *   - `_end` (or `end`) specifies the first location after all data.
1321   */
1322  extern int _data[], _end[];
1323  #    define DATASTART ((ptr_t)_data)
1324  #    define DATAEND ((ptr_t)_end)
1325  #    define MPROTECT_VDB
1326  #    define DYNAMIC_LOADING
1327  /*
1328   * Note: for really old versions of AIX, `DYNAMIC_LOADING` may have to
1329   * be removed.
1330   */
1331  #  endif
1332  #  ifdef NOSYS
1333  #    define OS_TYPE "NOSYS"
1334  #    define CPP_WORDSZ 32
1335  extern void __end[], __dso_handle[];
1336  #    define DATASTART ((ptr_t)__dso_handle) /*< OK, that is ugly */
1337  #    define DATAEND ((ptr_t)__end)
1338  /* Note: stack starts at 0xE0000000 for the simulator. */
1339  #    define STACKBOTTOM PTR_ALIGN_UP(GC_approx_sp(), 0x10000000)
1340  #  endif
1341  #endif /* POWERPC */
1342  
1343  #ifdef VAX
1344  #  define MACH_TYPE "VAX"
1345  #  define CPP_WORDSZ 32
1346  /* Pointers are `longword`-aligned by C compiler v4.2. */
1347  extern char etext[];
1348  #  define DATASTART ((ptr_t)etext)
1349  #  ifdef BSD
1350  #    define OS_TYPE "BSD"
1351  #    define STACK_GRAN 0x1000000
1352  #    define HEURISTIC1
1353  /* Note: `HEURISTIC2` may be OK, but it is hard to test. */
1354  #  endif
1355  #  ifdef ULTRIX
1356  #    define OS_TYPE "ULTRIX"
1357  #    define STACKBOTTOM MAKE_CPTR(0x7fffc800)
1358  #  endif
1359  #endif /* VAX */
1360  
1361  #ifdef SPARC
1362  #  define MACH_TYPE "SPARC"
1363  #  if defined(__arch64__) || defined(__sparcv9)
1364  #    define CPP_WORDSZ 64
1365  #    define ELF_CLASS ELFCLASS64
1366  #  else
1367  #    define CPP_WORDSZ 32
1368  #    define ALIGNMENT 4 /*< required by hardware */
1369  #  endif
1370  #  ifdef SOLARIS
1371  extern int _etext[];
1372  #    define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext)
1373  #    define PROC_VDB
1374  /*
1375   * `getpagesize()` appeared to be missing from at least one Solaris 5.4
1376   * installation.  Weird.
1377   */
1378  #    define GETPAGESIZE() (unsigned)sysconf(_SC_PAGESIZE)
1379  #  endif
1380  #  ifdef DRSNX
1381  #    define OS_TYPE "DRSNX"
1382  extern int etext[];
1383  #    define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)etext)
1384  #    define MPROTECT_VDB
1385  #    define STACKBOTTOM MAKE_CPTR(0xdfff0000)
1386  #    define DYNAMIC_LOADING
1387  #  endif
1388  #  ifdef LINUX
1389  extern int _etext[];
1390  #    ifdef __arch64__
1391  #      define DATASTART GC_SysVGetDataStart(0x100000, (ptr_t)_etext)
1392  #    else
1393  #      define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext)
1394  #    endif
1395  #  endif
1396  #  ifdef OPENBSD
1397  /* Nothing specific. */
1398  #  endif
1399  #  ifdef NETBSD
1400  /* Nothing specific. */
1401  #  endif
1402  #  ifdef FREEBSD
1403  extern char etext[];
1404  #    define DATASTART ((ptr_t)(&etext))
1405  #    define DATAEND ((ptr_t)GC_find_limit(DATASTART, TRUE))
1406  #    define DATAEND_IS_FUNC
1407  #    define GC_HAVE_DATAREGION2
1408  extern char edata[], end[];
1409  #    define DATASTART2 ((ptr_t)(&edata))
1410  #    define DATAEND2 ((ptr_t)(&end))
1411  #  endif
1412  #endif /* SPARC */
1413  
1414  #ifdef I386
1415  #  define MACH_TYPE "I386"
1416  #  if (defined(__LP64__) || defined(_WIN64)) && !defined(CPPCHECK)
1417  #    error This should be handled as X86_64
1418  #  endif
1419  #  define CPP_WORDSZ 32
1420  /*
1421   * The 4-byte alignment appears to hold for all 32-bit compilers
1422   * except Borland and Watcom.  If using the Borland (bcc32) or
1423   * Watcom (wcc386) compiler, `-a4` or `-zp4` option, respectively,
1424   * should be passed to the compiler, both for building the library
1425   * and client code.  (The alternate solution is to define
1426   * `FORCE_ALIGNMENT_ONE` macro but this would have significant
1427   * negative performance implications.)
1428   */
1429  #  if defined(FORCE_ALIGNMENT_ONE) \
1430        && (defined(__BORLANDC__) || defined(__WATCOMC__))
1431  #    define ALIGNMENT 1
1432  #  endif
1433  #  ifdef SEQUENT
1434  #    define OS_TYPE "SEQUENT"
1435  extern int etext[];
1436  #    define DATASTART PTR_ALIGN_UP((ptr_t)etext, 0x1000)
1437  #    define STACKBOTTOM MAKE_CPTR(0x3ffff000)
1438  #  endif
1439  #  ifdef HAIKU
1440  /* Nothing specific. */
1441  #  endif
1442  #  ifdef HURD
1443  /* Nothing specific. */
1444  #  endif
1445  #  ifdef EMBOX
1446  /* Nothing specific. */
1447  #  endif
1448  #  ifdef NACL
1449  /* Nothing specific. */
1450  #  endif
1451  #  ifdef QNX
1452  /* Nothing specific. */
1453  #  endif
1454  #  ifdef SERENITY
1455  /* Nothing specific. */
1456  #  endif
1457  #  ifdef SOLARIS
1458  extern int _etext[];
1459  #    define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)_etext)
1460  #    define PROC_VDB
1461  #  endif
1462  #  ifdef SCO
1463  #    define OS_TYPE "SCO"
1464  extern int etext[];
1465  #    define DATASTART \
1466        (PTR_ALIGN_UP((ptr_t)etext, 0x400000) + (ADDR(etext) & 0xfff))
1467  #    define STACKBOTTOM MAKE_CPTR(0x7ffffffc)
1468  #  endif
1469  #  ifdef SCO_ELF
1470  #    define OS_TYPE "SCO_ELF"
1471  extern int etext[];
1472  #    define DATASTART ((ptr_t)etext)
1473  #    define STACKBOTTOM MAKE_CPTR(0x8048000)
1474  #    define DYNAMIC_LOADING
1475  #    define ELF_CLASS ELFCLASS32
1476  #  endif
1477  #  ifdef DGUX
1478  #    define OS_TYPE "DGUX"
1479  extern int _etext, _end;
1480  #    define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)(&_etext))
1481  #    define DATASTART_USES_XGETDATASTART
1482  #    define DATAEND ((ptr_t)(&_end))
1483  #    define HEURISTIC2
1484  #    define DYNAMIC_LOADING
1485  #    ifndef USE_MMAP
1486  #      define USE_MMAP 1
1487  #    endif
1488  #    define MAP_FAILED ((void *)(~(GC_uintptr_t)0))
1489  #    define HEAP_START ((word)0x40000000)
1490  #  endif /* DGUX */
1491  #  ifdef LINUX
1492  /*
1493   * This encourages `mmap()` to give us low addresses, thus allowing the
1494   * heap to grow to ~3 GB.
1495   */
1496  #    define HEAP_START ((word)0x1000)
1497  #    ifdef __ELF__
1498  #      if GC_GLIBC_PREREQ(2, 0) || defined(HOST_ANDROID)
1499  #        define SEARCH_FOR_DATA_START
1500  #      else
1501  /* See the comment of the Linux/m68k case. */
1502  extern char **__environ;
1503  #        define DATASTART ((ptr_t)(&__environ))
1504  #      endif
1505  #      if !defined(GC_NO_SIGSETJMP)                                  \
1506            && (defined(HOST_TIZEN)                                    \
1507                || (defined(HOST_ANDROID)                              \
1508                    && !(GC_GNUC_PREREQ(4, 8) || GC_CLANG_PREREQ(3, 2) \
1509                         || __ANDROID_API__ >= 18)))
1510  /*
1511   * Older Android NDK releases lack `sigsetjmp` in x86 `libc` (`setjmp` is
1512   * used instead to find `data_start`).  The bug is fixed in Android NDK r8e
1513   * (so, it is OK to use `sigsetjmp` if gcc-4.8+, clang-3.2+ or Android
1514   * API level 18+).
1515   */
1516  #        define GC_NO_SIGSETJMP 1
1517  #      endif
1518  #    else
1519  extern int etext[];
1520  #      define DATASTART PTR_ALIGN_UP((ptr_t)etext, 0x1000)
1521  #    endif
1522  #    ifdef USE_I686_PREFETCH
1523  /*
1524   * Empirically `prefetcht0` is much more effective at reducing cache miss
1525   * stalls for the targeted load instructions.  But it seems to interfere
1526   * enough with other cache traffic that the net result is worse than
1527   * `prefetchnta`.
1528   */
1529  #      define PREFETCH(x) \
1530          __asm__ __volatile__("prefetchnta %0" : : "m"(*(char *)(x)))
1531  #      ifdef FORCE_WRITE_PREFETCH
1532  /*
1533   * Using prefetches for write seems to have a slight negative impact on
1534   * performance, at least for a PIII/500.
1535   */
1536  #        define GC_PREFETCH_FOR_WRITE(x) \
1537            __asm__ __volatile__("prefetcht0 %0" : : "m"(*(char *)(x)))
1538  #      else
1539  #        define GC_NO_PREFETCH_FOR_WRITE
1540  #      endif
1541  #    elif defined(USE_3DNOW_PREFETCH)
1542  #      define PREFETCH(x) \
1543          __asm__ __volatile__("prefetch %0" : : "m"(*(char *)(x)))
1544  #      define GC_PREFETCH_FOR_WRITE(x) \
1545          __asm__ __volatile__("prefetchw %0" : : "m"(*(char *)(x)))
1546  #    endif
1547  #    if defined(__GLIBC__) && !defined(__UCLIBC__) \
1548          && !defined(GLIBC_TSX_BUG_FIXED)
1549  /* Workaround lock elision implementation for some `glibc`. */
1550  #      define GLIBC_2_19_TSX_BUG
1551  EXTERN_C_END
1552  #      include <gnu/libc-version.h> /*< for `gnu_get_libc_version()` */
1553  EXTERN_C_BEGIN
1554  #    endif
1555  #    ifndef SOFT_VDB
1556  #      define SOFT_VDB
1557  #    endif
1558  #  endif
1559  #  ifdef CYGWIN32
1560  #    define WOW64_THREAD_CONTEXT_WORKAROUND
1561  #    define DATASTART ((ptr_t)GC_DATASTART) /*< defined in `gc.h` file */
1562  #    define DATAEND ((ptr_t)GC_DATAEND)
1563  #    ifndef USE_WINALLOC
1564  /* `MPROTECT_VDB` does not work, it leads to a spurious exit. */
1565  #    endif
1566  #  endif
1567  #  ifdef INTERIX
1568  #    define OS_TYPE "INTERIX"
1569  extern int _data_start__[], _bss_end__[];
1570  #    define DATASTART ((ptr_t)_data_start__)
1571  #    define DATAEND ((ptr_t)_bss_end__)
1572  #    define STACKBOTTOM                                        \
1573        ({                                                       \
1574          ptr_t rv;                                              \
1575          __asm__ __volatile__("movl %%fs:4, %%eax" : "=a"(rv)); \
1576          rv;                                                    \
1577        })
1578  #    define USE_MMAP_ANON
1579  #  endif
1580  #  ifdef OS2
1581  #    define OS_TYPE "OS2"
1582  /*
1583   * `STACKBOTTOM` and `DATASTART` are handled specially in `os_dep.c`
1584   * file.  OS/2 actually has the right system call!
1585   */
1586  #    define DATAEND /*< not needed */
1587  #    undef USE_MUNMAP
1588  #    define GETPAGESIZE() os2_getpagesize()
1589  #  endif
1590  #  ifdef MSWIN32
1591  #    define WOW64_THREAD_CONTEXT_WORKAROUND
1592  #    define RETRY_GET_THREAD_CONTEXT
1593  #    if defined(__BORLANDC__)
1594  /*
1595   * TODO: VDB based on `VirtualProtect` and `SetUnhandledExceptionFilter`
1596   * does not work correctly.
1597   */
1598  #    else
1599  #      define MPROTECT_VDB
1600  #    endif
1601  #  endif
1602  #  ifdef MSWINCE
1603  /* Nothing specific. */
1604  #  endif
1605  #  ifdef DJGPP
1606  #    define OS_TYPE "DJGPP"
1607  EXTERN_C_END
1608  #    include "stubinfo.h"
1609  EXTERN_C_BEGIN
1610  extern int etext[];
1611  #    define DATASTART PTR_ALIGN_UP((ptr_t)etext, 0x200)
1612  extern int __djgpp_stack_limit, _stklen;
1613  #    define STACKBOTTOM (MAKE_CPTR(__djgpp_stack_limit) + _stklen)
1614  #  endif
1615  #  ifdef OPENBSD
1616  /* Nothing specific. */
1617  #  endif
1618  #  ifdef FREEBSD
1619  #    if defined(__GLIBC__)
1620  extern int _end[];
1621  #      define DATAEND ((ptr_t)_end)
1622  #    endif
1623  #  endif
1624  #  ifdef NETBSD
1625  /* Nothing specific. */
1626  #  endif
1627  #  ifdef THREE86BSD
1628  #    define OS_TYPE "THREE86BSD"
1629  #    define HEURISTIC2
1630  extern char etext[];
1631  #    define DATASTART ((ptr_t)etext)
1632  #  endif
1633  #  ifdef BSDI
1634  #    define OS_TYPE "BSDI"
1635  #    define HEURISTIC2
1636  extern char etext[];
1637  #    define DATASTART ((ptr_t)etext)
1638  #  endif
1639  #  ifdef NEXT
1640  #    define STACKBOTTOM MAKE_CPTR(0xc0000000)
1641  #  endif
1642  #  ifdef RTEMS
1643  #    define OS_TYPE "RTEMS"
1644  EXTERN_C_END
1645  #    include <sys/unistd.h>
1646  EXTERN_C_BEGIN
1647  extern int etext[];
1648  #    define DATASTART ((ptr_t)etext)
1649  void *rtems_get_stack_bottom(void);
1650  #    define InitStackBottom rtems_get_stack_bottom()
1651  #    define STACKBOTTOM ((ptr_t)InitStackBottom)
1652  #    undef USE_MUNMAP
1653  #  endif
1654  #  ifdef DOS4GW
1655  #    define OS_TYPE "DOS4GW"
1656  extern long __nullarea;
1657  extern char _end;
1658  extern char *_STACKTOP;
1659  /*
1660   * Depending on calling conventions Watcom C either precedes or does not
1661   * precede the names of the C variables with an underscore.
1662   * Make sure the startup code variables always have the same name.
1663   */
1664  #    pragma aux __nullarea "*";
1665  #    pragma aux _end "*";
1666  #    define STACKBOTTOM ((ptr_t)_STACKTOP) /*< confused? me too */
1667  #    define DATASTART ((ptr_t)(&__nullarea))
1668  #    define DATAEND ((ptr_t)(&_end))
1669  #    undef USE_MUNMAP
1670  #    define GETPAGESIZE() 4096
1671  #  endif
1672  #  ifdef DARWIN
1673  #    define DARWIN_DONT_PARSE_STACK 1
1674  #    define STACKBOTTOM MAKE_CPTR(0xc0000000)
1675  #    define MPROTECT_VDB
1676  #  endif
1677  #endif /* I386 */
1678  
1679  #ifdef LOONGARCH
1680  #  define MACH_TYPE "LOONGARCH"
1681  #  define CPP_WORDSZ (__SIZEOF_SIZE_T__ * 8)
1682  #  ifdef LINUX
1683  #    pragma weak __data_start
1684  extern int __data_start[];
1685  #    define DATASTART ((ptr_t)__data_start)
1686  #  endif
1687  #endif /* LOONGARCH */
1688  
1689  #ifdef SW_64
1690  #  define MACH_TYPE "SW_64"
1691  #  define CPP_WORDSZ 64
1692  #  ifdef LINUX
1693  /* Nothing specific. */
1694  #  endif
1695  #endif /* SW_64 */
1696  
1697  #ifdef MIPS
1698  #  define MACH_TYPE "MIPS"
1699  #  ifdef LINUX
1700  #    ifdef _MIPS_SZPTR
1701  #      define CPP_WORDSZ _MIPS_SZPTR
1702  #    else
1703  #      define CPP_WORDSZ 32
1704  #    endif
1705  #    pragma weak __data_start
1706  extern int __data_start[];
1707  #    define DATASTART ((ptr_t)__data_start)
1708  #    ifndef HBLKSIZE
1709  #      define HBLKSIZE 4096
1710  #    endif
1711  #    if GC_GLIBC_PREREQ(2, 2)
1712  #      define SPECIFIC_MAIN_STACKBOTTOM
1713  #    else
1714  #      define STACKBOTTOM MAKE_CPTR(0x7fff8000)
1715  #    endif
1716  #  endif
1717  #  ifdef EWS4800
1718  #    define OS_TYPE "EWS4800"
1719  #    define HEURISTIC2
1720  #    if defined(_MIPS_SZPTR) && (_MIPS_SZPTR == 64)
1721  #      define CPP_WORDSZ _MIPS_SZPTR
1722  extern int _fdata[], _end[];
1723  #      define DATASTART ((ptr_t)_fdata)
1724  #      define DATAEND ((ptr_t)_end)
1725  #    else
1726  #      define CPP_WORDSZ 32
1727  extern int etext[], edata[];
1728  #      define DATASTART \
1729          (PTR_ALIGN_UP((ptr_t)etext, 0x40000) + (ADDR(etext) & 0xffff))
1730  #      define DATAEND ((ptr_t)edata)
1731  #      define GC_HAVE_DATAREGION2
1732  extern int _DYNAMIC_LINKING[], _gp[];
1733  #      define DATASTART2                                               \
1734          (_DYNAMIC_LINKING ? PTR_ALIGN_UP((ptr_t)_gp + 0x8000, 0x40000) \
1735                            : (ptr_t)edata)
1736  extern int end[];
1737  #      define DATAEND2 ((ptr_t)end)
1738  #    endif
1739  #  endif
1740  #  ifdef ULTRIX
1741  #    define OS_TYPE "ULTRIX"
1742  #    define CPP_WORDSZ 32
1743  #    define HEURISTIC2
1744  /*
1745   * Note: the actual beginning of the data segment could probably be
1746   * slightly higher since startup code allocates lots of stuff.
1747   */
1748  #    define DATASTART MAKE_CPTR(0x10000000)
1749  #  endif
1750  #  ifdef IRIX5
1751  #    define OS_TYPE "IRIX5"
1752  #    ifdef _MIPS_SZPTR
1753  #      define CPP_WORDSZ _MIPS_SZPTR
1754  #    else
1755  #      define CPP_WORDSZ 32
1756  #    endif
1757  #    define HEURISTIC2
1758  extern int _fdata[];
1759  #    define DATASTART ((ptr_t)_fdata)
1760  /*
1761   * Lowest plausible heap address.  In the `USE_MMAP` case, we map there.
1762   * In either case it is used to identify heap sections so they are not
1763   * considered as roots.
1764   */
1765  #    ifdef USE_MMAP
1766  #      define HEAP_START ((word)0x30000000)
1767  #    else
1768  #      define HEAP_START ADDR(DATASTART)
1769  #    endif
1770  /* `MPROTECT_VDB` should work, but there is evidence of a breakage. */
1771  #    define DYNAMIC_LOADING
1772  #  endif
1773  #  ifdef MSWINCE
1774  #    define CPP_WORDSZ 32
1775  #  endif
1776  #  ifdef NETBSD
1777  #    define CPP_WORDSZ 32
1778  #    ifndef __ELF__
1779  #      define DATASTART MAKE_CPTR(0x10000000)
1780  #      define STACKBOTTOM MAKE_CPTR(0x7ffff000)
1781  #    endif
1782  #  endif
1783  #  ifdef OPENBSD
1784  #    define CPP_WORDSZ 64 /*< all OpenBSD/mips platforms are 64-bit */
1785  #  endif
1786  #  ifdef FREEBSD
1787  #    define CPP_WORDSZ 32
1788  #  endif
1789  #  ifdef NONSTOP
1790  #    define OS_TYPE "NONSTOP"
1791  #    define CPP_WORDSZ 32
1792  #    define DATASTART MAKE_CPTR(0x8000000)
1793  extern char **environ;
1794  #    define DATAEND ((ptr_t)(environ - 0x10))
1795  #    define STACKBOTTOM MAKE_CPTR(0x4fffffff)
1796  #    undef USE_MUNMAP
1797  #  endif
1798  #endif /* MIPS */
1799  
1800  #ifdef NIOS2
1801  #  define MACH_TYPE "NIOS2"
1802  #  define CPP_WORDSZ 32
1803  #  ifndef HBLKSIZE
1804  #    define HBLKSIZE 4096
1805  #  endif
1806  #  ifdef LINUX
1807  extern int __data_start[];
1808  #    define DATASTART ((ptr_t)__data_start)
1809  #  endif
1810  #endif /* NIOS2 */
1811  
1812  #ifdef OR1K
1813  #  define MACH_TYPE "OR1K"
1814  #  define CPP_WORDSZ 32
1815  #  ifndef HBLKSIZE
1816  #    define HBLKSIZE 4096
1817  #  endif
1818  #  ifdef LINUX
1819  extern int __data_start[];
1820  #    define DATASTART ((ptr_t)__data_start)
1821  #  endif
1822  #endif /* OR1K */
1823  
1824  #ifdef HP_PA
1825  #  define MACH_TYPE "HP_PA"
1826  #  ifdef __LP64__
1827  #    define CPP_WORDSZ 64
1828  #  else
1829  #    define CPP_WORDSZ 32
1830  #  endif
1831  #  define STACK_GROWS_UP
1832  #  ifdef HPUX
1833  #    ifndef GC_THREADS
1834  #      define MPROTECT_VDB
1835  #    endif
1836  #    ifdef USE_HPUX_FIXED_STACKBOTTOM
1837  /*
1838   * The following appears to work for 7xx systems running HP/UX 9.xx.
1839   * Furthermore, it might result in much faster collections than `HEURISTIC2`,
1840   * which may involve scanning segments that directly precede the stack.
1841   * It is not the default, since it may not work on older machine/OS
1842   * combinations. (Thanks to Raymond X.T. Nijssen for uncovering this.)
1843   * This technique also does not work with HP/UX 11.xx.  The stack size is
1844   * settable using the kernel `maxssiz` variable, and the size can be set
1845   * dynamically in HP/UX 11.23 and later.  It also does not handle
1846   * `SHMEM_MAGIC` binaries that have stack and data in the first quadrant.
1847   * This is from platform `/etc/conf/h/param.h` file.
1848   */
1849  #      define STACKBOTTOM MAKE_CPTR(0x7b033000)
1850  #    elif defined(USE_ENVIRON_POINTER)
1851  /*
1852   * Gustavo Rodriguez-Rivera suggested changing `HEURISTIC2` to this.
1853   * Note that the collector must be initialized before the first `putenv()`
1854   * call.  Unfortunately, some clients do not obey.
1855   */
1856  extern char **environ;
1857  #      define STACKBOTTOM ((ptr_t)environ)
1858  #    elif !defined(HEURISTIC2)
1859  /* This uses `pst_vm_status` support. */
1860  #      define SPECIFIC_MAIN_STACKBOTTOM
1861  #    endif
1862  #    ifndef __GNUC__
1863  #      define PREFETCH(x)                   \
1864          do {                                \
1865            register long addr = (long)(x);   \
1866            (void)_asm("LDW", 0, 0, addr, 0); \
1867          } while (0)
1868  #    endif
1869  #  endif /* HPUX */
1870  #  ifdef LINUX
1871  #    define SEARCH_FOR_DATA_START
1872  #  endif
1873  #  ifdef OPENBSD
1874  /* Nothing specific. */
1875  #  endif
1876  #endif /* HP_PA */
1877  
1878  #ifdef ALPHA
1879  #  define MACH_TYPE "ALPHA"
1880  #  define CPP_WORDSZ 64
1881  #  ifdef NETBSD
1882  #    define ELFCLASS32 32
1883  #    define ELFCLASS64 64
1884  #    define ELF_CLASS ELFCLASS64
1885  #  endif
1886  #  ifdef OPENBSD
1887  /* Nothing specific. */
1888  #  endif
1889  #  ifdef FREEBSD
1890  extern char etext[];
1891  #    define DATASTART ((ptr_t)(&etext))
1892  #    define DATAEND ((ptr_t)GC_find_limit(DATASTART, TRUE))
1893  #    define DATAEND_IS_FUNC
1894  /*
1895   * Handle unmapped hole which `alpha*-*-freebsd[45]*` puts between
1896   * `etext` and `edata`.
1897   */
1898  #    define GC_HAVE_DATAREGION2
1899  extern char edata[], end[];
1900  #    define DATASTART2 ((ptr_t)(&edata))
1901  #    define DATAEND2 ((ptr_t)(&end))
1902  /* `MPROTECT_VDB` is not yet supported at all on FreeBSD/alpha. */
1903  #  endif
1904  #  ifdef OSF1
1905  #    define OS_TYPE "OSF1"
1906  #    define DATASTART MAKE_CPTR(0x140000000)
1907  extern int _end[];
1908  #    define DATAEND ((ptr_t)(&_end))
1909  extern char **environ;
1910  /*
1911   * Round up from the value of `environ` to the nearest page boundary.
1912   * Probably this is broken if `putenv()` is called before the collector
1913   * initialization.
1914   */
1915  #    define STACKBOTTOM PTR_ALIGN_UP((ptr_t)environ, getpagesize())
1916  /*
1917   * Normally `HEURISTIC2` is too conservative, since the text segment
1918   * immediately follows the stack.  Hence we give an upper bound.
1919   * This is currently unused, since `HEURISTIC2` is not defined.
1920   */
1921  extern int __start[];
1922  #    define HEURISTIC2_LIMIT PTR_ALIGN_DOWN((ptr_t)__start, getpagesize())
1923  #    ifndef GC_THREADS
1924  /* FIXME: Unresolved signal issues with threads. */
1925  #      define MPROTECT_VDB
1926  #    endif
1927  #    define DYNAMIC_LOADING
1928  #  endif
1929  #  ifdef LINUX
1930  #    ifdef __ELF__
1931  #      define SEARCH_FOR_DATA_START
1932  #    else
1933  #      define DATASTART MAKE_CPTR(0x140000000)
1934  extern int _end[];
1935  #      define DATAEND ((ptr_t)_end)
1936  #    endif
1937  #  endif
1938  #endif /* ALPHA */
1939  
1940  #ifdef IA64
1941  #  define MACH_TYPE "IA64"
1942  #  ifdef HPUX
1943  #    ifdef _ILP32
1944  #      define CPP_WORDSZ 32
1945  /* Note: requires 8-byte alignment (granularity) for `malloc()`. */
1946  #      define ALIGNMENT 4
1947  #    else
1948  #      if !defined(_LP64) && !defined(CPPCHECK)
1949  #        error Unknown ABI
1950  #      endif
1951  #      define CPP_WORDSZ 64
1952  /* Note: requires 16-byte alignment (granularity) for `malloc()`. */
1953  #      define ALIGNMENT 8
1954  #    endif
1955  /*
1956   * Note that the collector must be initialized before the 1st `putenv`
1957   * call.
1958   */
1959  extern char **environ;
1960  #    define STACKBOTTOM ((ptr_t)environ)
1961  /*
1962   * The following was empirically determined, and is probably not very
1963   * robust.  Note that the backing store base seems to be at a nice address
1964   * minus one page.
1965   */
1966  #    define BACKING_STORE_DISPLACEMENT 0x1000000
1967  #    define BACKING_STORE_ALIGNMENT 0x1000
1968  /* Known to be wrong for recent HP/UX versions!!! */
1969  #  endif
1970  #  ifdef LINUX
1971  #    define CPP_WORDSZ 64
1972  /*
1973   * The following works on NUE and older kernels:
1974   * `define STACKBOTTOM MAKE_CPTR(0xa000000000000000l)`.
1975   */
1976  /* TODO: `SPECIFIC_MAIN_STACKBOTTOM` does not work on NUE. */
1977  /* We also need the base address of the register stack backing store. */
1978  #    define SEARCH_FOR_DATA_START
1979  #    ifdef __GNUC__
1980  #      define DYNAMIC_LOADING
1981  #    else
1982  /*
1983   * In the Intel compiler environment, we seem to end up with statically
1984   * linked executables and an undefined reference to `_DYNAMIC`.
1985   */
1986  #    endif
1987  #    ifdef __GNUC__
1988  #      ifndef __INTEL_COMPILER
1989  #        define PREFETCH(x) __asm__("        lfetch  [%0]" : : "r"(x))
1990  #        define GC_PREFETCH_FOR_WRITE(x) \
1991            __asm__("        lfetch.excl     [%0]" : : "r"(x))
1992  #        define CLEAR_DOUBLE(x) \
1993            __asm__("        stf.spill       [%0]=f0" : : "r"((void *)(x)))
1994  #      else
1995  EXTERN_C_END
1996  #        include <ia64intrin.h>
1997  EXTERN_C_BEGIN
1998  #        define PREFETCH(x) __lfetch(__lfhint_none, (x))
1999  #        define GC_PREFETCH_FOR_WRITE(x) __lfetch(__lfhint_nta, (x))
2000  #        define CLEAR_DOUBLE(x) __stf_spill((void *)(x), 0)
2001  #      endif /* __INTEL_COMPILER */
2002  #    endif
2003  #  endif
2004  #  ifdef MSWIN32
2005  /* FIXME: This is a very partial guess.  There is no port, yet. */
2006  #    if defined(_WIN64)
2007  #      define CPP_WORDSZ 64
2008  #    else
2009  /* TODO: Is this possible? */
2010  #      define CPP_WORDSZ 32
2011  #    endif
2012  #  endif
2013  #endif /* IA64 */
2014  
2015  #ifdef E2K
2016  #  define MACH_TYPE "E2K"
2017  #  ifdef __LP64__
2018  #    define CPP_WORDSZ 64
2019  #  else
2020  #    define CPP_WORDSZ 32
2021  #  endif
2022  #  ifndef HBLKSIZE
2023  #    define HBLKSIZE 4096
2024  #  endif
2025  #  ifdef LINUX
2026  extern int __dso_handle[];
2027  #    define DATASTART ((ptr_t)__dso_handle)
2028  #    ifdef REDIRECT_MALLOC
2029  #      define NO_PROC_FOR_LIBRARIES
2030  #    endif
2031  #  endif
2032  #endif /* E2K */
2033  
2034  #ifdef M88K
2035  #  define MACH_TYPE "M88K"
2036  #  define CPP_WORDSZ 32
2037  #  define STACKBOTTOM MAKE_CPTR(0xf0000000) /*< determined empirically */
2038  extern int etext[];
2039  #  ifdef CX_UX
2040  #    define OS_TYPE "CX_UX"
2041  #    define DATASTART (PTR_ALIGN_UP((ptr_t)etext, 0x400000) + 0x10000)
2042  #  endif
2043  #  ifdef DGUX
2044  #    define OS_TYPE "DGUX"
2045  #    define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)etext)
2046  #    define DATASTART_USES_XGETDATASTART
2047  #  endif
2048  #endif /* M88K */
2049  
2050  #ifdef S370
2051  /*
2052   * If this still works, and if anyone cares, this should probably be moved
2053   * to the `S390` category.
2054   */
2055  #  define MACH_TYPE "S370"
2056  #  define CPP_WORDSZ 32
2057  #  define ALIGNMENT 4 /*< required by hardware */
2058  #  ifdef UTS4
2059  #    define OS_TYPE "UTS4"
2060  extern int _etext[], _end[];
2061  #    define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext)
2062  #    define DATAEND ((ptr_t)_end)
2063  #    define HEURISTIC2
2064  #  endif
2065  #endif /* S370 */
2066  
2067  #ifdef S390
2068  #  define MACH_TYPE "S390"
2069  #  ifndef __s390x__
2070  #    define CPP_WORDSZ 32
2071  #  else
2072  #    define CPP_WORDSZ 64
2073  #    ifndef HBLKSIZE
2074  #      define HBLKSIZE 4096
2075  #    endif
2076  #  endif
2077  #  ifdef LINUX
2078  extern int __data_start[] __attribute__((__weak__));
2079  extern int _end[] __attribute__((__weak__));
2080  #    define DATASTART ((ptr_t)__data_start)
2081  #    define DATAEND ((ptr_t)_end)
2082  #    define CACHE_LINE_SIZE 256
2083  #    define GETPAGESIZE() 4096
2084  #    ifndef SOFT_VDB
2085  #      define SOFT_VDB
2086  #    endif
2087  #  endif
2088  #endif /* S390 */
2089  
2090  #ifdef AARCH64
2091  #  define MACH_TYPE "AARCH64"
2092  #  ifdef __ILP32__
2093  #    define CPP_WORDSZ 32
2094  #  else
2095  #    define CPP_WORDSZ 64
2096  #  endif
2097  #  ifndef HBLKSIZE
2098  #    define HBLKSIZE 4096
2099  #  endif
2100  #  ifdef LINUX
2101  #    if defined(HOST_ANDROID)
2102  #      define SEARCH_FOR_DATA_START
2103  #    else
2104  extern int __data_start[] __attribute__((__weak__));
2105  #      define DATASTART ((ptr_t)__data_start)
2106  #    endif
2107  #  endif
2108  #  ifdef COSMO
2109  /* Empty. */
2110  #  endif
2111  #  ifdef DARWIN
2112  /* OS X, iOS, visionOS */
2113  #    define DARWIN_DONT_PARSE_STACK 1
2114  #    define STACKBOTTOM MAKE_CPTR(0x16fdfffff)
2115  #    if (TARGET_OS_IPHONE || TARGET_OS_XR || TARGET_OS_VISION)
2116  /*
2117   * `MPROTECT_VDB` causes use of non-public API like `exc_server`, this
2118   * could be a reason for blocking the client application in the store.
2119   */
2120  #    elif TARGET_OS_OSX
2121  #      define MPROTECT_VDB
2122  #    endif
2123  #  endif
2124  #  ifdef FREEBSD
2125  /* Nothing specific. */
2126  #  endif
2127  #  ifdef NETBSD
2128  #    define ELF_CLASS ELFCLASS64
2129  #  endif
2130  #  ifdef OPENBSD
2131  /* Nothing specific. */
2132  #  endif
2133  #  ifdef NINTENDO_SWITCH
2134  #    define OS_TYPE "NINTENDO_SWITCH"
2135  #    define NO_HANDLE_FORK 1
2136  extern int __bss_end[];
2137  #    define DATASTART ((ptr_t)ALIGNMENT) /*< cannot be `NULL` */
2138  #    define DATAEND ((ptr_t)(&__bss_end))
2139  void *switch_get_stack_bottom(void);
2140  #    define STACKBOTTOM ((ptr_t)switch_get_stack_bottom())
2141  void *switch_get_mem(size_t lb);
2142  #    define GET_MEM(lb) switch_get_mem(lb)
2143  #    define GETPAGESIZE() 4096
2144  #    undef USE_MMAP
2145  #    undef USE_MUNMAP
2146  #    ifndef HAVE_CLOCK_GETTIME
2147  #      define HAVE_CLOCK_GETTIME 1
2148  #    endif
2149  #  endif
2150  #  ifdef KOS
2151  /* Nothing specific. */
2152  #  endif
2153  #  ifdef QNX
2154  /* Nothing specific. */
2155  #  endif
2156  #  ifdef SERENITY
2157  /* Nothing specific. */
2158  #  endif
2159  #  ifdef MSWIN32
2160  /* UWP */
2161  /* TODO: Enable `MPROTECT_VDB`. */
2162  #  endif
2163  #  ifdef NOSYS
2164  #    define OS_TYPE "NOSYS"
2165  /* `__data_start` is usually defined in the target linker script. */
2166  extern int __data_start[];
2167  #    define DATASTART ((ptr_t)__data_start)
2168  extern void *__stack_base__;
2169  #    define STACKBOTTOM ((ptr_t)__stack_base__)
2170  #  endif
2171  #endif /* AARCH64 */
2172  
2173  #ifdef ARM32
2174  #  define MACH_TYPE "ARM32"
2175  #  define CPP_WORDSZ 32
2176  #  ifdef LINUX
2177  #    if GC_GLIBC_PREREQ(2, 0) || defined(HOST_ANDROID)
2178  #      define SEARCH_FOR_DATA_START
2179  #    else
2180  /* See the comment of the Linux/m68k case. */
2181  extern char **__environ;
2182  #      define DATASTART ((ptr_t)(&__environ))
2183  #    endif
2184  #  endif
2185  #  ifdef MSWINCE
2186  /* Nothing specific. */
2187  #  endif
2188  #  ifdef FREEBSD
2189  /* Nothing specific. */
2190  #  endif
2191  #  ifdef DARWIN
2192  /* iOS */
2193  #    define DARWIN_DONT_PARSE_STACK 1
2194  #    define STACKBOTTOM MAKE_CPTR(0x30000000)
2195  /* `MPROTECT_VDB` causes use of non-public API. */
2196  #  endif
2197  #  ifdef NETBSD
2198  /* Nothing specific. */
2199  #  endif
2200  #  ifdef OPENBSD
2201  /* Nothing specific. */
2202  #  endif
2203  #  ifdef QNX
2204  /* Nothing specific. */
2205  #  endif
2206  #  ifdef SN_TARGET_PSP2
2207  #    define OS_TYPE "SN_TARGET_PSP2"
2208  #    define NO_HANDLE_FORK 1
2209  #    ifndef HBLKSIZE
2210  #      define HBLKSIZE 65536 /*< page size is 64 KB */
2211  #    endif
2212  #    define DATASTART ((ptr_t)ALIGNMENT)
2213  #    define DATAEND ((ptr_t)ALIGNMENT)
2214  void *psp2_get_stack_bottom(void);
2215  #    define STACKBOTTOM ((ptr_t)psp2_get_stack_bottom())
2216  void *psp2_get_mem(size_t lb);
2217  #    define GET_MEM(lb) psp2_get_mem(lb)
2218  #  endif
2219  #  ifdef NN_PLATFORM_CTR
2220  #    define OS_TYPE "NN_PLATFORM_CTR"
2221  extern unsigned char Image$$ZI$$ZI$$Base[];
2222  #    define DATASTART ((ptr_t)Image$$ZI$$ZI$$Base)
2223  extern unsigned char Image$$ZI$$ZI$$Limit[];
2224  #    define DATAEND ((ptr_t)Image$$ZI$$ZI$$Limit)
2225  void *n3ds_get_stack_bottom(void);
2226  #    define STACKBOTTOM ((ptr_t)n3ds_get_stack_bottom())
2227  #  endif
2228  #  ifdef MSWIN32
2229  /* UWP */
2230  /* TODO: Enable `MPROTECT_VDB`. */
2231  #  endif
2232  #  ifdef NOSYS
2233  #    define OS_TYPE "NOSYS"
2234  /* `__data_start` is usually defined in the target linker script. */
2235  extern int __data_start[];
2236  #    define DATASTART ((ptr_t)__data_start)
2237  /* `__stack_base__` is set in platform `newlib/libc/sys/arm/crt0.S` file. */
2238  extern void *__stack_base__;
2239  #    define STACKBOTTOM ((ptr_t)__stack_base__)
2240  #  endif
2241  #  ifdef SYMBIAN
2242  /* Nothing specific. */
2243  #  endif
2244  #endif /* ARM32 */
2245  
2246  #ifdef CRIS
2247  #  define MACH_TYPE "CRIS"
2248  #  define CPP_WORDSZ 32
2249  #  define ALIGNMENT 1
2250  #  ifdef LINUX
2251  #    define SEARCH_FOR_DATA_START
2252  #  endif
2253  #endif /* CRIS */
2254  
2255  #if defined(SH) && !defined(SH4)
2256  #  define MACH_TYPE "SH"
2257  #  define CPP_WORDSZ 32
2258  #  ifdef LINUX
2259  #    define SEARCH_FOR_DATA_START
2260  #  endif
2261  #  ifdef NETBSD
2262  /* Nothing specific. */
2263  #  endif
2264  #  ifdef OPENBSD
2265  /* Nothing specific. */
2266  #  endif
2267  #  ifdef MSWINCE
2268  /* Nothing specific. */
2269  #  endif
2270  #endif
2271  
2272  #ifdef SH4
2273  #  define MACH_TYPE "SH4"
2274  #  define CPP_WORDSZ 32
2275  #  ifdef MSWINCE
2276  /* Nothing specific. */
2277  #  endif
2278  #endif /* SH4 */
2279  
2280  #ifdef AVR32
2281  #  define MACH_TYPE "AVR32"
2282  #  define CPP_WORDSZ 32
2283  #  ifdef LINUX
2284  #    define SEARCH_FOR_DATA_START
2285  #  endif
2286  #endif /* AVR32 */
2287  
2288  #ifdef M32R
2289  #  define MACH_TYPE "M32R"
2290  #  define CPP_WORDSZ 32
2291  #  ifdef LINUX
2292  #    define SEARCH_FOR_DATA_START
2293  #  endif
2294  #endif /* M32R */
2295  
2296  #ifdef X86_64
2297  #  define MACH_TYPE "X86_64"
2298  #  ifdef __ILP32__
2299  #    define CPP_WORDSZ 32
2300  #  else
2301  #    define CPP_WORDSZ 64
2302  #  endif
2303  #  ifndef HBLKSIZE
2304  #    define HBLKSIZE 4096
2305  #  endif
2306  #  ifndef CACHE_LINE_SIZE
2307  #    define CACHE_LINE_SIZE 64
2308  #  endif
2309  #  ifdef PLATFORM_GETMEM
2310  #    define OS_TYPE "PLATFORM_GETMEM"
2311  #    define DATASTART ((ptr_t)ALIGNMENT)
2312  #    define DATAEND ((ptr_t)ALIGNMENT)
2313  EXTERN_C_END
2314  #    include <pthread.h>
2315  EXTERN_C_BEGIN
2316  void *platform_get_stack_bottom(void);
2317  #    define STACKBOTTOM ((ptr_t)platform_get_stack_bottom())
2318  void *platform_get_mem(size_t lb);
2319  #    define GET_MEM(lb) platform_get_mem(lb)
2320  #  endif
2321  #  ifdef LINUX
2322  #    define SEARCH_FOR_DATA_START
2323  #    if defined(__GLIBC__) && !defined(__UCLIBC__)
2324  /*
2325   * A workaround for GCF (Google Cloud Function) which does not support
2326   * `mmap()` for `/dev/zero` pseudo-file.  Should not cause any harm to
2327   * other targets.
2328   */
2329  #      define USE_MMAP_ANON
2330  #    endif
2331  #    if defined(__GLIBC__) && !defined(__UCLIBC__) \
2332          && !defined(GETCONTEXT_FPU_BUG_FIXED)
2333  /*
2334   * At present, there is a bug in `glibc` `getcontext()` on Linux/x86_64
2335   * (it clears FPU exception mask).  We define this macro to workaround it.
2336   */
2337  /* TODO: This seems to be fixed in `glibc` 2.14. */
2338  #      define GETCONTEXT_FPU_EXCMASK_BUG
2339  #    endif
2340  #    if defined(__GLIBC__) && !defined(__UCLIBC__) \
2341          && !defined(GLIBC_TSX_BUG_FIXED)
2342  /* Workaround lock elision implementation for some `glibc`. */
2343  #      define GLIBC_2_19_TSX_BUG
2344  EXTERN_C_END
2345  #      include <gnu/libc-version.h> /*< for `gnu_get_libc_version()` */
2346  EXTERN_C_BEGIN
2347  #    endif
2348  #    ifndef SOFT_VDB
2349  #      define SOFT_VDB
2350  #    endif
2351  #  endif
2352  #  ifdef COSMO
2353  /* Empty. */
2354  #  endif
2355  #  ifdef DARWIN
2356  #    define DARWIN_DONT_PARSE_STACK 1
2357  #    define STACKBOTTOM MAKE_CPTR(0x7fff5fc00000)
2358  #    define MPROTECT_VDB
2359  #  endif
2360  #  ifdef FREEBSD
2361  #    if defined(__GLIBC__)
2362  extern int _end[];
2363  #      define DATAEND ((ptr_t)_end)
2364  #    endif
2365  #    if defined(__DragonFly__)
2366  /*
2367   * DragonFly BSD still has `vm.max_proc_mmap`, according to its
2368   * `mmap(2)` man page.
2369   */
2370  #      define COUNT_UNMAPPED_REGIONS
2371  #    endif
2372  #  endif
2373  #  ifdef NETBSD
2374  /* Nothing specific. */
2375  #  endif
2376  #  ifdef OPENBSD
2377  /* Nothing specific. */
2378  #  endif
2379  #  ifdef HAIKU
2380  /* Nothing specific. */
2381  #  endif
2382  #  ifdef HURD
2383  /* Nothing specific. */
2384  #  endif
2385  #  ifdef QNX
2386  /* Nothing specific. */
2387  #  endif
2388  #  ifdef SERENITY
2389  /* Nothing specific. */
2390  #  endif
2391  #  ifdef SOLARIS
2392  #    define ELF_CLASS ELFCLASS64
2393  extern int _etext[];
2394  #    define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)_etext)
2395  #    define PROC_VDB
2396  #  endif
2397  #  ifdef CYGWIN32
2398  #    ifndef USE_WINALLOC
2399  #      if defined(THREAD_LOCAL_ALLOC)
2400  /*
2401   * TODO: For an unknown reason, thread-local allocations lead to spurious
2402   * process exit after the fault handler is once invoked.
2403   */
2404  #      else
2405  #        define MPROTECT_VDB
2406  #      endif
2407  #    endif
2408  #  endif
2409  #  ifdef MSWIN_XBOX1
2410  #    define OS_TYPE "MSWIN_XBOX1"
2411  #    define NO_GETENV
2412  #    define DATASTART ((ptr_t)ALIGNMENT)
2413  #    define DATAEND ((ptr_t)ALIGNMENT)
2414  LONG64 durango_get_stack_bottom(void);
2415  #    define STACKBOTTOM ((ptr_t)durango_get_stack_bottom())
2416  #    define GETPAGESIZE() 4096
2417  #    ifndef USE_MMAP
2418  #      define USE_MMAP 1
2419  #    endif
2420  /* The following is from platform `sys/mman.h` file. */
2421  #    define PROT_NONE 0
2422  #    define PROT_READ 1
2423  #    define PROT_WRITE 2
2424  #    define PROT_EXEC 4
2425  #    define MAP_PRIVATE 2
2426  #    define MAP_FIXED 0x10
2427  #    define MAP_FAILED ((void *)(~(GC_uintptr_t)0))
2428  #  endif
2429  #  ifdef MSWIN32
2430  #    define RETRY_GET_THREAD_CONTEXT
2431  #    if !defined(__GNUC__) || defined(__INTEL_COMPILER) \
2432          || (GC_GNUC_PREREQ(4, 7) && !defined(__MINGW64__))
2433  /*
2434   * Older gcc and Mingw-w64 (both gcc and clang) do not support
2435   * `SetUnhandledExceptionFilter()` properly on x86_64.
2436   */
2437  #      define MPROTECT_VDB
2438  #    endif
2439  #  endif
2440  #endif /* X86_64 */
2441  
2442  #ifdef ARC
2443  #  define MACH_TYPE "ARC"
2444  #  define CPP_WORDSZ 32
2445  #  define CACHE_LINE_SIZE 64
2446  #  ifdef LINUX
2447  extern int __data_start[] __attribute__((__weak__));
2448  #    define DATASTART ((ptr_t)__data_start)
2449  #  endif
2450  #endif /* ARC */
2451  
2452  #ifdef HEXAGON
2453  #  define MACH_TYPE "HEXAGON"
2454  #  define CPP_WORDSZ 32
2455  #  ifdef LINUX
2456  #    if defined(__GLIBC__)
2457  #      define SEARCH_FOR_DATA_START
2458  #    elif !defined(CPPCHECK)
2459  #      error Unknown Hexagon libc configuration
2460  #    endif
2461  #  endif
2462  #endif /* HEXAGON */
2463  
2464  #ifdef TILEPRO
2465  #  define MACH_TYPE "TILEPRO"
2466  #  define CPP_WORDSZ 32
2467  #  define PREFETCH(x) __insn_prefetch(x)
2468  #  define CACHE_LINE_SIZE 64
2469  #  ifdef LINUX
2470  extern int __data_start[];
2471  #    define DATASTART ((ptr_t)__data_start)
2472  #  endif
2473  #endif /* TILEPRO */
2474  
2475  #ifdef TILEGX
2476  #  define MACH_TYPE "TILEGX"
2477  #  define CPP_WORDSZ (__SIZEOF_PTRDIFF_T__ * 8)
2478  #  if CPP_WORDSZ == 32
2479  #    define CLEAR_DOUBLE(x) (void)(*(long long *)(x) = 0)
2480  #  endif
2481  #  define PREFETCH(x) __insn_prefetch_l1(x)
2482  #  define CACHE_LINE_SIZE 64
2483  #  ifdef LINUX
2484  extern int __data_start[];
2485  #    define DATASTART ((ptr_t)__data_start)
2486  #  endif
2487  #endif /* TILEGX */
2488  
2489  #ifdef RISCV
2490  #  define MACH_TYPE "RISCV"
2491  #  define CPP_WORDSZ (__SIZEOF_SIZE_T__ * 8) /*< 32 or 64 */
2492  #  ifdef FREEBSD
2493  /* Nothing specific. */
2494  #  endif
2495  #  ifdef LINUX
2496  extern int __data_start[] __attribute__((__weak__));
2497  #    define DATASTART ((ptr_t)__data_start)
2498  #  endif
2499  #  ifdef NETBSD
2500  /* Nothing specific. */
2501  #  endif
2502  #  ifdef OPENBSD
2503  /* Nothing specific. */
2504  #  endif
2505  #  ifdef NOSYS
2506  #    define OS_TYPE "NOSYS"
2507  extern char etext[];
2508  #    define DATASTART ((ptr_t)etext)
2509  /* FIXME: `STACKBOTTOM` is wrong! */
2510  extern char **environ;
2511  #    define STACKBOTTOM ((ptr_t)environ)
2512  /* TODO: Support 64K page size. */
2513  #    define GETPAGESIZE() 4096
2514  #  endif
2515  #endif /* RISCV */
2516  
2517  #ifdef WEBASSEMBLY
2518  #  define MACH_TYPE "WEBASSEMBLY"
2519  #  if defined(__wasm64__) && !defined(CPPCHECK)
2520  #    error 64-bit WebAssembly is not yet supported
2521  #  endif
2522  #  define CPP_WORDSZ 32
2523  /*
2524   * Emscripten does emulate `mmap` and `munmap`, but those should not be
2525   * used in the collector, since WebAssembly lacks the native support of
2526   * memory mapping.  Use `sbrk()` instead (by default).
2527   */
2528  #  undef USE_MMAP
2529  #  undef USE_MUNMAP
2530  #  ifdef EMSCRIPTEN_TINY
2531  void *emmalloc_memalign(size_t align, size_t lb);
2532  #    define GET_MEM(lb) emmalloc_memalign(GC_page_size, lb)
2533  #  endif
2534  #  ifdef EMSCRIPTEN
2535  #    define OS_TYPE "EMSCRIPTEN"
2536  #    define DATASTART ((ptr_t)ALIGNMENT)
2537  #    define DATAEND ((ptr_t)ALIGNMENT)
2538  #    if defined(GC_THREADS) && !defined(CPPCHECK)
2539  #      error No thread support yet
2540  #    endif
2541  #  endif
2542  #  ifdef WASI
2543  #    define OS_TYPE "WASI"
2544  extern char __global_base, __heap_base;
2545  #    define DATASTART ((ptr_t)(&__global_base))
2546  #    define DATAEND ((ptr_t)(&__heap_base))
2547  #    define STACKBOTTOM DATASTART
2548  #    ifndef GC_NO_SIGSETJMP
2549  #      define GC_NO_SIGSETJMP 1 /*< no support of signals */
2550  #    endif
2551  #    ifndef NO_CLOCK
2552  #      define NO_CLOCK 1 /*< no support of `clock()` */
2553  #    endif
2554  #    if defined(GC_THREADS) && !defined(CPPCHECK)
2555  #      error No thread support yet
2556  #    endif
2557  #  endif
2558  #endif /* WEBASSEMBLY */
2559  
2560  #if defined(CYGWIN32) || defined(MSWIN32) || defined(MSWINCE)
2561  /* Note: it does not include Xbox One. */
2562  #  define ANY_MSWIN
2563  #endif
2564  
2565  #if defined(GC_PTHREADS) || defined(GC_WIN32_THREADS)          \
2566      || ((defined(NN_PLATFORM_CTR) || defined(NINTENDO_SWITCH)  \
2567           || defined(SN_TARGET_PS3) || defined(SN_TARGET_PSP2)) \
2568          && defined(GC_THREADS))
2569  #  define THREADS
2570  #endif
2571  
2572  /*
2573   * If the client app is known not to create threads (even indirectly in
2574   * the used libraries) and the collector is not multi-threaded, then the
2575   * collector could be built with `SINGLE_THREADED_PROCESS` macro defined.
2576   * But in practice the macro should never be defined.
2577   */
2578  #if defined(THREADS) && defined(SINGLE_THREADED_PROCESS)
2579  #  undef SINGLE_THREADED_PROCESS
2580  #endif
2581  
2582  #if defined(__CHERI_PURE_CAPABILITY__)
2583  #  define CHERI_PURECAP
2584  #endif
2585  
2586  #if defined(__GLIBC__) && !defined(DONT_USE_LIBC_PRIVATES)
2587  /* Use the stack-end marker of `glibc`. */
2588  #  define USE_LIBC_PRIVATES
2589  #endif
2590  
2591  #ifdef NO_RETRY_GET_THREAD_CONTEXT
2592  #  undef RETRY_GET_THREAD_CONTEXT
2593  #endif
2594  
2595  #if defined(LINUX) && defined(SPECIFIC_MAIN_STACKBOTTOM) \
2596      && defined(NO_PROC_STAT) && !defined(USE_LIBC_PRIVATES)
2597  /*
2598   * This combination will fail, since we have no way to get the stack bottom.
2599   * Use `HEURISTIC2` instead.
2600   */
2601  #  undef SPECIFIC_MAIN_STACKBOTTOM
2602  #  define HEURISTIC2
2603  /* This may still fail on some architectures like `IA64`.  We tried... */
2604  #endif
2605  
2606  #if defined(USE_MMAP_ANON) && !defined(USE_MMAP)
2607  #  define USE_MMAP 1
2608  #elif (defined(LINUX) || defined(OPENBSD)) && defined(USE_MMAP)
2609  /*
2610   * The OS kernel may do a somewhat better job merging mappings with
2611   * anonymous mappings.
2612   */
2613  #  define USE_MMAP_ANON
2614  #endif
2615  
2616  #if defined(CHERI_PURECAP) && defined(USE_MMAP)
2617  /* TODO: Currently turned off to avoid downgrading permissions on CHERI. */
2618  #  undef USE_MUNMAP
2619  #endif
2620  
2621  #if (defined(E2K) && defined(USE_PTR_HWTAG) || defined(CHERI_PURECAP)) \
2622      && !defined(NO_BLACK_LISTING)
2623  /*
2624   * Misinterpreting of an integer is not possible on the platforms with
2625   * H/W-tagged pointers, thus the black-listing mechanism is redundant.
2626   */
2627  #  define NO_BLACK_LISTING
2628  #endif
2629  
2630  #if defined(REDIRECT_MALLOC) && defined(THREADS) \
2631      && (defined(LINUX) || defined(NACL))
2632  /* TODO: Unclear if NaCl really needs this. */
2633  #  define REDIR_MALLOC_AND_LINUXTHREADS
2634  #endif
2635  
2636  #if defined(REDIR_MALLOC_AND_LINUXTHREADS) && !defined(NO_PROC_FOR_LIBRARIES) \
2637      && !defined(USE_PROC_FOR_LIBRARIES)
2638  /*
2639   * NPTL allocates thread stacks with `mmap`, which is fine.  But it
2640   * keeps a cache of thread stacks.  Each thread stack contains a thread
2641   * control block (TCB).  The latter, in turn, contains a pointer to
2642   * (`sizeof(void*)` from the beginning of) the `dtv` for thread-local
2643   * storage, which is `calloc`-allocated.  If we do not scan the cached
2644   * thread stacks, we appear to lose the `dtv`.  This tends to result in
2645   * something that looks like a bogus `dtv` count, which tends to result
2646   * in a `memset()` call on a block that is way too large.  Sometimes
2647   * we are lucky and the process just dies...  There seems to be
2648   * a similar issue with some other memory allocated by the dynamic
2649   * loader.  This should be avoidable by either:
2650   *   - Defining `USE_PROC_FOR_LIBRARIES` here (that performs very poorly,
2651   *     precisely because we end up scanning cached stacks);
2652   *   - Have `calloc()` look at its callers (in spite of the fact that it
2653   *     is gross and disgusting).
2654   *
2655   * In fact, neither seems to suffice, probably in part because even
2656   * with `USE_PROC_FOR_LIBRARIES`, we do not scan parts of stack
2657   * segments that appear to be out of bounds.  Thus we actually do both,
2658   * which seems to yield the best results.
2659   */
2660  #  define USE_PROC_FOR_LIBRARIES
2661  #endif
2662  
2663  #ifndef OS_TYPE
2664  #  define OS_TYPE ""
2665  #endif
2666  
2667  #ifndef MACH_TYPE
2668  #  define MACH_TYPE ""
2669  #endif
2670  
2671  #ifndef DATAEND
2672  extern int end[];
2673  #  define DATAEND ((ptr_t)end)
2674  #endif
2675  
2676  /*
2677   * Workaround for Android NDK clang-3.5+ (as of NDK r10e) which does
2678   * not provide correct `_end` symbol.  Unfortunately, alternate `__end__`
2679   * symbol is provided only by NDK `bfd` linker.
2680   */
2681  #if defined(HOST_ANDROID) && defined(__clang__) && !defined(BROKEN_UUENDUU_SYM)
2682  #  undef DATAEND
2683  #  pragma weak __end__
2684  extern int __end__[];
2685  #  define DATAEND (__end__ != 0 ? (ptr_t)__end__ : (ptr_t)_end)
2686  #endif
2687  
2688  #if defined(SOLARIS) || defined(DRSNX) || defined(UTS4) \
2689      || (defined(LINUX) && defined(SPARC))
2690  /* OS has SVR4 generic features.  Probably others also qualify. */
2691  #  define SVR4
2692  #  define DATASTART_USES_XGETDATASTART
2693  #endif
2694  
2695  #if defined(HAVE_SYS_TYPES_H)                                      \
2696      || !(defined(__CC_ARM) || defined(GC_NO_TYPES) || defined(OS2) \
2697           || defined(MSWINCE) || defined(SN_TARGET_PSP2))
2698  EXTERN_C_END
2699  #  if defined(COSMO) && defined(MPROTECT_VDB) && !defined(_GNU_SOURCE)
2700  #    define _GNU_SOURCE 1
2701  #  endif
2702  #  include <sys/types.h>
2703  EXTERN_C_BEGIN
2704  #endif /* HAVE_SYS_TYPES_H */
2705  
2706  #if defined(HAVE_UNISTD_H)                                                \
2707      || !(defined(GC_NO_TYPES) || defined(MSWIN32) || defined(MSWINCE)     \
2708           || defined(MSWIN_XBOX1) || defined(NINTENDO_SWITCH)              \
2709           || defined(NN_PLATFORM_CTR) || defined(OS2) || defined(SERENITY) \
2710           || defined(SN_TARGET_PSP2) || defined(__CC_ARM))
2711  EXTERN_C_END
2712  #  include <unistd.h>
2713  EXTERN_C_BEGIN
2714  #endif /* HAVE_UNISTD_H */
2715  
2716  #if !defined(ANY_MSWIN) && !defined(GETPAGESIZE)
2717  #  if defined(DGUX) || defined(HOST_ANDROID) || defined(HOST_TIZEN) \
2718        || defined(KOS) || defined(SERENITY)                          \
2719        || (defined(LINUX) && defined(SPARC))
2720  #    define GETPAGESIZE() (unsigned)sysconf(_SC_PAGESIZE)
2721  #  else
2722  #    define GETPAGESIZE() (unsigned)getpagesize()
2723  #  endif
2724  #endif /* !ANY_MSWIN && !GETPAGESIZE */
2725  
2726  #if defined(HOST_ANDROID) && !(__ANDROID_API__ >= 23)           \
2727      && ((defined(MIPS) && (CPP_WORDSZ == 32)) || defined(ARM32) \
2728          || defined(I386) /* but not x32 */)
2729  /*
2730   * `tkill()` exists only on arm32/mips(32)/x86.
2731   * NDK r11+ deprecates `tkill()` but keeps it for Mono clients.
2732   */
2733  #  define USE_TKILL_ON_ANDROID
2734  #endif
2735  
2736  #if defined(MPROTECT_VDB) && defined(__GLIBC__) && !GC_GLIBC_PREREQ(2, 2)
2737  #  error glibc too old?
2738  #endif
2739  
2740  #if defined(SOLARIS) || defined(DRSNX)
2741  /* OS has Solaris-style semi-undocumented interface to dynamic loader. */
2742  #  define SOLARISDL
2743  /* OS has Solaris-style signal handlers. */
2744  #  define SUNOS5SIGS
2745  #endif
2746  
2747  #if (defined(FREEBSD)                                     \
2748       && (defined(__DragonFly__) || defined(__GLIBC__)     \
2749           || __FreeBSD_kernel__ >= 4 || __FreeBSD__ >= 4)) \
2750      || defined(HPUX)
2751  #  define SUNOS5SIGS
2752  #endif
2753  
2754  #if defined(COSMO) || defined(HPUX) || defined(HURD) || defined(NETBSD) \
2755      || defined(SERENITY) || (defined(FREEBSD) && defined(SUNOS5SIGS))   \
2756      || (defined(IRIX5) && defined(_sigargs)) /*< Irix 5.x, not 6.x */
2757  #  define USE_SEGV_SIGACT
2758  /* We may also get `SIGBUS`. */
2759  #  define USE_BUS_SIGACT
2760  #elif defined(ANY_BSD) || defined(HAIKU) || defined(IRIX5) || defined(OSF1) \
2761      || defined(SUNOS5SIGS)
2762  #  define USE_SEGV_SIGACT
2763  #endif
2764  
2765  #if !defined(GC_EXPLICIT_SIGNALS_UNBLOCK) && defined(SUNOS5SIGS) \
2766      && !defined(GC_NO_PTHREAD_SIGMASK)
2767  #  define GC_EXPLICIT_SIGNALS_UNBLOCK
2768  #endif
2769  
2770  #if !defined(NO_SIGNALS_UNBLOCK_IN_MAIN) && defined(GC_NO_PTHREAD_SIGMASK)
2771  #  define NO_SIGNALS_UNBLOCK_IN_MAIN
2772  #endif
2773  
2774  #ifndef PARALLEL_MARK
2775  #  undef GC_PTHREADS_PARAMARK /*< just in case it is defined by client */
2776  #elif defined(GC_PTHREADS) && !defined(GC_PTHREADS_PARAMARK) \
2777      && !defined(__MINGW32__)
2778  /*
2779   * Use `pthreads`-based parallel mark implementation.  Except for
2780   * MinGW 32/64 to workaround a deadlock in winpthreads-3.0b internals.
2781   */
2782  #  define GC_PTHREADS_PARAMARK
2783  #endif
2784  
2785  #if !defined(NO_MARKER_SPECIAL_SIGMASK)                                 \
2786      && (defined(NACL) || defined(GC_WIN32_PTHREADS)                     \
2787          || (defined(GC_PTHREADS_PARAMARK) && defined(GC_WIN32_THREADS)) \
2788          || defined(GC_NO_PTHREAD_SIGMASK))
2789  /*
2790   * Either there is no `pthread_sigmask()`, or the GC marker thread cannot
2791   * steal and drop user signal calls.
2792   */
2793  #  define NO_MARKER_SPECIAL_SIGMASK
2794  #endif
2795  
2796  #if defined(NETBSD) && defined(THREADS)
2797  #  define SIGRTMIN 33
2798  #  define SIGRTMAX 63
2799  /*
2800   * It seems to be necessary to wait until threads have restarted.
2801   * But it is unclear why that is the case.
2802   */
2803  #  define GC_NETBSD_THREADS_WORKAROUND
2804  #endif
2805  
2806  #if defined(OPENBSD) && defined(THREADS)
2807  EXTERN_C_END
2808  #  include <sys/param.h>
2809  EXTERN_C_BEGIN
2810  #endif
2811  
2812  #if defined(AIX) || defined(ANY_BSD) || defined(BSD) || defined(COSMO)     \
2813      || defined(DARWIN) || defined(DGUX) || defined(HAIKU) || defined(HPUX) \
2814      || defined(HURD) || defined(IRIX5) || defined(LINUX) || defined(OSF1)  \
2815      || defined(QNX) || defined(SERENITY) || defined(SVR4)
2816  /* Basic UNIX-like system calls work. */
2817  #  define UNIX_LIKE
2818  #endif
2819  
2820  #if defined(CPPCHECK)
2821  #  undef CPP_WORDSZ
2822  #  define CPP_WORDSZ (__SIZEOF_PTRDIFF_T__ * 8)
2823  #elif CPP_WORDSZ != 32 && CPP_WORDSZ != 64
2824  #  error Bad word size
2825  #endif
2826  
2827  #ifndef CPP_PTRSZ
2828  #  ifdef CHERI_PURECAP
2829  #    define CPP_PTRSZ (__SIZEOF_POINTER__ * 8)
2830  #  else
2831  #    define CPP_PTRSZ CPP_WORDSZ
2832  #  endif
2833  #endif
2834  
2835  #ifndef CPPCHECK
2836  #  if GC_SIZEOF_PTR * 8 != CPP_PTRSZ
2837  #    error Bad pointer size
2838  #  endif
2839  #endif /* !CPPCHECK */
2840  
2841  #ifndef ALIGNMENT
2842  #  define ALIGNMENT (CPP_PTRSZ >> 3)
2843  #endif
2844  
2845  #if !defined(STACKBOTTOM) && (defined(ECOS) || defined(NOSYS)) \
2846      && !defined(CPPCHECK)
2847  #  error Undefined STACKBOTTOM
2848  #endif
2849  
2850  #ifdef IGNORE_DYNAMIC_LOADING
2851  #  undef DYNAMIC_LOADING
2852  #endif
2853  
2854  #if defined(SMALL_CONFIG) && !defined(GC_DISABLE_INCREMENTAL)
2855  /* Presumably not worth the space it takes. */
2856  #  define GC_DISABLE_INCREMENTAL
2857  #endif
2858  
2859  /* `USE_WINALLOC` is only an option for Cygwin. */
2860  #ifndef CYGWIN32
2861  #  undef USE_WINALLOC
2862  #endif
2863  #if defined(MSWIN32) || defined(MSWINCE)
2864  #  define USE_WINALLOC 1
2865  #endif
2866  
2867  #ifdef USE_WINALLOC
2868  #  undef USE_MMAP
2869  #endif
2870  
2871  #if defined(ANY_BSD) || defined(DARWIN) || defined(IRIX5) || defined(LINUX) \
2872      || defined(SERENITY) || defined(SOLARIS)                                \
2873      || ((defined(CYGWIN32) || defined(USE_MMAP) || defined(USE_MUNMAP))     \
2874          && !defined(USE_WINALLOC))
2875  /* Try both `sbrk` and `mmap`, in that order. */
2876  #  define MMAP_SUPPORTED
2877  #endif
2878  
2879  /*
2880   * Xbox One (DURANGO) may not need to be this aggressive, but the
2881   * default is likely too lax under heavy allocation pressure.
2882   * The platform does not have a virtual paging system, so it does not
2883   * have a large virtual address space that a standard x86_64 platform has.
2884   */
2885  #if defined(USE_MUNMAP) && !defined(MUNMAP_THRESHOLD)     \
2886      && (defined(SN_TARGET_PS3) || defined(SN_TARGET_PSP2) \
2887          || defined(MSWIN_XBOX1))
2888  #  define MUNMAP_THRESHOLD 3
2889  #endif
2890  
2891  #if defined(GC_DISABLE_INCREMENTAL) || defined(DEFAULT_VDB)
2892  #  undef GWW_VDB
2893  #  undef MPROTECT_VDB
2894  #  undef PROC_VDB
2895  #  undef SOFT_VDB
2896  #endif
2897  
2898  #ifdef NO_GWW_VDB
2899  #  undef GWW_VDB
2900  #endif
2901  
2902  #ifdef NO_MPROTECT_VDB
2903  #  undef MPROTECT_VDB
2904  #endif
2905  
2906  #ifdef NO_SOFT_VDB
2907  #  undef SOFT_VDB
2908  #endif
2909  
2910  #if defined(SOFT_VDB) && defined(SOFT_VDB_LINUX_VER_STATIC_CHECK)
2911  EXTERN_C_END
2912  #  include <linux/version.h> /*< for `LINUX_VERSION`, `LINUX_VERSION_CODE` */
2913  EXTERN_C_BEGIN
2914  #  if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
2915  /* Not reliable in Linux kernels prior to v3.18. */
2916  #    undef SOFT_VDB
2917  #  endif
2918  #endif /* SOFT_VDB */
2919  
2920  #ifdef GC_DISABLE_INCREMENTAL
2921  #  undef CHECKSUMS
2922  #endif
2923  
2924  #if defined(BASE_ATOMIC_OPS_EMULATED)
2925  /*
2926   * `GC_write_fault_handler()` cannot use lock-based atomic primitives
2927   * as this could lead to a deadlock.
2928   */
2929  #  undef MPROTECT_VDB
2930  #endif
2931  
2932  #if defined(USE_PROC_FOR_LIBRARIES) && defined(LINUX) && defined(THREADS)
2933  /* Incremental GC based on `mprotect` is incompatible with `/proc` roots. */
2934  #  undef MPROTECT_VDB
2935  #endif
2936  
2937  #if defined(MPROTECT_VDB) && defined(GC_PREFER_MPROTECT_VDB)
2938  /* Choose `MPROTECT_VDB` manually (if multiple strategies available). */
2939  #  undef PROC_VDB
2940  /* `GWW_VDB`, `SOFT_VDB` are handled in `os_dep.c` file. */
2941  #endif
2942  
2943  #ifdef PROC_VDB
2944  /* Mutually exclusive VDB implementations (for now). */
2945  #  undef MPROTECT_VDB
2946  /* For a test purpose only. */
2947  #  undef SOFT_VDB
2948  #endif
2949  
2950  #if defined(MPROTECT_VDB) && !defined(MSWIN32) && !defined(MSWINCE)
2951  EXTERN_C_END
2952  #  include <signal.h> /*< for `SA_SIGINFO`, `SIGBUS` */
2953  EXTERN_C_BEGIN
2954  #endif
2955  
2956  #if defined(SIGBUS) && !defined(HAVE_SIGBUS) && !defined(CPPCHECK)
2957  #  define HAVE_SIGBUS
2958  #endif
2959  
2960  #ifndef SA_SIGINFO
2961  #  define NO_SA_SIGACTION
2962  #endif
2963  
2964  #if (defined(NO_SA_SIGACTION) || defined(GC_NO_SIGSETJMP))            \
2965      && defined(MPROTECT_VDB) && !defined(DARWIN) && !defined(MSWIN32) \
2966      && !defined(MSWINCE)
2967  #  undef MPROTECT_VDB
2968  #endif
2969  
2970  #if !defined(DEFAULT_VDB) && !defined(GWW_VDB) && !defined(MPROTECT_VDB) \
2971      && !defined(PROC_VDB) && !defined(SOFT_VDB)                          \
2972      && !defined(GC_DISABLE_INCREMENTAL)
2973  #  define DEFAULT_VDB
2974  #endif
2975  
2976  #if defined(CHECK_SOFT_VDB) && !defined(CPPCHECK)             \
2977      && (defined(GC_PREFER_MPROTECT_VDB) || !defined(SOFT_VDB) \
2978          || !defined(MPROTECT_VDB))
2979  #  error Invalid config for CHECK_SOFT_VDB
2980  #endif
2981  
2982  #if (defined(GC_DISABLE_INCREMENTAL) || defined(BASE_ATOMIC_OPS_EMULATED) \
2983       || defined(REDIRECT_MALLOC) || defined(SMALL_CONFIG)                 \
2984       || defined(REDIRECT_MALLOC_IN_HEADER) || defined(CHECKSUMS))         \
2985      && !defined(NO_MANUAL_VDB)
2986  /* TODO: Implement `CHECKSUMS` for manual VDB. */
2987  #  define NO_MANUAL_VDB
2988  #endif
2989  
2990  #if !defined(PROC_VDB) && !defined(SOFT_VDB) \
2991      && !defined(NO_VDB_FOR_STATIC_ROOTS)
2992  /* Cannot determine whether a static root page is dirty. */
2993  #  define NO_VDB_FOR_STATIC_ROOTS
2994  #endif
2995  
2996  #if defined(MPROTECT_VDB) && !defined(DONT_COUNT_PROTECTED_REGIONS) \
2997      && !defined(COUNT_PROTECTED_REGIONS)                            \
2998      && (defined(LINUX) || defined(__DragonFly__))
2999  #  define COUNT_PROTECTED_REGIONS
3000  #endif
3001  
3002  #if (defined(COUNT_PROTECTED_REGIONS) || defined(COUNT_UNMAPPED_REGIONS)) \
3003      && !defined(GC_UNMAPPED_REGIONS_SOFT_LIMIT)
3004  /*
3005   * The default limit of `vm.max_map_count` on Linux is ~65530.
3006   * There is approximately one mapped region to every protected or
3007   * unmapped region.  Therefore if we aim to use up to half of
3008   * `vm.max_map_count` for the collector (leaving half for the rest
3009   * of the process), then the number of such regions should be one
3010   * quarter of `vm.max_map_count`.
3011   */
3012  #  if defined(__DragonFly__)
3013  #    define GC_UNMAPPED_REGIONS_SOFT_LIMIT (1000000 / 4)
3014  #  else
3015  #    define GC_UNMAPPED_REGIONS_SOFT_LIMIT 16384
3016  #  endif
3017  #endif
3018  
3019  #if (((defined(ARM32) || defined(AVR32) || defined(MIPS) || defined(NIOS2) \
3020         || defined(OR1K))                                                   \
3021        && defined(UNIX_LIKE))                                               \
3022       || defined(DARWIN) || defined(HAIKU) || defined(HURD)                 \
3023       || defined(OPENBSD) || defined(QNX) || defined(RTEMS)                 \
3024       || defined(SERENITY) || defined(HOST_ANDROID)                         \
3025       || (defined(LINUX) && !defined(__gnu_linux__)))                       \
3026      && !defined(NO_GETCONTEXT)
3027  #  define NO_GETCONTEXT 1
3028  #endif
3029  
3030  #if defined(MSWIN32) && !defined(CONSOLE_LOG) && defined(_MSC_VER) \
3031      && defined(_DEBUG) && !defined(NO_CRT)
3032  /*
3033   * This should be included before the platform `intrin.h` file to
3034   * workaround some bug in Windows Kit (as of 10.0.17763) headers
3035   * causing redefinition of `_malloca` macro.
3036   */
3037  EXTERN_C_END
3038  #  include <crtdbg.h> /*< for `_CrtDbgReport` */
3039  EXTERN_C_BEGIN
3040  #endif
3041  
3042  #ifndef PREFETCH
3043  #  if (GC_GNUC_PREREQ(3, 0) || defined(__clang__)) && !defined(NO_PREFETCH)
3044  #    define PREFETCH(x) __builtin_prefetch((x), 0, 0)
3045  #  elif defined(_MSC_VER) && !defined(NO_PREFETCH)                      \
3046        && (defined(_M_IX86) || defined(_M_X64)) && !defined(_CHPE_ONLY_) \
3047        && (_MSC_VER >= 1900 /* VS 2015+ */)
3048  EXTERN_C_END
3049  #    include <intrin.h>
3050  EXTERN_C_BEGIN
3051  #    define PREFETCH(x) _mm_prefetch((const char *)(x), _MM_HINT_T0)
3052  /* TODO: Support also `_M_ARM` and `_M_ARM64` (`__prefetch`). */
3053  #  else
3054  #    define PREFETCH(x) (void)0
3055  #  endif
3056  #endif /* !PREFETCH */
3057  
3058  #ifndef GC_PREFETCH_FOR_WRITE
3059  /*
3060   * The default `GC_PREFETCH_FOR_WRITE(x)` is defined in `gc_inline.h` file,
3061   * the latter one is included from `gc_priv.h` file.
3062   */
3063  #endif
3064  
3065  #ifndef CACHE_LINE_SIZE
3066  #  define CACHE_LINE_SIZE 32 /*< wild guess */
3067  #endif
3068  
3069  #ifndef STATIC
3070  #  ifdef GC_ASSERTIONS
3071  #    define STATIC /*< ignore to aid debugging (or profiling) */
3072  #  else
3073  #    define STATIC static
3074  #  endif
3075  #endif
3076  
3077  /*
3078   * Do we need the `GC_find_limit` machinery to find the end of
3079   * a data segment (or the backing store base)?
3080   */
3081  #if defined(HEURISTIC2) || defined(SEARCH_FOR_DATA_START) || defined(IA64)    \
3082      || defined(DGUX) || defined(FREEBSD) || defined(OPENBSD) || defined(SVR4) \
3083      || (defined(HPUX) && defined(SPECIFIC_MAIN_STACKBOTTOM))                  \
3084      || (defined(CYGWIN32) && defined(I386) && defined(USE_MMAP)               \
3085          && !defined(USE_WINALLOC))                                            \
3086      || (defined(NETBSD) && defined(__ELF__))
3087  #  define NEED_FIND_LIMIT
3088  #endif
3089  
3090  #if defined(LINUX)                                       \
3091      && (defined(USE_PROC_FOR_LIBRARIES) || defined(IA64) \
3092          || !defined(SMALL_CONFIG))
3093  #  define NEED_PROC_MAPS
3094  #endif
3095  
3096  #if defined(LINUX) || defined(HURD) || defined(__GLIBC__)
3097  #  define REGISTER_LIBRARIES_EARLY
3098  /*
3099   * We sometimes use `dl_iterate_phdr`, which may acquire an internal lock.
3100   * This is not safe after the world has stopped.  So we must call
3101   * `GC_register_dynamic_libraries` before stopping the world.
3102   * For performance reasons, this may be beneficial on other platforms
3103   * as well, though it should be avoided on Windows.
3104   */
3105  #endif /* LINUX */
3106  
3107  #if defined(SEARCH_FOR_DATA_START)
3108  extern ptr_t GC_data_start;
3109  #  define DATASTART GC_data_start
3110  #endif
3111  
3112  #ifndef HEAP_START
3113  #  define HEAP_START 0
3114  #endif
3115  
3116  #ifndef CLEAR_DOUBLE
3117  #  define CLEAR_DOUBLE(x) \
3118      (void)(((ptr_t *)(x))[0] = NULL, ((ptr_t *)(x))[1] = NULL)
3119  #endif
3120  
3121  /*
3122   * Some `libc` implementations like `bionic`, `musl` and `glibc` 2.34+
3123   * do not have `libpthread.so` file because the `pthreads`-related code
3124   * is located in `libc.so` file, thus potential `calloc()` calls from
3125   * such code are forwarded to real (`libc`) `calloc()` without any
3126   * special handling on the collector side.  Checking `glibc` version at
3127   * compile time for the purpose seems to be fine.
3128   */
3129  #if defined(REDIR_MALLOC_AND_LINUXTHREADS) && !defined(HAVE_LIBPTHREAD_SO) \
3130      && defined(__GLIBC__) && !GC_GLIBC_PREREQ(2, 34)
3131  #  define HAVE_LIBPTHREAD_SO
3132  #endif
3133  
3134  #if defined(REDIR_MALLOC_AND_LINUXTHREADS) \
3135      && !defined(INCLUDE_LINUX_THREAD_DESCR)
3136  /*
3137   * Will not work, since `libc` and the dynamic loader use thread locals,
3138   * sometimes as the only reference.
3139   */
3140  #  define INCLUDE_LINUX_THREAD_DESCR
3141  #endif
3142  
3143  #ifndef CPPCHECK
3144  #  if defined(GC_AIX_THREADS) && !defined(AIX)                            \
3145        || (defined(GC_DARWIN_THREADS) && !defined(DARWIN))                 \
3146        || (defined(GC_DGUX386_THREADS) && !defined(DGUX))                  \
3147        || (defined(GC_FREEBSD_THREADS) && !defined(FREEBSD))               \
3148        || (defined(GC_HAIKU_THREADS) && !defined(HAIKU))                   \
3149        || (defined(GC_HPUX_THREADS) && !defined(HPUX))                     \
3150        || (defined(GC_IRIX_THREADS) && !defined(IRIX5))                    \
3151        || (defined(GC_LINUX_THREADS) && !defined(LINUX) && !defined(NACL)) \
3152        || (defined(GC_NETBSD_THREADS) && !defined(NETBSD))                 \
3153        || (defined(GC_OPENBSD_THREADS) && !defined(OPENBSD))               \
3154        || (defined(GC_OSF1_THREADS) && !defined(OSF1))                     \
3155        || (defined(GC_RTEMS_PTHREADS) && !defined(RTEMS))                  \
3156        || (defined(GC_SOLARIS_THREADS) && !defined(SOLARIS))               \
3157        || (defined(GC_WIN32_THREADS) && !defined(ANY_MSWIN)                \
3158            && !defined(MSWIN_XBOX1))
3159  #    error Inconsistent configuration
3160  #  elif defined(GC_WIN32_PTHREADS) && defined(CYGWIN32)
3161  #    error Inconsistent configuration (GC_PTHREADS)
3162  #  endif
3163  #  if defined(PARALLEL_MARK) && !defined(THREADS)
3164  #    error Invalid config: PARALLEL_MARK requires GC_THREADS
3165  #  endif
3166  #  if defined(GWW_VDB) && !defined(USE_WINALLOC)
3167  #    error Invalid config: GWW_VDB requires USE_WINALLOC
3168  #  endif
3169  #  if (defined(GC_FINDLEAK_DELAY_FREE) && defined(SHORT_DBG_HDRS)) \
3170        || ((defined(FIND_LEAK) || defined(GC_FINDLEAK_DELAY_FREE))  \
3171            && defined(NO_FIND_LEAK))
3172  #    error Invalid config: FIND_LEAK and NO_FIND_LEAK are mutually exclusive
3173  #  endif
3174  #endif /* !CPPCHECK */
3175  
3176  #if defined(NO_FIND_LEAK) && !defined(DONT_USE_ATEXIT)
3177  #  define DONT_USE_ATEXIT
3178  #endif
3179  
3180  /* Whether `GC_page_size` is to be set to a value other than page size. */
3181  #if defined(CYGWIN32) && (defined(MPROTECT_VDB) || defined(USE_MUNMAP)) \
3182      || (!defined(ANY_MSWIN) && !defined(WASI) && !defined(USE_MMAP)     \
3183          && (defined(GC_DISABLE_INCREMENTAL) || defined(DEFAULT_VDB)))
3184  /*
3185   * Cygwin: use the allocation granularity instead.
3186   * Other than WASI and Windows: use `HBLKSIZE` instead (unless `mmap()`
3187   * is used).
3188   */
3189  #  define ALT_PAGESIZE_USED
3190  #  ifndef GC_NO_VALLOC
3191  /* Nonetheless, we need the real page size is some extra functions. */
3192  #    define REAL_PAGESIZE_NEEDED
3193  #  endif
3194  #endif
3195  
3196  #if defined(GC_PTHREADS) && !defined(DARWIN) && !defined(GC_WIN32_THREADS) \
3197      && !defined(PLATFORM_STOP_WORLD) && !defined(SN_TARGET_PSP2)
3198  #  define PTHREAD_STOP_WORLD_IMPL
3199  #endif
3200  
3201  #if defined(PTHREAD_STOP_WORLD_IMPL) && !defined(NACL)
3202  #  define SIGNAL_BASED_STOP_WORLD
3203  #endif
3204  
3205  #if (defined(E2K) || defined(HP_PA) || defined(IA64) || defined(M68K) \
3206       || defined(NO_SA_SIGACTION))                                     \
3207      && defined(SIGNAL_BASED_STOP_WORLD)
3208  #  define SUSPEND_HANDLER_NO_CONTEXT
3209  #endif
3210  
3211  #if (defined(MSWIN32) || defined(MSWINCE)                      \
3212       || (defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS))) \
3213      && !defined(NO_CRT) && !defined(NO_WRAP_MARK_SOME)
3214  /*
3215   * Under rare conditions, we may end up marking from nonexistent memory.
3216   * Hence we need to be prepared to recover by running `GC_mark_some` with
3217   * a suitable handler in place.
3218   */
3219  /* TODO: Should we also define it for Cygwin? */
3220  #  define WRAP_MARK_SOME
3221  #endif
3222  
3223  #if !defined(MSWIN32) && !defined(MSWINCE) || defined(__GNUC__) \
3224      || defined(NO_CRT)
3225  #  define NO_SEH_AVAILABLE
3226  #endif
3227  
3228  #ifdef GC_WIN32_THREADS
3229  /* The number of copied registers in `copy_ptr_regs()`. */
3230  #  if defined(I386)
3231  #    ifdef WOW64_THREAD_CONTEXT_WORKAROUND
3232  #      define PUSHED_REGS_COUNT 9
3233  #    else
3234  #      define PUSHED_REGS_COUNT 7
3235  #    endif
3236  #  elif defined(X86_64)
3237  #    ifdef XMM_CANT_STORE_PTRS
3238  /* If pointers cannot be located in Xmm registers. */
3239  #      define PUSHED_REGS_COUNT 15
3240  #    else
3241  /*
3242   * gcc-13 may store pointers into SIMD registers when certain compiler
3243   * optimizations are enabled.
3244   */
3245  #      define PUSHED_REGS_COUNT (15 + 32)
3246  #    endif
3247  #  elif defined(SHx)
3248  #    define PUSHED_REGS_COUNT 15
3249  #  elif defined(ARM32)
3250  #    define PUSHED_REGS_COUNT 13
3251  #  elif defined(AARCH64)
3252  #    define PUSHED_REGS_COUNT 30
3253  #  elif defined(MIPS) || defined(ALPHA)
3254  #    define PUSHED_REGS_COUNT 28
3255  #  elif defined(PPC)
3256  #    define PUSHED_REGS_COUNT 29
3257  #  endif
3258  #endif /* GC_WIN32_THREADS */
3259  
3260  #if !defined(GC_PTHREADS) && !defined(GC_PTHREADS_PARAMARK)
3261  #  undef HAVE_PTHREAD_SETNAME_NP_WITH_TID
3262  #  undef HAVE_PTHREAD_SETNAME_NP_WITH_TID_AND_ARG
3263  #  undef HAVE_PTHREAD_SET_NAME_NP
3264  #endif
3265  
3266  #if !(defined(GC_PTHREADS) || defined(GC_PTHREADS_PARAMARK) \
3267        || (defined(MPROTECT_VDB) && defined(DARWIN)))
3268  #  undef HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID
3269  #endif
3270  
3271  #if defined(USE_RWLOCK) || defined(GC_DISABLE_SUSPEND_THREAD)
3272  /*
3273   * At least in the Linux threads implementation, `rwlock` primitives are
3274   * not atomic in respect to signals, and suspending externally a thread
3275   * which is running inside `pthread_rwlock_rdlock()` may lead to a deadlock.
3276   */
3277  /* TODO: As a workaround `GC_suspend_thread()` API is disabled. */
3278  #  undef GC_ENABLE_SUSPEND_THREAD
3279  #endif
3280  
3281  #ifndef GC_NO_THREADS_DISCOVERY
3282  #  if defined(DARWIN) && defined(THREADS)
3283  /* Task-based thread registration requires stack-frame-walking code. */
3284  #    if defined(DARWIN_DONT_PARSE_STACK)
3285  #      define GC_NO_THREADS_DISCOVERY
3286  #    endif
3287  #  elif defined(GC_WIN32_THREADS)
3288  /*
3289   * `DllMain`-based thread registration is currently incompatible with
3290   * thread-local allocation, `pthreads` and WinCE.
3291   */
3292  #    if (!defined(GC_DLL) && !defined(GC_INSIDE_DLL)) || defined(GC_PTHREADS) \
3293          || defined(MSWINCE) || defined(NO_CRT) || defined(THREAD_LOCAL_ALLOC)
3294  #      define GC_NO_THREADS_DISCOVERY
3295  #    endif
3296  #  else
3297  #    define GC_NO_THREADS_DISCOVERY
3298  #  endif
3299  #endif /* !GC_NO_THREADS_DISCOVERY */
3300  
3301  #if defined(GC_DISCOVER_TASK_THREADS) && defined(GC_NO_THREADS_DISCOVERY) \
3302      && !defined(CPPCHECK)
3303  #  error Defined both GC_DISCOVER_TASK_THREADS and GC_NO_THREADS_DISCOVERY
3304  #endif
3305  
3306  #if defined(PARALLEL_MARK) && !defined(DEFAULT_STACK_MAYBE_SMALL) \
3307      && (defined(DGUX) || defined(HPUX)                            \
3308          || defined(NO_GETCONTEXT) /* e.g. musl */)
3309  /* TODO: Test default stack size in configure. */
3310  #  define DEFAULT_STACK_MAYBE_SMALL
3311  #endif
3312  
3313  #ifdef PARALLEL_MARK
3314  /* The minimum stack size for a marker thread. */
3315  #  define MIN_STACK_SIZE (8 * HBLKSIZE * sizeof(ptr_t))
3316  #endif
3317  
3318  #if defined(HOST_ANDROID) && !defined(THREADS) \
3319      && !defined(USE_GET_STACKBASE_FOR_MAIN)
3320  /*
3321   * Always use `pthread_attr_getstack` on Android (`-lpthread` option
3322   * is not needed to be specified manually) since Linux-specific
3323   * `os_main_stackbottom()` causes application crash if invoked inside
3324   * Dalvik VM.
3325   */
3326  #  define USE_GET_STACKBASE_FOR_MAIN
3327  #endif
3328  
3329  /*
3330   * Outline `pthreads` primitives to use in `GC_get_stack_base()` and
3331   * `GC_get_main_stack_base()`.
3332   */
3333  #if ((defined(FREEBSD) && defined(__GLIBC__) /* kFreeBSD */)               \
3334       || defined(COSMO) || defined(HAIKU) || defined(LINUX) || defined(KOS) \
3335       || defined(NETBSD))                                                   \
3336      && !defined(NO_PTHREAD_GETATTR_NP)
3337  #  define HAVE_PTHREAD_GETATTR_NP 1
3338  #elif defined(FREEBSD) && !defined(__GLIBC__) \
3339      && !defined(NO_PTHREAD_ATTR_GET_NP)
3340  #  define HAVE_PTHREAD_NP_H 1 /*< requires include `pthread_np.h` file */
3341  #  define HAVE_PTHREAD_ATTR_GET_NP 1
3342  #endif
3343  
3344  #if (defined(HAVE_PTHREAD_ATTR_GET_NP) || defined(HAVE_PTHREAD_GETATTR_NP)) \
3345      && defined(USE_GET_STACKBASE_FOR_MAIN) && !defined(STACKBOTTOM)         \
3346      && !defined(HEURISTIC1) && !defined(HEURISTIC2) && !defined(STACK_GRAN) \
3347      && !defined(SPECIFIC_MAIN_STACKBOTTOM)
3348  /* Dummy definitions; rely on `pthread_attr_getstack` actually. */
3349  #  define HEURISTIC1
3350  #  define STACK_GRAN 0x1000000
3351  #endif
3352  
3353  #if !defined(HAVE_CLOCK_GETTIME) && defined(_POSIX_TIMERS) \
3354      && (defined(CYGWIN32) || (defined(LINUX) && defined(__USE_POSIX199309)))
3355  #  define HAVE_CLOCK_GETTIME 1
3356  #endif
3357  
3358  #if defined(GC_PTHREADS) && !defined(E2K) && !defined(IA64)   \
3359      && (!defined(DARWIN) || defined(DARWIN_DONT_PARSE_STACK)) \
3360      && !defined(SN_TARGET_PSP2) && !defined(REDIRECT_MALLOC)
3361  /*
3362   * Note: unimplemented in case of redirection of `malloc()` because
3363   * the client-provided function might call some `pthreads` primitive
3364   * which, in turn, may use `malloc()` internally.
3365   */
3366  #  define STACKPTR_CORRECTOR_AVAILABLE
3367  #endif
3368  
3369  #if defined(UNIX_LIKE) && defined(THREADS) && !defined(NO_CANCEL_SAFE) \
3370      && !defined(HOST_ANDROID)
3371  /*
3372   * Make the code cancellation-safe.  This basically means that we ensure
3373   * that cancellation requests are ignored while we are in the collector.
3374   * This applies only to POSIX deferred cancellation; we do not handle POSIX
3375   * asynchronous cancellation.  Note that this only works if
3376   * `pthread_setcancelstate` is async-signal-safe, at least in the absence of
3377   * asynchronous cancellation.  This appears to be true for `glibc`, though it
3378   * is not documented.  Without that assumption, there seems to be no way to
3379   * safely wait in a signal handler, which we need to do for thread suspension.
3380   * Also note that little other code appears to be cancellation-safe.
3381   * Hence it may make sense to turn this off for performance.
3382   */
3383  #  define CANCEL_SAFE
3384  #endif
3385  
3386  #ifdef CANCEL_SAFE
3387  #  define IF_CANCEL(x) x
3388  #else
3389  #  define IF_CANCEL(x) /*< empty */
3390  #endif
3391  
3392  #if defined(DARWIN) && defined(MPROTECT_VDB)   \
3393      && !defined(NO_DESC_CATCH_EXCEPTION_RAISE) \
3394      && !defined(FORCE_DESC_CATCH_EXCEPTION_RAISE) && GC_CLANG_PREREQ(17, 0)
3395  /*
3396   * Workaround "REFERENCED_DYNAMICALLY flag on _catch_exception_raise"
3397   * linker deprecation warnings on macOS 15.4.
3398   */
3399  #  define NO_DESC_CATCH_EXCEPTION_RAISE
3400  #endif
3401  
3402  #if !defined(CAN_HANDLE_FORK) && !defined(NO_HANDLE_FORK)                 \
3403      && !defined(HAVE_NO_FORK)                                             \
3404      && ((defined(GC_PTHREADS) && !defined(NACL)                           \
3405           && !defined(GC_WIN32_PTHREADS) && !defined(USE_WINALLOC))        \
3406          || (defined(DARWIN) && defined(MPROTECT_VDB) /* `&& !THREADS` */) \
3407          || (defined(HANDLE_FORK) && defined(GC_PTHREADS)))
3408  /*
3409   * Attempts (where supported and requested) to make `GC_malloc` work in
3410   * a child process forked from a multi-threaded parent process.
3411   */
3412  #  define CAN_HANDLE_FORK
3413  #endif
3414  
3415  /*
3416   * Workaround "failed to create new win32 semaphore" Cygwin fatal error
3417   * during semaphores fixup-after-fork.
3418   */
3419  #if defined(CYGWIN32) && defined(THREADS) && defined(CAN_HANDLE_FORK) \
3420      && !defined(CYGWIN_SEM_FIXUP_AFTER_FORK_BUG_FIXED)                \
3421      && !defined(EMULATE_PTHREAD_SEMAPHORE)
3422  #  define EMULATE_PTHREAD_SEMAPHORE
3423  #endif
3424  
3425  #if defined(CAN_HANDLE_FORK) && !defined(CAN_CALL_ATFORK)      \
3426      && !defined(GC_NO_CAN_CALL_ATFORK) && !defined(HOST_TIZEN) \
3427      && !defined(HURD) && (!defined(HOST_ANDROID) || __ANDROID_API__ >= 21)
3428  /* Have working `pthread_atfork()`. */
3429  #  define CAN_CALL_ATFORK
3430  #endif
3431  
3432  #if !defined(CAN_HANDLE_FORK) && !defined(HAVE_NO_FORK) \
3433      && !(defined(CYGWIN32) || defined(SOLARIS) || defined(UNIX_LIKE))
3434  #  define HAVE_NO_FORK
3435  #endif
3436  
3437  #if !defined(USE_MARK_BITS) && !defined(USE_MARK_BYTES) \
3438      && defined(PARALLEL_MARK)
3439  /* Minimize compare-and-swap usage. */
3440  #  define USE_MARK_BYTES
3441  #endif
3442  
3443  #if (defined(MSWINCE) && !defined(__CEGCC__) || defined(MSWINRT_FLAVOR)) \
3444      && !defined(NO_GETENV)
3445  #  define NO_GETENV
3446  #endif
3447  
3448  #if (defined(NO_GETENV) || defined(MSWINCE)) && !defined(NO_GETENV_WIN32)
3449  #  define NO_GETENV_WIN32
3450  #endif
3451  
3452  #if !defined(MSGBOX_ON_ERROR) && !defined(NO_MSGBOX_ON_ERROR)                \
3453      && defined(MSWIN32) && !defined(MSWINRT_FLAVOR) && !defined(MSWIN_XBOX1) \
3454      && !defined(SMALL_CONFIG)
3455  /*
3456   * Show a Windows message box with "OK" button on a GC fatal error.
3457   * Client application is terminated once the user clicks the button.
3458   */
3459  #  define MSGBOX_ON_ERROR
3460  #endif
3461  
3462  #ifndef STRTOULL
3463  #  if defined(_WIN64) && !defined(__GNUC__)
3464  #    define STRTOULL _strtoui64
3465  #  elif defined(_LLP64) || defined(__LLP64__) || defined(_WIN64)
3466  #    define STRTOULL strtoull
3467  #  else
3468  /* `strtoul()` fits since `sizeof(long)` is not less than `sizeof(word)`. */
3469  #    define STRTOULL strtoul
3470  #  endif
3471  #endif /* !STRTOULL */
3472  
3473  #ifndef GC_WORD_C
3474  #  if defined(_WIN64) && !defined(__GNUC__)
3475  #    define GC_WORD_C(val) val##ui64
3476  #  elif defined(_LLP64) || defined(__LLP64__) || defined(_WIN64)
3477  #    define GC_WORD_C(val) val##ULL
3478  #  else
3479  #    define GC_WORD_C(val) ((word)val##UL)
3480  #  endif
3481  #endif /* !GC_WORD_C */
3482  
3483  #if defined(__has_feature)
3484  /* `__has_feature()` is supported. */
3485  #  if __has_feature(address_sanitizer)
3486  #    define ADDRESS_SANITIZER
3487  #  endif
3488  #  if __has_feature(memory_sanitizer)
3489  #    define MEMORY_SANITIZER
3490  #  endif
3491  #  if __has_feature(thread_sanitizer) && defined(THREADS)
3492  #    define THREAD_SANITIZER
3493  #  endif
3494  #else
3495  #  ifdef __SANITIZE_ADDRESS__
3496  /* gcc v4.8+ */
3497  #    define ADDRESS_SANITIZER
3498  #  endif
3499  #  if defined(__SANITIZE_THREAD__) && defined(THREADS)
3500  /* gcc v7.1+ */
3501  #    define THREAD_SANITIZER
3502  #  endif
3503  #endif /* !__has_feature */
3504  
3505  #if defined(SPARC)
3506  /* Stack clearing is crucial, and we include assembly code to do it well. */
3507  #  define ASM_CLEAR_CODE
3508  #endif
3509  
3510  /*
3511   * Can we save call chain in objects for debugging?  Set `NFRAMES`
3512   * (number of saved frames) and `NARGS` (number of arguments for each
3513   * frame) to reasonable values for the platform.
3514   * Define `SAVE_CALL_CHAIN` if we can.  `SAVE_CALL_COUNT` can be
3515   * specified at build time, though we feel free to adjust it slightly.
3516   * Define `NEED_CALLINFO` if we either save the call stack or
3517   * `GC_ADD_CALLER` is defined.  Note: `GC_CAN_SAVE_CALL_STACKS` is
3518   * defined (for certain platforms) in `gc_config_macros.h` file.
3519   */
3520  #if defined(SPARC)                         \
3521      || ((defined(I386) || defined(X86_64)) \
3522          && (defined(LINUX) || defined(__GLIBC__)))
3523  /*
3524   * Linux/x86: `SAVE_CALL_CHAIN` is supported if the code is compiled to save
3525   * frame pointers by default, i.e. no `-fomit-frame-pointer` flag is given.
3526   */
3527  #  define CAN_SAVE_CALL_ARGS
3528  #endif
3529  
3530  #if defined(SAVE_CALL_COUNT) && !defined(GC_ADD_CALLER) \
3531      && defined(GC_CAN_SAVE_CALL_STACKS)
3532  #  define SAVE_CALL_CHAIN
3533  #endif
3534  
3535  #ifdef SAVE_CALL_CHAIN
3536  /* Number of arguments to save for each call. */
3537  #  if defined(SAVE_CALL_NARGS) && defined(CAN_SAVE_CALL_ARGS)
3538  #    define NARGS SAVE_CALL_NARGS
3539  #  else
3540  #    define NARGS 0
3541  #  endif
3542  /* Number of frames to save.  Even for alignment reasons. */
3543  #  if !defined(SAVE_CALL_COUNT) || defined(CPPCHECK)
3544  #    define NFRAMES 6
3545  #  else
3546  #    define NFRAMES ((SAVE_CALL_COUNT + 1) & ~1)
3547  #  endif
3548  #  define NEED_CALLINFO
3549  #elif defined(GC_ADD_CALLER)
3550  #  define NFRAMES 1
3551  #  define NARGS 0
3552  #  define NEED_CALLINFO
3553  #endif
3554  
3555  #if (defined(FREEBSD) || (defined(DARWIN) && !defined(_POSIX_C_SOURCE)) \
3556       || (defined(SOLARIS)                                               \
3557           && (!defined(_XOPEN_SOURCE) || defined(__EXTENSIONS__)))       \
3558       || defined(LINUX))                                                 \
3559      && !defined(HAVE_DLADDR)
3560  #  define HAVE_DLADDR 1
3561  #endif
3562  
3563  #if defined(MAKE_BACK_GRAPH) && !defined(DBG_HDRS_ALL)
3564  #  define DBG_HDRS_ALL 1
3565  #endif
3566  
3567  #if defined(POINTER_MASK) && !defined(POINTER_SHIFT)
3568  #  define POINTER_SHIFT 0
3569  #elif !defined(POINTER_MASK) && defined(POINTER_SHIFT)
3570  #  define POINTER_MASK GC_WORD_MAX
3571  #endif
3572  
3573  #if defined(FIXUP_POINTER)
3574  /* Custom `FIXUP_POINTER(p)`. */
3575  #  define NEED_FIXUP_POINTER
3576  #elif defined(DYNAMIC_POINTER_MASK)
3577  #  define FIXUP_POINTER(p) \
3578      (p = (ptr_t)((((word)(p)) & GC_pointer_mask) << GC_pointer_shift))
3579  #  undef POINTER_MASK
3580  #  undef POINTER_SHIFT
3581  #  define NEED_FIXUP_POINTER
3582  #elif defined(POINTER_MASK)
3583  /*
3584   * Note: extra parentheses around custom-defined `POINTER_MASK` and
3585   *`POINTER_SHIFT` are intentional.
3586   */
3587  #  define FIXUP_POINTER(p) \
3588      (p = (ptr_t)(((word)(p) & (POINTER_MASK)) << (POINTER_SHIFT)))
3589  #  define NEED_FIXUP_POINTER
3590  #else
3591  #  define FIXUP_POINTER(p) (void)(p)
3592  #endif
3593  
3594  #ifdef LINT2
3595  /*
3596   * A macro (based on a tricky expression) to prevent false warnings
3597   * like "Array compared to 0", "Comparison of identical expressions",
3598   * "Untrusted loop bound" output by some static code analysis tools.
3599   * The argument should not be a literal value.  The result is
3600   * converted to `word` type.  (Actually, `GC_word` is used instead of
3601   * `word` type as the latter might be undefined at the place of use.)
3602   */
3603  #  define COVERT_DATAFLOW(w) (~(GC_word)(w) ^ (~(GC_word)0))
3604  #else
3605  #  define COVERT_DATAFLOW(w) ((GC_word)(w))
3606  #endif
3607  
3608  #if CPP_PTRSZ > CPP_WORDSZ
3609  /* TODO: Cannot use tricky operations on a pointer. */
3610  #  define COVERT_DATAFLOW_P(p) ((ptr_t)(p))
3611  #else
3612  #  define COVERT_DATAFLOW_P(p) ((ptr_t)COVERT_DATAFLOW(p))
3613  #endif
3614  
3615  #if defined(REDIRECT_MALLOC) && defined(THREADS) && !defined(LINUX) \
3616      && !defined(REDIRECT_MALLOC_IN_HEADER)
3617  /*
3618   * May work on other platforms (e.g. Darwin) provided the client
3619   * ensures all the client threads are registered with the collector,
3620   * e.g. by using the preprocessor-based interception of the thread
3621   * primitives (i.e., define `GC_THREADS` and include `gc.h` file from
3622   * all the client files those are using `pthread_create` and friends).
3623   */
3624  #endif
3625  
3626  EXTERN_C_END
3627  
3628  #endif /* GCCONFIG_H */
3629