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