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