vxx2 / thirdparty / libgc / gc.c
45849 lines · 41246 sloc · 1.31 MB · 2b808880f73948e12d8321e107bcab07cd438601
Raw
1/*
2 * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
3 * Copyright (c) 1996 by Silicon Graphics. All rights reserved.
4 * Copyright (c) 1998 by Fergus Henderson. All rights reserved.
5 * Copyright (c) 2000-2009 by Hewlett-Packard Development Company.
6 * All rights reserved.
7 * Copyright (c) 2009-2025 Ivan Maidanski
8 *
9 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
10 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
11 *
12 * Permission is hereby granted to use or copy this program
13 * for any purpose, provided the above notices are retained on all copies.
14 * Permission to modify the code and to distribute modified code is granted,
15 * provided the above notices are retained, and a notice that the code was
16 * modified is included with the above copyright notice.
17 */
18
19/*
20 * This file could be used for the following purposes:
21 * - get the complete collector as a single link object file (module);
22 * - enable more compiler optimizations.
23 *
24 * Tip: to get the highest level of compiler optimizations, the typical
25 * compiler options to use (assuming gcc) are:
26 * `-O3 -march=native -fprofile-generate`
27 *
28 * Warning: gcc for Linux (for C++ clients only): use `-fexceptions` both for
29 * the collector library and the client as otherwise `GC_thread_exit_proc()`
30 * is not guaranteed to be invoked (see the comments in `pthread_start.c`
31 * file).
32 */
33
34/*
35 * V note: the bundled libgc must be compiled with `-DALL_INTERIOR_POINTERS=1`
36 * (set in `vlib/builtin/builtin_d_gcboehm.c.v`). Without it, the conservative
37 * collector misses interior pointers into GC-allocated buffers — sumtype
38 * payloads referenced via offset (e.g. `toml.ast_to_any`, `yaml.Any.to_json`)
39 * get reclaimed mid-walk and `-gc boehm` builds crash with `signal 11`.
40 * Keep this requirement in sync when re-amalgamating from bdwgc.
41 */
42
43#define GC_SINGLE_OBJ_BUILD
44
45#ifndef __cplusplus
46/* `static` is desirable here for more efficient linkage. */
47/* TODO: Enable this in case of the compilation as C++ code. */
48# define GC_INNER STATIC
49# define GC_EXTERN GC_INNER
50/* Note: `STATIC` macro is defined in `gcconfig.h` file. */
51#endif
52
53/* Small files go first... */
54/*
55 * Copyright (c) 2001 by Hewlett-Packard Company. All rights reserved.
56 *
57 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
58 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
59 *
60 * Permission is hereby granted to use or copy this program
61 * for any purpose, provided the above notices are retained on all copies.
62 * Permission to modify the code and to distribute modified code is granted,
63 * provided the above notices are retained, and a notice that the code was
64 * modified is included with the above copyright notice.
65 */
66
67/*
68 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
69 * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
70 * Copyright (c) 1997 by Silicon Graphics. All rights reserved.
71 * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.
72 *
73 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
74 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
75 *
76 * Permission is hereby granted to use or copy this program
77 * for any purpose, provided the above notices are retained on all copies.
78 * Permission to modify the code and to distribute modified code is granted,
79 * provided the above notices are retained, and a notice that the code was
80 * modified is included with the above copyright notice.
81 */
82
83/*
84 * This is mostly an internal header file. Typical clients should
85 * not use it. Clients that define their own object kinds with
86 * debugging allocators will probably want to include this, however.
87 * No attempt is made to keep the namespace clean. This should not be
88 * included from header files that are frequently included by clients.
89 */
90
91#ifndef GC_DBG_MLC_H
92#define GC_DBG_MLC_H
93
94/*
95 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
96 * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
97 * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
98 * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.
99 * Copyright (c) 2008-2025 Ivan Maidanski
100 *
101 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
102 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
103 *
104 * Permission is hereby granted to use or copy this program
105 * for any purpose, provided the above notices are retained on all copies.
106 * Permission to modify the code and to distribute modified code is granted,
107 * provided the above notices are retained, and a notice that the code was
108 * modified is included with the above copyright notice.
109 */
110
111#ifndef GC_PRIVATE_H
112#define GC_PRIVATE_H
113
114#ifdef HAVE_CONFIG_H
115/* include/config.h. Generated from config.h.in by configure. */
116/* include/config.h.in. Generated from configure.ac by autoheader. */
117
118/* Define to recognize all pointers to the interior of objects. */
119#define ALL_INTERIOR_POINTERS 1
120
121/* AO load, store and/or test-and-set primitives are implemented in
122 `libatomic_ops` using locks. */
123/* #undef BASE_ATOMIC_OPS_EMULATED */
124
125/* Erroneously cleared dirty bits checking. Use only for debugging of the
126 incremental collector. */
127/* #undef CHECKSUMS */
128
129/* Define to discover thread stack bounds on Darwin without trying to walk the
130 frames on the stack. */
131/* #undef DARWIN_DONT_PARSE_STACK */
132
133/* Define to force debug headers on all objects. */
134#define DBG_HDRS_ALL 1
135
136/* Do not use user32.dll import library (Win32). */
137/* #undef DONT_USE_USER32_DLL */
138
139/* Define to support pointer mask/shift set at runtime. */
140/* #undef DYNAMIC_POINTER_MASK */
141
142/* Define to enable eCos target support. */
143/* #undef ECOS */
144
145/* Wine `getenv` may not return `NULL` for missing entry. */
146/* #undef EMPTY_GETENV_RESULTS */
147
148/* Define to enable alternative finalization interface. */
149#define ENABLE_DISCLAIM 1
150
151/* Define to enable internal debug assertions. */
152/* #undef GC_ASSERTIONS */
153
154/* Define to enable atomic uncollectible allocation. */
155#define GC_ATOMIC_UNCOLLECTABLE 1
156
157/* Use GCC atomic intrinsics instead of `libatomic_ops` primitives. */
158#define GC_BUILTIN_ATOMIC 1
159
160/* Define to build dynamic libraries with only API symbols exposed. */
161/* #undef GC_DLL */
162
163/* Skip the initial guess of data root sets. */
164/* #undef GC_DONT_REGISTER_MAIN_STATIC_DATA */
165
166/* Define to turn on `GC_suspend_thread` support (Linux only). */
167#define GC_ENABLE_SUSPEND_THREAD 1
168
169/* Define to include support for `gcj`. */
170#define GC_GCJ_SUPPORT 1
171
172/* Define if backtrace information is supported. */
173/* #undef GC_HAVE_BUILTIN_BACKTRACE */
174
175/* Define to use `pthread_sigmask` function if needed. */
176/* #undef GC_HAVE_PTHREAD_SIGMASK */
177
178/* Enable Win32 `DllMain`-based approach of threads registering. */
179/* #undef GC_INSIDE_DLL */
180
181/* Missing execinfo.h header. */
182/* #undef GC_MISSING_EXECINFO_H */
183
184/* Missing `sigsetjmp` function. */
185/* #undef GC_NO_SIGSETJMP */
186
187/* Disable threads discovery in the collector. */
188/* #undef GC_NO_THREADS_DISCOVERY */
189
190/* Read environment variables from the GC 'env' file. */
191/* #undef GC_READ_ENV_FILE */
192
193/* Define and export `GC_wcsdup` function. */
194#define GC_REQUIRE_WCSDUP 1
195
196/* Define to support platform-specific threads. */
197#define GC_THREADS 1
198
199/* Force the GC to use signals based on `SIGRTMIN+k`. */
200/* #undef GC_USESIGRT_SIGNALS */
201
202/* Define to cause the collector to redefine `malloc` and intercepted
203 `pthreads` routines with their real names while using `dlsym` to refer to
204 the original routines. */
205/* #undef GC_USE_DLOPEN_WRAP */
206
207/* The major version number of this GC release. */
208#define GC_VERSION_MAJOR 8
209
210/* The micro version number of this GC release. */
211#define GC_VERSION_MICRO 0
212
213/* The minor version number of this GC release. */
214#define GC_VERSION_MINOR 3
215
216/* Define to support pthreads-win32 or winpthreads. */
217/* #undef GC_WIN32_PTHREADS */
218
219/* Define to install `pthread_atfork` handlers by default. */
220#define HANDLE_FORK 1
221
222/* Define to use `dladdr` function. */
223#define HAVE_DLADDR 1
224
225/* Define to 1 if you have the <dlfcn.h> header file. */
226#define HAVE_DLFCN_H 1
227
228/* Define to 1 if you have the 'dl_iterate_phdr' function. */
229/* #undef HAVE_DL_ITERATE_PHDR */
230
231/* Define to 1 if you have the <inttypes.h> header file. */
232#define HAVE_INTTYPES_H 1
233
234/* `libatomic_ops` `AO_or` primitive implementation is lock-free. */
235/* #undef HAVE_LOCKFREE_AO_OR */
236
237/* Define to use `pthread_setname_np(const char *)` function. */
238#define HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID 1
239
240/* Define to use `pthread_setname_np(pthread_t, const char *)` function. */
241/* #undef HAVE_PTHREAD_SETNAME_NP_WITH_TID */
242
243/* Define to use `pthread_setname_np(pthread_t, const char *, void *)`
244 function. */
245/* #undef HAVE_PTHREAD_SETNAME_NP_WITH_TID_AND_ARG */
246
247/* Define to use `pthread_set_name_np(pthread_t, const char *)` function. */
248/* #undef HAVE_PTHREAD_SET_NAME_NP */
249
250/* Define to 1 if you have the <stdint.h> header file. */
251#define HAVE_STDINT_H 1
252
253/* Define to 1 if you have the <stdio.h> header file. */
254#define HAVE_STDIO_H 1
255
256/* Define to 1 if you have the <stdlib.h> header file. */
257#define HAVE_STDLIB_H 1
258
259/* Define to 1 if you have the <strings.h> header file. */
260#define HAVE_STRINGS_H 1
261
262/* Define to 1 if you have the <string.h> header file. */
263#define HAVE_STRING_H 1
264
265/* Define to 1 if you have the <sys/stat.h> header file. */
266#define HAVE_SYS_STAT_H 1
267
268/* Define to 1 if you have the <sys/types.h> header file. */
269#define HAVE_SYS_TYPES_H 1
270
271/* Define to 1 if you have the <unistd.h> header file. */
272#define HAVE_UNISTD_H 1
273
274/* Do not define `DYNAMIC_LOADING` even if supported (i.e., build the
275 collector with disabled tracing of dynamic library data roots). */
276/* #undef IGNORE_DYNAMIC_LOADING */
277
278/* Define to make it somewhat safer by default to finalize objects out of
279 order by specifying a nonstandard finalization mark procedure. */
280#define JAVA_FINALIZATION 1
281
282/* Define to save back-pointers in debugging headers. */
283#define KEEP_BACK_PTRS 1
284
285/* Define to optimize for large heaps or root sets. */
286/* #undef LARGE_CONFIG */
287
288/* Define to the sub-directory where libtool stores uninstalled libraries. */
289#define LT_OBJDIR ".libs/"
290
291/* Define to build the collector with the support of the functionality to
292 print max length of chain through unreachable objects ending in a reachable
293 one. */
294/* #undef MAKE_BACK_GRAPH */
295
296/* Number of sequential garbage collections during those a candidate block for
297 unmapping should be marked as free. */
298#define MUNMAP_THRESHOLD 7
299
300/* Define to not use system clock (cross compiling). */
301/* #undef NO_CLOCK */
302
303/* Disable debugging, like `GC_dump` and its callees. */
304/* #undef NO_DEBUGGING */
305
306/* Define to make the collector not allocate executable memory by default. */
307#define NO_EXECUTE_PERMISSION 1
308
309/* Missing `getcontext` function. */
310/* #undef NO_GETCONTEXT */
311
312/* Prohibit installation of `pthread_atfork` handlers. */
313/* #undef NO_HANDLE_FORK */
314
315/* Name of package */
316#define PACKAGE "gc"
317
318/* Define to the address where bug reports for this package should be sent. */
319#define PACKAGE_BUGREPORT "https://github.com/bdwgc/bdwgc/issues"
320
321/* Define to the full name of this package. */
322#define PACKAGE_NAME "gc"
323
324/* Define to the full name and version of this package. */
325#define PACKAGE_STRING "gc 8.3.0"
326
327/* Define to the one symbol short name of this package. */
328#define PACKAGE_TARNAME "gc"
329
330/* Define to the home page for this package. */
331#define PACKAGE_URL ""
332
333/* Define to the version of this package. */
334#define PACKAGE_VERSION "8.3.0"
335
336/* Define to enable parallel marking. */
337#define PARALLEL_MARK 1
338
339/* If defined, redirect `free` to this function. */
340/* #undef REDIRECT_FREE */
341
342/* If defined, redirect `malloc` to this function. */
343/* #undef REDIRECT_MALLOC */
344
345/* If defined, redirect `realloc` to this function. */
346/* #undef REDIRECT_REALLOC */
347
348/* The number of caller frames saved when allocating with the debugging API.
349 */
350/* #undef SAVE_CALL_COUNT */
351
352/* Shorten the headers to minimize object size at the expense of checking for
353 writes past the end. */
354/* #undef SHORT_DBG_HDRS */
355
356/* Define to tune the collector for small heap sizes. */
357/* #undef SMALL_CONFIG */
358
359/* Define to 1 if all of the C89 standard headers exist (not just the ones
360 required in a freestanding environment). This macro is provided for
361 backward compatibility; new code need not use it. */
362#define STDC_HEADERS 1
363
364/* Define to work around a Solaris 5.3 bug (see dyn_load.c). */
365/* #undef SUNOS53_SHARED_LIB */
366
367/* Define to enable thread-local allocation optimization. */
368/* #undef THREAD_LOCAL_ALLOC */
369
370/* Use Unicode (W) variant of Win32 API instead of ASCII (A) one. */
371/* #undef UNICODE */
372
373/* Define to use of compiler-support for thread-local variables. */
374/* #undef USE_COMPILER_TLS */
375
376/* Define to use `mmap` instead of `sbrk` to expand the heap. */
377#define USE_MMAP 1
378
379/* Define to return memory to OS with `munmap` calls. */
380#define USE_MUNMAP 1
381
382/* Use `rwlock` for the allocator lock instead of mutex. */
383/* #undef USE_RWLOCK */
384
385/* Define to use Win32 `VirtualAlloc` (instead of `sbrk` or `mmap`) to expand
386 the heap. */
387/* #undef USE_WINALLOC */
388
389/* Define to support tracking `GC_malloc` and friends for heap profiling
390 tools. */
391/* #undef VALGRIND_TRACKING */
392
393/* Version number of package */
394#define VERSION "8.3.0"
395
396/* The POSIX feature macro. */
397/* #undef _POSIX_C_SOURCE */
398
399/* Indicates the use of `pthreads` (NetBSD). */
400/* #undef _PTHREADS */
401
402/* Required define if using POSIX threads. */
403#define _REENTRANT 1
404
405/* Define to '__inline__' or '__inline' if that's what the C compiler
406 calls it, or to nothing if 'inline' is not supported under any name. */
407#ifndef __cplusplus
408/* #undef inline */
409#endif
410
411#endif
412
413#if !defined(GC_BUILD) && !defined(NOT_GCBUILD)
414# define GC_BUILD
415#endif
416
417#if (defined(__linux__) || defined(__GLIBC__) || defined(__GNU__) \
418 || defined(__CYGWIN__) || defined(HAVE_DLADDR) \
419 || (defined(__COSMOPOLITAN__) && defined(USE_MUNMAP)) \
420 || defined(GC_HAVE_PTHREAD_SIGMASK) \
421 || defined(HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID) \
422 || defined(HAVE_PTHREAD_SETNAME_NP_WITH_TID_AND_ARG) \
423 || defined(HAVE_PTHREAD_SETNAME_NP_WITH_TID)) \
424 && !defined(_GNU_SOURCE)
425/* Cannot test `LINUX`, since this must be defined before other includes. */
426# define _GNU_SOURCE 1
427#endif
428
429#if defined(__INTERIX) && !defined(_ALL_SOURCE)
430# define _ALL_SOURCE 1
431#endif
432
433#if (defined(DGUX) && defined(GC_THREADS) || defined(DGUX386_THREADS) \
434 || defined(GC_DGUX386_THREADS)) \
435 && !defined(_USING_POSIX4A_DRAFT10)
436# define _USING_POSIX4A_DRAFT10 1
437#endif
438
439#if defined(__MINGW32__) && !defined(__MINGW_EXCPT_DEFINE_PSDK) \
440 && defined(__i386__) \
441 && defined(GC_EXTERN) /*< defined in `extra/gc.c` file */
442/* See the description in `mark.c` file. */
443# define __MINGW_EXCPT_DEFINE_PSDK 1
444#endif
445
446#if defined(NO_DEBUGGING) && !defined(GC_ASSERTIONS) && !defined(NDEBUG)
447/* To turn off assertion checking (in `atomic_ops.h` file). */
448# define NDEBUG 1
449#endif
450
451#ifndef GC_H
452# include "gc/gc.h"
453#endif
454
455#include <stdlib.h>
456#if !defined(sony_news)
457# include <stddef.h>
458#endif
459
460#ifdef DGUX
461# include <sys/resource.h>
462# include <sys/time.h>
463#endif
464
465#ifdef BSD_TIME
466# include <sys/resource.h>
467# include <sys/time.h>
468#endif
469
470#ifdef PARALLEL_MARK
471# define AO_REQUIRE_CAS
472# if !defined(__GNUC__) && !defined(AO_ASSUME_WINDOWS98)
473# define AO_ASSUME_WINDOWS98
474# endif
475#endif
476
477#include "gc/gc_mark.h"
478#include "gc/gc_tiny_fl.h"
479
480typedef GC_word word;
481
482#ifndef PTR_T_DEFINED
483/*
484 * A generic pointer to which we can add byte displacements and which
485 * can be used for address comparisons.
486 */
487typedef char *ptr_t;
488# define PTR_T_DEFINED
489#endif
490
491#ifndef SIZE_MAX
492# include <limits.h>
493#endif
494#if defined(SIZE_MAX) && !defined(CPPCHECK)
495/*
496 * A constant representing maximum value for `size_t` type. Note: an extra
497 * cast is used to workaround some buggy `SIZE_MAX` definitions.
498 */
499# define GC_SIZE_MAX ((size_t)SIZE_MAX)
500#else
501# define GC_SIZE_MAX (~(size_t)0)
502#endif
503
504#if (GC_GNUC_PREREQ(3, 0) || defined(__clang__)) && !defined(LINT2)
505/* Equivalent to `e`, but predict that usually `e` is true (false). */
506# define LIKELY(e) __builtin_expect(e, 1 /* `TRUE` */)
507# define UNLIKELY(e) __builtin_expect(e, 0 /* `FALSE` */)
508#else
509# define LIKELY(e) (e)
510# define UNLIKELY(e) (e)
511#endif /* __GNUC__ */
512
513/*
514 * Saturated addition of `size_t` values. Used to avoid value wrap around
515 * on overflow. The arguments should have no side effects.
516 */
517#define SIZET_SAT_ADD(a, b) \
518 (LIKELY((a) < GC_SIZE_MAX - (b)) ? (a) + (b) : GC_SIZE_MAX)
519
520/*
521 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
522 * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
523 * Copyright (c) 1996 by Silicon Graphics. All rights reserved.
524 * Copyright (c) 2000-2004 Hewlett-Packard Development Company, L.P.
525 * Copyright (c) 2009-2025 Ivan Maidanski
526 *
527 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
528 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
529 *
530 * Permission is hereby granted to use or copy this program
531 * for any purpose, provided the above notices are retained on all copies.
532 * Permission to modify the code and to distribute modified code is granted,
533 * provided the above notices are retained, and a notice that the code was
534 * modified is included with the above copyright notice.
535 */
536
537/*
538 * This header is private to the collector. It is almost always
539 * included from `gc_priv.h` file. However it is possible to include
540 * it by itself if just the configuration macros are needed. In that
541 * case, a few declarations relying on types declared in `gc_priv.h`
542 * file will be omitted.
543 */
544
545#ifndef GCCONFIG_H
546#define GCCONFIG_H
547
548#ifndef GC_H
549# ifdef HAVE_CONFIG_H
550# endif
551
552
553#endif
554
555#ifdef CPPCHECK
556# undef CLOCKS_PER_SEC
557# undef FIXUP_POINTER
558# undef POINTER_MASK
559# undef POINTER_SHIFT
560# undef REDIRECT_REALLOC
561# undef _MAX_PATH
562#endif
563
564#ifndef PTR_T_DEFINED
565typedef char *ptr_t;
566# define PTR_T_DEFINED
567#endif
568
569#if !defined(sony_news)
570# include <stddef.h> /*< for `size_t`, etc. */
571#endif
572
573/*
574 * Note: only wrap our own declarations, and not the included headers;
575 * in this case, wrap our entire file, but temporarily unwrap/rewrap
576 * around `#include` entities; macros do not need such wrapping.
577 */
578#ifdef __cplusplus
579# define EXTERN_C_BEGIN extern "C" {
580# define EXTERN_C_END } /* extern "C" */
581#else
582# define EXTERN_C_BEGIN
583# define EXTERN_C_END
584#endif
585
586EXTERN_C_BEGIN
587
588/* Convenient internal macro to test version of Clang. */
589#if defined(__clang__) && defined(__clang_major__)
590# define GC_CLANG_PREREQ(major, minor) \
591 ((__clang_major__ << 8) + __clang_minor__ >= ((major) << 8) + (minor))
592# define GC_CLANG_PREREQ_FULL(major, minor, patchlevel) \
593 (GC_CLANG_PREREQ(major, (minor) + 1) \
594 || (__clang_major__ == (major) && __clang_minor__ == (minor) \
595 && __clang_patchlevel__ >= (patchlevel)))
596#else
597# define GC_CLANG_PREREQ(major, minor) 0 /*< `FALSE` */
598# define GC_CLANG_PREREQ_FULL(major, minor, patchlevel) 0
599#endif
600
601/*
602 * Machine-dependent parameters. Some tuning parameters can be found
603 * near the top of `gc_priv.h` file.
604 */
605
606/* Machine-specific parts contributed by various people. See `README` file. */
607
608#if defined(__ANDROID__) && !defined(HOST_ANDROID)
609/* A Linux-based OS. `__ANDROID__` macro is defined by Android NDK gcc. */
610# define HOST_ANDROID 1
611#endif
612
613#if defined(TIZEN) && !defined(HOST_TIZEN)
614/* A Linux-based OS. */
615# define HOST_TIZEN 1
616#endif
617
618#if defined(__SYMBIAN32__) && !defined(SYMBIAN)
619# define SYMBIAN
620# ifdef __WINS__
621# pragma data_seg(".data2")
622# endif
623#endif
624
625/* First a unified test for Linux. */
626#if (defined(linux) || defined(__linux__) || defined(HOST_ANDROID) \
627 || defined(HOST_TIZEN)) \
628 && !defined(LINUX) && !defined(__native_client__)
629# define LINUX
630#endif
631
632/* And one for NetBSD. */
633#if defined(__NetBSD__)
634# define NETBSD
635#endif
636
637/* And one for OpenBSD. */
638#if defined(__OpenBSD__)
639# define OPENBSD
640#endif
641
642/* And one for FreeBSD. */
643#if (defined(__FreeBSD__) || defined(__DragonFly__) \
644 || defined(__FreeBSD_kernel__)) \
645 && !defined(FREEBSD) \
646 && !defined(GC_NO_FREEBSD) /*< Orbis compiler defines `__FreeBSD__` */
647# define FREEBSD
648#endif
649
650#if defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD)
651# define ANY_BSD
652#endif
653
654#if defined(__COSMOPOLITAN__)
655# define COSMO
656#endif
657
658#if defined(__EMBOX__)
659# define EMBOX
660#endif
661
662#if defined(__KOS__)
663# define KOS
664#endif
665
666#if defined(__QNX__) && !defined(QNX)
667# define QNX
668#endif
669
670#if defined(__serenity__)
671# define SERENITY
672#endif
673
674/* And one for Darwin. */
675#if defined(macosx) || (defined(__APPLE__) && defined(__MACH__))
676# define DARWIN
677EXTERN_C_END
678# include <TargetConditionals.h>
679EXTERN_C_BEGIN
680#endif
681
682/* Determine the machine type. */
683#if defined(__native_client__)
684# define NACL
685# if !defined(__portable_native_client__) && !defined(__arm__)
686# define I386
687# define mach_type_known
688# else
689/* Here we will rely upon arch-specific defines. */
690# endif
691#endif
692#if defined(__aarch64__) && !defined(ANY_BSD) && !defined(COSMO) \
693 && !defined(DARWIN) && !defined(LINUX) && !defined(KOS) \
694 && !defined(NN_BUILD_TARGET_PLATFORM_NX) && !defined(QNX) \
695 && !defined(SERENITY) && !defined(_WIN32)
696# define AARCH64
697# define NOSYS
698# define mach_type_known
699#endif
700#if defined(__arm) || defined(__arm__) || defined(__thumb__)
701# define ARM32
702# if defined(NACL) || defined(SYMBIAN)
703# define mach_type_known
704# elif !defined(ANY_BSD) && !defined(DARWIN) && !defined(LINUX) \
705 && !defined(QNX) && !defined(NN_PLATFORM_CTR) \
706 && !defined(SN_TARGET_PSP2) && !defined(_WIN32) && !defined(__CEGCC__) \
707 && !defined(GC_NO_NOSYS)
708# define NOSYS
709# define mach_type_known
710# endif
711#endif
712#if defined(__riscv) && !defined(ANY_BSD) && !defined(LINUX)
713# define RISCV
714# define NOSYS
715# define mach_type_known
716#endif
717#if defined(vax) || defined(__vax__)
718# define VAX
719# ifdef ultrix
720# define ULTRIX
721# else
722# define BSD
723# endif
724# define mach_type_known
725#endif
726#if defined(NETBSD) && defined(__vax__)
727# define VAX
728# define mach_type_known
729#endif
730#if (defined(mips) || defined(__mips) || defined(_mips)) \
731 && !defined(__TANDEM) && !defined(ANY_BSD) && !defined(LINUX)
732# define MIPS
733# if defined(nec_ews) || defined(_nec_ews)
734# define EWS4800
735# define mach_type_known
736# elif defined(ultrix) || defined(__ultrix)
737# define ULTRIX
738# define mach_type_known
739# elif !defined(_WIN32_WCE) && !defined(__CEGCC__) && !defined(__MINGW32CE__)
740# define IRIX5 /*< or Irix 6.x */
741# define mach_type_known
742# endif /* !MSWINCE */
743#endif
744#if defined(DGUX) && (defined(i386) || defined(__i386__))
745# define I386
746# ifndef _USING_DGUX
747# define _USING_DGUX
748# endif
749# define mach_type_known
750#endif
751#if defined(sequent) && (defined(i386) || defined(__i386__))
752# define I386
753# define SEQUENT
754# define mach_type_known
755#endif
756#if (defined(sun) || defined(__sun)) && (defined(i386) || defined(__i386__))
757# define I386
758# define SOLARIS
759# define mach_type_known
760#endif
761#if (defined(sun) || defined(__sun)) && defined(__amd64)
762# define X86_64
763# define SOLARIS
764# define mach_type_known
765#endif
766#if (defined(__OS2__) || defined(__EMX__)) && defined(__32BIT__)
767# define I386
768# define OS2
769# define mach_type_known
770#endif
771#if (defined(sun) || defined(__sun)) && (defined(sparc) || defined(__sparc))
772/* SunOS 5.x */
773EXTERN_C_END
774# include <errno.h>
775EXTERN_C_BEGIN
776# define SPARC
777# define SOLARIS
778# define mach_type_known
779#elif defined(sparc) && defined(unix) && !defined(sun) && !defined(linux) \
780 && !defined(ANY_BSD)
781# define SPARC
782# define DRSNX
783# define mach_type_known
784#endif
785#if defined(_IBMR2) /* `&& defined(_AIX)` */
786# define POWERPC
787# define AIX
788# define mach_type_known
789#endif
790#if defined(_M_XENIX) && defined(_M_SYSV) && defined(_M_I386)
791/* TODO: The above test may need refinement. */
792# define I386
793# if defined(_SCO_ELF)
794# define SCO_ELF
795# else
796# define SCO
797# endif
798# define mach_type_known
799#endif
800#if defined(_PA_RISC1_0) || defined(_PA_RISC1_1) || defined(_PA_RISC2_0) \
801 || defined(hppa) || defined(__hppa__)
802# define HP_PA
803# if !defined(LINUX) && !defined(HPUX) && !defined(OPENBSD)
804# define HPUX
805# endif
806# define mach_type_known
807#endif
808#if defined(__ia64) && (defined(_HPUX_SOURCE) || defined(__HP_aCC))
809# define IA64
810# ifndef HPUX
811# define HPUX
812# endif
813# define mach_type_known
814#endif
815#if (defined(__BEOS__) || defined(__HAIKU__)) && defined(_X86_)
816# define I386
817# define HAIKU
818# define mach_type_known
819#endif
820#if defined(__HAIKU__) && (defined(__amd64__) || defined(__x86_64__))
821# define X86_64
822# define HAIKU
823# define mach_type_known
824#endif
825#if defined(__alpha) || defined(__alpha__)
826# define ALPHA
827# if !defined(ANY_BSD) && !defined(LINUX)
828# define OSF1 /*< Compaq Tru64 UNIX (Digital UNIX) */
829# endif
830# define mach_type_known
831#endif
832#if defined(__rtems__) && (defined(i386) || defined(__i386__))
833# define I386
834# define RTEMS
835# define mach_type_known
836#endif
837#if defined(NeXT) && defined(mc68000)
838# define M68K
839# define NEXT
840# define mach_type_known
841#endif
842#if defined(NeXT) && (defined(i386) || defined(__i386__))
843# define I386
844# define NEXT
845# define mach_type_known
846#endif
847#if defined(bsdi) && (defined(i386) || defined(__i386__))
848# define I386
849# define BSDI
850# define mach_type_known
851#endif
852#if defined(__386BSD__) && !defined(mach_type_known)
853# define I386
854# define THREE86BSD
855# define mach_type_known
856#endif
857#if defined(_CX_UX) && defined(_M88K)
858# define M88K
859# define CX_UX
860# define mach_type_known
861#endif
862#if defined(DGUX) && defined(m88k)
863# define M88K
864/* `DGUX` macro is already defined. */
865# define mach_type_known
866#endif
867#if defined(_WIN32_WCE) || defined(__CEGCC__) || defined(__MINGW32CE__)
868/*
869 * `SH3`, `SH4`, `MIPS` macros are already defined for the corresponding
870 * architectures.
871 */
872# if defined(SH3) || defined(SH4)
873# define SH
874# endif
875# if defined(x86) || defined(__i386__)
876# define I386
877# endif
878# if defined(_M_ARM) || defined(ARM) || defined(_ARM_)
879# define ARM32
880# endif
881# define MSWINCE
882# define mach_type_known
883#else
884# if ((defined(_MSDOS) || defined(_MSC_VER)) && (_M_IX86 >= 300)) \
885 || (defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__CYGWIN__) \
886 && !defined(__INTERIX) && !defined(SYMBIAN)) \
887 || defined(__MINGW32__)
888# if defined(__LP64__) || defined(_M_X64)
889# define X86_64
890# elif defined(_M_ARM)
891# define ARM32
892# elif defined(_M_ARM64)
893# define AARCH64
894# else /* _M_IX86 */
895# define I386
896# endif
897# ifdef _XBOX_ONE
898# define MSWIN_XBOX1
899# else
900# ifndef MSWIN32
901# define MSWIN32 /*< or Win64 */
902# endif
903# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
904# define MSWINRT_FLAVOR
905# endif
906# endif
907# define mach_type_known
908# endif
909# if defined(_MSC_VER) && defined(_M_IA64)
910# define IA64
911/*
912 * Really Win64, but we do not treat 64-bit variants as a different
913 * platform.
914 */
915# define MSWIN32
916# endif
917#endif /* !_WIN32_WCE && !__CEGCC__ && !__MINGW32CE__ */
918#if defined(__DJGPP__)
919# define I386
920# ifndef DJGPP
921/* MSDOS running the DJGPP port of gcc. */
922# define DJGPP
923# endif
924# define mach_type_known
925#endif
926#if defined(__CYGWIN32__) || defined(__CYGWIN__)
927# if defined(__LP64__)
928# define X86_64
929# else
930# define I386
931# endif
932# define CYGWIN32
933# define mach_type_known
934#endif /* __CYGWIN__ */
935#if defined(__INTERIX)
936# define I386
937# define INTERIX
938# define mach_type_known
939#endif
940#if defined(_UTS) && !defined(mach_type_known)
941# define S370
942# define UTS4
943# define mach_type_known
944#endif
945#if defined(__embedded__) && defined(PPC)
946# define POWERPC
947# define NOSYS
948# define mach_type_known
949#endif
950#if defined(__WATCOMC__) && defined(__386__)
951# define I386
952# if !defined(OS2) && !defined(MSWIN32) && !defined(DOS4GW)
953# if defined(__OS2__)
954# define OS2
955# elif defined(__WINDOWS_386__) || defined(__NT__)
956# define MSWIN32
957# else
958# define DOS4GW
959# endif
960# endif
961# define mach_type_known
962#endif /* __WATCOMC__ && __386__ */
963#if defined(__GNU__) && defined(__i386__)
964/* The Debian Hurd running on generic PC. */
965# define HURD
966# define I386
967# define mach_type_known
968#endif
969#if defined(__GNU__) && defined(__x86_64__)
970# define HURD
971# define X86_64
972# define mach_type_known
973#endif
974#if defined(__TANDEM)
975/* Nonstop S-series. */
976/* FIXME: Should recognize Integrity series? */
977# define MIPS
978# define NONSTOP
979# define mach_type_known
980#endif
981#if defined(__tile__) && defined(LINUX)
982# ifdef __tilegx__
983# define TILEGX
984# else
985# define TILEPRO
986# endif
987# define mach_type_known
988#endif
989#if defined(NN_BUILD_TARGET_PLATFORM_NX)
990# define AARCH64
991# define NINTENDO_SWITCH
992# define mach_type_known
993#endif
994#if defined(__EMSCRIPTEN__) || defined(EMSCRIPTEN)
995# define WEBASSEMBLY
996# ifndef EMSCRIPTEN
997# define EMSCRIPTEN
998# endif
999# define mach_type_known
1000#endif
1001#if defined(__wasi__)
1002/* The WebAssembly System Interface (WASI). */
1003# define WEBASSEMBLY
1004# define WASI
1005# define mach_type_known
1006#endif
1007
1008#if defined(__aarch64__) \
1009 && (defined(ANY_BSD) || defined(COSMO) || defined(DARWIN) \
1010 || defined(LINUX) || defined(KOS) || defined(QNX) \
1011 || defined(SERENITY))
1012# define AARCH64
1013# define mach_type_known
1014#elif defined(__arc__) && defined(LINUX)
1015# define ARC
1016# define mach_type_known
1017#elif (defined(__arm) || defined(__arm__) || defined(__arm32__) \
1018 || defined(__ARM__)) \
1019 && (defined(ANY_BSD) || defined(DARWIN) || defined(LINUX) || defined(QNX) \
1020 || defined(NN_PLATFORM_CTR) || defined(SN_TARGET_PSP2))
1021# define ARM32
1022# define mach_type_known
1023#elif defined(__avr32__) && defined(LINUX)
1024# define AVR32
1025# define mach_type_known
1026#elif defined(__cris__) && defined(LINUX)
1027# ifndef CRIS
1028# define CRIS
1029# endif
1030# define mach_type_known
1031#elif defined(__e2k__) && defined(LINUX)
1032# define E2K
1033# define mach_type_known
1034#elif defined(__hexagon__) && defined(LINUX)
1035# define HEXAGON
1036# define mach_type_known
1037#elif (defined(__i386__) || defined(i386) || defined(__X86__)) \
1038 && (defined(ANY_BSD) || defined(DARWIN) || defined(EMBOX) \
1039 || defined(LINUX) || defined(QNX) || defined(SERENITY))
1040# define I386
1041# define mach_type_known
1042#elif (defined(__ia64) || defined(__ia64__)) && defined(LINUX)
1043# define IA64
1044# define mach_type_known
1045#elif defined(__loongarch__) && defined(LINUX)
1046# define LOONGARCH
1047# define mach_type_known
1048#elif defined(__m32r__) && defined(LINUX)
1049# define M32R
1050# define mach_type_known
1051#elif ((defined(__m68k__) || defined(m68k)) \
1052 && (defined(NETBSD) || defined(OPENBSD))) \
1053 || (defined(__mc68000__) && defined(LINUX))
1054# define M68K
1055# define mach_type_known
1056#elif (defined(__mips) || defined(_mips) || defined(mips)) \
1057 && (defined(ANY_BSD) || defined(LINUX))
1058# define MIPS
1059# define mach_type_known
1060#elif (defined(__NIOS2__) || defined(__NIOS2) || defined(__nios2__)) \
1061 && defined(LINUX)
1062# define NIOS2 /*< Altera NIOS2 */
1063# define mach_type_known
1064#elif defined(__or1k__) && defined(LINUX)
1065# define OR1K /*< OpenRISC (or1k) */
1066# define mach_type_known
1067#elif (defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__) \
1068 || defined(__ppc64__) || defined(powerpc) || defined(powerpc64)) \
1069 && (defined(ANY_BSD) || defined(DARWIN) || defined(LINUX))
1070# define POWERPC
1071# define mach_type_known
1072#elif defined(__riscv) && (defined(ANY_BSD) || defined(LINUX))
1073# define RISCV
1074# define mach_type_known
1075#elif defined(__s390__) && defined(LINUX)
1076# define S390
1077# define mach_type_known
1078#elif defined(__sh__) \
1079 && (defined(LINUX) || defined(NETBSD) || defined(OPENBSD))
1080# define SH
1081# define mach_type_known
1082#elif (defined(__sparc) || defined(sparc)) \
1083 && (defined(ANY_BSD) || defined(LINUX))
1084# define SPARC
1085# define mach_type_known
1086#elif defined(__sw_64__) && defined(LINUX)
1087# define SW_64
1088# define mach_type_known
1089#elif (defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) \
1090 || defined(__X86_64__)) \
1091 && (defined(ANY_BSD) || defined(COSMO) || defined(DARWIN) \
1092 || defined(LINUX) || defined(QNX) || defined(SERENITY))
1093# define X86_64
1094# define mach_type_known
1095#endif
1096
1097/*
1098 * Feel free to add more clauses here. Or manually define the machine
1099 * type here. A machine type is characterized by the architecture.
1100 * Some machine types are further subdivided by OS. Macros such as
1101 * `LINUX`, `FREEBSD`, etc. distinguish them. The distinction in these
1102 * cases is usually the stack starting address.
1103 */
1104
1105#if !defined(mach_type_known) && !defined(CPPCHECK)
1106# error The collector has not been ported to this machine/OS combination
1107#endif
1108
1109/*
1110 * The CPU architecture mapping is:
1111 * - `AARCH64`: ARM AArch64 ILP32/64-bit (running `COSMO` environment,
1112 * `DARWIN` (OS X or iOS), `KOS`, `LINUX`, `MSWIN32`, `NETBSD`,
1113 * `NINTENDO_SWITCH`, `NOSYS` environment, `OPENBSD`, `QNX`, `SERENITY`);
1114 * - `ALPHA`: DEC Alpha (running `FREEBSD`, `LINUX`, `NETBSD`, `OPENBSD`,
1115 * `OSF1`);
1116 * - `ARC`: Synopsys ARC (running `LINUX`);
1117 * - `ARM32`: ARMv7 (running `DARWIN` (iOS), `FREEBSD`, `LINUX`, `MSWIN32`,
1118 * `MSWINCE`, `NETBSD`, `NN_PLATFORM_CTR`, `NOSYS` environment,
1119 * `OPENBSD`, `QNX`, `SN_TARGET_PSP2`, `SYMBIAN`);
1120 * - `AVR32`: Atmel RISC (running `LINUX`);
1121 * - `CRIS`: Axis Etrax (running `LINUX`);
1122 * - `E2K`: Elbrus 2000 32/64-bit (running `LINUX`);
1123 * - `HEXAGON`: Qualcomm Hexagon (running `LINUX`);
1124 * - `HP_PA`: HP9000/700 and HP9000/800 32/64-bit (running `HPUX`, `LINUX`,
1125 * `OPENBSD`);
1126 * - `I386`: Intel 486/586/686 (running `BSDI`, `CYGWIN32` environment,
1127 * `DARWIN` (macOS), `DGUX`, `DJGPP` environment, `DOS4GW` environment,
1128 * `EMBOX`, `FREEBSD`, `HAIKU`, `HURD`, `INTERIX`, `LINUX`, `MSWIN32`,
1129 * `MSWINCE`, `NACL` environment, `NETBSD`, `NEXT`, `OPENBSD`, `OS2`,
1130 * `QNX`, `RTEMS`, `SCO`, `SCO_ELF`, `SEQUENT`, `SERENITY`, `SOLARIS`,
1131 * `THREE86BSD`);
1132 * - `IA64`: Intel IPF, e.g. Itanium 32/64-bit (running `HPUX`, `LINUX`,
1133 * `MSWIN32`);
1134 * - `LOONGARCH`: Loongson LoongArch 32/64-bit (running `LINUX`);
1135 * - `M32R`: Renesas M32R (running `LINUX`);
1136 * - `M68K`: Motorola 680x0 (running `LINUX`, `NETBSD`, `NEXT`, `OPENBSD`);
1137 * - `M88K`: Motorola 88xx0 (running `CX_UX`, `DGUX`);
1138 * - `MIPS`: R2000+ 32/64-bit (running `EWS4800`, `FREEBSD`, `IRIX5`,
1139 * `LINUX`, `MSWINCE`, `NETBSD`, `NONSTOP`, `OPENBSD`, `ULTRIX`);
1140 * - `NIOS2`: Altera NIOS2 (running `LINUX`);
1141 * - `OR1K`: OpenRISC/or1k (running `LINUX`);
1142 * - `POWERPC`: IBM/Apple PowerPC 32/64-bit (running `AIX`, `DARWIN`,
1143 * `FREEBSD`, `LINUX`, `NETBSD`, `NOSYS` environment, `OPENBSD`,
1144 * `SN_TARGET_PS3`);
1145 * - `RISCV`: RISC-V 32/64-bit (running `FREEBSD`, `LINUX`, `NETBSD`,
1146 * `NOSYS` environment, `OPENBSD`);
1147 * - `S370`: A 370-like machine (running `UTS4`);
1148 * - `S390`: A 390-like machine 32/64-bit (running `LINUX`);
1149 * - `SH`: Hitachi SuperH (running `LINUX`, `MSWINCE`, `NETBSD`,
1150 * `OPENBSD`);
1151 * - `SH4`: Hitachi SH4 (running `MSWINCE`);
1152 * - `SPARC`: SPARC v7/v8/v9 32/64-bit (running `DRSNX`, `FREEBSD`,
1153 * `LINUX`, `NETBSD`, `OPENBSD`, `SOLARIS`);
1154 * - `SW_64`: Sunway/Shenwei (running `LINUX`);
1155 * - `TILEGX`: Tilera TILE-Gx 32/64-bit (running `LINUX`);
1156 * - `TILEPRO`: Tilera TILEPro (running `LINUX`);
1157 * - `VAX`: DEC VAX (running `BSD`, `ULTRIX`);
1158 * - `WEBASSEMBLY`: WebAssembly/Wasm (running `EMSCRIPTEN` environment,
1159 * `WASI` environment);
1160 * - `X86_64`: AMD x86-64 ILP32/64-bit (running `COSMO` environment,
1161 * `CYGWIN32` environment, `DARWIN` (macOS), `FREEBSD`, `HAIKU`,
1162 * `HURD`, `LINUX`, `MSWIN32`, `MSWIN_XBOX1`, `NETBSD`, `OPENBSD`,
1163 * `PLATFORM_GETMEM` environment, `QNX`, `SERENITY`, `SOLARIS`).
1164 */
1165
1166/*
1167 * For each architecture and OS, the following need to be defined:
1168 *
1169 * `CPP_WORDSZ` is a simple integer constant representing the word size
1170 * in bits. We assume byte addressability, where a byte has 8 bits.
1171 * We also assume `CPP_WORDSZ` is either 32 or 64.
1172 * (We care about the length of a pointer address, not hardware
1173 * bus widths. Thus a 64-bit processor with a C compiler that uses
1174 * 32-bit pointers should use `CPP_WORDSZ` of 32, not 64.)
1175 *
1176 * `CPP_PTRSZ` is the pointer size in bits. For most of the supported
1177 * targets, it is equal to `CPP_WORDSZ`.
1178 *
1179 * `MACH_TYPE` is a string representation of the machine type.
1180 * `OS_TYPE` is analogous for the OS.
1181 *
1182 * `ALIGNMENT` is the largest `n`, such that all pointer are guaranteed
1183 * to be aligned on `n`-byte boundary. Defining it to be 1 will always
1184 * work, but will perform poorly. Should not be larger than size of
1185 * a pointer.
1186 *
1187 * `DATASTART` is the beginning of the data segment. On some platforms
1188 * `SEARCH_FOR_DATA_START` is defined. The latter will cause
1189 * `GC_data_start` to be set to an address determined by accessing data
1190 * backwards from `_end` until an unmapped page is found. `DATASTART` will
1191 * be defined to be `GC_data_start`. On UNIX-like systems, the collector
1192 * will scan the area between `DATASTART` and `DATAEND` for root pointers.
1193 *
1194 * `DATAEND`, if not `end`, where `end` is defined as `extern int end[]`.
1195 * RTH suggests gaining access to linker script synth'd values with
1196 * this idiom instead of `&end`, where `end` is defined as `extern int end`.
1197 * Otherwise, "gcc will assume these are in .sdata/.sbss" and it will, e.g.,
1198 * cause failures on `alpha*-*-*` with `-msmall-data` or `-fpic` or
1199 * `mips-*-*` without any special options.
1200 *
1201 * `STACKBOTTOM` is the cold end of the stack, which is usually the
1202 * highest address in the stack.
1203 * Under OS/2, we have other ways of finding thread stacks.
1204 * For each machine, the following should:
1205 * 1. Define `STACK_GROWS_UP` if the stack grows toward higher addresses;
1206 * 2. Define exactly one of
1207 * - `STACKBOTTOM` (should be defined to be an expression),
1208 * - `HEURISTIC1`,
1209 * - `SPECIFIC_MAIN_STACKBOTTOM`,
1210 * - `HEURISTIC2`.
1211 *
1212 * If `STACKBOTTOM` is defined, then its value will be used directly (as
1213 * the stack bottom). If `SPECIFIC_MAIN_STACKBOTTOM` is defined, then it
1214 * will be determined with a specific method appropriate for the operating
1215 * system. Currently we look first for `__libc_stack_end` (currently only
1216 * if `USE_LIBC_PRIVATES` is defined), and if that fails, read it from
1217 * `/proc` pseudo-file. (If `USE_LIBC_PRIVATES` is not defined and
1218 * `NO_PROC_STAT` is defined, we revert to `HEURISTIC2`.)
1219 * If either of the last two macros are defined, then `STACKBOTTOM` is
1220 * computed during collector startup using one of the following two
1221 * heuristics:
1222 * - `HEURISTIC1`: Take an address inside `GC_init`'s frame, and round it
1223 * up to the next multiple of `STACK_GRAN`;
1224 * - `HEURISTIC2`: Take an address inside `GC_init`'s frame, increment it
1225 * repeatedly in small steps (decrement if `STACK_GROWS_UP`), and read
1226 * the value at each location, remember the value when the first
1227 * Segmentation violation or Bus error is signaled, round that to the
1228 * nearest plausible page boundary, and use that instead of
1229 * `STACKBOTTOM`.
1230 *
1231 * Gustavo Rodriguez-Rivera points out that on most (all?) UNIX machines,
1232 * the value of `environ` is a pointer that can serve as `STACKBOTTOM`.
1233 * I expect that `HEURISTIC2` can be replaced by this approach, which
1234 * interferes far less with debugging. However it has the disadvantage that
1235 * it is confused by a `putenv()` call before the collector is initialized.
1236 * This could be dealt with by intercepting `putenv()`...
1237 *
1238 * If no expression for `STACKBOTTOM` can be found, and neither of the above
1239 * heuristics are usable, the collector can still be used with all of the
1240 * above undefined, provided one of the following is done:
1241 * 1. `GC_mark_roots` can be changed to somehow mark from the correct
1242 * stack(s) without reference to `STACKBOTTOM`. This is appropriate for
1243 * use in conjunction with thread packages, since there will be multiple
1244 * stacks. (Allocating thread stacks in the heap, and treating them as
1245 * ordinary heap data objects is also possible as a last resort.
1246 * However, this is likely to introduce significant amounts of excess
1247 * storage retention unless the dead parts of the thread stacks are
1248 * periodically cleared.)
1249 * 2. Client code may set `GC_stackbottom` before calling any `GC_`
1250 * routines. If the author of the client code owns the main program,
1251 * this could be accomplished by introducing a new `main` function,
1252 * calling `GC_call_with_gc_active()` which sets `GC_stackbottom` and
1253 * then calls the original (real) `main` function.
1254 *
1255 * Each architecture may also define the style of virtual dirty bit
1256 * implementation to be used:
1257 * - `GWW_VDB`: use Win32 `GetWriteWatch` primitive;
1258 * - `MPROTECT_VDB`: write-protect the heap and catch faults;
1259 * - `PROC_VDB`: use the SVR4 `/proc` primitives to read dirty bits;
1260 * - `SOFT_VDB`: use the Linux `/proc` primitives to track dirty bits.
1261 *
1262 * The first and second one may be combined, in which case a runtime
1263 * selection will be made, based on `GetWriteWatch` availability.
1264 *
1265 * An architecture may define `DYNAMIC_LOADING` if `dyn_load.c` file
1266 * implements `GC_register_dynamic_libraries()` for the architecture.
1267 *
1268 * An architecture may define `PREFETCH(x)` to preload the cache with `*x`.
1269 * This defaults to gcc built-in operation (or a no-op for other compilers).
1270 *
1271 * `GC_PREFETCH_FOR_WRITE(x)` is used if `*x` is about to be written.
1272 *
1273 * An architecture may also define `CLEAR_DOUBLE(x)` to be a fast way to
1274 * clear 2 pointers at `GC_malloc`-aligned address `x`. The default
1275 * implementation is just to store two `NULL` pointers.
1276 *
1277 * `HEAP_START` may be defined as the initial address hint for `mmap`-based
1278 * allocation.
1279 */
1280
1281#ifdef LINUX
1282/* TODO: FreeBSD too? */
1283EXTERN_C_END
1284# include <features.h> /*< for `__GLIBC__` and `__GLIBC_MINOR__`, at least */
1285EXTERN_C_BEGIN
1286#endif
1287
1288/* Convenient internal macro to test `glibc` version (if compiled against). */
1289#if defined(__GLIBC__) && defined(__GLIBC_MINOR__)
1290# define GC_GLIBC_PREREQ(major, minor) \
1291 ((__GLIBC__ << 8) + __GLIBC_MINOR__ >= ((major) << 8) + (minor))
1292#else
1293# define GC_GLIBC_PREREQ(major, minor) 0 /*< `FALSE` */
1294#endif
1295
1296/*
1297 * Align a `ptr_t` pointer down/up to a given boundary. The latter should
1298 * be a power of two.
1299 */
1300#if GC_CLANG_PREREQ(11, 0)
1301# define PTR_ALIGN_DOWN(p, b) __builtin_align_down(p, b)
1302# if defined(DARWIN) && defined(GC_SINGLE_OBJ_BUILD) && GC_CLANG_PREREQ(17, 0)
1303/* Workaround a crash in Apple clang-17. */
1304/* TODO: Disable for later clang versions when the bug is fixed. */
1305# define PTR_ALIGN_UP(p, b) \
1306 ((ptr_t)__builtin_align_up((GC_uintptr_t)(p), b))
1307# else
1308# define PTR_ALIGN_UP(p, b) __builtin_align_up(p, b)
1309# endif
1310#else
1311# define PTR_ALIGN_DOWN(p, b) \
1312 ((ptr_t)((GC_uintptr_t)(p) & ~((GC_uintptr_t)(b) - (GC_uintptr_t)1)))
1313# define PTR_ALIGN_UP(p, b) \
1314 ((ptr_t)(((GC_uintptr_t)(p) + (GC_uintptr_t)(b) - (GC_uintptr_t)1) \
1315 & ~((GC_uintptr_t)(b) - (GC_uintptr_t)1)))
1316#endif
1317
1318/*
1319 * If available, we can use `__builtin_unwind_init()` to push the relevant
1320 * registers onto the stack.
1321 */
1322#if GC_GNUC_PREREQ(2, 8) \
1323 && !GC_GNUC_PREREQ(11, 0) /*< broken at least in 11.2.0 on cygwin64 */ \
1324 && !defined(__INTEL_COMPILER) && !defined(__PATHCC__) \
1325 && !defined(__FUJITSU) /*< for FX10 system */ \
1326 && !(defined(POWERPC) && defined(DARWIN)) /*< for MacOS X 10.3.9 */ \
1327 && !defined(E2K) && !defined(RTEMS) \
1328 && !defined(__ARMCC_VERSION) /*< does not exist in armcc gnu emu */ \
1329 && !(defined(__clang__) \
1330 && defined(__ARM_ARCH_5TE__) /* clang-19 emits `vpush`/`vpop` */) \
1331 && (!defined(__clang__) \
1332 || GC_CLANG_PREREQ(8, 0) /* was no-op in clang-3 at least */)
1333# define HAVE_BUILTIN_UNWIND_INIT
1334#endif
1335
1336#if (defined(__CC_ARM) || defined(CX_UX) || defined(DJGPP) || defined(EMBOX) \
1337 || defined(EWS4800) || defined(LINUX) || defined(OS2) || defined(RTEMS) \
1338 || defined(UTS4) || defined(MSWIN32) || defined(MSWINCE) \
1339 || (defined(NOSYS) && defined(RISCV))) \
1340 && !defined(NO_UNDERSCORE_SETJMP)
1341# define NO_UNDERSCORE_SETJMP
1342#endif
1343
1344/*
1345 * The common OS-specific definitions. Should be applicable to all
1346 * (or most, at least) supported architectures.
1347 */
1348
1349#ifdef CYGWIN32
1350# define OS_TYPE "CYGWIN32"
1351# define RETRY_GET_THREAD_CONTEXT
1352# ifdef USE_WINALLOC
1353# define GWW_VDB
1354# elif defined(USE_MMAP)
1355# define USE_MMAP_ANON
1356# endif
1357#endif /* CYGWIN32 */
1358
1359#ifdef COSMO
1360# define OS_TYPE "COSMO"
1361# ifndef USE_GET_STACKBASE_FOR_MAIN
1362# define USE_GET_STACKBASE_FOR_MAIN
1363# endif
1364extern int __data_start[] __attribute__((__weak__));
1365# define DATASTART ((ptr_t)__data_start)
1366extern int _end[];
1367# define DATAEND ((ptr_t)_end)
1368# define USE_MMAP_ANON
1369# ifndef HAVE_CLOCK_GETTIME
1370# define HAVE_CLOCK_GETTIME 1
1371# endif
1372# ifndef HAVE_PTHREAD_SETNAME_NP_WITH_TID
1373/* Normally should be defined by `configure`, etc. */
1374# define HAVE_PTHREAD_SETNAME_NP_WITH_TID 1
1375# endif
1376# if !defined(GC_THREADS) || defined(NO_HANDLE_FORK) \
1377 || defined(GC_NO_CAN_CALL_ATFORK)
1378# define MPROTECT_VDB
1379/* FIXME: Otherwise `gctest` crashes in child process. */
1380# endif
1381/* FIXME: A deadlock occurs in markers, thus disabled for now. */
1382# undef PARALLEL_MARK
1383#endif /* COSMO */
1384
1385#ifdef DARWIN
1386# define OS_TYPE "DARWIN"
1387# define DYNAMIC_LOADING
1388/*
1389 * TODO: See `get_end(3)`, `get_etext` and `get_end` should not be used.
1390 * These are not used when `dyld` support is enabled (it is the default).
1391 */
1392# define DATASTART ((ptr_t)get_etext())
1393# define DATAEND ((ptr_t)get_end())
1394# define USE_MMAP_ANON
1395/* There seems to be some issues with try-lock hanging on Darwin. */
1396/* TODO: This should be looked into some more. */
1397# define NO_PTHREAD_TRYLOCK
1398# ifndef TARGET_OS_XR
1399# define TARGET_OS_XR 0
1400# endif
1401# ifndef TARGET_OS_VISION
1402# define TARGET_OS_VISION 0
1403# endif
1404#endif /* DARWIN */
1405
1406#ifdef EMBOX
1407# define OS_TYPE "EMBOX"
1408extern int _modules_data_start[], _apps_bss_end[];
1409# define DATASTART ((ptr_t)_modules_data_start)
1410# define DATAEND ((ptr_t)_apps_bss_end)
1411/*
1412 * Note: the designated area might be quite large (several dozens of MBs)
1413 * as it includes `.data` and `.bss` of all apps and modules of the built
1414 * binary image.
1415 */
1416#endif /* EMBOX */
1417
1418#ifdef FREEBSD
1419# define OS_TYPE "FREEBSD"
1420# define SPECIFIC_MAIN_STACKBOTTOM
1421# ifdef __ELF__
1422# define DYNAMIC_LOADING
1423# endif
1424# ifndef USE_MMAP
1425/* `sbrk()` is not available. */
1426# define USE_MMAP 1
1427# endif
1428# if !defined(ALPHA) && !defined(SPARC)
1429extern char etext[];
1430# define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)etext)
1431# define DATASTART_USES_XGETDATASTART
1432# ifndef REDIRECT_MALLOC
1433# define MPROTECT_VDB
1434# else
1435/* Similar as on Linux, `fread()` might use `malloc()`. */
1436# endif
1437# endif
1438#endif /* FREEBSD */
1439
1440#ifdef HAIKU
1441# define OS_TYPE "HAIKU"
1442# define DYNAMIC_LOADING
1443/* Note: `DATASTART` is not used really, see `GC_register_main_static_data`. */
1444extern int etext[];
1445# define DATASTART PTR_ALIGN_UP((ptr_t)etext, 0x1000)
1446# ifndef USE_GET_STACKBASE_FOR_MAIN
1447# define USE_GET_STACKBASE_FOR_MAIN
1448# endif
1449# define USE_MMAP_ANON
1450/*
1451 * On Haiku R1, at least, `pthreads` locks never spin but always call
1452 * into the kernel if the lock cannot be acquired with a simple atomic
1453 * operation. (Up to 5x overall performance improvement of the
1454 * collector is observed by forcing use of spin locks.)
1455 */
1456# ifndef USE_SPIN_LOCK
1457# define USE_SPIN_LOCK
1458# endif
1459/*
1460 * TODO: `MPROTECT_VDB` is not working correctly on anything other than
1461 * recent nightly Haiku OS builds (as of Nov 2024), and also it is
1462 * considerably slower than regular collecting, so do not enable it for now.
1463 */
1464EXTERN_C_END
1465# include <OS.h>
1466EXTERN_C_BEGIN
1467# define GETPAGESIZE() (unsigned)B_PAGE_SIZE
1468# ifndef HAVE_CLOCK_GETTIME
1469# define HAVE_CLOCK_GETTIME 1
1470# endif
1471#endif /* HAIKU */
1472
1473#ifdef HPUX
1474# define OS_TYPE "HPUX"
1475extern int __data_start[];
1476# define DATASTART ((ptr_t)__data_start)
1477# ifdef USE_MMAP
1478# define USE_MMAP_ANON
1479# endif
1480# define DYNAMIC_LOADING
1481# define GETPAGESIZE() (unsigned)sysconf(_SC_PAGE_SIZE)
1482#endif /* HPUX */
1483
1484#ifdef HURD
1485# define OS_TYPE "HURD"
1486# define HEURISTIC2
1487# define SEARCH_FOR_DATA_START
1488extern int _end[];
1489# define DATAEND ((ptr_t)_end)
1490/* TODO: `MPROTECT_VDB` is not quite working yet? */
1491# define DYNAMIC_LOADING
1492# define USE_MMAP_ANON
1493#endif /* HURD */
1494
1495#ifdef LINUX
1496# define OS_TYPE "LINUX"
1497# if defined(FORCE_MPROTECT_BEFORE_MADVISE) || defined(PREFER_MMAP_PROT_NONE)
1498# define COUNT_UNMAPPED_REGIONS
1499# endif
1500# define RETRY_TKILL_ON_EAGAIN
1501# if !defined(MIPS) && !defined(POWERPC)
1502# define SPECIFIC_MAIN_STACKBOTTOM
1503# endif
1504# if defined(__ELF__) && !defined(IA64)
1505# define DYNAMIC_LOADING
1506# endif
1507# if defined(__ELF__) && !defined(ARC) && !defined(RISCV) && !defined(S390) \
1508 && !defined(TILEGX) && !defined(TILEPRO)
1509extern int _end[];
1510# define DATAEND ((ptr_t)_end)
1511# endif
1512# if !defined(REDIRECT_MALLOC) && !defined(E2K)
1513/* Requires Linux 2.3.47 or later. */
1514# define MPROTECT_VDB
1515# else
1516/*
1517 * We seem to get random errors in the incremental mode, possibly because
1518 * the Linux threads implementation itself is a `malloc` client and cannot
1519 * deal with the signals. `fread()` uses `malloc()` too.
1520 * In case of e2k, unless `-fsemi-spec-ld` (or `-O0`) option is passed
1521 * to gcc (both when compiling the collector library and the client),
1522 * a semi-speculative optimization may lead to `SIGILL` (with `ILL_ILLOPN`
1523 * `si_code`) instead of `SIGSEGV`.
1524 */
1525# endif
1526#endif /* LINUX */
1527
1528#ifdef KOS
1529# define OS_TYPE "KOS"
1530# ifndef USE_GET_STACKBASE_FOR_MAIN
1531/* Note: this requires `-lpthread` option. */
1532# define USE_GET_STACKBASE_FOR_MAIN
1533# endif
1534extern int __data_start[];
1535# define DATASTART ((ptr_t)__data_start)
1536#endif /* KOS */
1537
1538#ifdef MSWIN32
1539# define OS_TYPE "MSWIN32"
1540/* `STACKBOTTOM` and `DATASTART` are handled specially in `os_dep.c` file. */
1541# if !defined(CPPCHECK)
1542# define DATAEND /*< not needed */
1543# endif
1544# if defined(USE_GLOBAL_ALLOC) && !defined(MSWINRT_FLAVOR)
1545/* Cannot pass `MEM_WRITE_WATCH` to `GlobalAlloc()`. */
1546# else
1547# define GWW_VDB
1548# endif
1549#endif
1550
1551#ifdef MSWINCE
1552# define OS_TYPE "MSWINCE"
1553# if !defined(CPPCHECK)
1554# define DATAEND /*< not needed */
1555# endif
1556#endif
1557
1558#ifdef NACL
1559# define OS_TYPE "NACL"
1560# if defined(__GLIBC__)
1561# define DYNAMIC_LOADING
1562# endif
1563# define DATASTART MAKE_CPTR(0x10020000)
1564extern int _end[];
1565# define DATAEND ((ptr_t)_end)
1566# define STACK_GRAN 0x10000
1567# define HEURISTIC1
1568# define NO_PTHREAD_GETATTR_NP
1569# define USE_MMAP_ANON
1570/* FIXME: Not real page size. */
1571# define GETPAGESIZE() 65536
1572# define MAX_NACL_GC_THREADS 1024
1573#endif /* NACL */
1574
1575#ifdef NETBSD
1576# define OS_TYPE "NETBSD"
1577# define HEURISTIC2
1578# ifdef __ELF__
1579# define SEARCH_FOR_DATA_START
1580# define DYNAMIC_LOADING
1581# elif !defined(MIPS)
1582/* TODO: Probably do not exclude it. */
1583extern char etext[];
1584# define DATASTART ((ptr_t)etext)
1585# endif
1586# define MPROTECT_VDB
1587#endif /* NETBSD */
1588
1589#ifdef NEXT
1590# define OS_TYPE "NEXT"
1591# define DATASTART ((ptr_t)get_etext())
1592# define DATAEND /*< not needed */
1593# undef USE_MUNMAP
1594#endif
1595
1596#ifdef OPENBSD
1597# define OS_TYPE "OPENBSD"
1598# ifndef GC_THREADS
1599# define HEURISTIC2
1600# endif
1601# ifdef __ELF__
1602extern int __data_start[], _end[];
1603# define DATASTART ((ptr_t)__data_start)
1604# define DATAEND ((ptr_t)_end)
1605# define DYNAMIC_LOADING
1606# else
1607extern char etext[];
1608# define DATASTART ((ptr_t)etext)
1609# endif
1610# define MPROTECT_VDB
1611#endif /* OPENBSD */
1612
1613#ifdef QNX
1614# define OS_TYPE "QNX"
1615# define SA_RESTART 0
1616# ifndef SPECIFIC_MAIN_STACKBOTTOM
1617/* TODO: This is not used by default. */
1618# define STACK_GRAN 0x1000000
1619# define HEURISTIC1
1620# endif
1621extern char etext[];
1622# define DATASTART ((ptr_t)etext)
1623extern int _end[];
1624# define DATAEND ((ptr_t)_end)
1625#endif /* QNX */
1626
1627#ifdef SERENITY
1628# define OS_TYPE "SERENITY"
1629extern int etext[], _end[];
1630# define DATASTART PTR_ALIGN_UP((ptr_t)etext, 0x1000)
1631# define DATAEND ((ptr_t)_end)
1632# define DYNAMIC_LOADING
1633/* TODO: Enable `mprotect`-based VDB. */
1634# define USE_MMAP_ANON
1635#endif /* SERENITY */
1636
1637#ifdef SOLARIS
1638# define OS_TYPE "SOLARIS"
1639extern int _end[];
1640# define DATAEND ((ptr_t)_end)
1641# if !defined(USE_MMAP) && defined(REDIRECT_MALLOC)
1642# define USE_MMAP 1
1643/*
1644 * Otherwise we now use `calloc()`. `mmap()` may result in the heap
1645 * interleaved with thread stacks, which can result in excessive
1646 * black-listing. `sbrk()` is unusable since it does not interact
1647 * correctly with the system `malloc()`.
1648 */
1649# endif
1650# ifdef USE_MMAP
1651# define HEAP_START ((word)0x40000000)
1652# else
1653# define HEAP_START ADDR(DATAEND)
1654# endif
1655# ifndef GC_THREADS
1656# define MPROTECT_VDB
1657# endif
1658# define DYNAMIC_LOADING
1659/*
1660 * Define `STACKBOTTOM` as `(ptr_t)_start` worked through 2.7, but
1661 * reportedly breaks under 2.8. It appears that the stack base is
1662 * a property of the executable, so this should not break old executables.
1663 * `HEURISTIC1` reportedly no longer works under Solaris 2.7.
1664 * `HEURISTIC2` probably works, but this appears to be preferable.
1665 * Apparently `USRSTACK` is defined to be `USERLIMIT`, but in some
1666 * installations that is undefined. We work around this with a gross hack.
1667 */
1668EXTERN_C_END
1669# include <sys/vmparam.h>
1670EXTERN_C_BEGIN
1671# ifdef USERLIMIT
1672/* This should work everywhere, but does not. */
1673# define STACKBOTTOM ((ptr_t)USRSTACK)
1674# else
1675# define HEURISTIC2
1676# endif
1677#endif /* SOLARIS */
1678
1679#ifdef SYMBIAN
1680# define OS_TYPE "SYMBIAN"
1681# define DATASTART ((ptr_t)ALIGNMENT) /*< cannot be `NULL` */
1682# define DATAEND ((ptr_t)ALIGNMENT)
1683# ifndef USE_MMAP
1684/* `sbrk()` is not available. */
1685# define USE_MMAP 1
1686# endif
1687#endif /* SYMBIAN */
1688
1689/*
1690 * Below are the definitions specific to each supported architecture
1691 * and OS, grouped by the former.
1692 */
1693
1694#ifdef M68K
1695# define MACH_TYPE "M68K"
1696# define CPP_WORDSZ 32
1697# define ALIGNMENT 2 /*< not 4 */
1698# ifdef OPENBSD
1699/* Nothing specific. */
1700# endif
1701# ifdef NETBSD
1702/* Nothing specific. */
1703# endif
1704# ifdef LINUX
1705# ifdef __ELF__
1706# if GC_GLIBC_PREREQ(2, 0)
1707# define SEARCH_FOR_DATA_START
1708# else
1709/*
1710 * Hideous kludge: `__environ` is the first word in platform `crt0.o` file,
1711 * and delimits the start of the data segment, no matter which `ld` options
1712 * were passed through. We could use `_etext` instead, but that would
1713 * include `.rodata`, which may contain large read-only data tables that
1714 * we would rather not scan.
1715 */
1716extern char **__environ;
1717# define DATASTART ((ptr_t)(&__environ))
1718# endif
1719# else
1720extern int etext[];
1721# define DATASTART PTR_ALIGN_UP((ptr_t)etext, 0x1000)
1722# endif
1723# endif
1724# ifdef NEXT
1725# define STACKBOTTOM MAKE_CPTR(0x4000000)
1726# endif
1727#endif
1728
1729#ifdef POWERPC
1730# define MACH_TYPE "POWERPC"
1731# ifdef LINUX
1732# if defined(__powerpc64__)
1733# define CPP_WORDSZ 64
1734# ifndef HBLKSIZE
1735# define HBLKSIZE 4096
1736# endif
1737# else
1738# define CPP_WORDSZ 32
1739# endif
1740/*
1741 * `HEURISTIC1` has been reliably reported to fail for a 32-bit executable
1742 * on a 64-bit kernel.
1743 */
1744# if defined(__bg__)
1745/*
1746 * The Linux Compute Node Kernel (used on BlueGene systems) does not
1747 * support the `SPECIFIC_MAIN_STACKBOTTOM` way.
1748 */
1749# define HEURISTIC2
1750# define NO_PTHREAD_GETATTR_NP
1751# else
1752# define SPECIFIC_MAIN_STACKBOTTOM
1753# endif
1754# define SEARCH_FOR_DATA_START
1755# ifndef SOFT_VDB
1756# define SOFT_VDB
1757# endif
1758# endif
1759# ifdef DARWIN
1760# if defined(__ppc64__)
1761# define CPP_WORDSZ 64
1762# define STACKBOTTOM MAKE_CPTR(0x7fff5fc00000)
1763# define CACHE_LINE_SIZE 64
1764# ifndef HBLKSIZE
1765# define HBLKSIZE 4096
1766# endif
1767# else
1768# define CPP_WORDSZ 32
1769# define STACKBOTTOM MAKE_CPTR(0xc0000000)
1770# endif
1771# define MPROTECT_VDB
1772# if defined(USE_PPC_PREFETCH) && defined(__GNUC__)
1773/* The performance impact of prefetches is untested. */
1774# define PREFETCH(x) \
1775 __asm__ __volatile__("dcbt 0,%0" : : "r"((const void *)(x)))
1776# define GC_PREFETCH_FOR_WRITE(x) \
1777 __asm__ __volatile__("dcbtst 0,%0" : : "r"((const void *)(x)))
1778# endif
1779# endif
1780# ifdef OPENBSD
1781# if defined(__powerpc64__)
1782# define CPP_WORDSZ 64
1783# else
1784# define CPP_WORDSZ 32
1785# endif
1786# endif
1787# ifdef FREEBSD
1788# if defined(__powerpc64__)
1789# define CPP_WORDSZ 64
1790# ifndef HBLKSIZE
1791# define HBLKSIZE 4096
1792# endif
1793# else
1794# define CPP_WORDSZ 32
1795# endif
1796# endif
1797# ifdef NETBSD
1798# define CPP_WORDSZ 32
1799# endif
1800# ifdef SN_TARGET_PS3
1801# define OS_TYPE "SN_TARGET_PS3"
1802# define CPP_WORDSZ 32
1803# define NO_GETENV
1804extern int _end[], __bss_start;
1805# define DATASTART ((ptr_t)__bss_start)
1806# define DATAEND ((ptr_t)_end)
1807# define STACKBOTTOM ((ptr_t)ps3_get_stack_bottom())
1808void *ps3_get_mem(size_t lb);
1809# define GET_MEM(lb) ps3_get_mem(lb)
1810/*
1811 * The current `LOCK()` implementation for PS3 explicitly uses
1812 * `pthread_mutex_lock()` for some reason.
1813 */
1814# define NO_PTHREAD_TRYLOCK
1815# endif
1816# ifdef AIX
1817# define OS_TYPE "AIX"
1818# undef ALIGNMENT /*< in case it is defined */
1819# undef IA64
1820/*
1821 * DOB: some AIX installs stupidly define `IA64` in platform
1822 * `sys/systemcfg.h` file.
1823 */
1824# ifdef __64BIT__
1825# define CPP_WORDSZ 64
1826# define STACKBOTTOM MAKE_CPTR(0x1000000000000000)
1827# else
1828# define CPP_WORDSZ 32
1829extern int errno;
1830# define STACKBOTTOM ((ptr_t)(&errno))
1831# endif
1832# define USE_MMAP_ANON
1833/*
1834 * From AIX linker man page:
1835 * - `_text` specifies the first location of the program;
1836 * - `_etext` specifies the first location after the program;
1837 * - `_data` specifies the first location of the data;
1838 * - `_edata` specifies the first location after the initialized data;
1839 * - `_end` (or `end`) specifies the first location after all data.
1840 */
1841extern int _data[], _end[];
1842# define DATASTART ((ptr_t)_data)
1843# define DATAEND ((ptr_t)_end)
1844# define MPROTECT_VDB
1845# define DYNAMIC_LOADING
1846/*
1847 * Note: for really old versions of AIX, `DYNAMIC_LOADING` may have to
1848 * be removed.
1849 */
1850# endif
1851# ifdef NOSYS
1852# define OS_TYPE "NOSYS"
1853# define CPP_WORDSZ 32
1854extern void __end[], __dso_handle[];
1855# define DATASTART ((ptr_t)__dso_handle) /*< OK, that is ugly */
1856# define DATAEND ((ptr_t)__end)
1857/* Note: stack starts at 0xE0000000 for the simulator. */
1858# define STACKBOTTOM PTR_ALIGN_UP(GC_approx_sp(), 0x10000000)
1859# endif
1860#endif /* POWERPC */
1861
1862#ifdef VAX
1863# define MACH_TYPE "VAX"
1864# define CPP_WORDSZ 32
1865/* Pointers are `longword`-aligned by C compiler v4.2. */
1866extern char etext[];
1867# define DATASTART ((ptr_t)etext)
1868# ifdef BSD
1869# define OS_TYPE "BSD"
1870# define STACK_GRAN 0x1000000
1871# define HEURISTIC1
1872/* Note: `HEURISTIC2` may be OK, but it is hard to test. */
1873# endif
1874# ifdef ULTRIX
1875# define OS_TYPE "ULTRIX"
1876# define STACKBOTTOM MAKE_CPTR(0x7fffc800)
1877# endif
1878#endif /* VAX */
1879
1880#ifdef SPARC
1881# define MACH_TYPE "SPARC"
1882# if defined(__arch64__) || defined(__sparcv9)
1883# define CPP_WORDSZ 64
1884# define ELF_CLASS ELFCLASS64
1885# else
1886# define CPP_WORDSZ 32
1887# define ALIGNMENT 4 /*< required by hardware */
1888# endif
1889# ifdef SOLARIS
1890extern int _etext[];
1891# define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext)
1892# define PROC_VDB
1893/*
1894 * `getpagesize()` appeared to be missing from at least one Solaris 5.4
1895 * installation. Weird.
1896 */
1897# define GETPAGESIZE() (unsigned)sysconf(_SC_PAGESIZE)
1898# endif
1899# ifdef DRSNX
1900# define OS_TYPE "DRSNX"
1901extern int etext[];
1902# define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)etext)
1903# define MPROTECT_VDB
1904# define STACKBOTTOM MAKE_CPTR(0xdfff0000)
1905# define DYNAMIC_LOADING
1906# endif
1907# ifdef LINUX
1908extern int _etext[];
1909# ifdef __arch64__
1910# define DATASTART GC_SysVGetDataStart(0x100000, (ptr_t)_etext)
1911# else
1912# define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext)
1913# endif
1914# endif
1915# ifdef OPENBSD
1916/* Nothing specific. */
1917# endif
1918# ifdef NETBSD
1919/* Nothing specific. */
1920# endif
1921# ifdef FREEBSD
1922extern char etext[];
1923# define DATASTART ((ptr_t)(&etext))
1924# define DATAEND ((ptr_t)GC_find_limit(DATASTART, TRUE))
1925# define DATAEND_IS_FUNC
1926# define GC_HAVE_DATAREGION2
1927extern char edata[], end[];
1928# define DATASTART2 ((ptr_t)(&edata))
1929# define DATAEND2 ((ptr_t)(&end))
1930# endif
1931#endif /* SPARC */
1932
1933#ifdef I386
1934# define MACH_TYPE "I386"
1935# if (defined(__LP64__) || defined(_WIN64)) && !defined(CPPCHECK)
1936# error This should be handled as X86_64
1937# endif
1938# define CPP_WORDSZ 32
1939/*
1940 * The 4-byte alignment appears to hold for all 32-bit compilers
1941 * except Borland and Watcom. If using the Borland (bcc32) or
1942 * Watcom (wcc386) compiler, `-a4` or `-zp4` option, respectively,
1943 * should be passed to the compiler, both for building the library
1944 * and client code. (The alternate solution is to define
1945 * `FORCE_ALIGNMENT_ONE` macro but this would have significant
1946 * negative performance implications.)
1947 */
1948# if defined(FORCE_ALIGNMENT_ONE) \
1949 && (defined(__BORLANDC__) || defined(__WATCOMC__))
1950# define ALIGNMENT 1
1951# endif
1952# ifdef SEQUENT
1953# define OS_TYPE "SEQUENT"
1954extern int etext[];
1955# define DATASTART PTR_ALIGN_UP((ptr_t)etext, 0x1000)
1956# define STACKBOTTOM MAKE_CPTR(0x3ffff000)
1957# endif
1958# ifdef HAIKU
1959/* Nothing specific. */
1960# endif
1961# ifdef HURD
1962/* Nothing specific. */
1963# endif
1964# ifdef EMBOX
1965/* Nothing specific. */
1966# endif
1967# ifdef NACL
1968/* Nothing specific. */
1969# endif
1970# ifdef QNX
1971/* Nothing specific. */
1972# endif
1973# ifdef SERENITY
1974/* Nothing specific. */
1975# endif
1976# ifdef SOLARIS
1977extern int _etext[];
1978# define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)_etext)
1979# define PROC_VDB
1980# endif
1981# ifdef SCO
1982# define OS_TYPE "SCO"
1983extern int etext[];
1984# define DATASTART \
1985 (PTR_ALIGN_UP((ptr_t)etext, 0x400000) + (ADDR(etext) & 0xfff))
1986# define STACKBOTTOM MAKE_CPTR(0x7ffffffc)
1987# endif
1988# ifdef SCO_ELF
1989# define OS_TYPE "SCO_ELF"
1990extern int etext[];
1991# define DATASTART ((ptr_t)etext)
1992# define STACKBOTTOM MAKE_CPTR(0x8048000)
1993# define DYNAMIC_LOADING
1994# define ELF_CLASS ELFCLASS32
1995# endif
1996# ifdef DGUX
1997# define OS_TYPE "DGUX"
1998extern int _etext, _end;
1999# define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)(&_etext))
2000# define DATASTART_USES_XGETDATASTART
2001# define DATAEND ((ptr_t)(&_end))
2002# define HEURISTIC2
2003# define DYNAMIC_LOADING
2004# ifndef USE_MMAP
2005# define USE_MMAP 1
2006# endif
2007# define MAP_FAILED ((void *)(~(GC_uintptr_t)0))
2008# define HEAP_START ((word)0x40000000)
2009# endif /* DGUX */
2010# ifdef LINUX
2011/*
2012 * This encourages `mmap()` to give us low addresses, thus allowing the
2013 * heap to grow to ~3 GB.
2014 */
2015# define HEAP_START ((word)0x1000)
2016# ifdef __ELF__
2017# if GC_GLIBC_PREREQ(2, 0) || defined(HOST_ANDROID)
2018# define SEARCH_FOR_DATA_START
2019# else
2020/* See the comment of the Linux/m68k case. */
2021extern char **__environ;
2022# define DATASTART ((ptr_t)(&__environ))
2023# endif
2024# if !defined(GC_NO_SIGSETJMP) \
2025 && (defined(HOST_TIZEN) \
2026 || (defined(HOST_ANDROID) \
2027 && !(GC_GNUC_PREREQ(4, 8) || GC_CLANG_PREREQ(3, 2) \
2028 || __ANDROID_API__ >= 18)))
2029/*
2030 * Older Android NDK releases lack `sigsetjmp` in x86 `libc` (`setjmp` is
2031 * used instead to find `data_start`). The bug is fixed in Android NDK r8e
2032 * (so, it is OK to use `sigsetjmp` if gcc-4.8+, clang-3.2+ or Android
2033 * API level 18+).
2034 */
2035# define GC_NO_SIGSETJMP 1
2036# endif
2037# else
2038extern int etext[];
2039# define DATASTART PTR_ALIGN_UP((ptr_t)etext, 0x1000)
2040# endif
2041# ifdef USE_I686_PREFETCH
2042/*
2043 * Empirically `prefetcht0` is much more effective at reducing cache miss
2044 * stalls for the targeted load instructions. But it seems to interfere
2045 * enough with other cache traffic that the net result is worse than
2046 * `prefetchnta`.
2047 */
2048# define PREFETCH(x) \
2049 __asm__ __volatile__("prefetchnta %0" : : "m"(*(char *)(x)))
2050# ifdef FORCE_WRITE_PREFETCH
2051/*
2052 * Using prefetches for write seems to have a slight negative impact on
2053 * performance, at least for a PIII/500.
2054 */
2055# define GC_PREFETCH_FOR_WRITE(x) \
2056 __asm__ __volatile__("prefetcht0 %0" : : "m"(*(char *)(x)))
2057# else
2058# define GC_NO_PREFETCH_FOR_WRITE
2059# endif
2060# elif defined(USE_3DNOW_PREFETCH)
2061# define PREFETCH(x) \
2062 __asm__ __volatile__("prefetch %0" : : "m"(*(char *)(x)))
2063# define GC_PREFETCH_FOR_WRITE(x) \
2064 __asm__ __volatile__("prefetchw %0" : : "m"(*(char *)(x)))
2065# endif
2066# if defined(__GLIBC__) && !defined(__UCLIBC__) \
2067 && !defined(GLIBC_TSX_BUG_FIXED)
2068/* Workaround lock elision implementation for some `glibc`. */
2069# define GLIBC_2_19_TSX_BUG
2070EXTERN_C_END
2071# include <gnu/libc-version.h> /*< for `gnu_get_libc_version()` */
2072EXTERN_C_BEGIN
2073# endif
2074# ifndef SOFT_VDB
2075# define SOFT_VDB
2076# endif
2077# endif
2078# ifdef CYGWIN32
2079# define WOW64_THREAD_CONTEXT_WORKAROUND
2080# define DATASTART ((ptr_t)GC_DATASTART) /*< defined in `gc.h` file */
2081# define DATAEND ((ptr_t)GC_DATAEND)
2082# ifndef USE_WINALLOC
2083/* `MPROTECT_VDB` does not work, it leads to a spurious exit. */
2084# endif
2085# endif
2086# ifdef INTERIX
2087# define OS_TYPE "INTERIX"
2088extern int _data_start__[], _bss_end__[];
2089# define DATASTART ((ptr_t)_data_start__)
2090# define DATAEND ((ptr_t)_bss_end__)
2091# define STACKBOTTOM \
2092 ({ \
2093 ptr_t rv; \
2094 __asm__ __volatile__("movl %%fs:4, %%eax" : "=a"(rv)); \
2095 rv; \
2096 })
2097# define USE_MMAP_ANON
2098# endif
2099# ifdef OS2
2100# define OS_TYPE "OS2"
2101/*
2102 * `STACKBOTTOM` and `DATASTART` are handled specially in `os_dep.c`
2103 * file. OS/2 actually has the right system call!
2104 */
2105# define DATAEND /*< not needed */
2106# undef USE_MUNMAP
2107# define GETPAGESIZE() os2_getpagesize()
2108# endif
2109# ifdef MSWIN32
2110# define WOW64_THREAD_CONTEXT_WORKAROUND
2111# define RETRY_GET_THREAD_CONTEXT
2112# if defined(__BORLANDC__)
2113/*
2114 * TODO: VDB based on `VirtualProtect` and `SetUnhandledExceptionFilter`
2115 * does not work correctly.
2116 */
2117# else
2118# define MPROTECT_VDB
2119# endif
2120# endif
2121# ifdef MSWINCE
2122/* Nothing specific. */
2123# endif
2124# ifdef DJGPP
2125# define OS_TYPE "DJGPP"
2126EXTERN_C_END
2127# include "stubinfo.h"
2128EXTERN_C_BEGIN
2129extern int etext[];
2130# define DATASTART PTR_ALIGN_UP((ptr_t)etext, 0x200)
2131extern int __djgpp_stack_limit, _stklen;
2132# define STACKBOTTOM (MAKE_CPTR(__djgpp_stack_limit) + _stklen)
2133# endif
2134# ifdef OPENBSD
2135/* Nothing specific. */
2136# endif
2137# ifdef FREEBSD
2138# if defined(__GLIBC__)
2139extern int _end[];
2140# define DATAEND ((ptr_t)_end)
2141# endif
2142# endif
2143# ifdef NETBSD
2144/* Nothing specific. */
2145# endif
2146# ifdef THREE86BSD
2147# define OS_TYPE "THREE86BSD"
2148# define HEURISTIC2
2149extern char etext[];
2150# define DATASTART ((ptr_t)etext)
2151# endif
2152# ifdef BSDI
2153# define OS_TYPE "BSDI"
2154# define HEURISTIC2
2155extern char etext[];
2156# define DATASTART ((ptr_t)etext)
2157# endif
2158# ifdef NEXT
2159# define STACKBOTTOM MAKE_CPTR(0xc0000000)
2160# endif
2161# ifdef RTEMS
2162# define OS_TYPE "RTEMS"
2163EXTERN_C_END
2164# include <sys/unistd.h>
2165EXTERN_C_BEGIN
2166extern int etext[];
2167# define DATASTART ((ptr_t)etext)
2168void *rtems_get_stack_bottom(void);
2169# define InitStackBottom rtems_get_stack_bottom()
2170# define STACKBOTTOM ((ptr_t)InitStackBottom)
2171# undef USE_MUNMAP
2172# endif
2173# ifdef DOS4GW
2174# define OS_TYPE "DOS4GW"
2175extern long __nullarea;
2176extern char _end;
2177extern char *_STACKTOP;
2178/*
2179 * Depending on calling conventions Watcom C either precedes or does not
2180 * precede the names of the C variables with an underscore.
2181 * Make sure the startup code variables always have the same name.
2182 */
2183# pragma aux __nullarea "*";
2184# pragma aux _end "*";
2185# define STACKBOTTOM ((ptr_t)_STACKTOP) /*< confused? me too */
2186# define DATASTART ((ptr_t)(&__nullarea))
2187# define DATAEND ((ptr_t)(&_end))
2188# undef USE_MUNMAP
2189# define GETPAGESIZE() 4096
2190# endif
2191# ifdef DARWIN
2192# define DARWIN_DONT_PARSE_STACK 1
2193# define STACKBOTTOM MAKE_CPTR(0xc0000000)
2194# define MPROTECT_VDB
2195# endif
2196#endif /* I386 */
2197
2198#ifdef LOONGARCH
2199# define MACH_TYPE "LOONGARCH"
2200# define CPP_WORDSZ (__SIZEOF_SIZE_T__ * 8)
2201# ifdef LINUX
2202# pragma weak __data_start
2203extern int __data_start[];
2204# define DATASTART ((ptr_t)__data_start)
2205# endif
2206#endif /* LOONGARCH */
2207
2208#ifdef SW_64
2209# define MACH_TYPE "SW_64"
2210# define CPP_WORDSZ 64
2211# ifdef LINUX
2212/* Nothing specific. */
2213# endif
2214#endif /* SW_64 */
2215
2216#ifdef MIPS
2217# define MACH_TYPE "MIPS"
2218# ifdef LINUX
2219# ifdef _MIPS_SZPTR
2220# define CPP_WORDSZ _MIPS_SZPTR
2221# else
2222# define CPP_WORDSZ 32
2223# endif
2224# pragma weak __data_start
2225extern int __data_start[];
2226# define DATASTART ((ptr_t)__data_start)
2227# ifndef HBLKSIZE
2228# define HBLKSIZE 4096
2229# endif
2230# if GC_GLIBC_PREREQ(2, 2)
2231# define SPECIFIC_MAIN_STACKBOTTOM
2232# else
2233# define STACKBOTTOM MAKE_CPTR(0x7fff8000)
2234# endif
2235# endif
2236# ifdef EWS4800
2237# define OS_TYPE "EWS4800"
2238# define HEURISTIC2
2239# if defined(_MIPS_SZPTR) && (_MIPS_SZPTR == 64)
2240# define CPP_WORDSZ _MIPS_SZPTR
2241extern int _fdata[], _end[];
2242# define DATASTART ((ptr_t)_fdata)
2243# define DATAEND ((ptr_t)_end)
2244# else
2245# define CPP_WORDSZ 32
2246extern int etext[], edata[];
2247# define DATASTART \
2248 (PTR_ALIGN_UP((ptr_t)etext, 0x40000) + (ADDR(etext) & 0xffff))
2249# define DATAEND ((ptr_t)edata)
2250# define GC_HAVE_DATAREGION2
2251extern int _DYNAMIC_LINKING[], _gp[];
2252# define DATASTART2 \
2253 (_DYNAMIC_LINKING ? PTR_ALIGN_UP((ptr_t)_gp + 0x8000, 0x40000) \
2254 : (ptr_t)edata)
2255extern int end[];
2256# define DATAEND2 ((ptr_t)end)
2257# endif
2258# endif
2259# ifdef ULTRIX
2260# define OS_TYPE "ULTRIX"
2261# define CPP_WORDSZ 32
2262# define HEURISTIC2
2263/*
2264 * Note: the actual beginning of the data segment could probably be
2265 * slightly higher since startup code allocates lots of stuff.
2266 */
2267# define DATASTART MAKE_CPTR(0x10000000)
2268# endif
2269# ifdef IRIX5
2270# define OS_TYPE "IRIX5"
2271# ifdef _MIPS_SZPTR
2272# define CPP_WORDSZ _MIPS_SZPTR
2273# else
2274# define CPP_WORDSZ 32
2275# endif
2276# define HEURISTIC2
2277extern int _fdata[];
2278# define DATASTART ((ptr_t)_fdata)
2279/*
2280 * Lowest plausible heap address. In the `USE_MMAP` case, we map there.
2281 * In either case it is used to identify heap sections so they are not
2282 * considered as roots.
2283 */
2284# ifdef USE_MMAP
2285# define HEAP_START ((word)0x30000000)
2286# else
2287# define HEAP_START ADDR(DATASTART)
2288# endif
2289/* `MPROTECT_VDB` should work, but there is evidence of a breakage. */
2290# define DYNAMIC_LOADING
2291# endif
2292# ifdef MSWINCE
2293# define CPP_WORDSZ 32
2294# endif
2295# ifdef NETBSD
2296# define CPP_WORDSZ 32
2297# ifndef __ELF__
2298# define DATASTART MAKE_CPTR(0x10000000)
2299# define STACKBOTTOM MAKE_CPTR(0x7ffff000)
2300# endif
2301# endif
2302# ifdef OPENBSD
2303# define CPP_WORDSZ 64 /*< all OpenBSD/mips platforms are 64-bit */
2304# endif
2305# ifdef FREEBSD
2306# define CPP_WORDSZ 32
2307# endif
2308# ifdef NONSTOP
2309# define OS_TYPE "NONSTOP"
2310# define CPP_WORDSZ 32
2311# define DATASTART MAKE_CPTR(0x8000000)
2312extern char **environ;
2313# define DATAEND ((ptr_t)(environ - 0x10))
2314# define STACKBOTTOM MAKE_CPTR(0x4fffffff)
2315# undef USE_MUNMAP
2316# endif
2317#endif /* MIPS */
2318
2319#ifdef NIOS2
2320# define MACH_TYPE "NIOS2"
2321# define CPP_WORDSZ 32
2322# ifndef HBLKSIZE
2323# define HBLKSIZE 4096
2324# endif
2325# ifdef LINUX
2326extern int __data_start[];
2327# define DATASTART ((ptr_t)__data_start)
2328# endif
2329#endif /* NIOS2 */
2330
2331#ifdef OR1K
2332# define MACH_TYPE "OR1K"
2333# define CPP_WORDSZ 32
2334# ifndef HBLKSIZE
2335# define HBLKSIZE 4096
2336# endif
2337# ifdef LINUX
2338extern int __data_start[];
2339# define DATASTART ((ptr_t)__data_start)
2340# endif
2341#endif /* OR1K */
2342
2343#ifdef HP_PA
2344# define MACH_TYPE "HP_PA"
2345# ifdef __LP64__
2346# define CPP_WORDSZ 64
2347# else
2348# define CPP_WORDSZ 32
2349# endif
2350# define STACK_GROWS_UP
2351# ifdef HPUX
2352# ifndef GC_THREADS
2353# define MPROTECT_VDB
2354# endif
2355# ifdef USE_HPUX_FIXED_STACKBOTTOM
2356/*
2357 * The following appears to work for 7xx systems running HP/UX 9.xx.
2358 * Furthermore, it might result in much faster collections than `HEURISTIC2`,
2359 * which may involve scanning segments that directly precede the stack.
2360 * It is not the default, since it may not work on older machine/OS
2361 * combinations. (Thanks to Raymond X.T. Nijssen for uncovering this.)
2362 * This technique also does not work with HP/UX 11.xx. The stack size is
2363 * settable using the kernel `maxssiz` variable, and the size can be set
2364 * dynamically in HP/UX 11.23 and later. It also does not handle
2365 * `SHMEM_MAGIC` binaries that have stack and data in the first quadrant.
2366 * This is from platform `/etc/conf/h/param.h` file.
2367 */
2368# define STACKBOTTOM MAKE_CPTR(0x7b033000)
2369# elif defined(USE_ENVIRON_POINTER)
2370/*
2371 * Gustavo Rodriguez-Rivera suggested changing `HEURISTIC2` to this.
2372 * Note that the collector must be initialized before the first `putenv()`
2373 * call. Unfortunately, some clients do not obey.
2374 */
2375extern char **environ;
2376# define STACKBOTTOM ((ptr_t)environ)
2377# elif !defined(HEURISTIC2)
2378/* This uses `pst_vm_status` support. */
2379# define SPECIFIC_MAIN_STACKBOTTOM
2380# endif
2381# ifndef __GNUC__
2382# define PREFETCH(x) \
2383 do { \
2384 register long addr = (long)(x); \
2385 (void)_asm("LDW", 0, 0, addr, 0); \
2386 } while (0)
2387# endif
2388# endif /* HPUX */
2389# ifdef LINUX
2390# define SEARCH_FOR_DATA_START
2391# endif
2392# ifdef OPENBSD
2393/* Nothing specific. */
2394# endif
2395#endif /* HP_PA */
2396
2397#ifdef ALPHA
2398# define MACH_TYPE "ALPHA"
2399# define CPP_WORDSZ 64
2400# ifdef NETBSD
2401# define ELFCLASS32 32
2402# define ELFCLASS64 64
2403# define ELF_CLASS ELFCLASS64
2404# endif
2405# ifdef OPENBSD
2406/* Nothing specific. */
2407# endif
2408# ifdef FREEBSD
2409extern char etext[];
2410# define DATASTART ((ptr_t)(&etext))
2411# define DATAEND ((ptr_t)GC_find_limit(DATASTART, TRUE))
2412# define DATAEND_IS_FUNC
2413/*
2414 * Handle unmapped hole which `alpha*-*-freebsd[45]*` puts between
2415 * `etext` and `edata`.
2416 */
2417# define GC_HAVE_DATAREGION2
2418extern char edata[], end[];
2419# define DATASTART2 ((ptr_t)(&edata))
2420# define DATAEND2 ((ptr_t)(&end))
2421/* `MPROTECT_VDB` is not yet supported at all on FreeBSD/alpha. */
2422# endif
2423# ifdef OSF1
2424# define OS_TYPE "OSF1"
2425# define DATASTART MAKE_CPTR(0x140000000)
2426extern int _end[];
2427# define DATAEND ((ptr_t)(&_end))
2428extern char **environ;
2429/*
2430 * Round up from the value of `environ` to the nearest page boundary.
2431 * Probably this is broken if `putenv()` is called before the collector
2432 * initialization.
2433 */
2434# define STACKBOTTOM PTR_ALIGN_UP((ptr_t)environ, getpagesize())
2435/*
2436 * Normally `HEURISTIC2` is too conservative, since the text segment
2437 * immediately follows the stack. Hence we give an upper bound.
2438 * This is currently unused, since `HEURISTIC2` is not defined.
2439 */
2440extern int __start[];
2441# define HEURISTIC2_LIMIT PTR_ALIGN_DOWN((ptr_t)__start, getpagesize())
2442# ifndef GC_THREADS
2443/* FIXME: Unresolved signal issues with threads. */
2444# define MPROTECT_VDB
2445# endif
2446# define DYNAMIC_LOADING
2447# endif
2448# ifdef LINUX
2449# ifdef __ELF__
2450# define SEARCH_FOR_DATA_START
2451# else
2452# define DATASTART MAKE_CPTR(0x140000000)
2453extern int _end[];
2454# define DATAEND ((ptr_t)_end)
2455# endif
2456# endif
2457#endif /* ALPHA */
2458
2459#ifdef IA64
2460# define MACH_TYPE "IA64"
2461# ifdef HPUX
2462# ifdef _ILP32
2463# define CPP_WORDSZ 32
2464/* Note: requires 8-byte alignment (granularity) for `malloc()`. */
2465# define ALIGNMENT 4
2466# else
2467# if !defined(_LP64) && !defined(CPPCHECK)
2468# error Unknown ABI
2469# endif
2470# define CPP_WORDSZ 64
2471/* Note: requires 16-byte alignment (granularity) for `malloc()`. */
2472# define ALIGNMENT 8
2473# endif
2474/*
2475 * Note that the collector must be initialized before the 1st `putenv`
2476 * call.
2477 */
2478extern char **environ;
2479# define STACKBOTTOM ((ptr_t)environ)
2480/*
2481 * The following was empirically determined, and is probably not very
2482 * robust. Note that the backing store base seems to be at a nice address
2483 * minus one page.
2484 */
2485# define BACKING_STORE_DISPLACEMENT 0x1000000
2486# define BACKING_STORE_ALIGNMENT 0x1000
2487/* Known to be wrong for recent HP/UX versions!!! */
2488# endif
2489# ifdef LINUX
2490# define CPP_WORDSZ 64
2491/*
2492 * The following works on NUE and older kernels:
2493 * `define STACKBOTTOM MAKE_CPTR(0xa000000000000000l)`.
2494 */
2495/* TODO: `SPECIFIC_MAIN_STACKBOTTOM` does not work on NUE. */
2496/* We also need the base address of the register stack backing store. */
2497# define SEARCH_FOR_DATA_START
2498# ifdef __GNUC__
2499# define DYNAMIC_LOADING
2500# else
2501/*
2502 * In the Intel compiler environment, we seem to end up with statically
2503 * linked executables and an undefined reference to `_DYNAMIC`.
2504 */
2505# endif
2506# ifdef __GNUC__
2507# ifndef __INTEL_COMPILER
2508# define PREFETCH(x) __asm__(" lfetch [%0]" : : "r"(x))
2509# define GC_PREFETCH_FOR_WRITE(x) \
2510 __asm__(" lfetch.excl [%0]" : : "r"(x))
2511# define CLEAR_DOUBLE(x) \
2512 __asm__(" stf.spill [%0]=f0" : : "r"((void *)(x)))
2513# else
2514EXTERN_C_END
2515# include <ia64intrin.h>
2516EXTERN_C_BEGIN
2517# define PREFETCH(x) __lfetch(__lfhint_none, (x))
2518# define GC_PREFETCH_FOR_WRITE(x) __lfetch(__lfhint_nta, (x))
2519# define CLEAR_DOUBLE(x) __stf_spill((void *)(x), 0)
2520# endif /* __INTEL_COMPILER */
2521# endif
2522# endif
2523# ifdef MSWIN32
2524/* FIXME: This is a very partial guess. There is no port, yet. */
2525# if defined(_WIN64)
2526# define CPP_WORDSZ 64
2527# else
2528/* TODO: Is this possible? */
2529# define CPP_WORDSZ 32
2530# endif
2531# endif
2532#endif /* IA64 */
2533
2534#ifdef E2K
2535# define MACH_TYPE "E2K"
2536# ifdef __LP64__
2537# define CPP_WORDSZ 64
2538# else
2539# define CPP_WORDSZ 32
2540# endif
2541# ifndef HBLKSIZE
2542# define HBLKSIZE 4096
2543# endif
2544# ifdef LINUX
2545extern int __dso_handle[];
2546# define DATASTART ((ptr_t)__dso_handle)
2547# ifdef REDIRECT_MALLOC
2548# define NO_PROC_FOR_LIBRARIES
2549# endif
2550# endif
2551#endif /* E2K */
2552
2553#ifdef M88K
2554# define MACH_TYPE "M88K"
2555# define CPP_WORDSZ 32
2556# define STACKBOTTOM MAKE_CPTR(0xf0000000) /*< determined empirically */
2557extern int etext[];
2558# ifdef CX_UX
2559# define OS_TYPE "CX_UX"
2560# define DATASTART (PTR_ALIGN_UP((ptr_t)etext, 0x400000) + 0x10000)
2561# endif
2562# ifdef DGUX
2563# define OS_TYPE "DGUX"
2564# define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)etext)
2565# define DATASTART_USES_XGETDATASTART
2566# endif
2567#endif /* M88K */
2568
2569#ifdef S370
2570/*
2571 * If this still works, and if anyone cares, this should probably be moved
2572 * to the `S390` category.
2573 */
2574# define MACH_TYPE "S370"
2575# define CPP_WORDSZ 32
2576# define ALIGNMENT 4 /*< required by hardware */
2577# ifdef UTS4
2578# define OS_TYPE "UTS4"
2579extern int _etext[], _end[];
2580# define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext)
2581# define DATAEND ((ptr_t)_end)
2582# define HEURISTIC2
2583# endif
2584#endif /* S370 */
2585
2586#ifdef S390
2587# define MACH_TYPE "S390"
2588# ifndef __s390x__
2589# define CPP_WORDSZ 32
2590# else
2591# define CPP_WORDSZ 64
2592# ifndef HBLKSIZE
2593# define HBLKSIZE 4096
2594# endif
2595# endif
2596# ifdef LINUX
2597extern int __data_start[] __attribute__((__weak__));
2598extern int _end[] __attribute__((__weak__));
2599# define DATASTART ((ptr_t)__data_start)
2600# define DATAEND ((ptr_t)_end)
2601# define CACHE_LINE_SIZE 256
2602# define GETPAGESIZE() 4096
2603# ifndef SOFT_VDB
2604# define SOFT_VDB
2605# endif
2606# endif
2607#endif /* S390 */
2608
2609#ifdef AARCH64
2610# define MACH_TYPE "AARCH64"
2611# ifdef __ILP32__
2612# define CPP_WORDSZ 32
2613# else
2614# define CPP_WORDSZ 64
2615# endif
2616# ifndef HBLKSIZE
2617# define HBLKSIZE 4096
2618# endif
2619# ifdef LINUX
2620# if defined(HOST_ANDROID)
2621# define SEARCH_FOR_DATA_START
2622# else
2623extern int __data_start[] __attribute__((__weak__));
2624# define DATASTART ((ptr_t)__data_start)
2625# endif
2626# endif
2627# ifdef COSMO
2628/* Empty. */
2629# endif
2630# ifdef DARWIN
2631/* OS X, iOS, visionOS */
2632# define DARWIN_DONT_PARSE_STACK 1
2633# define STACKBOTTOM MAKE_CPTR(0x16fdfffff)
2634# if (TARGET_OS_IPHONE || TARGET_OS_XR || TARGET_OS_VISION)
2635/*
2636 * `MPROTECT_VDB` causes use of non-public API like `exc_server`, this
2637 * could be a reason for blocking the client application in the store.
2638 */
2639# elif TARGET_OS_OSX
2640# define MPROTECT_VDB
2641# endif
2642# endif
2643# ifdef FREEBSD
2644/* Nothing specific. */
2645# endif
2646# ifdef NETBSD
2647# define ELF_CLASS ELFCLASS64
2648# endif
2649# ifdef OPENBSD
2650/* Nothing specific. */
2651# endif
2652# ifdef NINTENDO_SWITCH
2653# define OS_TYPE "NINTENDO_SWITCH"
2654# define NO_HANDLE_FORK 1
2655extern int __bss_end[];
2656# define DATASTART ((ptr_t)ALIGNMENT) /*< cannot be `NULL` */
2657# define DATAEND ((ptr_t)(&__bss_end))
2658void *switch_get_stack_bottom(void);
2659# define STACKBOTTOM ((ptr_t)switch_get_stack_bottom())
2660void *switch_get_mem(size_t lb);
2661# define GET_MEM(lb) switch_get_mem(lb)
2662# define GETPAGESIZE() 4096
2663# undef USE_MMAP
2664# undef USE_MUNMAP
2665# ifndef HAVE_CLOCK_GETTIME
2666# define HAVE_CLOCK_GETTIME 1
2667# endif
2668# endif
2669# ifdef KOS
2670/* Nothing specific. */
2671# endif
2672# ifdef QNX
2673/* Nothing specific. */
2674# endif
2675# ifdef SERENITY
2676/* Nothing specific. */
2677# endif
2678# ifdef MSWIN32
2679/* UWP */
2680/* TODO: Enable `MPROTECT_VDB`. */
2681# endif
2682# ifdef NOSYS
2683# define OS_TYPE "NOSYS"
2684/* `__data_start` is usually defined in the target linker script. */
2685extern int __data_start[];
2686# define DATASTART ((ptr_t)__data_start)
2687extern void *__stack_base__;
2688# define STACKBOTTOM ((ptr_t)__stack_base__)
2689# endif
2690#endif /* AARCH64 */
2691
2692#ifdef ARM32
2693# define MACH_TYPE "ARM32"
2694# define CPP_WORDSZ 32
2695# ifdef LINUX
2696# if GC_GLIBC_PREREQ(2, 0) || defined(HOST_ANDROID)
2697# define SEARCH_FOR_DATA_START
2698# else
2699/* See the comment of the Linux/m68k case. */
2700extern char **__environ;
2701# define DATASTART ((ptr_t)(&__environ))
2702# endif
2703# endif
2704# ifdef MSWINCE
2705/* Nothing specific. */
2706# endif
2707# ifdef FREEBSD
2708/* Nothing specific. */
2709# endif
2710# ifdef DARWIN
2711/* iOS */
2712# define DARWIN_DONT_PARSE_STACK 1
2713# define STACKBOTTOM MAKE_CPTR(0x30000000)
2714/* `MPROTECT_VDB` causes use of non-public API. */
2715# endif
2716# ifdef NETBSD
2717/* Nothing specific. */
2718# endif
2719# ifdef OPENBSD
2720/* Nothing specific. */
2721# endif
2722# ifdef QNX
2723/* Nothing specific. */
2724# endif
2725# ifdef SN_TARGET_PSP2
2726# define OS_TYPE "SN_TARGET_PSP2"
2727# define NO_HANDLE_FORK 1
2728# ifndef HBLKSIZE
2729# define HBLKSIZE 65536 /*< page size is 64 KB */
2730# endif
2731# define DATASTART ((ptr_t)ALIGNMENT)
2732# define DATAEND ((ptr_t)ALIGNMENT)
2733void *psp2_get_stack_bottom(void);
2734# define STACKBOTTOM ((ptr_t)psp2_get_stack_bottom())
2735void *psp2_get_mem(size_t lb);
2736# define GET_MEM(lb) psp2_get_mem(lb)
2737# endif
2738# ifdef NN_PLATFORM_CTR
2739# define OS_TYPE "NN_PLATFORM_CTR"
2740extern unsigned char Image$$ZI$$ZI$$Base[];
2741# define DATASTART ((ptr_t)Image$$ZI$$ZI$$Base)
2742extern unsigned char Image$$ZI$$ZI$$Limit[];
2743# define DATAEND ((ptr_t)Image$$ZI$$ZI$$Limit)
2744void *n3ds_get_stack_bottom(void);
2745# define STACKBOTTOM ((ptr_t)n3ds_get_stack_bottom())
2746# endif
2747# ifdef MSWIN32
2748/* UWP */
2749/* TODO: Enable `MPROTECT_VDB`. */
2750# endif
2751# ifdef NOSYS
2752# define OS_TYPE "NOSYS"
2753/* `__data_start` is usually defined in the target linker script. */
2754extern int __data_start[];
2755# define DATASTART ((ptr_t)__data_start)
2756/* `__stack_base__` is set in platform `newlib/libc/sys/arm/crt0.S` file. */
2757extern void *__stack_base__;
2758# define STACKBOTTOM ((ptr_t)__stack_base__)
2759# endif
2760# ifdef SYMBIAN
2761/* Nothing specific. */
2762# endif
2763#endif /* ARM32 */
2764
2765#ifdef CRIS
2766# define MACH_TYPE "CRIS"
2767# define CPP_WORDSZ 32
2768# define ALIGNMENT 1
2769# ifdef LINUX
2770# define SEARCH_FOR_DATA_START
2771# endif
2772#endif /* CRIS */
2773
2774#if defined(SH) && !defined(SH4)
2775# define MACH_TYPE "SH"
2776# define CPP_WORDSZ 32
2777# ifdef LINUX
2778# define SEARCH_FOR_DATA_START
2779# endif
2780# ifdef NETBSD
2781/* Nothing specific. */
2782# endif
2783# ifdef OPENBSD
2784/* Nothing specific. */
2785# endif
2786# ifdef MSWINCE
2787/* Nothing specific. */
2788# endif
2789#endif
2790
2791#ifdef SH4
2792# define MACH_TYPE "SH4"
2793# define CPP_WORDSZ 32
2794# ifdef MSWINCE
2795/* Nothing specific. */
2796# endif
2797#endif /* SH4 */
2798
2799#ifdef AVR32
2800# define MACH_TYPE "AVR32"
2801# define CPP_WORDSZ 32
2802# ifdef LINUX
2803# define SEARCH_FOR_DATA_START
2804# endif
2805#endif /* AVR32 */
2806
2807#ifdef M32R
2808# define MACH_TYPE "M32R"
2809# define CPP_WORDSZ 32
2810# ifdef LINUX
2811# define SEARCH_FOR_DATA_START
2812# endif
2813#endif /* M32R */
2814
2815#ifdef X86_64
2816# define MACH_TYPE "X86_64"
2817# ifdef __ILP32__
2818# define CPP_WORDSZ 32
2819# else
2820# define CPP_WORDSZ 64
2821# endif
2822# ifndef HBLKSIZE
2823# define HBLKSIZE 4096
2824# endif
2825# ifndef CACHE_LINE_SIZE
2826# define CACHE_LINE_SIZE 64
2827# endif
2828# ifdef PLATFORM_GETMEM
2829# define OS_TYPE "PLATFORM_GETMEM"
2830# define DATASTART ((ptr_t)ALIGNMENT)
2831# define DATAEND ((ptr_t)ALIGNMENT)
2832EXTERN_C_END
2833# include <pthread.h>
2834EXTERN_C_BEGIN
2835void *platform_get_stack_bottom(void);
2836# define STACKBOTTOM ((ptr_t)platform_get_stack_bottom())
2837void *platform_get_mem(size_t lb);
2838# define GET_MEM(lb) platform_get_mem(lb)
2839# endif
2840# ifdef LINUX
2841# define SEARCH_FOR_DATA_START
2842# if defined(__GLIBC__) && !defined(__UCLIBC__)
2843/*
2844 * A workaround for GCF (Google Cloud Function) which does not support
2845 * `mmap()` for `/dev/zero` pseudo-file. Should not cause any harm to
2846 * other targets.
2847 */
2848# define USE_MMAP_ANON
2849# endif
2850# if defined(__GLIBC__) && !defined(__UCLIBC__) \
2851 && !defined(GETCONTEXT_FPU_BUG_FIXED)
2852/*
2853 * At present, there is a bug in `glibc` `getcontext()` on Linux/x86_64
2854 * (it clears FPU exception mask). We define this macro to workaround it.
2855 */
2856/* TODO: This seems to be fixed in `glibc` 2.14. */
2857# define GETCONTEXT_FPU_EXCMASK_BUG
2858# endif
2859# if defined(__GLIBC__) && !defined(__UCLIBC__) \
2860 && !defined(GLIBC_TSX_BUG_FIXED)
2861/* Workaround lock elision implementation for some `glibc`. */
2862# define GLIBC_2_19_TSX_BUG
2863EXTERN_C_END
2864# include <gnu/libc-version.h> /*< for `gnu_get_libc_version()` */
2865EXTERN_C_BEGIN
2866# endif
2867# ifndef SOFT_VDB
2868# define SOFT_VDB
2869# endif
2870# endif
2871# ifdef COSMO
2872/* Empty. */
2873# endif
2874# ifdef DARWIN
2875# define DARWIN_DONT_PARSE_STACK 1
2876# define STACKBOTTOM MAKE_CPTR(0x7fff5fc00000)
2877# define MPROTECT_VDB
2878# endif
2879# ifdef FREEBSD
2880# if defined(__GLIBC__)
2881extern int _end[];
2882# define DATAEND ((ptr_t)_end)
2883# endif
2884# if defined(__DragonFly__)
2885/*
2886 * DragonFly BSD still has `vm.max_proc_mmap`, according to its
2887 * `mmap(2)` man page.
2888 */
2889# define COUNT_UNMAPPED_REGIONS
2890# endif
2891# endif
2892# ifdef NETBSD
2893/* Nothing specific. */
2894# endif
2895# ifdef OPENBSD
2896/* Nothing specific. */
2897# endif
2898# ifdef HAIKU
2899/* Nothing specific. */
2900# endif
2901# ifdef HURD
2902/* Nothing specific. */
2903# endif
2904# ifdef QNX
2905/* Nothing specific. */
2906# endif
2907# ifdef SERENITY
2908/* Nothing specific. */
2909# endif
2910# ifdef SOLARIS
2911# define ELF_CLASS ELFCLASS64
2912extern int _etext[];
2913# define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)_etext)
2914# define PROC_VDB
2915# endif
2916# ifdef CYGWIN32
2917# ifndef USE_WINALLOC
2918# if defined(THREAD_LOCAL_ALLOC)
2919/*
2920 * TODO: For an unknown reason, thread-local allocations lead to spurious
2921 * process exit after the fault handler is once invoked.
2922 */
2923# else
2924# define MPROTECT_VDB
2925# endif
2926# endif
2927# endif
2928# ifdef MSWIN_XBOX1
2929# define OS_TYPE "MSWIN_XBOX1"
2930# define NO_GETENV
2931# define DATASTART ((ptr_t)ALIGNMENT)
2932# define DATAEND ((ptr_t)ALIGNMENT)
2933LONG64 durango_get_stack_bottom(void);
2934# define STACKBOTTOM ((ptr_t)durango_get_stack_bottom())
2935# define GETPAGESIZE() 4096
2936# ifndef USE_MMAP
2937# define USE_MMAP 1
2938# endif
2939/* The following is from platform `sys/mman.h` file. */
2940# define PROT_NONE 0
2941# define PROT_READ 1
2942# define PROT_WRITE 2
2943# define PROT_EXEC 4
2944# define MAP_PRIVATE 2
2945# define MAP_FIXED 0x10
2946# define MAP_FAILED ((void *)(~(GC_uintptr_t)0))
2947# endif
2948# ifdef MSWIN32
2949# define RETRY_GET_THREAD_CONTEXT
2950# if !defined(__GNUC__) || defined(__INTEL_COMPILER) \
2951 || (GC_GNUC_PREREQ(4, 7) && !defined(__MINGW64__))
2952/*
2953 * Older gcc and Mingw-w64 (both gcc and clang) do not support
2954 * `SetUnhandledExceptionFilter()` properly on x86_64.
2955 */
2956# define MPROTECT_VDB
2957# endif
2958# endif
2959#endif /* X86_64 */
2960
2961#ifdef ARC
2962# define MACH_TYPE "ARC"
2963# define CPP_WORDSZ 32
2964# define CACHE_LINE_SIZE 64
2965# ifdef LINUX
2966extern int __data_start[] __attribute__((__weak__));
2967# define DATASTART ((ptr_t)__data_start)
2968# endif
2969#endif /* ARC */
2970
2971#ifdef HEXAGON
2972# define MACH_TYPE "HEXAGON"
2973# define CPP_WORDSZ 32
2974# ifdef LINUX
2975# if defined(__GLIBC__)
2976# define SEARCH_FOR_DATA_START
2977# elif !defined(CPPCHECK)
2978# error Unknown Hexagon libc configuration
2979# endif
2980# endif
2981#endif /* HEXAGON */
2982
2983#ifdef TILEPRO
2984# define MACH_TYPE "TILEPRO"
2985# define CPP_WORDSZ 32
2986# define PREFETCH(x) __insn_prefetch(x)
2987# define CACHE_LINE_SIZE 64
2988# ifdef LINUX
2989extern int __data_start[];
2990# define DATASTART ((ptr_t)__data_start)
2991# endif
2992#endif /* TILEPRO */
2993
2994#ifdef TILEGX
2995# define MACH_TYPE "TILEGX"
2996# define CPP_WORDSZ (__SIZEOF_PTRDIFF_T__ * 8)
2997# if CPP_WORDSZ == 32
2998# define CLEAR_DOUBLE(x) (void)(*(long long *)(x) = 0)
2999# endif
3000# define PREFETCH(x) __insn_prefetch_l1(x)
3001# define CACHE_LINE_SIZE 64
3002# ifdef LINUX
3003extern int __data_start[];
3004# define DATASTART ((ptr_t)__data_start)
3005# endif
3006#endif /* TILEGX */
3007
3008#ifdef RISCV
3009# define MACH_TYPE "RISCV"
3010# define CPP_WORDSZ (__SIZEOF_SIZE_T__ * 8) /*< 32 or 64 */
3011# ifdef FREEBSD
3012/* Nothing specific. */
3013# endif
3014# ifdef LINUX
3015extern int __data_start[] __attribute__((__weak__));
3016# define DATASTART ((ptr_t)__data_start)
3017# endif
3018# ifdef NETBSD
3019/* Nothing specific. */
3020# endif
3021# ifdef OPENBSD
3022/* Nothing specific. */
3023# endif
3024# ifdef NOSYS
3025# define OS_TYPE "NOSYS"
3026extern char etext[];
3027# define DATASTART ((ptr_t)etext)
3028/* FIXME: `STACKBOTTOM` is wrong! */
3029extern char **environ;
3030# define STACKBOTTOM ((ptr_t)environ)
3031/* TODO: Support 64K page size. */
3032# define GETPAGESIZE() 4096
3033# endif
3034#endif /* RISCV */
3035
3036#ifdef WEBASSEMBLY
3037# define MACH_TYPE "WEBASSEMBLY"
3038# if defined(__wasm64__) && !defined(CPPCHECK)
3039# error 64-bit WebAssembly is not yet supported
3040# endif
3041# define CPP_WORDSZ 32
3042/*
3043 * Emscripten does emulate `mmap` and `munmap`, but those should not be
3044 * used in the collector, since WebAssembly lacks the native support of
3045 * memory mapping. Use `sbrk()` instead (by default).
3046 */
3047# undef USE_MMAP
3048# undef USE_MUNMAP
3049# ifdef EMSCRIPTEN_TINY
3050void *emmalloc_memalign(size_t align, size_t lb);
3051# define GET_MEM(lb) emmalloc_memalign(GC_page_size, lb)
3052# endif
3053# ifdef EMSCRIPTEN
3054# define OS_TYPE "EMSCRIPTEN"
3055# define DATASTART ((ptr_t)ALIGNMENT)
3056# define DATAEND ((ptr_t)ALIGNMENT)
3057# if defined(GC_THREADS) && !defined(CPPCHECK)
3058# error No thread support yet
3059# endif
3060# endif
3061# ifdef WASI
3062# define OS_TYPE "WASI"
3063extern char __global_base, __heap_base;
3064# define DATASTART ((ptr_t)(&__global_base))
3065# define DATAEND ((ptr_t)(&__heap_base))
3066# define STACKBOTTOM DATASTART
3067# ifndef GC_NO_SIGSETJMP
3068# define GC_NO_SIGSETJMP 1 /*< no support of signals */
3069# endif
3070# ifndef NO_CLOCK
3071# define NO_CLOCK 1 /*< no support of `clock()` */
3072# endif
3073# if defined(GC_THREADS) && !defined(CPPCHECK)
3074# error No thread support yet
3075# endif
3076# endif
3077#endif /* WEBASSEMBLY */
3078
3079#if defined(CYGWIN32) || defined(MSWIN32) || defined(MSWINCE)
3080/* Note: it does not include Xbox One. */
3081# define ANY_MSWIN
3082#endif
3083
3084#if defined(GC_PTHREADS) || defined(GC_WIN32_THREADS) \
3085 || ((defined(NN_PLATFORM_CTR) || defined(NINTENDO_SWITCH) \
3086 || defined(SN_TARGET_PS3) || defined(SN_TARGET_PSP2)) \
3087 && defined(GC_THREADS))
3088# define THREADS
3089#endif
3090
3091/*
3092 * If the client app is known not to create threads (even indirectly in
3093 * the used libraries) and the collector is not multi-threaded, then the
3094 * collector could be built with `SINGLE_THREADED_PROCESS` macro defined.
3095 * But in practice the macro should never be defined.
3096 */
3097#if defined(THREADS) && defined(SINGLE_THREADED_PROCESS)
3098# undef SINGLE_THREADED_PROCESS
3099#endif
3100
3101#if defined(__CHERI_PURE_CAPABILITY__)
3102# define CHERI_PURECAP
3103#endif
3104
3105#if defined(__GLIBC__) && !defined(DONT_USE_LIBC_PRIVATES)
3106/* Use the stack-end marker of `glibc`. */
3107# define USE_LIBC_PRIVATES
3108#endif
3109
3110#ifdef NO_RETRY_GET_THREAD_CONTEXT
3111# undef RETRY_GET_THREAD_CONTEXT
3112#endif
3113
3114#if defined(LINUX) && defined(SPECIFIC_MAIN_STACKBOTTOM) \
3115 && defined(NO_PROC_STAT) && !defined(USE_LIBC_PRIVATES)
3116/*
3117 * This combination will fail, since we have no way to get the stack bottom.
3118 * Use `HEURISTIC2` instead.
3119 */
3120# undef SPECIFIC_MAIN_STACKBOTTOM
3121# define HEURISTIC2
3122/* This may still fail on some architectures like `IA64`. We tried... */
3123#endif
3124
3125#if defined(USE_MMAP_ANON) && !defined(USE_MMAP)
3126# define USE_MMAP 1
3127#elif (defined(LINUX) || defined(OPENBSD)) && defined(USE_MMAP)
3128/*
3129 * The OS kernel may do a somewhat better job merging mappings with
3130 * anonymous mappings.
3131 */
3132# define USE_MMAP_ANON
3133#endif
3134
3135#if defined(CHERI_PURECAP) && defined(USE_MMAP)
3136/* TODO: Currently turned off to avoid downgrading permissions on CHERI. */
3137# undef USE_MUNMAP
3138#endif
3139
3140#if (defined(E2K) && defined(USE_PTR_HWTAG) || defined(CHERI_PURECAP)) \
3141 && !defined(NO_BLACK_LISTING)
3142/*
3143 * Misinterpreting of an integer is not possible on the platforms with
3144 * H/W-tagged pointers, thus the black-listing mechanism is redundant.
3145 */
3146# define NO_BLACK_LISTING
3147#endif
3148
3149#if defined(REDIRECT_MALLOC) && defined(THREADS) \
3150 && (defined(LINUX) || defined(NACL))
3151/* TODO: Unclear if NaCl really needs this. */
3152# define REDIR_MALLOC_AND_LINUXTHREADS
3153#endif
3154
3155#if defined(REDIR_MALLOC_AND_LINUXTHREADS) && !defined(NO_PROC_FOR_LIBRARIES) \
3156 && !defined(USE_PROC_FOR_LIBRARIES)
3157/*
3158 * NPTL allocates thread stacks with `mmap`, which is fine. But it
3159 * keeps a cache of thread stacks. Each thread stack contains a thread
3160 * control block (TCB). The latter, in turn, contains a pointer to
3161 * (`sizeof(void*)` from the beginning of) the `dtv` for thread-local
3162 * storage, which is `calloc`-allocated. If we do not scan the cached
3163 * thread stacks, we appear to lose the `dtv`. This tends to result in
3164 * something that looks like a bogus `dtv` count, which tends to result
3165 * in a `memset()` call on a block that is way too large. Sometimes
3166 * we are lucky and the process just dies... There seems to be
3167 * a similar issue with some other memory allocated by the dynamic
3168 * loader. This should be avoidable by either:
3169 * - Defining `USE_PROC_FOR_LIBRARIES` here (that performs very poorly,
3170 * precisely because we end up scanning cached stacks);
3171 * - Have `calloc()` look at its callers (in spite of the fact that it
3172 * is gross and disgusting).
3173 *
3174 * In fact, neither seems to suffice, probably in part because even
3175 * with `USE_PROC_FOR_LIBRARIES`, we do not scan parts of stack
3176 * segments that appear to be out of bounds. Thus we actually do both,
3177 * which seems to yield the best results.
3178 */
3179# define USE_PROC_FOR_LIBRARIES
3180#endif
3181
3182#ifndef OS_TYPE
3183# define OS_TYPE ""
3184#endif
3185
3186#ifndef MACH_TYPE
3187# define MACH_TYPE ""
3188#endif
3189
3190#ifndef DATAEND
3191extern int end[];
3192# define DATAEND ((ptr_t)end)
3193#endif
3194
3195/*
3196 * Workaround for Android NDK clang-3.5+ (as of NDK r10e) which does
3197 * not provide correct `_end` symbol. Unfortunately, alternate `__end__`
3198 * symbol is provided only by NDK `bfd` linker.
3199 */
3200#if defined(HOST_ANDROID) && defined(__clang__) && !defined(BROKEN_UUENDUU_SYM)
3201# undef DATAEND
3202# pragma weak __end__
3203extern int __end__[];
3204# define DATAEND (__end__ != 0 ? (ptr_t)__end__ : (ptr_t)_end)
3205#endif
3206
3207#if defined(SOLARIS) || defined(DRSNX) || defined(UTS4) \
3208 || (defined(LINUX) && defined(SPARC))
3209/* OS has SVR4 generic features. Probably others also qualify. */
3210# define SVR4
3211# define DATASTART_USES_XGETDATASTART
3212#endif
3213
3214#if defined(HAVE_SYS_TYPES_H) \
3215 || !(defined(__CC_ARM) || defined(GC_NO_TYPES) || defined(OS2) \
3216 || defined(MSWINCE) || defined(SN_TARGET_PSP2))
3217EXTERN_C_END
3218# if defined(COSMO) && defined(MPROTECT_VDB) && !defined(_GNU_SOURCE)
3219# define _GNU_SOURCE 1
3220# endif
3221# include <sys/types.h>
3222EXTERN_C_BEGIN
3223#endif /* HAVE_SYS_TYPES_H */
3224
3225#if defined(HAVE_UNISTD_H) \
3226 || !(defined(GC_NO_TYPES) || defined(MSWIN32) || defined(MSWINCE) \
3227 || defined(MSWIN_XBOX1) || defined(NINTENDO_SWITCH) \
3228 || defined(NN_PLATFORM_CTR) || defined(OS2) || defined(SERENITY) \
3229 || defined(SN_TARGET_PSP2) || defined(__CC_ARM))
3230EXTERN_C_END
3231# include <unistd.h>
3232EXTERN_C_BEGIN
3233#endif /* HAVE_UNISTD_H */
3234
3235#if !defined(ANY_MSWIN) && !defined(GETPAGESIZE)
3236# if defined(DGUX) || defined(HOST_ANDROID) || defined(HOST_TIZEN) \
3237 || defined(KOS) || defined(SERENITY) \
3238 || (defined(LINUX) && defined(SPARC))
3239# define GETPAGESIZE() (unsigned)sysconf(_SC_PAGESIZE)
3240# else
3241# define GETPAGESIZE() (unsigned)getpagesize()
3242# endif
3243#endif /* !ANY_MSWIN && !GETPAGESIZE */
3244
3245#if defined(HOST_ANDROID) && !(__ANDROID_API__ >= 23) \
3246 && ((defined(MIPS) && (CPP_WORDSZ == 32)) || defined(ARM32) \
3247 || defined(I386) /* but not x32 */)
3248/*
3249 * `tkill()` exists only on arm32/mips(32)/x86.
3250 * NDK r11+ deprecates `tkill()` but keeps it for Mono clients.
3251 */
3252# define USE_TKILL_ON_ANDROID
3253#endif
3254
3255#if defined(MPROTECT_VDB) && defined(__GLIBC__) && !GC_GLIBC_PREREQ(2, 2)
3256# error glibc too old?
3257#endif
3258
3259#if defined(SOLARIS) || defined(DRSNX)
3260/* OS has Solaris-style semi-undocumented interface to dynamic loader. */
3261# define SOLARISDL
3262/* OS has Solaris-style signal handlers. */
3263# define SUNOS5SIGS
3264#endif
3265
3266#if (defined(FREEBSD) \
3267 && (defined(__DragonFly__) || defined(__GLIBC__) \
3268 || __FreeBSD_kernel__ >= 4 || __FreeBSD__ >= 4)) \
3269 || defined(HPUX)
3270# define SUNOS5SIGS
3271#endif
3272
3273#if defined(COSMO) || defined(HPUX) || defined(HURD) || defined(NETBSD) \
3274 || defined(SERENITY) || (defined(FREEBSD) && defined(SUNOS5SIGS)) \
3275 || (defined(IRIX5) && defined(_sigargs)) /*< Irix 5.x, not 6.x */
3276# define USE_SEGV_SIGACT
3277/* We may also get `SIGBUS`. */
3278# define USE_BUS_SIGACT
3279#elif defined(ANY_BSD) || defined(HAIKU) || defined(IRIX5) || defined(OSF1) \
3280 || defined(SUNOS5SIGS)
3281# define USE_SEGV_SIGACT
3282#endif
3283
3284#if !defined(GC_EXPLICIT_SIGNALS_UNBLOCK) && defined(SUNOS5SIGS) \
3285 && !defined(GC_NO_PTHREAD_SIGMASK)
3286# define GC_EXPLICIT_SIGNALS_UNBLOCK
3287#endif
3288
3289#if !defined(NO_SIGNALS_UNBLOCK_IN_MAIN) && defined(GC_NO_PTHREAD_SIGMASK)
3290# define NO_SIGNALS_UNBLOCK_IN_MAIN
3291#endif
3292
3293#ifndef PARALLEL_MARK
3294# undef GC_PTHREADS_PARAMARK /*< just in case it is defined by client */
3295#elif defined(GC_PTHREADS) && !defined(GC_PTHREADS_PARAMARK) \
3296 && !defined(__MINGW32__)
3297/*
3298 * Use `pthreads`-based parallel mark implementation. Except for
3299 * MinGW 32/64 to workaround a deadlock in winpthreads-3.0b internals.
3300 */
3301# define GC_PTHREADS_PARAMARK
3302#endif
3303
3304#if !defined(NO_MARKER_SPECIAL_SIGMASK) \
3305 && (defined(NACL) || defined(GC_WIN32_PTHREADS) \
3306 || (defined(GC_PTHREADS_PARAMARK) && defined(GC_WIN32_THREADS)) \
3307 || defined(GC_NO_PTHREAD_SIGMASK))
3308/*
3309 * Either there is no `pthread_sigmask()`, or the GC marker thread cannot
3310 * steal and drop user signal calls.
3311 */
3312# define NO_MARKER_SPECIAL_SIGMASK
3313#endif
3314
3315#if defined(NETBSD) && defined(THREADS)
3316# define SIGRTMIN 33
3317# define SIGRTMAX 63
3318/*
3319 * It seems to be necessary to wait until threads have restarted.
3320 * But it is unclear why that is the case.
3321 */
3322# define GC_NETBSD_THREADS_WORKAROUND
3323#endif
3324
3325#if defined(OPENBSD) && defined(THREADS)
3326EXTERN_C_END
3327# include <sys/param.h>
3328EXTERN_C_BEGIN
3329#endif
3330
3331#if defined(AIX) || defined(ANY_BSD) || defined(BSD) || defined(COSMO) \
3332 || defined(DARWIN) || defined(DGUX) || defined(HAIKU) || defined(HPUX) \
3333 || defined(HURD) || defined(IRIX5) || defined(LINUX) || defined(OSF1) \
3334 || defined(QNX) || defined(SERENITY) || defined(SVR4)
3335/* Basic UNIX-like system calls work. */
3336# define UNIX_LIKE
3337#endif
3338
3339#if defined(CPPCHECK)
3340# undef CPP_WORDSZ
3341# define CPP_WORDSZ (__SIZEOF_PTRDIFF_T__ * 8)
3342#elif CPP_WORDSZ != 32 && CPP_WORDSZ != 64
3343# error Bad word size
3344#endif
3345
3346#ifndef CPP_PTRSZ
3347# ifdef CHERI_PURECAP
3348# define CPP_PTRSZ (__SIZEOF_POINTER__ * 8)
3349# else
3350# define CPP_PTRSZ CPP_WORDSZ
3351# endif
3352#endif
3353
3354#ifndef CPPCHECK
3355# if GC_SIZEOF_PTR * 8 != CPP_PTRSZ
3356# error Bad pointer size
3357# endif
3358#endif /* !CPPCHECK */
3359
3360#ifndef ALIGNMENT
3361# define ALIGNMENT (CPP_PTRSZ >> 3)
3362#endif
3363
3364#if !defined(STACKBOTTOM) && (defined(ECOS) || defined(NOSYS)) \
3365 && !defined(CPPCHECK)
3366# error Undefined STACKBOTTOM
3367#endif
3368
3369#ifdef IGNORE_DYNAMIC_LOADING
3370# undef DYNAMIC_LOADING
3371#endif
3372
3373#if defined(SMALL_CONFIG) && !defined(GC_DISABLE_INCREMENTAL)
3374/* Presumably not worth the space it takes. */
3375# define GC_DISABLE_INCREMENTAL
3376#endif
3377
3378/* `USE_WINALLOC` is only an option for Cygwin. */
3379#ifndef CYGWIN32
3380# undef USE_WINALLOC
3381#endif
3382#if defined(MSWIN32) || defined(MSWINCE)
3383# define USE_WINALLOC 1
3384#endif
3385
3386#ifdef USE_WINALLOC
3387# undef USE_MMAP
3388#endif
3389
3390#if defined(ANY_BSD) || defined(DARWIN) || defined(IRIX5) || defined(LINUX) \
3391 || defined(SERENITY) || defined(SOLARIS) \
3392 || ((defined(CYGWIN32) || defined(USE_MMAP) || defined(USE_MUNMAP)) \
3393 && !defined(USE_WINALLOC))
3394/* Try both `sbrk` and `mmap`, in that order. */
3395# define MMAP_SUPPORTED
3396#endif
3397
3398/*
3399 * Xbox One (DURANGO) may not need to be this aggressive, but the
3400 * default is likely too lax under heavy allocation pressure.
3401 * The platform does not have a virtual paging system, so it does not
3402 * have a large virtual address space that a standard x86_64 platform has.
3403 */
3404#if defined(USE_MUNMAP) && !defined(MUNMAP_THRESHOLD) \
3405 && (defined(SN_TARGET_PS3) || defined(SN_TARGET_PSP2) \
3406 || defined(MSWIN_XBOX1))
3407# define MUNMAP_THRESHOLD 3
3408#endif
3409
3410#if defined(GC_DISABLE_INCREMENTAL) || defined(DEFAULT_VDB)
3411# undef GWW_VDB
3412# undef MPROTECT_VDB
3413# undef PROC_VDB
3414# undef SOFT_VDB
3415#endif
3416
3417#ifdef NO_GWW_VDB
3418# undef GWW_VDB
3419#endif
3420
3421#ifdef NO_MPROTECT_VDB
3422# undef MPROTECT_VDB
3423#endif
3424
3425#ifdef NO_SOFT_VDB
3426# undef SOFT_VDB
3427#endif
3428
3429#if defined(SOFT_VDB) && defined(SOFT_VDB_LINUX_VER_STATIC_CHECK)
3430EXTERN_C_END
3431# include <linux/version.h> /*< for `LINUX_VERSION`, `LINUX_VERSION_CODE` */
3432EXTERN_C_BEGIN
3433# if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
3434/* Not reliable in Linux kernels prior to v3.18. */
3435# undef SOFT_VDB
3436# endif
3437#endif /* SOFT_VDB */
3438
3439#ifdef GC_DISABLE_INCREMENTAL
3440# undef CHECKSUMS
3441#endif
3442
3443#if defined(BASE_ATOMIC_OPS_EMULATED)
3444/*
3445 * `GC_write_fault_handler()` cannot use lock-based atomic primitives
3446 * as this could lead to a deadlock.
3447 */
3448# undef MPROTECT_VDB
3449#endif
3450
3451#if defined(USE_PROC_FOR_LIBRARIES) && defined(LINUX) && defined(THREADS)
3452/* Incremental GC based on `mprotect` is incompatible with `/proc` roots. */
3453# undef MPROTECT_VDB
3454#endif
3455
3456#if defined(MPROTECT_VDB) && defined(GC_PREFER_MPROTECT_VDB)
3457/* Choose `MPROTECT_VDB` manually (if multiple strategies available). */
3458# undef PROC_VDB
3459/* `GWW_VDB`, `SOFT_VDB` are handled in `os_dep.c` file. */
3460#endif
3461
3462#ifdef PROC_VDB
3463/* Mutually exclusive VDB implementations (for now). */
3464# undef MPROTECT_VDB
3465/* For a test purpose only. */
3466# undef SOFT_VDB
3467#endif
3468
3469#if defined(MPROTECT_VDB) && !defined(MSWIN32) && !defined(MSWINCE)
3470EXTERN_C_END
3471# include <signal.h> /*< for `SA_SIGINFO`, `SIGBUS` */
3472EXTERN_C_BEGIN
3473#endif
3474
3475#if defined(SIGBUS) && !defined(HAVE_SIGBUS) && !defined(CPPCHECK)
3476# define HAVE_SIGBUS
3477#endif
3478
3479#ifndef SA_SIGINFO
3480# define NO_SA_SIGACTION
3481#endif
3482
3483#if (defined(NO_SA_SIGACTION) || defined(GC_NO_SIGSETJMP)) \
3484 && defined(MPROTECT_VDB) && !defined(DARWIN) && !defined(MSWIN32) \
3485 && !defined(MSWINCE)
3486# undef MPROTECT_VDB
3487#endif
3488
3489#if !defined(DEFAULT_VDB) && !defined(GWW_VDB) && !defined(MPROTECT_VDB) \
3490 && !defined(PROC_VDB) && !defined(SOFT_VDB) \
3491 && !defined(GC_DISABLE_INCREMENTAL)
3492# define DEFAULT_VDB
3493#endif
3494
3495#if defined(CHECK_SOFT_VDB) && !defined(CPPCHECK) \
3496 && (defined(GC_PREFER_MPROTECT_VDB) || !defined(SOFT_VDB) \
3497 || !defined(MPROTECT_VDB))
3498# error Invalid config for CHECK_SOFT_VDB
3499#endif
3500
3501#if (defined(GC_DISABLE_INCREMENTAL) || defined(BASE_ATOMIC_OPS_EMULATED) \
3502 || defined(REDIRECT_MALLOC) || defined(SMALL_CONFIG) \
3503 || defined(REDIRECT_MALLOC_IN_HEADER) || defined(CHECKSUMS)) \
3504 && !defined(NO_MANUAL_VDB)
3505/* TODO: Implement `CHECKSUMS` for manual VDB. */
3506# define NO_MANUAL_VDB
3507#endif
3508
3509#if !defined(PROC_VDB) && !defined(SOFT_VDB) \
3510 && !defined(NO_VDB_FOR_STATIC_ROOTS)
3511/* Cannot determine whether a static root page is dirty. */
3512# define NO_VDB_FOR_STATIC_ROOTS
3513#endif
3514
3515#if defined(MPROTECT_VDB) && !defined(DONT_COUNT_PROTECTED_REGIONS) \
3516 && !defined(COUNT_PROTECTED_REGIONS) \
3517 && (defined(LINUX) || defined(__DragonFly__))
3518# define COUNT_PROTECTED_REGIONS
3519#endif
3520
3521#if (defined(COUNT_PROTECTED_REGIONS) || defined(COUNT_UNMAPPED_REGIONS)) \
3522 && !defined(GC_UNMAPPED_REGIONS_SOFT_LIMIT)
3523/*
3524 * The default limit of `vm.max_map_count` on Linux is ~65530.
3525 * There is approximately one mapped region to every protected or
3526 * unmapped region. Therefore if we aim to use up to half of
3527 * `vm.max_map_count` for the collector (leaving half for the rest
3528 * of the process), then the number of such regions should be one
3529 * quarter of `vm.max_map_count`.
3530 */
3531# if defined(__DragonFly__)
3532# define GC_UNMAPPED_REGIONS_SOFT_LIMIT (1000000 / 4)
3533# else
3534# define GC_UNMAPPED_REGIONS_SOFT_LIMIT 16384
3535# endif
3536#endif
3537
3538#if (((defined(ARM32) || defined(AVR32) || defined(MIPS) || defined(NIOS2) \
3539 || defined(OR1K)) \
3540 && defined(UNIX_LIKE)) \
3541 || defined(DARWIN) || defined(HAIKU) || defined(HURD) \
3542 || defined(OPENBSD) || defined(QNX) || defined(RTEMS) \
3543 || defined(SERENITY) || defined(HOST_ANDROID) \
3544 || (defined(LINUX) && !defined(__gnu_linux__))) \
3545 && !defined(NO_GETCONTEXT)
3546# define NO_GETCONTEXT 1
3547#endif
3548
3549#if defined(MSWIN32) && !defined(CONSOLE_LOG) && defined(_MSC_VER) \
3550 && defined(_DEBUG) && !defined(NO_CRT)
3551/*
3552 * This should be included before the platform `intrin.h` file to
3553 * workaround some bug in Windows Kit (as of 10.0.17763) headers
3554 * causing redefinition of `_malloca` macro.
3555 */
3556EXTERN_C_END
3557# include <crtdbg.h> /*< for `_CrtDbgReport` */
3558EXTERN_C_BEGIN
3559#endif
3560
3561#ifndef PREFETCH
3562# if (GC_GNUC_PREREQ(3, 0) || defined(__clang__)) && !defined(NO_PREFETCH)
3563# define PREFETCH(x) __builtin_prefetch((x), 0, 0)
3564# elif defined(_MSC_VER) && !defined(NO_PREFETCH) \
3565 && (defined(_M_IX86) || defined(_M_X64)) && !defined(_CHPE_ONLY_) \
3566 && (_MSC_VER >= 1900 /* VS 2015+ */)
3567EXTERN_C_END
3568# include <intrin.h>
3569EXTERN_C_BEGIN
3570# define PREFETCH(x) _mm_prefetch((const char *)(x), _MM_HINT_T0)
3571/* TODO: Support also `_M_ARM` and `_M_ARM64` (`__prefetch`). */
3572# else
3573# define PREFETCH(x) (void)0
3574# endif
3575#endif /* !PREFETCH */
3576
3577#ifndef GC_PREFETCH_FOR_WRITE
3578/*
3579 * The default `GC_PREFETCH_FOR_WRITE(x)` is defined in `gc_inline.h` file,
3580 * the latter one is included from `gc_priv.h` file.
3581 */
3582#endif
3583
3584#ifndef CACHE_LINE_SIZE
3585# define CACHE_LINE_SIZE 32 /*< wild guess */
3586#endif
3587
3588#ifndef STATIC
3589# ifdef GC_ASSERTIONS
3590# define STATIC /*< ignore to aid debugging (or profiling) */
3591# else
3592# define STATIC static
3593# endif
3594#endif
3595
3596/*
3597 * Do we need the `GC_find_limit` machinery to find the end of
3598 * a data segment (or the backing store base)?
3599 */
3600#if defined(HEURISTIC2) || defined(SEARCH_FOR_DATA_START) || defined(IA64) \
3601 || defined(DGUX) || defined(FREEBSD) || defined(OPENBSD) || defined(SVR4) \
3602 || (defined(HPUX) && defined(SPECIFIC_MAIN_STACKBOTTOM)) \
3603 || (defined(CYGWIN32) && defined(I386) && defined(USE_MMAP) \
3604 && !defined(USE_WINALLOC)) \
3605 || (defined(NETBSD) && defined(__ELF__))
3606# define NEED_FIND_LIMIT
3607#endif
3608
3609#if defined(LINUX) \
3610 && (defined(USE_PROC_FOR_LIBRARIES) || defined(IA64) \
3611 || !defined(SMALL_CONFIG))
3612# define NEED_PROC_MAPS
3613#endif
3614
3615#if defined(LINUX) || defined(HURD) || defined(__GLIBC__)
3616# define REGISTER_LIBRARIES_EARLY
3617/*
3618 * We sometimes use `dl_iterate_phdr`, which may acquire an internal lock.
3619 * This is not safe after the world has stopped. So we must call
3620 * `GC_register_dynamic_libraries` before stopping the world.
3621 * For performance reasons, this may be beneficial on other platforms
3622 * as well, though it should be avoided on Windows.
3623 */
3624#endif /* LINUX */
3625
3626#if defined(SEARCH_FOR_DATA_START)
3627extern ptr_t GC_data_start;
3628# define DATASTART GC_data_start
3629#endif
3630
3631#ifndef HEAP_START
3632# define HEAP_START 0
3633#endif
3634
3635#ifndef CLEAR_DOUBLE
3636# define CLEAR_DOUBLE(x) \
3637 (void)(((ptr_t *)(x))[0] = NULL, ((ptr_t *)(x))[1] = NULL)
3638#endif
3639
3640/*
3641 * Some `libc` implementations like `bionic`, `musl` and `glibc` 2.34+
3642 * do not have `libpthread.so` file because the `pthreads`-related code
3643 * is located in `libc.so` file, thus potential `calloc()` calls from
3644 * such code are forwarded to real (`libc`) `calloc()` without any
3645 * special handling on the collector side. Checking `glibc` version at
3646 * compile time for the purpose seems to be fine.
3647 */
3648#if defined(REDIR_MALLOC_AND_LINUXTHREADS) && !defined(HAVE_LIBPTHREAD_SO) \
3649 && defined(__GLIBC__) && !GC_GLIBC_PREREQ(2, 34)
3650# define HAVE_LIBPTHREAD_SO
3651#endif
3652
3653#if defined(REDIR_MALLOC_AND_LINUXTHREADS) \
3654 && !defined(INCLUDE_LINUX_THREAD_DESCR)
3655/*
3656 * Will not work, since `libc` and the dynamic loader use thread locals,
3657 * sometimes as the only reference.
3658 */
3659# define INCLUDE_LINUX_THREAD_DESCR
3660#endif
3661
3662#ifndef CPPCHECK
3663# if defined(GC_AIX_THREADS) && !defined(AIX) \
3664 || (defined(GC_DARWIN_THREADS) && !defined(DARWIN)) \
3665 || (defined(GC_DGUX386_THREADS) && !defined(DGUX)) \
3666 || (defined(GC_FREEBSD_THREADS) && !defined(FREEBSD)) \
3667 || (defined(GC_HAIKU_THREADS) && !defined(HAIKU)) \
3668 || (defined(GC_HPUX_THREADS) && !defined(HPUX)) \
3669 || (defined(GC_IRIX_THREADS) && !defined(IRIX5)) \
3670 || (defined(GC_LINUX_THREADS) && !defined(LINUX) && !defined(NACL)) \
3671 || (defined(GC_NETBSD_THREADS) && !defined(NETBSD)) \
3672 || (defined(GC_OPENBSD_THREADS) && !defined(OPENBSD)) \
3673 || (defined(GC_OSF1_THREADS) && !defined(OSF1)) \
3674 || (defined(GC_RTEMS_PTHREADS) && !defined(RTEMS)) \
3675 || (defined(GC_SOLARIS_THREADS) && !defined(SOLARIS)) \
3676 || (defined(GC_WIN32_THREADS) && !defined(ANY_MSWIN) \
3677 && !defined(MSWIN_XBOX1))
3678# error Inconsistent configuration
3679# elif defined(GC_WIN32_PTHREADS) && defined(CYGWIN32)
3680# error Inconsistent configuration (GC_PTHREADS)
3681# endif
3682# if defined(PARALLEL_MARK) && !defined(THREADS)
3683# error Invalid config: PARALLEL_MARK requires GC_THREADS
3684# endif
3685# if defined(GWW_VDB) && !defined(USE_WINALLOC)
3686# error Invalid config: GWW_VDB requires USE_WINALLOC
3687# endif
3688# if (defined(GC_FINDLEAK_DELAY_FREE) && defined(SHORT_DBG_HDRS)) \
3689 || ((defined(FIND_LEAK) || defined(GC_FINDLEAK_DELAY_FREE)) \
3690 && defined(NO_FIND_LEAK))
3691# error Invalid config: FIND_LEAK and NO_FIND_LEAK are mutually exclusive
3692# endif
3693#endif /* !CPPCHECK */
3694
3695#if defined(NO_FIND_LEAK) && !defined(DONT_USE_ATEXIT)
3696# define DONT_USE_ATEXIT
3697#endif
3698
3699/* Whether `GC_page_size` is to be set to a value other than page size. */
3700#if defined(CYGWIN32) && (defined(MPROTECT_VDB) || defined(USE_MUNMAP)) \
3701 || (!defined(ANY_MSWIN) && !defined(WASI) && !defined(USE_MMAP) \
3702 && (defined(GC_DISABLE_INCREMENTAL) || defined(DEFAULT_VDB)))
3703/*
3704 * Cygwin: use the allocation granularity instead.
3705 * Other than WASI and Windows: use `HBLKSIZE` instead (unless `mmap()`
3706 * is used).
3707 */
3708# define ALT_PAGESIZE_USED
3709# ifndef GC_NO_VALLOC
3710/* Nonetheless, we need the real page size is some extra functions. */
3711# define REAL_PAGESIZE_NEEDED
3712# endif
3713#endif
3714
3715#if defined(GC_PTHREADS) && !defined(DARWIN) && !defined(GC_WIN32_THREADS) \
3716 && !defined(PLATFORM_STOP_WORLD) && !defined(SN_TARGET_PSP2)
3717# define PTHREAD_STOP_WORLD_IMPL
3718#endif
3719
3720#if defined(PTHREAD_STOP_WORLD_IMPL) && !defined(NACL)
3721# define SIGNAL_BASED_STOP_WORLD
3722#endif
3723
3724#if (defined(E2K) || defined(HP_PA) || defined(IA64) || defined(M68K) \
3725 || defined(NO_SA_SIGACTION)) \
3726 && defined(SIGNAL_BASED_STOP_WORLD)
3727# define SUSPEND_HANDLER_NO_CONTEXT
3728#endif
3729
3730#if (defined(MSWIN32) || defined(MSWINCE) \
3731 || (defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS))) \
3732 && !defined(NO_CRT) && !defined(NO_WRAP_MARK_SOME)
3733/*
3734 * Under rare conditions, we may end up marking from nonexistent memory.
3735 * Hence we need to be prepared to recover by running `GC_mark_some` with
3736 * a suitable handler in place.
3737 */
3738/* TODO: Should we also define it for Cygwin? */
3739# define WRAP_MARK_SOME
3740#endif
3741
3742#if !defined(MSWIN32) && !defined(MSWINCE) || defined(__GNUC__) \
3743 || defined(NO_CRT)
3744# define NO_SEH_AVAILABLE
3745#endif
3746
3747#ifdef GC_WIN32_THREADS
3748/* The number of copied registers in `copy_ptr_regs()`. */
3749# if defined(I386)
3750# ifdef WOW64_THREAD_CONTEXT_WORKAROUND
3751# define PUSHED_REGS_COUNT 9
3752# else
3753# define PUSHED_REGS_COUNT 7
3754# endif
3755# elif defined(X86_64)
3756# ifdef XMM_CANT_STORE_PTRS
3757/* If pointers cannot be located in Xmm registers. */
3758# define PUSHED_REGS_COUNT 15
3759# else
3760/*
3761 * gcc-13 may store pointers into SIMD registers when certain compiler
3762 * optimizations are enabled.
3763 */
3764# define PUSHED_REGS_COUNT (15 + 32)
3765# endif
3766# elif defined(SHx)
3767# define PUSHED_REGS_COUNT 15
3768# elif defined(ARM32)
3769# define PUSHED_REGS_COUNT 13
3770# elif defined(AARCH64)
3771# define PUSHED_REGS_COUNT 30
3772# elif defined(MIPS) || defined(ALPHA)
3773# define PUSHED_REGS_COUNT 28
3774# elif defined(PPC)
3775# define PUSHED_REGS_COUNT 29
3776# endif
3777#endif /* GC_WIN32_THREADS */
3778
3779#if !defined(GC_PTHREADS) && !defined(GC_PTHREADS_PARAMARK)
3780# undef HAVE_PTHREAD_SETNAME_NP_WITH_TID
3781# undef HAVE_PTHREAD_SETNAME_NP_WITH_TID_AND_ARG
3782# undef HAVE_PTHREAD_SET_NAME_NP
3783#endif
3784
3785#if !(defined(GC_PTHREADS) || defined(GC_PTHREADS_PARAMARK) \
3786 || (defined(MPROTECT_VDB) && defined(DARWIN)))
3787# undef HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID
3788#endif
3789
3790#if defined(USE_RWLOCK) || defined(GC_DISABLE_SUSPEND_THREAD)
3791/*
3792 * At least in the Linux threads implementation, `rwlock` primitives are
3793 * not atomic in respect to signals, and suspending externally a thread
3794 * which is running inside `pthread_rwlock_rdlock()` may lead to a deadlock.
3795 */
3796/* TODO: As a workaround `GC_suspend_thread()` API is disabled. */
3797# undef GC_ENABLE_SUSPEND_THREAD
3798#endif
3799
3800#ifndef GC_NO_THREADS_DISCOVERY
3801# if defined(DARWIN) && defined(THREADS)
3802/* Task-based thread registration requires stack-frame-walking code. */
3803# if defined(DARWIN_DONT_PARSE_STACK)
3804# define GC_NO_THREADS_DISCOVERY
3805# endif
3806# elif defined(GC_WIN32_THREADS)
3807/*
3808 * `DllMain`-based thread registration is currently incompatible with
3809 * thread-local allocation, `pthreads` and WinCE.
3810 */
3811# if (!defined(GC_DLL) && !defined(GC_INSIDE_DLL)) || defined(GC_PTHREADS) \
3812 || defined(MSWINCE) || defined(NO_CRT) || defined(THREAD_LOCAL_ALLOC)
3813# define GC_NO_THREADS_DISCOVERY
3814# endif
3815# else
3816# define GC_NO_THREADS_DISCOVERY
3817# endif
3818#endif /* !GC_NO_THREADS_DISCOVERY */
3819
3820#if defined(GC_DISCOVER_TASK_THREADS) && defined(GC_NO_THREADS_DISCOVERY) \
3821 && !defined(CPPCHECK)
3822# error Defined both GC_DISCOVER_TASK_THREADS and GC_NO_THREADS_DISCOVERY
3823#endif
3824
3825#if defined(PARALLEL_MARK) && !defined(DEFAULT_STACK_MAYBE_SMALL) \
3826 && (defined(DGUX) || defined(HPUX) \
3827 || defined(NO_GETCONTEXT) /* e.g. musl */)
3828/* TODO: Test default stack size in configure. */
3829# define DEFAULT_STACK_MAYBE_SMALL
3830#endif
3831
3832#ifdef PARALLEL_MARK
3833/* The minimum stack size for a marker thread. */
3834# define MIN_STACK_SIZE (8 * HBLKSIZE * sizeof(ptr_t))
3835#endif
3836
3837#if defined(HOST_ANDROID) && !defined(THREADS) \
3838 && !defined(USE_GET_STACKBASE_FOR_MAIN)
3839/*
3840 * Always use `pthread_attr_getstack` on Android (`-lpthread` option
3841 * is not needed to be specified manually) since Linux-specific
3842 * `os_main_stackbottom()` causes application crash if invoked inside
3843 * Dalvik VM.
3844 */
3845# define USE_GET_STACKBASE_FOR_MAIN
3846#endif
3847
3848/*
3849 * Outline `pthreads` primitives to use in `GC_get_stack_base()` and
3850 * `GC_get_main_stack_base()`.
3851 */
3852#if ((defined(FREEBSD) && defined(__GLIBC__) /* kFreeBSD */) \
3853 || defined(COSMO) || defined(HAIKU) || defined(LINUX) || defined(KOS) \
3854 || defined(NETBSD)) \
3855 && !defined(NO_PTHREAD_GETATTR_NP)
3856# define HAVE_PTHREAD_GETATTR_NP 1
3857#elif defined(FREEBSD) && !defined(__GLIBC__) \
3858 && !defined(NO_PTHREAD_ATTR_GET_NP)
3859# define HAVE_PTHREAD_NP_H 1 /*< requires include `pthread_np.h` file */
3860# define HAVE_PTHREAD_ATTR_GET_NP 1
3861#endif
3862
3863#if (defined(HAVE_PTHREAD_ATTR_GET_NP) || defined(HAVE_PTHREAD_GETATTR_NP)) \
3864 && defined(USE_GET_STACKBASE_FOR_MAIN) && !defined(STACKBOTTOM) \
3865 && !defined(HEURISTIC1) && !defined(HEURISTIC2) && !defined(STACK_GRAN) \
3866 && !defined(SPECIFIC_MAIN_STACKBOTTOM)
3867/* Dummy definitions; rely on `pthread_attr_getstack` actually. */
3868# define HEURISTIC1
3869# define STACK_GRAN 0x1000000
3870#endif
3871
3872#if !defined(HAVE_CLOCK_GETTIME) && defined(_POSIX_TIMERS) \
3873 && (defined(CYGWIN32) || (defined(LINUX) && defined(__USE_POSIX199309)))
3874# define HAVE_CLOCK_GETTIME 1
3875#endif
3876
3877#if defined(GC_PTHREADS) && !defined(E2K) && !defined(IA64) \
3878 && (!defined(DARWIN) || defined(DARWIN_DONT_PARSE_STACK)) \
3879 && !defined(SN_TARGET_PSP2) && !defined(REDIRECT_MALLOC)
3880/*
3881 * Note: unimplemented in case of redirection of `malloc()` because
3882 * the client-provided function might call some `pthreads` primitive
3883 * which, in turn, may use `malloc()` internally.
3884 */
3885# define STACKPTR_CORRECTOR_AVAILABLE
3886#endif
3887
3888#if defined(UNIX_LIKE) && defined(THREADS) && !defined(NO_CANCEL_SAFE) \
3889 && !defined(HOST_ANDROID)
3890/*
3891 * Make the code cancellation-safe. This basically means that we ensure
3892 * that cancellation requests are ignored while we are in the collector.
3893 * This applies only to POSIX deferred cancellation; we do not handle POSIX
3894 * asynchronous cancellation. Note that this only works if
3895 * `pthread_setcancelstate` is async-signal-safe, at least in the absence of
3896 * asynchronous cancellation. This appears to be true for `glibc`, though it
3897 * is not documented. Without that assumption, there seems to be no way to
3898 * safely wait in a signal handler, which we need to do for thread suspension.
3899 * Also note that little other code appears to be cancellation-safe.
3900 * Hence it may make sense to turn this off for performance.
3901 */
3902# define CANCEL_SAFE
3903#endif
3904
3905#ifdef CANCEL_SAFE
3906# define IF_CANCEL(x) x
3907#else
3908# define IF_CANCEL(x) /*< empty */
3909#endif
3910
3911#if defined(DARWIN) && defined(MPROTECT_VDB) \
3912 && !defined(NO_DESC_CATCH_EXCEPTION_RAISE) \
3913 && !defined(FORCE_DESC_CATCH_EXCEPTION_RAISE) && GC_CLANG_PREREQ(17, 0)
3914/*
3915 * Workaround "REFERENCED_DYNAMICALLY flag on _catch_exception_raise"
3916 * linker deprecation warnings on macOS 15.4.
3917 */
3918# define NO_DESC_CATCH_EXCEPTION_RAISE
3919#endif
3920
3921#if !defined(CAN_HANDLE_FORK) && !defined(NO_HANDLE_FORK) \
3922 && !defined(HAVE_NO_FORK) \
3923 && ((defined(GC_PTHREADS) && !defined(NACL) \
3924 && !defined(GC_WIN32_PTHREADS) && !defined(USE_WINALLOC)) \
3925 || (defined(DARWIN) && defined(MPROTECT_VDB) /* `&& !THREADS` */) \
3926 || (defined(HANDLE_FORK) && defined(GC_PTHREADS)))
3927/*
3928 * Attempts (where supported and requested) to make `GC_malloc` work in
3929 * a child process forked from a multi-threaded parent process.
3930 */
3931# define CAN_HANDLE_FORK
3932#endif
3933
3934/*
3935 * Workaround "failed to create new win32 semaphore" Cygwin fatal error
3936 * during semaphores fixup-after-fork.
3937 */
3938#if defined(CYGWIN32) && defined(THREADS) && defined(CAN_HANDLE_FORK) \
3939 && !defined(CYGWIN_SEM_FIXUP_AFTER_FORK_BUG_FIXED) \
3940 && !defined(EMULATE_PTHREAD_SEMAPHORE)
3941# define EMULATE_PTHREAD_SEMAPHORE
3942#endif
3943
3944#if defined(CAN_HANDLE_FORK) && !defined(CAN_CALL_ATFORK) \
3945 && !defined(GC_NO_CAN_CALL_ATFORK) && !defined(HOST_TIZEN) \
3946 && !defined(HURD) && (!defined(HOST_ANDROID) || __ANDROID_API__ >= 21)
3947/* Have working `pthread_atfork()`. */
3948# define CAN_CALL_ATFORK
3949#endif
3950
3951#if !defined(CAN_HANDLE_FORK) && !defined(HAVE_NO_FORK) \
3952 && !(defined(CYGWIN32) || defined(SOLARIS) || defined(UNIX_LIKE))
3953# define HAVE_NO_FORK
3954#endif
3955
3956#if !defined(USE_MARK_BITS) && !defined(USE_MARK_BYTES) \
3957 && defined(PARALLEL_MARK)
3958/* Minimize compare-and-swap usage. */
3959# define USE_MARK_BYTES
3960#endif
3961
3962#if (defined(MSWINCE) && !defined(__CEGCC__) || defined(MSWINRT_FLAVOR)) \
3963 && !defined(NO_GETENV)
3964# define NO_GETENV
3965#endif
3966
3967#if (defined(NO_GETENV) || defined(MSWINCE)) && !defined(NO_GETENV_WIN32)
3968# define NO_GETENV_WIN32
3969#endif
3970
3971#if !defined(MSGBOX_ON_ERROR) && !defined(NO_MSGBOX_ON_ERROR) \
3972 && defined(MSWIN32) && !defined(MSWINRT_FLAVOR) && !defined(MSWIN_XBOX1) \
3973 && !defined(SMALL_CONFIG)
3974/*
3975 * Show a Windows message box with "OK" button on a GC fatal error.
3976 * Client application is terminated once the user clicks the button.
3977 */
3978# define MSGBOX_ON_ERROR
3979#endif
3980
3981#ifndef STRTOULL
3982# if defined(_WIN64) && !defined(__GNUC__)
3983# define STRTOULL _strtoui64
3984# elif defined(_LLP64) || defined(__LLP64__) || defined(_WIN64)
3985# define STRTOULL strtoull
3986# else
3987/* `strtoul()` fits since `sizeof(long)` is not less than `sizeof(word)`. */
3988# define STRTOULL strtoul
3989# endif
3990#endif /* !STRTOULL */
3991
3992#ifndef GC_WORD_C
3993# if defined(_WIN64) && !defined(__GNUC__)
3994# define GC_WORD_C(val) val##ui64
3995# elif defined(_LLP64) || defined(__LLP64__) || defined(_WIN64)
3996# define GC_WORD_C(val) val##ULL
3997# else
3998# define GC_WORD_C(val) ((word)val##UL)
3999# endif
4000#endif /* !GC_WORD_C */
4001
4002#if defined(__has_feature)
4003/* `__has_feature()` is supported. */
4004# if __has_feature(address_sanitizer)
4005# define ADDRESS_SANITIZER
4006# endif
4007# if __has_feature(memory_sanitizer)
4008# define MEMORY_SANITIZER
4009# endif
4010# if __has_feature(thread_sanitizer) && defined(THREADS)
4011# define THREAD_SANITIZER
4012# endif
4013#else
4014# ifdef __SANITIZE_ADDRESS__
4015/* gcc v4.8+ */
4016# define ADDRESS_SANITIZER
4017# endif
4018# if defined(__SANITIZE_THREAD__) && defined(THREADS)
4019/* gcc v7.1+ */
4020# define THREAD_SANITIZER
4021# endif
4022#endif /* !__has_feature */
4023
4024#if defined(SPARC)
4025/* Stack clearing is crucial, and we include assembly code to do it well. */
4026# define ASM_CLEAR_CODE
4027#endif
4028
4029/*
4030 * Can we save call chain in objects for debugging? Set `NFRAMES`
4031 * (number of saved frames) and `NARGS` (number of arguments for each
4032 * frame) to reasonable values for the platform.
4033 * Define `SAVE_CALL_CHAIN` if we can. `SAVE_CALL_COUNT` can be
4034 * specified at build time, though we feel free to adjust it slightly.
4035 * Define `NEED_CALLINFO` if we either save the call stack or
4036 * `GC_ADD_CALLER` is defined. Note: `GC_CAN_SAVE_CALL_STACKS` is
4037 * defined (for certain platforms) in `gc_config_macros.h` file.
4038 */
4039#if defined(SPARC) \
4040 || ((defined(I386) || defined(X86_64)) \
4041 && (defined(LINUX) || defined(__GLIBC__)))
4042/*
4043 * Linux/x86: `SAVE_CALL_CHAIN` is supported if the code is compiled to save
4044 * frame pointers by default, i.e. no `-fomit-frame-pointer` flag is given.
4045 */
4046# define CAN_SAVE_CALL_ARGS
4047#endif
4048
4049#if defined(SAVE_CALL_COUNT) && !defined(GC_ADD_CALLER) \
4050 && defined(GC_CAN_SAVE_CALL_STACKS)
4051# define SAVE_CALL_CHAIN
4052#endif
4053
4054#ifdef SAVE_CALL_CHAIN
4055/* Number of arguments to save for each call. */
4056# if defined(SAVE_CALL_NARGS) && defined(CAN_SAVE_CALL_ARGS)
4057# define NARGS SAVE_CALL_NARGS
4058# else
4059# define NARGS 0
4060# endif
4061/* Number of frames to save. Even for alignment reasons. */
4062# if !defined(SAVE_CALL_COUNT) || defined(CPPCHECK)
4063# define NFRAMES 6
4064# else
4065# define NFRAMES ((SAVE_CALL_COUNT + 1) & ~1)
4066# endif
4067# define NEED_CALLINFO
4068#elif defined(GC_ADD_CALLER)
4069# define NFRAMES 1
4070# define NARGS 0
4071# define NEED_CALLINFO
4072#endif
4073
4074#if (defined(FREEBSD) || (defined(DARWIN) && !defined(_POSIX_C_SOURCE)) \
4075 || (defined(SOLARIS) \
4076 && (!defined(_XOPEN_SOURCE) || defined(__EXTENSIONS__))) \
4077 || defined(LINUX)) \
4078 && !defined(HAVE_DLADDR)
4079# define HAVE_DLADDR 1
4080#endif
4081
4082#if defined(MAKE_BACK_GRAPH) && !defined(DBG_HDRS_ALL)
4083# define DBG_HDRS_ALL 1
4084#endif
4085
4086#if defined(POINTER_MASK) && !defined(POINTER_SHIFT)
4087# define POINTER_SHIFT 0
4088#elif !defined(POINTER_MASK) && defined(POINTER_SHIFT)
4089# define POINTER_MASK GC_WORD_MAX
4090#endif
4091
4092#if defined(FIXUP_POINTER)
4093/* Custom `FIXUP_POINTER(p)`. */
4094# define NEED_FIXUP_POINTER
4095#elif defined(DYNAMIC_POINTER_MASK)
4096# define FIXUP_POINTER(p) \
4097 (p = (ptr_t)((((word)(p)) & GC_pointer_mask) << GC_pointer_shift))
4098# undef POINTER_MASK
4099# undef POINTER_SHIFT
4100# define NEED_FIXUP_POINTER
4101#elif defined(POINTER_MASK)
4102/*
4103 * Note: extra parentheses around custom-defined `POINTER_MASK` and
4104 *`POINTER_SHIFT` are intentional.
4105 */
4106# define FIXUP_POINTER(p) \
4107 (p = (ptr_t)(((word)(p) & (POINTER_MASK)) << (POINTER_SHIFT)))
4108# define NEED_FIXUP_POINTER
4109#else
4110# define FIXUP_POINTER(p) (void)(p)
4111#endif
4112
4113#ifdef LINT2
4114/*
4115 * A macro (based on a tricky expression) to prevent false warnings
4116 * like "Array compared to 0", "Comparison of identical expressions",
4117 * "Untrusted loop bound" output by some static code analysis tools.
4118 * The argument should not be a literal value. The result is
4119 * converted to `word` type. (Actually, `GC_word` is used instead of
4120 * `word` type as the latter might be undefined at the place of use.)
4121 */
4122# define COVERT_DATAFLOW(w) (~(GC_word)(w) ^ (~(GC_word)0))
4123#else
4124# define COVERT_DATAFLOW(w) ((GC_word)(w))
4125#endif
4126
4127#if CPP_PTRSZ > CPP_WORDSZ
4128/* TODO: Cannot use tricky operations on a pointer. */
4129# define COVERT_DATAFLOW_P(p) ((ptr_t)(p))
4130#else
4131# define COVERT_DATAFLOW_P(p) ((ptr_t)COVERT_DATAFLOW(p))
4132#endif
4133
4134#if defined(REDIRECT_MALLOC) && defined(THREADS) && !defined(LINUX) \
4135 && !defined(REDIRECT_MALLOC_IN_HEADER)
4136/*
4137 * May work on other platforms (e.g. Darwin) provided the client
4138 * ensures all the client threads are registered with the collector,
4139 * e.g. by using the preprocessor-based interception of the thread
4140 * primitives (i.e., define `GC_THREADS` and include `gc.h` file from
4141 * all the client files those are using `pthread_create` and friends).
4142 */
4143#endif
4144
4145EXTERN_C_END
4146
4147#endif /* GCCONFIG_H */
4148
4149
4150#ifdef __cplusplus
4151typedef bool GC_bool;
4152#elif defined(__BORLANDC__) || defined(__WATCOMC__)
4153typedef int GC_bool;
4154#else
4155typedef char GC_bool;
4156#endif
4157
4158#if defined(__cplusplus) && !defined(ANY_MSWIN)
4159/* Avoid macro redefinition on a Windows platform. */
4160# define TRUE true
4161# define FALSE false
4162#else
4163# define TRUE 1
4164# define FALSE 0
4165#endif
4166
4167#if !defined(GC_ATOMIC_UNCOLLECTABLE) && defined(ATOMIC_UNCOLLECTABLE)
4168/* For compatibility with old-style naming. */
4169# define GC_ATOMIC_UNCOLLECTABLE
4170#endif
4171
4172#ifndef GC_INNER
4173/*
4174 * This tagging macro must be used at the start of every variable definition
4175 * which is declared with `GC_EXTERN`. Should be also used for the GC-scope
4176 * function definitions and prototypes. Must not be used in `gcconfig.h`
4177 * file. Should not be used for the debugging-only functions.
4178 */
4179# if defined(GC_DLL) && defined(__GNUC__) && !defined(ANY_MSWIN)
4180# if GC_GNUC_PREREQ(4, 0) && !defined(GC_NO_VISIBILITY)
4181/* See the corresponding `GC_API` definition. */
4182# define GC_INNER __attribute__((__visibility__("hidden")))
4183# else
4184/* The attribute is unsupported. */
4185# define GC_INNER /*< empty */
4186# endif
4187# else
4188# define GC_INNER /*< empty */
4189# endif
4190
4191# define GC_EXTERN extern GC_INNER
4192/*
4193 * Used only for the GC-scope variables (prefixed with `GC_`) declared
4194 * in the private header files. Must not be used for thread-local
4195 * variables. Must not be used in `gcconfig.h` file.
4196 * The corresponding variable definition must start with `GC_INNER`.
4197 * Should not be used for the debugging- or profiling-only variables.
4198 * As of now, there are some other exceptions, e.g. for the variables
4199 * that are known to be used by some popular clients.
4200 */
4201#endif /* !GC_INNER */
4202
4203#ifdef __cplusplus
4204/* `register` storage specifier is deprecated in C++11. */
4205# define REGISTER /*< empty */
4206#else
4207/*
4208 * Used only for several local variables in the performance-critical
4209 * functions. Should not be used for new code.
4210 */
4211# define REGISTER register
4212#endif
4213
4214#if defined(CPPCHECK)
4215# define MACRO_BLKSTMT_BEGIN {
4216# define MACRO_BLKSTMT_END }
4217# define LOCAL_VAR_INIT_OK = 0 /*< to avoid "uninit var" false positive */
4218#else
4219# define MACRO_BLKSTMT_BEGIN do {
4220# define MACRO_BLKSTMT_END \
4221 } \
4222 while (0)
4223# define LOCAL_VAR_INIT_OK /*< empty */
4224#endif
4225
4226#if defined(M68K) && defined(__GNUC__)
4227/*
4228 * By default, `__alignof__(void *)` is 2 on m68k architecture.
4229 * Use this attribute to have the machine-word alignment (i.e. 4-byte one
4230 * on the given 32-bit architecture).
4231 */
4232# define GC_ATTR_PTRT_ALIGNED __attribute__((__aligned__(sizeof(ptr_t))))
4233#else
4234# define GC_ATTR_PTRT_ALIGNED /*< empty */
4235#endif
4236
4237#ifdef CHERI_PURECAP
4238# include <cheriintrin.h>
4239#endif
4240
4241EXTERN_C_BEGIN
4242
4243typedef GC_uintptr_t GC_funcptr_uint;
4244#define FUNCPTR_IS_DATAPTR
4245
4246typedef unsigned int unsigned32;
4247
4248#define hblk GC_hblk_s
4249struct hblk;
4250
4251typedef struct hblkhdr hdr;
4252
4253EXTERN_C_END
4254
4255/*
4256 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
4257 * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
4258 *
4259 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
4260 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
4261 *
4262 * Permission is hereby granted to use or copy this program
4263 * for any purpose, provided the above notices are retained on all copies.
4264 * Permission to modify the code and to distribute modified code is granted,
4265 * provided the above notices are retained, and a notice that the code was
4266 * modified is included with the above copyright notice.
4267 */
4268
4269#ifndef GC_HEADERS_H
4270#define GC_HEADERS_H
4271
4272#if !defined(GC_PRIVATE_H) && !defined(CPPCHECK)
4273# error gc_hdrs.h should be included from gc_priv.h
4274#endif
4275
4276#if CPP_WORDSZ != 32 && CPP_WORDSZ < 36 && !defined(CPPCHECK)
4277# error Get a real machine
4278#endif
4279
4280EXTERN_C_BEGIN
4281
4282/*
4283 * The 2-level tree data structure that is used to find block headers.
4284 * If there are more than 32 bits in a pointer, the top level is a hash
4285 * table.
4286 *
4287 * This defines `HDR()`, `GET_HDR()`, and `SET_HDR()`, the main macros
4288 * used to retrieve and set object headers.
4289 *
4290 * We take advantage of a header lookup cache. This is a locally declared
4291 * direct mapped cache, used inside the marker. The `HC_GET_HDR()` macro
4292 * uses and maintains this cache. Assuming we get reasonable hit rates,
4293 * this saves a few memory references from each pointer validation.
4294 */
4295
4296#if CPP_WORDSZ > 32
4297# define HASH_TL
4298#endif
4299
4300/* Define appropriate out-degrees for each of the two tree levels. */
4301#if defined(LARGE_CONFIG) || !defined(SMALL_CONFIG)
4302# define LOG_BOTTOM_SZ 10
4303#else
4304/* Keep top index size reasonable with smaller blocks. */
4305# define LOG_BOTTOM_SZ 11
4306#endif
4307#define BOTTOM_SZ (1 << LOG_BOTTOM_SZ)
4308
4309#ifndef HASH_TL
4310# define LOG_TOP_SZ (CPP_WORDSZ - LOG_BOTTOM_SZ - LOG_HBLKSIZE)
4311#else
4312# define LOG_TOP_SZ 11
4313#endif
4314#define TOP_SZ (1 << LOG_TOP_SZ)
4315
4316#ifdef COUNT_HDR_CACHE_HITS
4317extern word GC_hdr_cache_hits; /*< used for debugging/profiling */
4318extern word GC_hdr_cache_misses;
4319# define HC_HIT() (void)(++GC_hdr_cache_hits)
4320# define HC_MISS() (void)(++GC_hdr_cache_misses)
4321#else
4322# define HC_HIT() (void)0
4323# define HC_MISS() (void)0
4324#endif
4325
4326typedef struct hce {
4327 word block_addr; /*< right-shifted by `LOG_HBLKSIZE` */
4328 hdr *hce_hdr;
4329} hdr_cache_entry;
4330
4331#define HDR_CACHE_SIZE 8 /*< a power of two */
4332
4333#define DECLARE_HDR_CACHE hdr_cache_entry hdr_cache[HDR_CACHE_SIZE]
4334
4335#define INIT_HDR_CACHE BZERO(hdr_cache, sizeof(hdr_cache))
4336
4337#define HCE(h) (hdr_cache + ((ADDR(h) >> LOG_HBLKSIZE) & (HDR_CACHE_SIZE - 1)))
4338
4339#define HCE_VALID_FOR(hce, h) ((hce)->block_addr == (ADDR(h) >> LOG_HBLKSIZE))
4340
4341#define HCE_HDR(h) ((hce)->hce_hdr)
4342
4343#ifdef PRINT_BLACK_LIST
4344/*
4345 * Handle a header cache miss. Returns a pointer to the header
4346 * corresponding to `p`, if the latter can possibly be a valid object
4347 * pointer, and `NULL` otherwise. Guaranteed to return `NULL` for
4348 * a pointer past the first page of an object unless both
4349 * `GC_all_interior_pointers` is set and `p` is in fact a valid object
4350 * pointer. Never returns a pointer to a free `hblk`.
4351 */
4352GC_INNER hdr *GC_header_cache_miss(ptr_t p, hdr_cache_entry *hce,
4353 ptr_t source);
4354
4355# define HEADER_CACHE_MISS(p, hce, source) \
4356 GC_header_cache_miss(p, hce, source)
4357#else
4358GC_INNER hdr *GC_header_cache_miss(ptr_t p, hdr_cache_entry *hce);
4359# define HEADER_CACHE_MISS(p, hce, source) GC_header_cache_miss(p, hce)
4360#endif
4361
4362/*
4363 * Set `hhdr` to the header for `p`. Analogous to `GET_HDR()` below,
4364 * except that in the case of large objects, it gets the header for the
4365 * object beginning if `GC_all_interior_pointers` is true. Sets `hhdr`
4366 * to `NULL` if `p` points to somewhere other than the first page of an
4367 * object, and it is not a valid pointer to the object.
4368 */
4369#define HC_GET_HDR(p, hhdr, source) \
4370 { /*< cannot use `do ... while (0)` here */ \
4371 hdr_cache_entry *hce = HCE(p); \
4372 if (LIKELY(HCE_VALID_FOR(hce, p))) { \
4373 HC_HIT(); \
4374 hhdr = hce->hce_hdr; \
4375 } else { \
4376 hhdr = HEADER_CACHE_MISS(p, hce, source); \
4377 if (NULL == hhdr) \
4378 break; /*< go to the enclosing loop end */ \
4379 } \
4380 }
4381
4382typedef struct bi {
4383 /*
4384 * The bottom-level index contains one of three kinds of values:
4385 * - 0 means we are not responsible for this block, or this is
4386 * a block other than the first one in a free block;
4387 * - 1 < (long)`x` <= `MAX_JUMP` means the block starts at least
4388 * `x * HBLKSIZE` bytes before the current address;
4389 * - a valid pointer points to a `hdr` structure (the above cannot
4390 * be valid pointers due to the `GET_MEM()` return convention).
4391 */
4392 hdr *index[BOTTOM_SZ];
4393
4394 /*
4395 * All indices are linked in the ascending and descending orders,
4396 * respectively.
4397 */
4398 struct bi *asc_link;
4399 struct bi *desc_link;
4400
4401 word key; /*< high-order address bits */
4402#ifdef HASH_TL
4403 struct bi *hash_link; /*< hash chain link */
4404#endif
4405} bottom_index;
4406
4407#define MAX_JUMP (HBLKSIZE - 1)
4408
4409#define HDR_FROM_BI(bi, p) \
4410 (bi)->index[(ADDR(p) >> LOG_HBLKSIZE) & (BOTTOM_SZ - 1)]
4411#ifndef HASH_TL
4412# define BI(p) GC_top_index[ADDR(p) >> (LOG_BOTTOM_SZ + LOG_HBLKSIZE)]
4413# define HDR_INNER(p) HDR_FROM_BI(BI(p), p)
4414# ifdef SMALL_CONFIG
4415# define HDR(p) GC_find_header(p)
4416# else
4417# define HDR(p) HDR_INNER(p)
4418# endif
4419# define GET_BI(p, bottom_indx) (void)((bottom_indx) = BI(p))
4420# define GET_HDR(p, hhdr) (void)((hhdr) = HDR(p))
4421# define SET_HDR(p, hhdr) (void)(HDR_INNER(p) = (hhdr))
4422# define GET_HDR_ADDR(p, ha) (void)((ha) = &HDR_INNER(p))
4423#else
4424/* A hash function for the tree top level. */
4425# define TL_HASH(hi) ((hi) & (TOP_SZ - 1))
4426/* Set `bottom_indx` to point to the bottom index for address `p`. */
4427# define GET_BI(p, bottom_indx) \
4428 do { \
4429 REGISTER word hi = ADDR(p) >> (LOG_BOTTOM_SZ + LOG_HBLKSIZE); \
4430 REGISTER bottom_index *_bi = GC_top_index[TL_HASH(hi)]; \
4431 while (_bi->key != hi && _bi != GC_all_nils) \
4432 _bi = _bi->hash_link; \
4433 (bottom_indx) = _bi; \
4434 } while (0)
4435# define GET_HDR_ADDR(p, ha) \
4436 do { \
4437 REGISTER bottom_index *bi; \
4438 GET_BI(p, bi); \
4439 (ha) = &HDR_FROM_BI(bi, p); \
4440 } while (0)
4441# define GET_HDR(p, hhdr) \
4442 do { \
4443 REGISTER hdr **_ha; \
4444 GET_HDR_ADDR(p, _ha); \
4445 (hhdr) = *_ha; \
4446 } while (0)
4447# define SET_HDR(p, hhdr) \
4448 do { \
4449 REGISTER bottom_index *bi; \
4450 GET_BI(p, bi); \
4451 GC_ASSERT(bi != GC_all_nils); \
4452 HDR_FROM_BI(bi, p) = (hhdr); \
4453 } while (0)
4454# define HDR(p) GC_find_header(p)
4455#endif
4456
4457/*
4458 * Is the result a forwarding address to someplace closer to the
4459 * beginning of the block or `NULL`?
4460 */
4461#define IS_FORWARDING_ADDR_OR_NIL(hhdr) ((size_t)ADDR(hhdr) <= MAX_JUMP)
4462
4463/*
4464 * Get an `HBLKSIZE`-aligned address closer to the beginning of the
4465 * block `h`. Assumes that `hhdr` is equal to `HDR(h)`,
4466 * `IS_FORWARDING_ADDR(hhdr)` is true and `hhdr` is not `NULL`.
4467 * `HDR(result)` is expected to be non-`NULL`.
4468 */
4469#define FORWARDED_ADDR(h, hhdr) \
4470 ((struct hblk *)(h) - (size_t)(GC_uintptr_t)(hhdr))
4471
4472EXTERN_C_END
4473
4474#endif /* GC_HEADERS_H */
4475
4476
4477#ifndef GC_ATTR_NO_SANITIZE_ADDR
4478# ifndef ADDRESS_SANITIZER
4479# define GC_ATTR_NO_SANITIZE_ADDR /*< empty */
4480# elif GC_CLANG_PREREQ(3, 8)
4481# define GC_ATTR_NO_SANITIZE_ADDR \
4482 __attribute__((__no_sanitize__("address")))
4483# else
4484# define GC_ATTR_NO_SANITIZE_ADDR __attribute__((__no_sanitize_address__))
4485# endif
4486#endif /* !GC_ATTR_NO_SANITIZE_ADDR */
4487
4488#ifndef GC_ATTR_NO_SANITIZE_MEMORY
4489# ifndef MEMORY_SANITIZER
4490# define GC_ATTR_NO_SANITIZE_MEMORY /*< empty */
4491# elif GC_CLANG_PREREQ(3, 8)
4492# define GC_ATTR_NO_SANITIZE_MEMORY \
4493 __attribute__((__no_sanitize__("memory")))
4494# else
4495# define GC_ATTR_NO_SANITIZE_MEMORY __attribute__((__no_sanitize_memory__))
4496# endif
4497#endif /* !GC_ATTR_NO_SANITIZE_MEMORY */
4498
4499#ifndef GC_ATTR_NO_SANITIZE_THREAD
4500# ifndef THREAD_SANITIZER
4501# define GC_ATTR_NO_SANITIZE_THREAD /*< empty */
4502# elif GC_CLANG_PREREQ(3, 8)
4503# define GC_ATTR_NO_SANITIZE_THREAD \
4504 __attribute__((__no_sanitize__("thread")))
4505# else
4506/*
4507 * It seems that `no_sanitize_thread` attribute has no effect if the
4508 * function is inlined (as of gcc-11.1.0, at least).
4509 */
4510# define GC_ATTR_NO_SANITIZE_THREAD \
4511 GC_ATTR_NOINLINE __attribute__((__no_sanitize_thread__))
4512# endif
4513#endif /* !GC_ATTR_NO_SANITIZE_THREAD */
4514
4515#define GC_ATTR_NO_SANITIZE_ADDR_MEM_THREAD \
4516 GC_ATTR_NO_SANITIZE_ADDR GC_ATTR_NO_SANITIZE_MEMORY \
4517 GC_ATTR_NO_SANITIZE_THREAD
4518
4519#ifndef UNUSED_ARG
4520# define UNUSED_ARG(arg) ((void)(arg))
4521#endif
4522
4523#ifdef HAVE_CONFIG_H
4524/* The `inline` keyword is determined by `AC_C_INLINE` of `autoconf`. */
4525# define GC_INLINE static inline
4526#elif defined(_MSC_VER) || defined(__INTEL_COMPILER) || defined(__DMC__) \
4527 || (GC_GNUC_PREREQ(3, 0) && defined(__STRICT_ANSI__)) \
4528 || defined(__BORLANDC__) || defined(__WATCOMC__)
4529# define GC_INLINE static __inline
4530#elif GC_GNUC_PREREQ(3, 0) || defined(__sun)
4531# define GC_INLINE static inline
4532#else
4533# define GC_INLINE static
4534#endif
4535
4536#ifndef GC_ATTR_NOINLINE
4537# if GC_GNUC_PREREQ(4, 0)
4538# define GC_ATTR_NOINLINE __attribute__((__noinline__))
4539# elif _MSC_VER >= 1400
4540# define GC_ATTR_NOINLINE __declspec(noinline)
4541# else
4542# define GC_ATTR_NOINLINE /*< empty */
4543# endif
4544#endif
4545
4546#ifndef GC_API_OSCALL
4547/* This is used to identify GC routines called by name from OS. */
4548# if defined(__GNUC__)
4549# if GC_GNUC_PREREQ(4, 0) && !defined(GC_NO_VISIBILITY)
4550/* Same as `GC_API` macro if `GC_DLL` one is defined. */
4551# define GC_API_OSCALL extern __attribute__((__visibility__("default")))
4552# else
4553/* The attribute is unsupported. */
4554# define GC_API_OSCALL extern
4555# endif
4556# else
4557# define GC_API_OSCALL GC_API
4558# endif
4559#endif
4560
4561#ifndef GC_API_PRIV
4562# define GC_API_PRIV GC_API
4563#endif
4564
4565#ifndef GC_API_PATCHABLE
4566# define GC_API_PATCHABLE GC_ATTR_NOINLINE GC_API
4567#endif
4568
4569#if defined(THREADS) && !defined(NN_PLATFORM_CTR)
4570/*
4571 * Copyright (c) 2017 Ivan Maidanski
4572 *
4573 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
4574 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
4575 *
4576 * Permission is hereby granted to use or copy this program
4577 * for any purpose, provided the above notices are retained on all copies.
4578 * Permission to modify the code and to distribute modified code is granted,
4579 * provided the above notices are retained, and a notice that the code was
4580 * modified is included with the above copyright notice.
4581 */
4582
4583/*
4584 * This is a private collector header which provides an implementation of
4585 * `libatomic_ops` subset primitives sufficient for the collector assuming
4586 * that gcc atomic intrinsics are available (and have the correct
4587 * implementation). This is enabled by defining `GC_BUILTIN_ATOMIC` macro.
4588 * Otherwise, `libatomic_ops` library is used to define the primitives.
4589 */
4590
4591#ifndef GC_ATOMIC_OPS_H
4592#define GC_ATOMIC_OPS_H
4593
4594#ifdef GC_BUILTIN_ATOMIC
4595
4596
4597
4598
4599# ifdef __cplusplus
4600extern "C" {
4601# endif
4602
4603typedef size_t AO_t;
4604
4605# ifdef GC_PRIVATE_H /*< i.e. have `GC_INLINE` */
4606# define AO_INLINE GC_INLINE
4607# else
4608# define AO_INLINE static __inline
4609# endif
4610
4611# if !defined(THREAD_SANITIZER) && !defined(GC_PRIVATE_H)
4612/* Similar to that in `gcconfig.h` file. */
4613# if defined(__has_feature)
4614# if __has_feature(thread_sanitizer)
4615# define THREAD_SANITIZER
4616# endif
4617# elif defined(__SANITIZE_THREAD__)
4618# define THREAD_SANITIZER
4619# endif
4620# endif /* !THREAD_SANITIZER && !GC_PRIVATE_H */
4621
4622typedef unsigned char AO_TS_t;
4623# define AO_TS_CLEAR 0
4624# define AO_TS_INITIALIZER ((AO_TS_t)AO_TS_CLEAR)
4625# if defined(__GCC_ATOMIC_TEST_AND_SET_TRUEVAL) && !defined(CPPCHECK)
4626# define AO_TS_SET __GCC_ATOMIC_TEST_AND_SET_TRUEVAL
4627# else
4628# define AO_TS_SET (AO_TS_t)1 /*< true */
4629# endif
4630# define AO_CLEAR(p) __atomic_clear(p, __ATOMIC_RELEASE)
4631# define AO_test_and_set_acquire(p) \
4632 (__atomic_test_and_set(p, __ATOMIC_ACQUIRE) ? AO_TS_SET : AO_TS_CLEAR)
4633# define AO_HAVE_test_and_set_acquire
4634
4635# define AO_compiler_barrier() __atomic_signal_fence(__ATOMIC_SEQ_CST)
4636
4637# if defined(THREAD_SANITIZER) && !defined(AO_USE_ATOMIC_THREAD_FENCE)
4638/*
4639 * Workaround a compiler warning (reported by gcc-11, at least) that
4640 * `__atomic_thread_fence` is unsupported with thread sanitizer.
4641 */
4642AO_INLINE void
4643AO_nop_full(void)
4644{
4645 volatile AO_TS_t dummy = AO_TS_INITIALIZER;
4646 (void)__atomic_test_and_set(&dummy, __ATOMIC_SEQ_CST);
4647}
4648# else
4649# define AO_nop_full() __atomic_thread_fence(__ATOMIC_SEQ_CST)
4650# endif
4651# define AO_HAVE_nop_full
4652
4653# define AO_fetch_and_add(p, v) __atomic_fetch_add(p, v, __ATOMIC_RELAXED)
4654# define AO_HAVE_fetch_and_add
4655# define AO_fetch_and_add1(p) AO_fetch_and_add(p, 1)
4656# define AO_HAVE_fetch_and_add1
4657# define AO_fetch_and_sub1(p) AO_fetch_and_add(p, ~(AO_t)0 /* -1 */)
4658# define AO_HAVE_fetch_and_sub1
4659
4660# define AO_or(p, v) (void)__atomic_or_fetch(p, v, __ATOMIC_RELAXED)
4661# define AO_HAVE_or
4662
4663# define AO_load(p) __atomic_load_n(p, __ATOMIC_RELAXED)
4664# define AO_HAVE_load
4665# define AO_load_acquire(p) __atomic_load_n(p, __ATOMIC_ACQUIRE)
4666# define AO_HAVE_load_acquire
4667/*
4668 * `AO_load_acquire_read(p)` is not defined as it is unused, but we need
4669 * its `AO_HAVE_` macro defined.
4670 */
4671# define AO_HAVE_load_acquire_read
4672
4673# define AO_store(p, v) __atomic_store_n(p, v, __ATOMIC_RELAXED)
4674# define AO_HAVE_store
4675# define AO_store_release(p, v) __atomic_store_n(p, v, __ATOMIC_RELEASE)
4676# define AO_HAVE_store_release
4677# define AO_store_release_write(p, v) AO_store_release(p, v)
4678# define AO_HAVE_store_release_write
4679
4680# define AO_char_load(p) __atomic_load_n(p, __ATOMIC_RELAXED)
4681# define AO_HAVE_char_load
4682# define AO_char_store(p, v) __atomic_store_n(p, v, __ATOMIC_RELAXED)
4683# define AO_HAVE_char_store
4684# define AO_char_fetch_and_add1(p) __atomic_fetch_add(p, 1, __ATOMIC_RELAXED)
4685# define AO_HAVE_char_fetch_and_add1
4686
4687# ifdef AO_REQUIRE_CAS
4688AO_INLINE int
4689AO_compare_and_swap_release(volatile AO_t *p, AO_t ov, AO_t nv)
4690{
4691 return (int)__atomic_compare_exchange_n(p, &ov, nv, 0, __ATOMIC_RELEASE,
4692 __ATOMIC_RELAXED /* on fail */);
4693}
4694# define AO_HAVE_compare_and_swap_release
4695# endif
4696
4697# ifdef __cplusplus
4698} /* extern "C" */
4699# endif
4700
4701# ifndef NO_LOCKFREE_AO_OR
4702/* `__atomic_or_fetch()` is assumed to be lock-free. */
4703# define HAVE_LOCKFREE_AO_OR 1
4704# endif
4705
4706#else
4707/* Fall back to `libatomic_ops`. */
4708# include "atomic_ops.h"
4709
4710/*
4711 * `AO_compiler_barrier`, `AO_load` and `AO_store` should be defined
4712 * for all targets; the rest of the primitives are guaranteed to exist
4713 * only if `AO_REQUIRE_CAS` is defined (or if the corresponding
4714 * `AO_HAVE_` macro is defined). i686 and x86_64 targets have
4715 * `AO_nop_full`, `AO_load_acquire`, `AO_store_release`, at least.
4716 */
4717# if (!defined(AO_HAVE_load) || !defined(AO_HAVE_store)) && !defined(CPPCHECK)
4718# error AO_load or AO_store is missing; probably old version of atomic_ops
4719# endif
4720
4721#endif /* !GC_BUILTIN_ATOMIC */
4722
4723#if defined(GC_BUILTIN_ATOMIC) || defined(__CHERI_PURE_CAPABILITY__)
4724/*
4725 * Assume that gcc atomic intrinsics are available (and have correct
4726 * implementation). `p` should be of a pointer to `ptr_t` (`char *`) value.
4727 */
4728# define GC_cptr_load(p) __atomic_load_n(p, __ATOMIC_RELAXED)
4729# define GC_cptr_load_acquire(p) __atomic_load_n(p, __ATOMIC_ACQUIRE)
4730# define GC_cptr_load_acquire_read(p) GC_cptr_load_acquire(p)
4731# define GC_cptr_store(p, v) __atomic_store_n(p, v, __ATOMIC_RELAXED)
4732# define GC_cptr_store_release(p, v) __atomic_store_n(p, v, __ATOMIC_RELEASE)
4733# define GC_cptr_store_release_write(p, v) GC_cptr_store_release(p, v)
4734# ifdef AO_REQUIRE_CAS
4735AO_INLINE int
4736GC_cptr_compare_and_swap(char *volatile *p, char *ov, char *nv)
4737{
4738 return (int)__atomic_compare_exchange_n(p, &ov, nv, 0, __ATOMIC_RELAXED,
4739 __ATOMIC_RELAXED);
4740}
4741# endif
4742#else
4743/*
4744 * Redirect to the `AO_` primitives. Assume the size of `AO_t` matches
4745 * that of a pointer.
4746 */
4747# define GC_cptr_load(p) (char *)AO_load((volatile AO_t *)(p))
4748# define GC_cptr_load_acquire(p) (char *)AO_load_acquire((volatile AO_t *)(p))
4749# define GC_cptr_load_acquire_read(p) \
4750 (char *)AO_load_acquire_read((volatile AO_t *)(p))
4751# define GC_cptr_store(p, v) AO_store((volatile AO_t *)(p), (AO_t)(v))
4752# define GC_cptr_store_release(p, v) \
4753 AO_store_release((volatile AO_t *)(p), (AO_t)(v))
4754# define GC_cptr_store_release_write(p, v) \
4755 AO_store_release_write((volatile AO_t *)(p), (AO_t)(v))
4756# ifdef AO_REQUIRE_CAS
4757# define GC_cptr_compare_and_swap(p, ov, nv) \
4758 AO_compare_and_swap((volatile AO_t *)(p), (AO_t)(ov), (AO_t)(nv))
4759# endif
4760#endif /* !GC_BUILTIN_ATOMIC */
4761
4762#endif /* GC_ATOMIC_OPS_H */
4763
4764# ifndef AO_HAVE_compiler_barrier
4765# define AO_HAVE_compiler_barrier 1
4766# endif
4767#endif
4768
4769#ifdef ANY_MSWIN
4770# ifndef WIN32_LEAN_AND_MEAN
4771# define WIN32_LEAN_AND_MEAN 1
4772# endif
4773# define NOSERVICE
4774# include <windows.h>
4775
4776/* This is included strictly after the platform `windows.h` file. */
4777# include <winbase.h>
4778#endif /* ANY_MSWIN */
4779
4780/*
4781 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
4782 * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
4783 * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
4784 * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.
4785 * Copyright (c) 2008-2025 Ivan Maidanski
4786 *
4787 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
4788 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
4789 *
4790 * Permission is hereby granted to use or copy this program
4791 * for any purpose, provided the above notices are retained on all copies.
4792 * Permission to modify the code and to distribute modified code is granted,
4793 * provided the above notices are retained, and a notice that the code was
4794 * modified is included with the above copyright notice.
4795 */
4796
4797#ifndef GC_LOCKS_H
4798#define GC_LOCKS_H
4799
4800#if !defined(GC_PRIVATE_H) && !defined(CPPCHECK)
4801# error gc_locks.h should be included from gc_priv.h
4802#endif
4803
4804/*
4805 * Mutual exclusion between allocator/collector routines. Needed if
4806 * there is more than one allocator thread. Note that `I_HOLD_LOCK`,
4807 * `I_DONT_HOLD_LOCK` and `I_HOLD_READER_LOCK` macros are used only
4808 * positively in assertions, and may return `TRUE` in the "do not know"
4809 * case.
4810 */
4811
4812#ifdef THREADS
4813
4814EXTERN_C_BEGIN
4815
4816# if defined(NN_PLATFORM_CTR) || defined(NINTENDO_SWITCH)
4817extern void GC_lock(void);
4818extern void GC_unlock(void);
4819# define UNCOND_LOCK() GC_lock()
4820# define UNCOND_UNLOCK() GC_unlock()
4821# ifdef GC_ASSERTIONS
4822# define SET_LOCK_HOLDER() (void)0
4823# endif
4824# endif
4825
4826# if (!defined(AO_HAVE_test_and_set_acquire) || defined(GC_WIN32_THREADS) \
4827 || defined(LINT2) || defined(RTEMS) || defined(SN_TARGET_PS3) \
4828 || defined(BASE_ATOMIC_OPS_EMULATED) || defined(USE_RWLOCK)) \
4829 && defined(GC_PTHREADS)
4830# define USE_PTHREAD_LOCKS
4831# undef USE_SPIN_LOCK
4832# if (defined(GC_WIN32_THREADS) || defined(LINT2) || defined(USE_RWLOCK)) \
4833 && !defined(NO_PTHREAD_TRYLOCK)
4834/*
4835 * `pthread_mutex_trylock` may not win in `GC_lock` on Win32, due to
4836 * built-in support for spinning first?
4837 */
4838# define NO_PTHREAD_TRYLOCK
4839# endif
4840# endif
4841
4842# if defined(GC_WIN32_THREADS) && !defined(USE_PTHREAD_LOCKS) \
4843 || defined(GC_PTHREADS)
4844/* A value which is not equal to `NUMERIC_THREAD_ID(id)` for any thread. */
4845# define NO_THREAD ((unsigned long)(-1L))
4846# ifdef GC_ASSERTIONS
4847GC_EXTERN unsigned long GC_lock_holder;
4848# define UNSET_LOCK_HOLDER() (void)(GC_lock_holder = NO_THREAD)
4849# endif
4850# endif /* GC_WIN32_THREADS || GC_PTHREADS */
4851
4852# if defined(GC_WIN32_THREADS) && !defined(USE_PTHREAD_LOCKS)
4853# ifdef USE_RWLOCK
4854GC_EXTERN SRWLOCK GC_allocate_ml;
4855# else
4856GC_EXTERN CRITICAL_SECTION GC_allocate_ml;
4857# endif
4858# ifdef GC_ASSERTIONS
4859# define SET_LOCK_HOLDER() (void)(GC_lock_holder = GetCurrentThreadId())
4860# define I_HOLD_LOCK() \
4861 (!GC_need_to_lock || GC_lock_holder == GetCurrentThreadId())
4862# ifdef THREAD_SANITIZER
4863# define I_DONT_HOLD_LOCK() TRUE /*< conservatively say yes */
4864# else
4865# define I_DONT_HOLD_LOCK() \
4866 (!GC_need_to_lock || GC_lock_holder != GetCurrentThreadId())
4867# endif
4868# ifdef USE_RWLOCK
4869# define UNCOND_READER_LOCK() \
4870 { \
4871 GC_ASSERT(I_DONT_HOLD_LOCK()); \
4872 AcquireSRWLockShared(&GC_allocate_ml); \
4873 }
4874# define UNCOND_READER_UNLOCK() \
4875 { \
4876 GC_ASSERT(I_DONT_HOLD_LOCK()); \
4877 ReleaseSRWLockShared(&GC_allocate_ml); \
4878 }
4879# define UNCOND_LOCK() \
4880 { \
4881 GC_ASSERT(I_DONT_HOLD_LOCK()); \
4882 AcquireSRWLockExclusive(&GC_allocate_ml); \
4883 SET_LOCK_HOLDER(); \
4884 }
4885# define UNCOND_UNLOCK() \
4886 { \
4887 GC_ASSERT(I_HOLD_LOCK()); \
4888 UNSET_LOCK_HOLDER(); \
4889 ReleaseSRWLockExclusive(&GC_allocate_ml); \
4890 }
4891# else
4892# define UNCOND_LOCK() \
4893 { \
4894 GC_ASSERT(I_DONT_HOLD_LOCK()); \
4895 EnterCriticalSection(&GC_allocate_ml); \
4896 SET_LOCK_HOLDER(); \
4897 }
4898# define UNCOND_UNLOCK() \
4899 { \
4900 GC_ASSERT(I_HOLD_LOCK()); \
4901 UNSET_LOCK_HOLDER(); \
4902 LeaveCriticalSection(&GC_allocate_ml); \
4903 }
4904# endif
4905# else
4906# ifdef USE_RWLOCK
4907# define UNCOND_READER_LOCK() AcquireSRWLockShared(&GC_allocate_ml)
4908# define UNCOND_READER_UNLOCK() ReleaseSRWLockShared(&GC_allocate_ml)
4909# define UNCOND_LOCK() AcquireSRWLockExclusive(&GC_allocate_ml)
4910# define UNCOND_UNLOCK() ReleaseSRWLockExclusive(&GC_allocate_ml)
4911# else
4912# define UNCOND_LOCK() EnterCriticalSection(&GC_allocate_ml)
4913# define UNCOND_UNLOCK() LeaveCriticalSection(&GC_allocate_ml)
4914# endif
4915# endif /* !GC_ASSERTIONS */
4916# elif defined(GC_PTHREADS)
4917EXTERN_C_END
4918# include <pthread.h>
4919EXTERN_C_BEGIN
4920/*
4921 * POSIX allows `pthread_t` to be a structure type, though it rarely is.
4922 * Unfortunately, we need to use a `pthread_t` to index a data structure.
4923 * It also helps if comparisons do not involve a function call.
4924 * Hence we introduce platform-dependent macros to compare `pthread_t` ids
4925 * and to map them to integers (of `unsigned long` type). This mapping
4926 * does not need to result in different values for each thread, though
4927 * that should be true as much as possible.
4928 */
4929# if !defined(GC_WIN32_PTHREADS)
4930# define NUMERIC_THREAD_ID(id) ((unsigned long)(GC_uintptr_t)(id))
4931# define THREAD_EQUAL(id1, id2) ((id1) == (id2))
4932# define NUMERIC_THREAD_ID_UNIQUE
4933# elif defined(__WINPTHREADS_VERSION_MAJOR) /*< winpthreads */
4934# define NUMERIC_THREAD_ID(id) ((unsigned long)(id))
4935# define THREAD_EQUAL(id1, id2) ((id1) == (id2))
4936/* `NUMERIC_THREAD_ID()` is 32-bit and, thus, not unique on Win64. */
4937# ifndef _WIN64
4938# define NUMERIC_THREAD_ID_UNIQUE
4939# endif
4940# else /* pthreads-win32 */
4941# define NUMERIC_THREAD_ID(id) ((unsigned long)(word)(id.p))
4942/*
4943 * The platform on which `pthread_t` is a structure.
4944 * Using documented internal details of pthreads-win32 library.
4945 * Faster than `pthread_equal()`. Should not change with the
4946 * future versions of pthreads-win32 library.
4947 */
4948# define THREAD_EQUAL(id1, id2) (id1.p == id2.p && id1.x == id2.x)
4949/*
4950 * Generic definitions based on `pthread_equal()` always work but will
4951 * result in poor performance (as `NUMERIC_THREAD_ID()` might give
4952 * a constant value) and weak assertion checking.
4953 */
4954# undef NUMERIC_THREAD_ID_UNIQUE
4955# endif
4956
4957# ifdef SN_TARGET_PSP2
4958EXTERN_C_END
4959# include "psp2-support.h"
4960EXTERN_C_BEGIN
4961GC_EXTERN WapiMutex GC_allocate_ml_PSP2;
4962# define UNCOND_LOCK() \
4963 { \
4964 int res; \
4965 GC_ASSERT(I_DONT_HOLD_LOCK()); \
4966 res = PSP2_MutexLock(&GC_allocate_ml_PSP2); \
4967 GC_ASSERT(0 == res); \
4968 (void)res; \
4969 SET_LOCK_HOLDER(); \
4970 }
4971# define UNCOND_UNLOCK() \
4972 { \
4973 int res; \
4974 GC_ASSERT(I_HOLD_LOCK()); \
4975 UNSET_LOCK_HOLDER(); \
4976 res = PSP2_MutexUnlock(&GC_allocate_ml_PSP2); \
4977 GC_ASSERT(0 == res); \
4978 (void)res; \
4979 }
4980
4981# elif (!defined(THREAD_LOCAL_ALLOC) || defined(USE_SPIN_LOCK)) \
4982 && !defined(USE_PTHREAD_LOCKS) && !defined(THREAD_SANITIZER) \
4983 && !defined(USE_RWLOCK)
4984/*
4985 * In the `THREAD_LOCAL_ALLOC` case, the allocator lock tends to
4986 * be held for long periods, if it is held at all.
4987 * Thus spinning and sleeping for fixed periods are likely to result
4988 * in significant wasted time. We thus rely mostly on queued locks.
4989 */
4990# undef USE_SPIN_LOCK
4991# define USE_SPIN_LOCK
4992GC_INNER void GC_lock(void);
4993# ifdef GC_ASSERTIONS
4994# define UNCOND_LOCK() \
4995 { \
4996 GC_ASSERT(I_DONT_HOLD_LOCK()); \
4997 if (AO_test_and_set_acquire(&GC_allocate_lock) == AO_TS_SET) \
4998 GC_lock(); \
4999 SET_LOCK_HOLDER(); \
5000 }
5001# define UNCOND_UNLOCK() \
5002 { \
5003 GC_ASSERT(I_HOLD_LOCK()); \
5004 UNSET_LOCK_HOLDER(); \
5005 AO_CLEAR(&GC_allocate_lock); \
5006 }
5007# else
5008# define UNCOND_LOCK() \
5009 { \
5010 if (AO_test_and_set_acquire(&GC_allocate_lock) == AO_TS_SET) \
5011 GC_lock(); \
5012 }
5013# define UNCOND_UNLOCK() AO_CLEAR(&GC_allocate_lock)
5014# endif /* !GC_ASSERTIONS */
5015# else
5016# ifndef USE_PTHREAD_LOCKS
5017# define USE_PTHREAD_LOCKS
5018# endif
5019# endif /* THREAD_LOCAL_ALLOC || USE_PTHREAD_LOCKS */
5020# ifdef USE_PTHREAD_LOCKS
5021EXTERN_C_END
5022# include <pthread.h>
5023EXTERN_C_BEGIN
5024# ifdef GC_ASSERTIONS
5025GC_INNER void GC_lock(void);
5026# define UNCOND_LOCK() \
5027 { \
5028 GC_ASSERT(I_DONT_HOLD_LOCK()); \
5029 GC_lock(); \
5030 SET_LOCK_HOLDER(); \
5031 }
5032# endif
5033# ifdef USE_RWLOCK
5034GC_EXTERN pthread_rwlock_t GC_allocate_ml;
5035# ifdef GC_ASSERTIONS
5036# define UNCOND_READER_LOCK() \
5037 { \
5038 GC_ASSERT(I_DONT_HOLD_LOCK()); \
5039 (void)pthread_rwlock_rdlock(&GC_allocate_ml); \
5040 }
5041# define UNCOND_READER_UNLOCK() \
5042 { \
5043 GC_ASSERT(I_DONT_HOLD_LOCK()); \
5044 (void)pthread_rwlock_unlock(&GC_allocate_ml); \
5045 }
5046# define UNCOND_UNLOCK() \
5047 { \
5048 GC_ASSERT(I_HOLD_LOCK()); \
5049 UNSET_LOCK_HOLDER(); \
5050 (void)pthread_rwlock_unlock(&GC_allocate_ml); \
5051 }
5052# else
5053# define UNCOND_READER_LOCK() \
5054 (void)pthread_rwlock_rdlock(&GC_allocate_ml)
5055# define UNCOND_READER_UNLOCK() UNCOND_UNLOCK()
5056# define UNCOND_LOCK() (void)pthread_rwlock_wrlock(&GC_allocate_ml)
5057# define UNCOND_UNLOCK() (void)pthread_rwlock_unlock(&GC_allocate_ml)
5058# endif /* !GC_ASSERTIONS */
5059# else
5060GC_EXTERN pthread_mutex_t GC_allocate_ml;
5061# ifdef GC_ASSERTIONS
5062# define UNCOND_UNLOCK() \
5063 { \
5064 GC_ASSERT(I_HOLD_LOCK()); \
5065 UNSET_LOCK_HOLDER(); \
5066 pthread_mutex_unlock(&GC_allocate_ml); \
5067 }
5068# else
5069# if defined(NO_PTHREAD_TRYLOCK)
5070# define UNCOND_LOCK() pthread_mutex_lock(&GC_allocate_ml)
5071# else
5072GC_INNER void GC_lock(void);
5073# define UNCOND_LOCK() \
5074 { \
5075 if (pthread_mutex_trylock(&GC_allocate_ml) != 0) \
5076 GC_lock(); \
5077 }
5078# endif
5079# define UNCOND_UNLOCK() pthread_mutex_unlock(&GC_allocate_ml)
5080# endif /* !GC_ASSERTIONS */
5081# endif
5082# endif /* USE_PTHREAD_LOCKS */
5083# ifdef GC_ASSERTIONS
5084/* The allocator lock holder. */
5085# define SET_LOCK_HOLDER() \
5086 (void)(GC_lock_holder = NUMERIC_THREAD_ID(pthread_self()))
5087# define I_HOLD_LOCK() \
5088 (!GC_need_to_lock \
5089 || GC_lock_holder == NUMERIC_THREAD_ID(pthread_self()))
5090# if !defined(NUMERIC_THREAD_ID_UNIQUE) || defined(THREAD_SANITIZER)
5091# define I_DONT_HOLD_LOCK() TRUE /*< conservatively say yes */
5092# else
5093# define I_DONT_HOLD_LOCK() \
5094 (!GC_need_to_lock \
5095 || GC_lock_holder != NUMERIC_THREAD_ID(pthread_self()))
5096# endif
5097# endif /* GC_ASSERTIONS */
5098# if !defined(GC_WIN32_THREADS)
5099/*
5100 * A hint that we are in the collector and holding the allocator lock
5101 * for an extended period.
5102 */
5103GC_EXTERN volatile unsigned char GC_collecting;
5104
5105# ifdef AO_HAVE_char_store
5106# if defined(GC_ASSERTIONS) && defined(AO_HAVE_char_fetch_and_add1)
5107/* Ensure `ENTER_GC()` is not used recursively. */
5108# define ENTER_GC() GC_ASSERT(!AO_char_fetch_and_add1(&GC_collecting))
5109# else
5110# define ENTER_GC() AO_char_store(&GC_collecting, TRUE)
5111# endif
5112# define EXIT_GC() AO_char_store(&GC_collecting, FALSE)
5113# else
5114# define ENTER_GC() (void)(GC_collecting = TRUE)
5115# define EXIT_GC() (void)(GC_collecting = FALSE)
5116# endif
5117# endif
5118# endif /* GC_PTHREADS */
5119# if defined(GC_ALWAYS_MULTITHREADED) \
5120 && (defined(USE_PTHREAD_LOCKS) || defined(USE_SPIN_LOCK))
5121# define GC_need_to_lock TRUE
5122# define set_need_to_lock() (void)0
5123# else
5124# if defined(GC_ALWAYS_MULTITHREADED) && !defined(CPPCHECK)
5125# error Runtime initialization of the allocator lock is needed!
5126# endif
5127# undef GC_ALWAYS_MULTITHREADED
5128# ifdef THREAD_SANITIZER
5129/*
5130 * To workaround TSan false positive (e.g., when `GC_pthread_create()` is
5131 * called from multiple threads in parallel), do not set `GC_need_to_lock`
5132 * if it is already set.
5133 */
5134# define set_need_to_lock() \
5135 (void)(*(GC_bool volatile *)&GC_need_to_lock \
5136 ? FALSE \
5137 : (GC_need_to_lock = TRUE))
5138# else
5139# define set_need_to_lock() (void)(GC_need_to_lock = TRUE)
5140/* We are multi-threaded now. */
5141# endif
5142# endif
5143
5144EXTERN_C_END
5145
5146#else /* !THREADS */
5147# define LOCK() (void)0
5148# define UNLOCK() (void)0
5149# ifdef GC_ASSERTIONS
5150/*
5151 * `I_HOLD_LOCK()` and `I_DONT_HOLD_LOCK()` are used only in positive
5152 * assertions or to test whether we still need to acquire the allocator
5153 * lock; `TRUE` works in either case.
5154 */
5155# define I_HOLD_LOCK() TRUE
5156# define I_DONT_HOLD_LOCK() TRUE
5157# endif
5158#endif /* !THREADS */
5159
5160#if defined(UNCOND_LOCK) && !defined(LOCK)
5161# if (defined(LINT2) && defined(USE_PTHREAD_LOCKS)) \
5162 || defined(GC_ALWAYS_MULTITHREADED)
5163/*
5164 * Instruct code analysis tools not to care about `GC_need_to_lock`
5165 * influence to `LOCK`/`UNLOCK` semantic.
5166 */
5167# define LOCK() UNCOND_LOCK()
5168# define UNLOCK() UNCOND_UNLOCK()
5169# ifdef UNCOND_READER_LOCK
5170# define READER_LOCK() UNCOND_READER_LOCK()
5171# define READER_UNLOCK() UNCOND_READER_UNLOCK()
5172# endif
5173# else
5174/* At least two thread running; need to lock. */
5175# define LOCK() \
5176 do { \
5177 if (GC_need_to_lock) \
5178 UNCOND_LOCK(); \
5179 } while (0)
5180# define UNLOCK() \
5181 do { \
5182 if (GC_need_to_lock) \
5183 UNCOND_UNLOCK(); \
5184 } while (0)
5185# ifdef UNCOND_READER_LOCK
5186# define READER_LOCK() \
5187 do { \
5188 if (GC_need_to_lock) \
5189 UNCOND_READER_LOCK(); \
5190 } while (0)
5191# define READER_UNLOCK() \
5192 do { \
5193 if (GC_need_to_lock) \
5194 UNCOND_READER_UNLOCK(); \
5195 } while (0)
5196# endif
5197# endif
5198#endif /* UNCOND_LOCK && !LOCK */
5199
5200#ifdef READER_LOCK
5201# define HAS_REAL_READER_LOCK
5202/* TODO: Implement I_HOLD_READER_LOCK, conservatively say yes for now. */
5203# define I_HOLD_READER_LOCK() TRUE
5204#else
5205# define READER_LOCK() LOCK()
5206# define READER_UNLOCK() UNLOCK()
5207# ifdef GC_ASSERTIONS
5208/*
5209 * A macro to check that the allocator lock is held at least in the
5210 * reader mode.
5211 */
5212# define I_HOLD_READER_LOCK() I_HOLD_LOCK()
5213# endif
5214#endif /* !READER_LOCK */
5215
5216/*
5217 * A variant of `READER_UNLOCK()` which ensures that data written
5218 * before the unlock will be visible to the thread which acquires the
5219 * allocator lock in the exclusive mode. But according to some `rwlock`
5220 * documentation: writers synchronize with prior writers and readers.
5221 */
5222#define READER_UNLOCK_RELEASE() READER_UNLOCK()
5223
5224#ifndef ENTER_GC
5225# define ENTER_GC()
5226# define EXIT_GC()
5227#endif
5228
5229#endif /* GC_LOCKS_H */
5230
5231
5232#ifdef GC_ASSERTIONS
5233# define GC_ASSERT(e) \
5234 do { \
5235 if (UNLIKELY(!(e))) { \
5236 GC_err_printf("Assertion failure: %s:%d\n", __FILE__, __LINE__); \
5237 ABORT("assertion failure"); \
5238 } \
5239 } while (0)
5240#else
5241# define GC_ASSERT(e)
5242#endif
5243
5244#include "gc/gc_inline.h"
5245
5246/*
5247 * Prevent certain compiler warnings by making a pointer-related cast
5248 * through a "pointer-sized" numeric type.
5249 */
5250#define CAST_THRU_UINTPTR(t, x) ((t)(GC_uintptr_t)(x))
5251
5252#define CAST_AWAY_VOLATILE_PVOID(p) \
5253 CAST_THRU_UINTPTR(/* no volatile */ void *, p)
5254
5255/*
5256 * Convert an `unsigned` value to a `void` pointer. Typically used to
5257 * print a numeric value using "%p" format specifier. The pointer is not
5258 * supposed to be dereferenced.
5259 */
5260#define NUMERIC_TO_VPTR(v) ((void *)(GC_uintptr_t)(v))
5261
5262/* Create a `ptr_t` pointer from a number (of `word` type). */
5263#define MAKE_CPTR(w) ((ptr_t)(GC_uintptr_t)(word)(w))
5264
5265#define GC_WORD_MAX (~(word)0)
5266
5267/* Convert given pointer to its address. Result is of `word` type. */
5268#ifdef CHERI_PURECAP
5269# define ADDR(p) cheri_address_get(p)
5270#else
5271# define ADDR(p) ((word)(GC_uintptr_t)(p))
5272#endif
5273
5274#define ADDR_LT(p, q) GC_ADDR_LT(p, q)
5275#define ADDR_GE(p, q) (!ADDR_LT(p, q))
5276
5277/*
5278 * Check whether pointer `p` is in range [`s`, `e_p1`).
5279 * `p` should not have side effects.
5280 */
5281#define ADDR_INSIDE(p, s, e_p1) (ADDR_GE(p, s) && ADDR_LT(p, e_p1))
5282
5283/* Handy definitions to compare and adjust pointers in a stack. */
5284#ifdef STACK_GROWS_UP
5285# define HOTTER_THAN(p, q) ADDR_LT(q, p) /*< inverse */
5286# define MAKE_COOLER(p, d) \
5287 (void)((p) -= ADDR(p) > (word)((d) * sizeof(*(p))) ? (d) : 0)
5288# define MAKE_HOTTER(p, d) (void)((p) += (d))
5289#else
5290# define HOTTER_THAN(p, q) ADDR_LT(p, q)
5291# define MAKE_COOLER(p, d) \
5292 (void)((p) \
5293 += ADDR(p) <= (word)(GC_WORD_MAX - (d) * sizeof(*(p))) ? (d) : 0)
5294# define MAKE_HOTTER(p, d) (void)((p) -= (d))
5295#endif /* !STACK_GROWS_UP */
5296
5297/* Clear/set flags (given by a mask) in a pointer. */
5298#define CPTR_CLEAR_FLAGS(p, mask) \
5299 (ptr_t)((GC_uintptr_t)(p) & ~(GC_uintptr_t)(word)(mask))
5300#define CPTR_SET_FLAGS(p, mask) (ptr_t)((GC_uintptr_t)(p) | (word)(mask))
5301
5302/* Easily changeable parameters are below. */
5303
5304#ifdef ALL_INTERIOR_POINTERS
5305/*
5306 * Forces all pointers into the interior of an object to be considered valid.
5307 * Also causes the sizes of all objects to be inflated by at least one byte.
5308 * This should suffice to guarantee that in the presence of a compiler that
5309 * does not perform garbage-collector-unsafe optimizations, all portable,
5310 * strictly ANSI conforming C programs should be safely usable with `malloc`
5311 * replaced by `GC_malloc` and `free` calls removed. There are several
5312 * disadvantages:
5313 * 1. There are probably no interesting, portable, strictly ANSI-conforming
5314 * C programs;
5315 * 2. This option makes it hard for the collector to allocate space that is
5316 * not "pointed to" by integers, etc. (Under SunOS 4.x with a statically
5317 * linked `libc`, we empirically observed that it would be difficult to
5318 * allocate individual objects larger than 100 KB; even if only smaller
5319 * objects are allocated, more swap space is likely to be needed;
5320 * fortunately, much of this will never be touched.)
5321 *
5322 * If you can easily avoid using this option, do. If not, try to keep
5323 * individual objects small. This is really controlled at startup, through
5324 * `GC_all_interior_pointers` variable.
5325 */
5326#endif
5327
5328EXTERN_C_BEGIN
5329
5330#ifndef GC_NO_FINALIZATION
5331/*
5332 * If `GC_finalize_on_demand` is not set, invoke eligible finalizers.
5333 * Otherwise: call `(*GC_finalizer_notifier)()` if there are finalizers to
5334 * be run, and we have not called this procedure yet this collection cycle.
5335 */
5336GC_INNER void GC_notify_or_invoke_finalizers(void);
5337
5338/*
5339 * Perform all indicated finalization actions on unmarked objects.
5340 * Unreachable finalizable objects are enqueued for processing by
5341 * `GC_invoke_finalizers()`. Cause disappearing links to disappear
5342 * and unreachable objects to be enqueued for finalization.
5343 * Invoked with the allocator lock held but the world is running.
5344 */
5345GC_INNER void GC_finalize(void);
5346
5347# ifndef GC_TOGGLE_REFS_NOT_NEEDED
5348/* Process the "toggle-refs" before GC starts. */
5349GC_INNER void GC_process_togglerefs(void);
5350# endif
5351# ifndef SMALL_CONFIG
5352GC_INNER void GC_print_finalization_stats(void);
5353# endif
5354#else
5355# define GC_notify_or_invoke_finalizers() (void)0
5356#endif /* GC_NO_FINALIZATION */
5357
5358#if !defined(DONT_ADD_BYTE_AT_END)
5359# ifdef LINT2
5360/*
5361 * Explicitly instruct the code analysis tool that `GC_all_interior_pointers`
5362 * is assumed to have only value of 0 or 1.
5363 */
5364# define EXTRA_BYTES ((size_t)(GC_all_interior_pointers ? 1 : 0))
5365# else
5366# define EXTRA_BYTES ((size_t)GC_all_interior_pointers)
5367# endif
5368# define MAX_EXTRA_BYTES 1
5369#else
5370# define EXTRA_BYTES 0
5371# define MAX_EXTRA_BYTES 0
5372#endif
5373
5374#ifdef LARGE_CONFIG
5375# define MINHINCR 64
5376# define MAXHINCR 4096
5377#else
5378/*
5379 * Minimum heap increment, in blocks of `HBLKSIZE`. Note: must be multiple
5380 * of largest page size.
5381 */
5382# define MINHINCR 16
5383
5384/* Maximum heap increment, in blocks. */
5385# define MAXHINCR 2048
5386#endif /* !LARGE_CONFIG */
5387
5388/* Stack saving for debugging. */
5389
5390#ifdef NEED_CALLINFO
5391struct callinfo {
5392 GC_return_addr_t ci_pc; /*< `pc` of caller, not callee */
5393# if NARGS > 0
5394 GC_hidden_pointer ci_arg[NARGS]; /*< hide to avoid retention */
5395# endif
5396# if (NFRAMES * (NARGS + 1)) % 2 == 1
5397 /* Likely alignment problem. */
5398 ptr_t ci_dummy;
5399# endif
5400};
5401
5402# ifdef SAVE_CALL_CHAIN
5403/*
5404 * Fill in the `pc` and argument information for up to `NFRAMES` of
5405 * my callers. Ignore my frame and my callers frame.
5406 */
5407GC_INNER void GC_save_callers(struct callinfo info[NFRAMES]);
5408# endif
5409
5410/* Print `info` to `stderr`. We do not hold the allocator lock. */
5411GC_INNER void GC_print_callers(struct callinfo info[NFRAMES]);
5412#endif /* NEED_CALLINFO */
5413
5414EXTERN_C_END
5415
5416/*
5417 * Macros to ensure same formatting of C array/struct/union initializer
5418 * across multiple versions of clang-format.
5419 */
5420#define C_INITIALIZER_BEGIN {
5421#define C_INITIALIZER_END }
5422
5423/* OS interface routines. */
5424
5425#ifndef NO_CLOCK
5426# ifdef BSD_TIME
5427# undef CLOCK_TYPE
5428# undef GET_TIME
5429# undef MS_TIME_DIFF
5430# define CLOCK_TYPE struct timeval
5431# define CLOCK_TYPE_INITIALIZER C_INITIALIZER_BEGIN 0, 0 C_INITIALIZER_END
5432# define GET_TIME(x) \
5433 do { \
5434 struct rusage rusage; \
5435 getrusage(RUSAGE_SELF, &rusage); \
5436 x = rusage.ru_utime; \
5437 } while (0)
5438
5439/*
5440 * Compute time difference. `a` time is expected to be not earlier
5441 * than `b` one; the result has `unsigned long` type.
5442 */
5443# define MS_TIME_DIFF(a, b) \
5444 ((unsigned long)((long)(a.tv_sec - b.tv_sec) * 1000 \
5445 + (long)(a.tv_usec - b.tv_usec) / 1000 \
5446 - (a.tv_usec < b.tv_usec \
5447 && (long)(a.tv_usec - b.tv_usec) % 1000 \
5448 != 0 \
5449 ? 1 \
5450 : 0)))
5451
5452/*
5453 * The nanosecond part of the time difference. The total time difference
5454 * could be computed as:
5455 * `MS_TIME_DIFF(a, b) * 1000000 + NS_FRAC_TIME_DIFF(a, b)`.
5456 */
5457# define NS_FRAC_TIME_DIFF(a, b) \
5458 ((unsigned long)((a.tv_usec < b.tv_usec \
5459 && (long)(a.tv_usec - b.tv_usec) % 1000 != 0 \
5460 ? 1000L \
5461 : 0) \
5462 + (long)(a.tv_usec - b.tv_usec) % 1000) \
5463 * 1000)
5464
5465# elif defined(MSWIN32) || defined(MSWINCE) || defined(WINXP_USE_PERF_COUNTER)
5466# if defined(MSWINRT_FLAVOR) || defined(WINXP_USE_PERF_COUNTER)
5467# define CLOCK_TYPE ULONGLONG
5468/*
5469 * Note: two standalone `if` statements below are used to avoid MS VC
5470 * false warning (FP) about potentially uninitialized `tc` variable.
5471 */
5472# define GET_TIME(x) \
5473 do { \
5474 LARGE_INTEGER freq, tc; \
5475 if (!QueryPerformanceFrequency(&freq)) \
5476 ABORT("QueryPerformanceFrequency requires WinXP+"); \
5477 if (!QueryPerformanceCounter(&tc)) \
5478 ABORT("QueryPerformanceCounter failed"); \
5479 x = (CLOCK_TYPE)((double)tc.QuadPart / freq.QuadPart * 1e9); \
5480 /* TODO: Call QueryPerformanceFrequency once at GC init. */ \
5481 } while (0)
5482# define MS_TIME_DIFF(a, b) ((unsigned long)(((a) - (b)) / 1000000UL))
5483# define NS_FRAC_TIME_DIFF(a, b) \
5484 ((unsigned long)(((a) - (b)) % 1000000UL))
5485# else
5486# define CLOCK_TYPE DWORD
5487# define GET_TIME(x) (void)(x = GetTickCount())
5488# define MS_TIME_DIFF(a, b) ((unsigned long)((a) - (b)))
5489# define NS_FRAC_TIME_DIFF(a, b) 0UL
5490# endif /* !WINXP_USE_PERF_COUNTER */
5491
5492# elif defined(NN_PLATFORM_CTR)
5493# define CLOCK_TYPE long long
5494EXTERN_C_BEGIN
5495CLOCK_TYPE n3ds_get_system_tick(void);
5496CLOCK_TYPE n3ds_convert_tick_to_ms(CLOCK_TYPE tick);
5497EXTERN_C_END
5498# define GET_TIME(x) (void)(x = n3ds_get_system_tick())
5499# define MS_TIME_DIFF(a, b) \
5500 ((unsigned long)n3ds_convert_tick_to_ms((a) - (b)))
5501/* TODO: Implement NS_FRAC_TIME_DIFF(). */
5502# define NS_FRAC_TIME_DIFF(a, b) 0UL
5503
5504# elif defined(HAVE_CLOCK_GETTIME)
5505# include <time.h>
5506# define CLOCK_TYPE struct timespec
5507# define CLOCK_TYPE_INITIALIZER C_INITIALIZER_BEGIN 0, 0 C_INITIALIZER_END
5508# if defined(_POSIX_MONOTONIC_CLOCK) && !defined(NINTENDO_SWITCH)
5509# define GET_TIME(x) \
5510 do { \
5511 if (clock_gettime(CLOCK_MONOTONIC, &x) == -1) \
5512 ABORT("clock_gettime failed"); \
5513 } while (0)
5514# else
5515# define GET_TIME(x) \
5516 do { \
5517 if (clock_gettime(CLOCK_REALTIME, &x) == -1) \
5518 ABORT("clock_gettime failed"); \
5519 } while (0)
5520# endif
5521# define MS_TIME_DIFF(a, b) \
5522 /* `a.tv_nsec - b.tv_nsec` is in range -1e9 to 1e9, exclusively. */ \
5523 ((unsigned long)((a).tv_nsec + (1000000L * 1000 - (b).tv_nsec)) \
5524 / 1000000UL \
5525 + ((unsigned long)((a).tv_sec - (b).tv_sec) * 1000UL) - 1000UL)
5526# define NS_FRAC_TIME_DIFF(a, b) \
5527 ((unsigned long)((a).tv_nsec + (1000000L * 1000 - (b).tv_nsec)) \
5528 % 1000000UL)
5529
5530# else /* !BSD_TIME && !LINUX && !NN_PLATFORM_CTR && !MSWIN32 */
5531# include <time.h>
5532# if defined(FREEBSD) && !defined(CLOCKS_PER_SEC)
5533# include <machine/limits.h>
5534# define CLOCKS_PER_SEC CLK_TCK
5535# endif
5536# if !defined(CLOCKS_PER_SEC)
5537/*
5538 * This is technically a bug in the implementation.
5539 * ANSI requires that `CLOCKS_PER_SEC` be defined. But at least under
5540 * SunOS 4.1.1, it is not. Also note that the combination of ANSI C
5541 * and POSIX is incredibly gross here. The type `clock_t` is used by
5542 * both `clock()` and `times()`. But on some machines these use
5543 * different notions of a clock tick, `CLOCKS_PER_SEC` seems to apply
5544 * only to `clock()`. Hence we use it here. On many machines,
5545 * including SunOS, `clock()` actually uses units of microseconds (that
5546 * are not really clock ticks).
5547 */
5548# define CLOCKS_PER_SEC 1000000
5549# endif
5550# define CLOCK_TYPE clock_t
5551# define GET_TIME(x) (void)(x = clock())
5552# define MS_TIME_DIFF(a, b) \
5553 (CLOCKS_PER_SEC % 1000 == 0 \
5554 ? (unsigned long)((a) - (b)) \
5555 / (unsigned long)(CLOCKS_PER_SEC / 1000) \
5556 : ((unsigned long)((a) - (b)) * 1000) \
5557 / (unsigned long)CLOCKS_PER_SEC)
5558/*
5559 * Avoid using `double` type since some targets (like ARM) might
5560 * require `-lm` option for `double`-to-`long` conversion.
5561 */
5562# define NS_FRAC_TIME_DIFF(a, b) \
5563 (CLOCKS_PER_SEC <= 1000 \
5564 ? 0UL \
5565 : (unsigned long)(CLOCKS_PER_SEC <= (clock_t)1000000UL \
5566 ? (((a) - (b)) \
5567 * ((clock_t)1000000UL / CLOCKS_PER_SEC) \
5568 % 1000) \
5569 * 1000 \
5570 : (CLOCKS_PER_SEC \
5571 <= (clock_t)1000000UL * 1000 \
5572 ? ((a) - (b)) \
5573 * ((clock_t)1000000UL * 1000 \
5574 / CLOCKS_PER_SEC) \
5575 : (((a) - (b)) * (clock_t)1000000UL \
5576 * 1000) \
5577 / CLOCKS_PER_SEC) \
5578 % (clock_t)1000000UL))
5579# endif /* !BSD_TIME && !MSWIN32 */
5580# ifndef CLOCK_TYPE_INITIALIZER
5581/*
5582 * This is used to initialize `CLOCK_TYPE` variables (to some value)
5583 * to avoid "variable might be uninitialized" compiler warnings.
5584 */
5585# define CLOCK_TYPE_INITIALIZER 0
5586# endif
5587#endif /* !NO_CLOCK */
5588
5589/* We use `bzero()` and `bcopy()` internally. They may not be available. */
5590#if defined(M68K) && defined(NEXT) || defined(VAX)
5591# define BCOPY_EXISTS
5592#elif defined(DARWIN)
5593# include <string.h>
5594# define BCOPY_EXISTS
5595#endif
5596
5597#if !defined(BCOPY_EXISTS) || defined(CPPCHECK)
5598# include <string.h>
5599# define BCOPY(x, y, n) memcpy(y, x, (size_t)(n))
5600# define BZERO(x, n) memset(x, 0, (size_t)(n))
5601#else
5602# define BCOPY(x, y, n) bcopy((void *)(x), (void *)(y), (size_t)(n))
5603# define BZERO(x, n) bzero((void *)(x), (size_t)(n))
5604#endif
5605
5606EXTERN_C_BEGIN
5607
5608#if defined(CPPCHECK) && defined(ANY_MSWIN)
5609# undef TEXT
5610# ifdef UNICODE
5611# define TEXT(s) L##s
5612# else
5613# define TEXT(s) s
5614# endif
5615#endif /* CPPCHECK && ANY_MSWIN */
5616
5617/* Stop and restart mutator threads. */
5618#if defined(NN_PLATFORM_CTR) || defined(NINTENDO_SWITCH) \
5619 || defined(GC_WIN32_THREADS) || defined(GC_PTHREADS)
5620GC_INNER void GC_stop_world(void);
5621GC_INNER void GC_start_world(void);
5622# define STOP_WORLD() GC_stop_world()
5623# define START_WORLD() GC_start_world()
5624#else
5625/* Just do a sanity check: we are not inside `GC_do_blocking()`. */
5626# define STOP_WORLD() GC_ASSERT(GC_blocked_sp == NULL)
5627# define START_WORLD()
5628#endif
5629
5630/* Abandon ship. */
5631#ifdef SMALL_CONFIG
5632# define GC_on_abort(msg) (void)0 /*< be silent on abort */
5633#else
5634GC_API_PRIV GC_abort_func GC_on_abort;
5635#endif
5636#if defined(CPPCHECK)
5637# define ABORT(msg) \
5638 { \
5639 GC_on_abort(msg); \
5640 abort(); \
5641 }
5642#else
5643# if defined(MSWIN_XBOX1) && !defined(DebugBreak)
5644# define DebugBreak() __debugbreak()
5645# elif defined(MSWINCE) && !defined(DebugBreak) \
5646 && (!defined(UNDER_CE) || (defined(__MINGW32CE__) && !defined(ARM32)))
5647/*
5648 * This simplifies linking for WinCE (and, probably, does not
5649 * hurt debugging much); use `-D DebugBreak=DebugBreak` to override
5650 * this behavior if really needed. This is also a workaround for
5651 * x86mingw32ce toolchain (if it is still declaring `DebugBreak()`
5652 * instead of defining it as a macro).
5653 */
5654# define DebugBreak() _exit(-1) /*< there is no `abort()` in WinCE */
5655# endif
5656# if defined(MSWIN32) && (defined(NO_DEBUGGING) || defined(LINT2))
5657/*
5658 * A more user-friendly abort after showing fatal message.
5659 * Exit on error without running "at-exit" callbacks.
5660 */
5661# define ABORT(msg) (GC_on_abort(msg), _exit(-1))
5662# elif defined(MSWINCE) && defined(NO_DEBUGGING)
5663# define ABORT(msg) (GC_on_abort(msg), ExitProcess(-1))
5664# elif defined(MSWIN32) || defined(MSWINCE)
5665# if defined(_CrtDbgBreak) && defined(_DEBUG) && defined(_MSC_VER)
5666# define ABORT(msg) \
5667 { \
5668 GC_on_abort(msg); \
5669 _CrtDbgBreak() /*< `__debugbreak()` */; \
5670 }
5671# else
5672# define ABORT(msg) \
5673 { \
5674 GC_on_abort(msg); \
5675 DebugBreak(); \
5676 }
5677/*
5678 * Note: on a WinCE box, this could be silently ignored (i.e., the program
5679 * is not aborted); `DebugBreak()` is a statement in some toolchains.
5680 */
5681# endif
5682# else /* !MSWIN32 */
5683# define ABORT(msg) (GC_on_abort(msg), abort())
5684# endif
5685#endif /* !CPPCHECK */
5686
5687/*
5688 * For the abort message with 1 .. 3 arguments. `C_msg` and `C_fmt`
5689 * should be literals. `C_msg` should not contain format specifiers.
5690 * Arguments should match their format specifiers.
5691 */
5692#define ABORT_ARG1(C_msg, C_fmt, arg1) \
5693 MACRO_BLKSTMT_BEGIN \
5694 GC_ERRINFO_PRINTF(C_msg /* + */ C_fmt "\n", arg1); \
5695 ABORT(C_msg); \
5696 MACRO_BLKSTMT_END
5697#define ABORT_ARG2(C_msg, C_fmt, arg1, arg2) \
5698 MACRO_BLKSTMT_BEGIN \
5699 GC_ERRINFO_PRINTF(C_msg /* + */ C_fmt "\n", arg1, arg2); \
5700 ABORT(C_msg); \
5701 MACRO_BLKSTMT_END
5702#define ABORT_ARG3(C_msg, C_fmt, arg1, arg2, arg3) \
5703 MACRO_BLKSTMT_BEGIN \
5704 GC_ERRINFO_PRINTF(C_msg /* + */ C_fmt "\n", arg1, arg2, arg3); \
5705 ABORT(C_msg); \
5706 MACRO_BLKSTMT_END
5707
5708/*
5709 * Same as `ABORT` but does not have a `noreturn` attribute.
5710 * I.e. `ABORT` on a dummy condition (which is always true).
5711 */
5712#define ABORT_RET(msg) \
5713 if ((GC_funcptr_uint)GC_current_warn_proc == ~(GC_funcptr_uint)0) { \
5714 } else \
5715 ABORT(msg)
5716
5717/* Exit process abnormally, but without making a mess (e.g. out of memory). */
5718#define EXIT() (GC_on_abort(NULL), exit(1 /* `EXIT_FAILURE` */))
5719
5720/*
5721 * Print warning message, e.g. almost out of memory. The argument (if any)
5722 * format specifier should be: "%s", "%p", "%"`WARN_PRIdPTR` or
5723 * "%"`WARN_PRIuPTR`.
5724 */
5725#define WARN(msg, arg) \
5726 GC_current_warn_proc("GC Warning: " msg, (GC_uintptr_t)(arg))
5727GC_EXTERN GC_warn_proc GC_current_warn_proc;
5728
5729/*
5730 * Print format type macro for decimal `GC_signed_word` value passed to
5731 * `WARN()`. This could be redefined for Win64 or LLP64, but typically
5732 * should not be done as the `WARN` format string is, possibly,
5733 * processed on the client side, so non-standard print type modifiers
5734 * (like MS "I64d") should be avoided here if possible.
5735 * TODO: Assuming `sizeof(void *)` is equal to `sizeof(long)` or this
5736 * is a little-endian machine.
5737 */
5738#ifndef WARN_PRIdPTR
5739# define WARN_PRIdPTR "ld"
5740# define WARN_PRIuPTR "lu"
5741#endif
5742
5743/*
5744 * A tagging macro (for a code static analyzer) to indicate that the
5745 * string obtained from an untrusted source (e.g., `argv[]`, `getenv`)
5746 * is safe to use in a vulnerable operation (e.g., `open`, `exec`).
5747 */
5748#define TRUSTED_STRING(s) COVERT_DATAFLOW_P(s)
5749
5750#ifdef GC_READ_ENV_FILE
5751/*
5752 * This routine scans `GC_envfile_content` for the specified environment
5753 * variable (and returns its value if found).
5754 */
5755GC_INNER char *GC_envfile_getenv(const char *name);
5756
5757/* Get the process environment entry. */
5758# define GETENV(name) GC_envfile_getenv(name)
5759#elif defined(NO_GETENV) && !defined(CPPCHECK)
5760# define GETENV(name) NULL
5761#elif defined(EMPTY_GETENV_RESULTS) && !defined(CPPCHECK)
5762/* Workaround for a reputed Wine bug. */
5763GC_INLINE char *
5764fixed_getenv(const char *name)
5765{
5766 char *value = getenv(name);
5767 return value != NULL && *value != '\0' ? value : NULL;
5768}
5769# define GETENV(name) fixed_getenv(name)
5770#else
5771# define GETENV(name) getenv(name)
5772#endif
5773
5774EXTERN_C_END
5775
5776#if defined(DARWIN)
5777# include <mach/thread_status.h>
5778# ifndef MAC_OS_X_VERSION_MAX_ALLOWED
5779/* Include this header just to import the above macro. */
5780# include <AvailabilityMacros.h>
5781# endif
5782# if defined(POWERPC)
5783# if CPP_WORDSZ == 32
5784# define GC_THREAD_STATE_T ppc_thread_state_t
5785# else
5786# define GC_THREAD_STATE_T ppc_thread_state64_t
5787# define GC_MACH_THREAD_STATE PPC_THREAD_STATE64
5788# define GC_MACH_THREAD_STATE_COUNT PPC_THREAD_STATE64_COUNT
5789# endif
5790# elif defined(I386) || defined(X86_64)
5791# if CPP_WORDSZ == 32
5792# if defined(i386_THREAD_STATE_COUNT) \
5793 && !defined(x86_THREAD_STATE32_COUNT)
5794/* Use old naming convention for i686. */
5795# define GC_THREAD_STATE_T i386_thread_state_t
5796# define GC_MACH_THREAD_STATE i386_THREAD_STATE
5797# define GC_MACH_THREAD_STATE_COUNT i386_THREAD_STATE_COUNT
5798# else
5799# define GC_THREAD_STATE_T x86_thread_state32_t
5800# define GC_MACH_THREAD_STATE x86_THREAD_STATE32
5801# define GC_MACH_THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT
5802# endif
5803# else
5804# define GC_THREAD_STATE_T x86_thread_state64_t
5805# define GC_MACH_THREAD_STATE x86_THREAD_STATE64
5806# define GC_MACH_THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT
5807# endif
5808# elif defined(ARM32) && defined(ARM_UNIFIED_THREAD_STATE) \
5809 && !defined(CPPCHECK)
5810# define GC_THREAD_STATE_T arm_unified_thread_state_t
5811# define GC_MACH_THREAD_STATE ARM_UNIFIED_THREAD_STATE
5812# define GC_MACH_THREAD_STATE_COUNT ARM_UNIFIED_THREAD_STATE_COUNT
5813# elif defined(ARM32)
5814# define GC_THREAD_STATE_T arm_thread_state_t
5815# ifdef ARM_MACHINE_THREAD_STATE_COUNT
5816# define GC_MACH_THREAD_STATE ARM_MACHINE_THREAD_STATE
5817# define GC_MACH_THREAD_STATE_COUNT ARM_MACHINE_THREAD_STATE_COUNT
5818# endif
5819# elif defined(AARCH64)
5820# define GC_THREAD_STATE_T arm_thread_state64_t
5821# define GC_MACH_THREAD_STATE ARM_THREAD_STATE64
5822# define GC_MACH_THREAD_STATE_COUNT ARM_THREAD_STATE64_COUNT
5823# elif !defined(CPPCHECK)
5824# error define GC_THREAD_STATE_T
5825# endif
5826# ifndef GC_MACH_THREAD_STATE
5827# define GC_MACH_THREAD_STATE MACHINE_THREAD_STATE
5828# define GC_MACH_THREAD_STATE_COUNT MACHINE_THREAD_STATE_COUNT
5829# endif
5830
5831/*
5832 * Try to work out the right way to access thread state structure members.
5833 * The structure has different definition in different Darwin versions.
5834 * This now defaults to the (older) names without `__`, thus hopefully
5835 * not breaking any existing `Makefile.direct` builds.
5836 */
5837# if __DARWIN_UNIX03
5838# define THREAD_FLD_NAME(x) __##x
5839# else
5840# define THREAD_FLD_NAME(x) x
5841# endif
5842# if defined(ARM32) && defined(ARM_UNIFIED_THREAD_STATE)
5843# define THREAD_FLD(x) ts_32.THREAD_FLD_NAME(x)
5844# else
5845# define THREAD_FLD(x) THREAD_FLD_NAME(x)
5846# endif
5847#endif /* DARWIN */
5848
5849#ifndef WASI
5850# include <setjmp.h>
5851#endif
5852
5853#include <stdio.h>
5854
5855#if defined(CAN_HANDLE_FORK) && defined(GC_PTHREADS)
5856# include <pthread.h> /*< for `pthread_t` */
5857#endif
5858
5859#if __STDC_VERSION__ >= 201112L
5860# include <assert.h> /*< for `static_assert` */
5861#endif
5862
5863EXTERN_C_BEGIN
5864
5865/* Definitions depending on `word` size. */
5866
5867#define modWORDSZ(n) ((n) & (CPP_WORDSZ - 1)) /*< `n mod size_of_word` */
5868#define divWORDSZ(n) ((n) / CPP_WORDSZ)
5869
5870#define SIGNB ((word)1 << (CPP_WORDSZ - 1))
5871#define SIZET_SIGNB (GC_SIZE_MAX ^ (GC_SIZE_MAX >> 1))
5872
5873#if CPP_PTRSZ / 8 != ALIGNMENT
5874# define UNALIGNED_PTRS
5875#endif
5876
5877#define BYTES_TO_GRANULES(lb) ((lb) / GC_GRANULE_BYTES)
5878#define GRANULES_TO_BYTES(lg) (GC_GRANULE_BYTES * (lg))
5879#define BYTES_TO_PTRS(lb) ((lb) / sizeof(ptr_t))
5880#define PTRS_TO_BYTES(lpw) ((lpw) * sizeof(ptr_t))
5881#define GRANULES_TO_PTRS(lg) (GC_GRANULE_PTRS * (lg))
5882
5883/*
5884 * Convert size in bytes to that in pointers rounding up (but not adding
5885 * extra byte at end).
5886 */
5887#define BYTES_TO_PTRS_ROUNDUP(lb) BYTES_TO_PTRS((lb) + sizeof(ptr_t) - 1)
5888
5889/* Size parameters. */
5890
5891/*
5892 * Heap block size, in bytes. Should be a power of two.
5893 * Incremental collection with `MPROTECT_VDB` currently requires the
5894 * page size to be a multiple of `HBLKSIZE`. Since most modern
5895 * architectures support variable page sizes down to 4 KB, and i686 and
5896 * x86_64 are generally 4 KB, we now default to 4 KB, except for:
5897 * - Alpha: seems to be used with 8 KB pages;
5898 * - `SMALL_CONFIG`: want less block-level fragmentation.
5899 */
5900#ifndef HBLKSIZE
5901# if defined(SMALL_CONFIG) && !defined(LARGE_CONFIG)
5902# define CPP_LOG_HBLKSIZE 10
5903# elif defined(ALPHA)
5904# define CPP_LOG_HBLKSIZE 13
5905# else
5906# define CPP_LOG_HBLKSIZE 12
5907# endif
5908#else
5909# if HBLKSIZE == 512
5910# define CPP_LOG_HBLKSIZE 9
5911# elif HBLKSIZE == 1024
5912# define CPP_LOG_HBLKSIZE 10
5913# elif HBLKSIZE == 2048
5914# define CPP_LOG_HBLKSIZE 11
5915# elif HBLKSIZE == 4096
5916# define CPP_LOG_HBLKSIZE 12
5917# elif HBLKSIZE == 8192
5918# define CPP_LOG_HBLKSIZE 13
5919# elif HBLKSIZE == 16384
5920# define CPP_LOG_HBLKSIZE 14
5921# elif HBLKSIZE == 32768
5922# define CPP_LOG_HBLKSIZE 15
5923# elif HBLKSIZE == 65536
5924# define CPP_LOG_HBLKSIZE 16
5925# elif !defined(CPPCHECK)
5926# error Bad HBLKSIZE value
5927# endif
5928# undef HBLKSIZE
5929#endif
5930
5931#define LOG_HBLKSIZE ((size_t)CPP_LOG_HBLKSIZE)
5932#define HBLKSIZE ((size_t)1 << CPP_LOG_HBLKSIZE)
5933
5934#define GC_SQRT_SIZE_MAX ((((size_t)1) << (sizeof(size_t) * 8 / 2)) - 1)
5935
5936/*
5937 * Maximum size of objects supported by free list (larger objects are
5938 * allocated directly with `GC_alloc_large()`, by rounding to the next
5939 * multiple of `HBLKSIZE`).
5940 */
5941#define MAXOBJBYTES (HBLKSIZE >> 1)
5942#define MAXOBJGRANULES BYTES_TO_GRANULES(MAXOBJBYTES)
5943
5944#define divHBLKSZ(n) ((n) >> LOG_HBLKSIZE)
5945
5946/*
5947 * Equivalent to subtracting one `hblk` pointer from another. We do it
5948 * this way because a compiler should find it hard to use an integer
5949 * division instead of a shift. The bundled SunOS 4.1 otherwise sometimes
5950 * pessimizes the subtraction to involve a call to `.div`.
5951 */
5952#define HBLK_PTR_DIFF(p, q) divHBLKSZ((ptr_t)p - (ptr_t)q)
5953
5954#define modHBLKSZ(n) ((n) & (HBLKSIZE - 1))
5955
5956#define HBLKPTR(objptr) \
5957 ((struct hblk *)PTR_ALIGN_DOWN((ptr_t)(objptr), HBLKSIZE))
5958#define HBLKDISPL(objptr) modHBLKSZ((size_t)ADDR(objptr))
5959
5960/* Same as `HBLKPTR` but points to the first block in the page. */
5961#define HBLK_PAGE_ALIGNED(objptr) \
5962 ((struct hblk *)PTR_ALIGN_DOWN((ptr_t)(objptr), GC_page_size))
5963
5964/* Round up allocation size (in bytes) to a multiple of a granule. */
5965#define ROUNDUP_GRANULE_SIZE(lb) /*< `lb` should have no side-effect */ \
5966 (SIZET_SAT_ADD(lb, GC_GRANULE_BYTES - 1) & ~(size_t)(GC_GRANULE_BYTES - 1))
5967
5968/*
5969 * Round up byte allocation request (after adding `EXTRA_BYTES`) to
5970 * a multiple of a granule, then convert it to granules.
5971 */
5972#define ALLOC_REQUEST_GRANS(lb) /*< `lb` should have no side-effect */ \
5973 BYTES_TO_GRANULES(SIZET_SAT_ADD(lb, GC_GRANULE_BYTES - 1 + EXTRA_BYTES))
5974
5975#if MAX_EXTRA_BYTES == 0
5976# define ADD_EXTRA_BYTES(lb) (lb)
5977# define SMALL_OBJ(lb) LIKELY((lb) <= MAXOBJBYTES)
5978#else
5979# define ADD_EXTRA_BYTES(lb) /*< `lb` should have no side-effect */ \
5980 SIZET_SAT_ADD(lb, EXTRA_BYTES)
5981
5982/*
5983 * This really just tests that `lb` is not greater than
5984 * `MAXOBJBYTES - EXTRA_BYTES`, but we try to avoid looking up `EXTRA_BYTES`.
5985 */
5986# define SMALL_OBJ(lb) /*< `lb` should have no side-effect */ \
5987 (LIKELY((lb) <= MAXOBJBYTES - MAX_EXTRA_BYTES) \
5988 || (lb) <= MAXOBJBYTES - EXTRA_BYTES)
5989#endif
5990
5991/*
5992 * Hash table representation of sets of pages. Implements a map from
5993 * `HBLKSIZE`-aligned chunks of the address space to one bit each.
5994 * This assumes it is OK to spuriously set bits, e.g. because multiple
5995 * addresses are represented by a single location. Used by
5996 * black-listing code, and perhaps by dirty bit maintenance code.
5997 */
5998#ifndef LOG_PHT_ENTRIES
5999# ifdef LARGE_CONFIG
6000# if CPP_WORDSZ == 32
6001/*
6002 * Collisions are impossible (because of a 4 GB space limit).
6003 * Each table takes 128 KB, some of which may never be touched.
6004 */
6005# define LOG_PHT_ENTRIES 20
6006# else
6007/*
6008 * Collisions likely at 2M blocks, which is greater than 8 GB.
6009 * Each table takes 256 KB, some of which may never be touched.
6010 */
6011# define LOG_PHT_ENTRIES 21
6012# endif
6013# elif !defined(SMALL_CONFIG)
6014/*
6015 * Collisions are likely if heap grows to more than 256K blocks,
6016 * which is greater than 1 GB. Each hash table occupies 32 KB.
6017 * Even for somewhat smaller heaps, say half of that, collisions may
6018 * be an issue because we blacklist addresses outside the heap.
6019 */
6020# define LOG_PHT_ENTRIES 18
6021# else
6022/*
6023 * Collisions are likely if heap grows to more than 32K blocks,
6024 * which is 128 MB. Each hash table occupies 4 KB.
6025 */
6026# define LOG_PHT_ENTRIES 15
6027# endif
6028#endif /* !LOG_PHT_ENTRIES */
6029
6030#define PHT_ENTRIES (1 << LOG_PHT_ENTRIES)
6031#define PHT_SIZE (PHT_ENTRIES > CPP_WORDSZ ? PHT_ENTRIES / CPP_WORDSZ : 1)
6032typedef word page_hash_table[PHT_SIZE];
6033
6034#define PHT_HASH(p) ((size_t)((ADDR(p) >> LOG_HBLKSIZE) & (PHT_ENTRIES - 1)))
6035
6036#define get_pht_entry_from_index(bl, index) \
6037 (((bl)[divWORDSZ(index)] >> modWORDSZ(index)) & 1)
6038#define set_pht_entry_from_index(bl, index) \
6039 (void)((bl)[divWORDSZ(index)] |= (word)1 << modWORDSZ(index))
6040
6041#if defined(THREADS) && defined(AO_HAVE_or)
6042/*
6043 * And, one more variant for `GC_add_to_black_list_normal` and
6044 *`GC_add_to_black_list_stack` (invoked indirectly by `GC_do_local_mark()`)
6045 * and `async_set_pht_entry_from_index()` (invoked by `GC_dirty()` or the
6046 * write fault handler).
6047 */
6048# define set_pht_entry_from_index_concurrent(bl, index) \
6049 AO_or((volatile AO_t *)&(bl)[divWORDSZ(index)], \
6050 (AO_t)1 << modWORDSZ(index))
6051# ifdef MPROTECT_VDB
6052# define set_pht_entry_from_index_concurrent_volatile(bl, index) \
6053 set_pht_entry_from_index_concurrent(bl, index)
6054# endif
6055#else
6056# define set_pht_entry_from_index_concurrent(bl, index) \
6057 set_pht_entry_from_index(bl, index)
6058# ifdef MPROTECT_VDB
6059/*
6060 * Same as `set_pht_entry_from_index` but avoiding the compound assignment
6061 * for a `volatile` array.
6062 */
6063# define set_pht_entry_from_index_concurrent_volatile(bl, index) \
6064 (void)((bl)[divWORDSZ(index)] \
6065 = (bl)[divWORDSZ(index)] | ((word)1 << modWORDSZ(index)))
6066# endif
6067#endif
6068
6069/* Heap blocks. */
6070
6071/*
6072 * The upper bound. We allocate 1 bit per allocation granule.
6073 * If `MARK_BIT_PER_OBJ` is not defined, we use every `n`-th bit, where
6074 * `n` is the number of allocation granules per object. Otherwise, we only
6075 * use the initial group of mark bits, and it is safe to allocate smaller
6076 * header for large objects.
6077 */
6078#define MARK_BITS_PER_HBLK (HBLKSIZE / GC_GRANULE_BYTES)
6079
6080#ifndef MARK_BIT_PER_OBJ
6081/*
6082 * We maintain layout maps for heap blocks containing objects of
6083 * a given size. Each entry in this map describes a byte offset
6084 * (displacement) and has the following type.
6085 */
6086# if (1 << (CPP_LOG_HBLKSIZE - 1)) / GC_GRANULE_BYTES <= 0x100
6087typedef unsigned char hb_map_entry_t;
6088# else
6089typedef unsigned short hb_map_entry_t;
6090# endif
6091#endif /* !MARK_BIT_PER_OBJ */
6092
6093struct hblkhdr {
6094 /*
6095 * Link field for `hblk` free list and for lists of chunks waiting to
6096 * be reclaimed.
6097 */
6098 struct hblk *hb_next;
6099
6100 struct hblk *hb_prev; /*< backwards link for free list */
6101
6102 struct hblk *hb_block; /*< the corresponding block */
6103
6104 /*
6105 * Kind of objects in the block. Each kind identifies a mark
6106 * procedure and a set of list headers. Sometimes called regions.
6107 */
6108 unsigned char hb_obj_kind;
6109
6110 unsigned char hb_flags;
6111
6112 /* Ignore pointers that do not point to the first `hblk` of this object. */
6113#define IGNORE_OFF_PAGE 1
6114
6115 /*
6116 * This is a free block, which has been unmapped from the address space.
6117 * `GC_remap()` must be invoked on it before it can be reallocated.
6118 * Set only if `USE_MUNMAP` macro is defined.
6119 */
6120#define WAS_UNMAPPED 2
6121
6122 /* Block is free, i.e. not in use. */
6123#define FREE_BLK 4
6124
6125#ifdef ENABLE_DISCLAIM
6126 /* This kind has a callback on reclaim. */
6127# define HAS_DISCLAIM 8
6128
6129 /*
6130 * Mark from all objects, marked or not. Used to mark objects needed
6131 * by reclaim notifier.
6132 */
6133# define MARK_UNCONDITIONALLY 0x10
6134#endif
6135
6136#ifndef MARK_BIT_PER_OBJ
6137# define LARGE_BLOCK 0x20
6138#endif
6139
6140 /*
6141 * Value of `GC_gc_no` when block was last allocated or swept.
6142 * May wrap. For a free block, this is maintained only for `USE_MUNMAP`,
6143 * and indicates when the header was allocated, or when the size of the
6144 * block last changed.
6145 */
6146 unsigned short hb_last_reclaimed;
6147
6148#ifdef MARK_BIT_PER_OBJ
6149# define LARGE_INV_SZ ((unsigned32)1 << 16)
6150
6151 /*
6152 * A good upper bound for `2**32 / hb_sz`.
6153 * For large objects, we use `LARGE_INV_SZ`.
6154 */
6155 unsigned32 hb_inv_sz;
6156#endif
6157
6158 /*
6159 * If in use, size in bytes, of objects in the block.
6160 * Otherwise, the size of the whole free block. We assume that this is
6161 * convertible to `GC_signed_word` without generating a negative result.
6162 * We avoid generating free blocks larger than that.
6163 */
6164 size_t hb_sz;
6165
6166 /* Object descriptor for marking. See `gc_mark.h` file. */
6167 word hb_descr;
6168
6169#ifndef MARK_BIT_PER_OBJ
6170 /*
6171 * A table of remainders `mod BYTES_TO_GRANULES(hb_sz)` essentially,
6172 * except for large blocks. See `GC_obj_map`.
6173 */
6174 hb_map_entry_t *hb_map;
6175#endif
6176
6177#ifdef PARALLEL_MARK
6178 /*
6179 * Number of set mark bits, excluding the one always set at the end.
6180 * Currently it is updated concurrently and hence only approximate.
6181 * But a zero value does guarantee that the block contains
6182 * no marked objects. Ensuring this property means that we never
6183 * decrement it to zero during a collection, and hence the count may
6184 * be one too high. Due to concurrent updates, an arbitrary number
6185 * of increments, but not all of them (!) may be lost, hence it may,
6186 * in theory, be much too low. The count may also be too high
6187 * if multiple mark threads mark the same object due to a race.
6188 */
6189 volatile AO_t hb_n_marks;
6190#else
6191 /* Without parallel marking, the count is accurate. */
6192 size_t hb_n_marks;
6193#endif
6194
6195#ifdef USE_MARK_BYTES
6196 /*
6197 * Unlike the other case, this is in units of bytes. Since we force
6198 * certain alignment, we need at most one mark bit per a granule.
6199 * But we do allocate and set one extra mark bit to avoid
6200 * an explicit check for the partial object at the end of each block.
6201 */
6202# define HB_MARKS_SZ (MARK_BITS_PER_HBLK + 1)
6203 union {
6204 /*
6205 * The `i`-th byte is 1 if the object starting at granule `i`
6206 * or object `i` is marked, 0 otherwise. The mark bit for the
6207 * "one past the end" object is always set to avoid a special case
6208 * test in the marker.
6209 */
6210 char _hb_marks[HB_MARKS_SZ];
6211 word dummy; /*< force word alignment of mark bytes */
6212 } _mark_byte_union;
6213# define hb_marks _mark_byte_union._hb_marks
6214#else
6215# define HB_MARKS_SZ (MARK_BITS_PER_HBLK / CPP_WORDSZ + 1)
6216
6217# if defined(PARALLEL_MARK) || (defined(THREAD_SANITIZER) && defined(THREADS))
6218 volatile AO_t hb_marks[HB_MARKS_SZ];
6219# else
6220 word hb_marks[HB_MARKS_SZ];
6221# endif
6222#endif /* !USE_MARK_BYTES */
6223};
6224
6225/* A "random" mark bit index for assertions. */
6226#define ANY_INDEX 23
6227
6228/* Heap block body. */
6229
6230#define HBLK_WORDS (HBLKSIZE / sizeof(word))
6231#define HBLK_GRANULES (HBLKSIZE / GC_GRANULE_BYTES)
6232
6233/*
6234 * The number of objects in a block dedicated to a certain size.
6235 * May erroneously yield zero (instead of one) for large objects.
6236 */
6237#define HBLK_OBJS(sz_in_bytes) (HBLKSIZE / (sz_in_bytes))
6238
6239struct hblk {
6240 char hb_body[HBLKSIZE];
6241};
6242
6243#define HBLK_IS_FREE(hhdr) (((hhdr)->hb_flags & FREE_BLK) != 0)
6244
6245#define OBJ_SZ_TO_BLOCKS(lb) divHBLKSZ((lb) + HBLKSIZE - 1)
6246
6247/*
6248 * Size of block (in units of `HBLKSIZE`) needed to hold objects of
6249 * given `lb` (in bytes). The checked variant prevents wrap around.
6250 */
6251#define OBJ_SZ_TO_BLOCKS_CHECKED(lb) /*< `lb` should have no side-effect */ \
6252 divHBLKSZ(SIZET_SAT_ADD(lb, HBLKSIZE - 1))
6253
6254/* The object free-list link. */
6255#define obj_link(p) (*(void **)(p))
6256
6257/*
6258 * Root sets. Logically private to `mark_rts.c` file. But we do not
6259 * want the tables scanned, so we put them here.
6260 */
6261
6262/* The maximum number of ranges that can be registered as static roots. */
6263#ifdef LARGE_CONFIG
6264# define MAX_ROOT_SETS 8192
6265#elif !defined(SMALL_CONFIG)
6266# define MAX_ROOT_SETS 2048
6267#else
6268# define MAX_ROOT_SETS 512
6269#endif
6270
6271/* Maximum number of segments that can be excluded from root sets. */
6272#define MAX_EXCLUSIONS (MAX_ROOT_SETS / 4)
6273
6274/* A data structure for excluded static roots. */
6275struct exclusion {
6276 ptr_t e_start;
6277 ptr_t e_end;
6278};
6279
6280/*
6281 * A data structure for list of root sets. We keep a hash table, so that
6282 * we can filter out duplicate additions. Under Win32, we need to do
6283 * a better job of filtering overlaps, so we resort to sequential search,
6284 * and pay the price.
6285 */
6286struct roots {
6287 ptr_t r_start; /*< multiple of pointer size */
6288 ptr_t r_end; /*< multiple of pointer size and greater than `r_start` */
6289#ifndef ANY_MSWIN
6290 struct roots *r_next;
6291#endif
6292 /* Delete before registering new dynamic libraries if set. */
6293 GC_bool r_tmp;
6294};
6295
6296#ifndef ANY_MSWIN
6297/* Size of hash table index to roots. */
6298# define LOG_RT_SIZE 6
6299
6300/* `RT_SIZE` should be a power of 2, may be not equal to `MAX_ROOT_SETS`. */
6301# define RT_SIZE (1 << LOG_RT_SIZE)
6302#endif
6303
6304#if (!defined(MAX_HEAP_SECTS) || defined(CPPCHECK)) \
6305 && (defined(ANY_MSWIN) || defined(USE_PROC_FOR_LIBRARIES))
6306# ifdef LARGE_CONFIG
6307# if CPP_WORDSZ > 32
6308# define MAX_HEAP_SECTS 81920
6309# else
6310# define MAX_HEAP_SECTS 7680
6311# endif
6312# elif defined(SMALL_CONFIG) && !defined(USE_PROC_FOR_LIBRARIES)
6313# if defined(PARALLEL_MARK) && (defined(MSWIN32) || defined(CYGWIN32))
6314# define MAX_HEAP_SECTS 384
6315# else
6316# define MAX_HEAP_SECTS 128 /*< roughly 256 MB (`128 * 2048 * 1024`) */
6317# endif
6318# elif CPP_WORDSZ > 32
6319# define MAX_HEAP_SECTS 1024 /*< roughly 8 GB */
6320# else
6321# define MAX_HEAP_SECTS 512 /*< roughly 4 GB */
6322# endif
6323#endif /* !MAX_HEAP_SECTS */
6324
6325typedef struct GC_ms_entry {
6326 ptr_t mse_start; /*< beginning of object, pointer-aligned one */
6327#ifdef PARALLEL_MARK
6328 volatile AO_t mse_descr;
6329#else
6330 /*
6331 * The descriptor; the low-order two bits are tags, as described
6332 * in `gc_mark.h` file.
6333 */
6334 word mse_descr;
6335#endif
6336} mse;
6337
6338/*
6339 * Current state of marking. Used to remember where we are during the
6340 * concurrent marking.
6341 */
6342typedef int mark_state_t;
6343
6344struct disappearing_link;
6345struct finalizable_object;
6346
6347struct dl_hashtbl_s {
6348 struct disappearing_link **head;
6349 size_t entries;
6350 unsigned log_size;
6351};
6352
6353struct fnlz_roots_s {
6354 struct finalizable_object **fo_head;
6355 /* List of objects that should be finalized now. */
6356 struct finalizable_object *finalize_now;
6357};
6358
6359union toggle_ref_u {
6360 /* The least significant bit is used to distinguish between choices. */
6361 void *strong_ref;
6362 GC_hidden_pointer weak_ref;
6363};
6364
6365/*
6366 * Extended descriptors. `GC_typed_mark_proc` understands these.
6367 * These are used for simple objects that are larger than what can
6368 * be described by a `BITMAP_BITS`-sized bitmap.
6369 */
6370typedef struct {
6371 /*
6372 * The least significant bit corresponds to the first "pointer-sized"
6373 * word.
6374 */
6375 word ed_bitmap;
6376 GC_bool ed_continued; /*< next entry is continuation */
6377} typed_ext_descr_t;
6378
6379struct HeapSect {
6380 ptr_t hs_start;
6381 size_t hs_bytes;
6382};
6383
6384#ifdef MAKE_BACK_GRAPH
6385/* The maximum in-degree we handle directly. */
6386# define BACKGRAPH_MAX_IN 10
6387
6388struct back_edges_s {
6389 /* Number of edges, including those in continuation structures. */
6390 word n_edges;
6391
6392 unsigned short flags;
6393
6394 /*
6395 * If `height` is greater than zero, then keeps the `GC_gc_no` value
6396 * when it was computed. If it was computed this cycle, then it is
6397 * current. If it was computed during the last cycle, then it belongs
6398 * to the old height, which is only saved for live objects referenced by
6399 * dead ones. This may grow due to references from newly dead objects.
6400 */
6401 unsigned short height_gc_no;
6402
6403 /*
6404 * Longest path through unreachable nodes to this node that we found
6405 * using depth first search.
6406 */
6407 GC_signed_word height;
6408
6409 ptr_t edges[BACKGRAPH_MAX_IN];
6410
6411 /*
6412 * Pointer to continuation structure; we use only the edges field in
6413 * the continuation. Also used as a free-list link.
6414 */
6415 struct back_edges_s *cont;
6416};
6417#endif
6418
6419/*
6420 * Lists of all heap blocks and free lists as well as other random data
6421 * structures that should not be scanned by the collector. These are
6422 * grouped together in a structure so that they can be easily skipped by
6423 * `GC_push_conditional_with_exclusions()`. The ordering is weird to
6424 * make `GC_malloc` faster by keeping the important fields sufficiently
6425 * close together that a single load of a base register will do.
6426 * Scalars that could easily appear to be pointers are also put here.
6427 * The main fields should precede any conditionally included fields, where
6428 * possible.
6429 */
6430struct _GC_arrays {
6431#define GC_heapsize GC_arrays._heapsize
6432 word _heapsize; /*< heap size in bytes (value never goes down) */
6433
6434#define GC_requested_heapsize GC_arrays._requested_heapsize
6435 word _requested_heapsize; /*< heap size due to explicit expansion */
6436
6437#define GC_heapsize_on_gc_disable GC_arrays._heapsize_on_gc_disable
6438 word _heapsize_on_gc_disable;
6439
6440#define GC_heapsize_at_forced_unmap GC_arrays._heapsize_at_forced_unmap
6441 word _heapsize_at_forced_unmap; /*< accessed with the allocator lock held */
6442
6443#define GC_last_heap_addr GC_arrays._last_heap_addr
6444 word _last_heap_addr;
6445
6446 /*
6447 * Total bytes contained in blocks on the free list of large objects.
6448 * (A large object is the one that occupies a block of at least
6449 * two `HBLKSIZE`.)
6450 */
6451#define GC_large_free_bytes GC_arrays._large_free_bytes
6452 word _large_free_bytes;
6453
6454 /* Total number of bytes in allocated large objects blocks. */
6455#define GC_large_allocd_bytes GC_arrays._large_allocd_bytes
6456 word _large_allocd_bytes;
6457
6458 /*
6459 * Maximum number of bytes that were ever allocated in large object blocks.
6460 * This is used to help decide when it is safe to split up a large block.
6461 */
6462#define GC_max_large_allocd_bytes GC_arrays._max_large_allocd_bytes
6463 word _max_large_allocd_bytes;
6464
6465 /* Number of bytes allocated before this collection cycle. */
6466#define GC_bytes_allocd_before_gc GC_arrays._bytes_allocd_before_gc
6467 word _bytes_allocd_before_gc;
6468
6469#define GC_our_mem_bytes GC_arrays._our_mem_bytes
6470 word _our_mem_bytes;
6471
6472 /* Number of bytes allocated during this collection cycle. */
6473#define GC_bytes_allocd GC_arrays._bytes_allocd
6474 word _bytes_allocd;
6475
6476 /*
6477 * Number of black-listed bytes dropped during GC cycle as a result
6478 * of repeated scanning during allocation attempts. These are treated
6479 * largely as allocated, even though they are not useful to the client.
6480 */
6481#define GC_bytes_dropped GC_arrays._bytes_dropped
6482 word _bytes_dropped;
6483
6484 /*
6485 * Approximate number of bytes in objects (and headers) that became
6486 * ready for finalization in the last collection.
6487 */
6488#define GC_bytes_finalized GC_arrays._bytes_finalized
6489 word _bytes_finalized;
6490
6491 /*
6492 * Number of explicitly deallocated bytes of memory since last
6493 * collection.
6494 */
6495#define GC_bytes_freed GC_arrays._bytes_freed
6496 word _bytes_freed;
6497
6498 /*
6499 * Bytes of memory explicitly deallocated while finalizers were running.
6500 * Used to approximate size of memory explicitly deallocated by finalizers.
6501 */
6502#define GC_finalizer_bytes_freed GC_arrays._finalizer_bytes_freed
6503 word _finalizer_bytes_freed;
6504
6505 /*
6506 * Pointer to the first (lowest address) `bottom_index` entity;
6507 * assumes the allocator lock is held.
6508 */
6509#define GC_all_bottom_indices GC_arrays._all_bottom_indices
6510 bottom_index *_all_bottom_indices;
6511
6512 /*
6513 * Pointer to the last (highest address) `bottom_index` entity;
6514 * assumes the allocator lock is held.
6515 */
6516#define GC_all_bottom_indices_end GC_arrays._all_bottom_indices_end
6517 bottom_index *_all_bottom_indices_end;
6518
6519#define GC_scratch_free_ptr GC_arrays._scratch_free_ptr
6520 ptr_t _scratch_free_ptr;
6521
6522#define GC_hdr_free_list GC_arrays._hdr_free_list
6523 hdr *_hdr_free_list;
6524
6525#define GC_scratch_end_addr GC_arrays._scratch_end_addr
6526 word _scratch_end_addr; /*< the end point of the current scratch area */
6527
6528#if defined(IRIX5) || (defined(USE_PROC_FOR_LIBRARIES) && !defined(LINUX))
6529# define USE_SCRATCH_LAST_END_PTR
6530 /*
6531 * The address of the end point of the last obtained scratch area.
6532 * Used by `GC_register_dynamic_libraries()`.
6533 */
6534# define GC_scratch_last_end_addr GC_arrays._scratch_last_end_addr
6535 word _scratch_last_end_addr;
6536#endif
6537
6538#if defined(GC_ASSERTIONS) || defined(MAKE_BACK_GRAPH) \
6539 || defined(INCLUDE_LINUX_THREAD_DESCR) \
6540 || (defined(KEEP_BACK_PTRS) && ALIGNMENT == 1)
6541# define SET_REAL_HEAP_BOUNDS
6542
6543 /*
6544 * Similar to `GC_least_plausible_heap_addr` and
6545 * `GC_greatest_plausible_heap_addr` but do not include future
6546 * (potential) heap expansion. Both variables are zero initially.
6547 */
6548# define GC_least_real_heap_addr GC_arrays._least_real_heap_addr
6549# define GC_greatest_real_heap_addr GC_arrays._greatest_real_heap_addr
6550 word _least_real_heap_addr;
6551 word _greatest_real_heap_addr;
6552#endif
6553
6554#define GC_used_heap_size_after_full GC_arrays._used_heap_size_after_full
6555 word _used_heap_size_after_full;
6556
6557 /* Number of explicitly managed bytes of storage at last collection. */
6558#define GC_non_gc_bytes_at_gc GC_arrays._non_gc_bytes_at_gc
6559 word _non_gc_bytes_at_gc;
6560
6561 /* The number of extra calls to `GC_mark_some` that we have made. */
6562#define GC_mark_deficit GC_arrays._mark_deficit
6563 size_t _mark_deficit;
6564
6565#ifndef NO_BLACK_LISTING
6566 /*
6567 * Counter of the cases when found block by `GC_allochblk_nth` is
6568 * black-listed completely.
6569 */
6570# define GC_drop_blacklisted_count GC_arrays._drop_blacklisted_count
6571 unsigned _drop_blacklisted_count;
6572
6573 /* Number of warnings suppressed so far. */
6574# define GC_large_alloc_warn_suppressed GC_arrays._large_alloc_warn_suppressed
6575 long _large_alloc_warn_suppressed;
6576
6577 /* Non-stack false references seen at last full collection. */
6578# define GC_old_normal_bl GC_arrays._old_normal_bl
6579 word *_old_normal_bl;
6580 /* Non-stack false references seen since last full collection. */
6581# define GC_incomplete_normal_bl GC_arrays._incomplete_normal_bl
6582 word *_incomplete_normal_bl;
6583
6584# define GC_old_stack_bl GC_arrays._old_stack_bl
6585# define GC_incomplete_stack_bl GC_arrays._incomplete_stack_bl
6586 word *_old_stack_bl;
6587 word *_incomplete_stack_bl;
6588#endif
6589
6590 /* The limits of stack for `GC_mark_some()` and friends. */
6591#define GC_mark_stack GC_arrays._mark_stack
6592#define GC_mark_stack_limit GC_arrays._mark_stack_limit
6593 mse *_mark_stack;
6594 mse *_mark_stack_limit;
6595
6596 /*
6597 * All ranges between `GC_mark_stack` (incl.) and `GC_mark_stack_top`
6598 * (incl.) still need to be marked from.
6599 */
6600#define GC_mark_stack_top GC_arrays._mark_stack_top
6601#ifdef PARALLEL_MARK
6602 /* Updated only with the mark lock held, but read asynchronously. */
6603 mse *volatile _mark_stack_top;
6604
6605# define GC_mark_no GC_arrays._mark_no
6606 word _mark_no; /*< protected by the mark lock */
6607
6608 /*
6609 * Number of bytes of memory allocated since we released the allocator lock.
6610 * Instead of reacquiring the allocator lock just to add this in, we add it
6611 * in the next time we reacquire the allocator lock. (Atomically adding it
6612 * does not work, since we would have to atomically update it in
6613 * `GC_malloc`, which is too expensive.)
6614 */
6615# define GC_bytes_allocd_tmp GC_arrays._bytes_allocd_tmp
6616 volatile AO_t _bytes_allocd_tmp;
6617#else
6618 mse *_mark_stack_top;
6619#endif
6620
6621#ifdef DYNAMIC_POINTER_MASK
6622 /*
6623 * Both mask and shift are zeros by default; if mask is zero, then
6624 * correct it to ~0 at the collector initialization.
6625 */
6626# define GC_pointer_mask GC_arrays._pointer_mask
6627# define GC_pointer_shift GC_arrays._pointer_shift
6628 word _pointer_mask;
6629 unsigned char _pointer_shift;
6630#endif
6631
6632#ifdef THREADS
6633# ifdef USE_SPIN_LOCK
6634# define GC_allocate_lock GC_arrays._allocate_lock
6635 volatile AO_TS_t _allocate_lock;
6636# endif
6637# if !defined(HAVE_LOCKFREE_AO_OR) && defined(AO_HAVE_test_and_set_acquire) \
6638 && (!defined(NO_MANUAL_VDB) || defined(MPROTECT_VDB))
6639# define NEED_FAULT_HANDLER_LOCK
6640# define GC_fault_handler_lock GC_arrays._fault_handler_lock
6641 volatile AO_TS_t _fault_handler_lock;
6642# endif
6643# if !(defined(GC_ALWAYS_MULTITHREADED) \
6644 && (defined(USE_PTHREAD_LOCKS) || defined(USE_SPIN_LOCK)))
6645# define GC_need_to_lock GC_arrays._need_to_lock
6646 GC_bool _need_to_lock;
6647# endif
6648
6649# ifdef GC_ASSERTIONS
6650# define GC_thr_initialized GC_arrays._thr_initialized
6651 GC_bool _thr_initialized;
6652# endif
6653# if defined(GC_USE_DLOPEN_WRAP) && !defined(GC_WIN32_THREADS) \
6654 && !defined(PLATFORM_THREADS) && !defined(SN_TARGET_PSP2)
6655# define GC_syms_wrap_initialized GC_arrays._syms_wrap_initialized
6656 GC_bool _syms_wrap_initialized;
6657# endif
6658
6659# define GC_roots_were_cleared GC_arrays._roots_were_cleared
6660 GC_bool _roots_were_cleared;
6661#else
6662# ifndef GC_NO_FINALIZATION
6663/*
6664 * The variables to minimize the level of recursion when a client
6665 * finalizer allocates memory.
6666 */
6667# define GC_finalizer_nested GC_arrays._finalizer_nested
6668# define GC_finalizer_skipped GC_arrays._finalizer_skipped
6669 unsigned char _finalizer_nested;
6670 unsigned short _finalizer_skipped;
6671# endif
6672#endif
6673
6674 /* Has `GC_init()` been run? */
6675#define GC_is_initialized GC_arrays._is_initialized
6676 GC_bool _is_initialized;
6677
6678 /*
6679 * Do we need a larger mark stack? May be set by client-supplied
6680 * mark routines.
6681 */
6682#define GC_mark_stack_too_small GC_arrays._mark_stack_too_small
6683 GC_bool _mark_stack_too_small;
6684
6685 /* Are there collectible marked objects in the heap? */
6686#define GC_objects_are_marked GC_arrays._objects_are_marked
6687 GC_bool _objects_are_marked;
6688
6689#ifndef GC_DISABLE_INCREMENTAL
6690# define GC_should_start_incremental_collection \
6691 GC_arrays._should_start_incremental_collection
6692 GC_bool _should_start_incremental_collection;
6693#endif
6694
6695#ifndef GC_NO_FINALIZATION
6696 /* Avoid the work if unreachable finalizable objects are not used. */
6697 /* TODO: Turn this variable into a counter. */
6698# define GC_need_unreachable_finalization \
6699 GC_arrays._need_unreachable_finalization
6700 GC_bool _need_unreachable_finalization;
6701#endif
6702
6703#ifndef DONT_USE_ATEXIT
6704# ifdef SMALL_CONFIG
6705# define GC_skip_collect_atexit FALSE
6706# else
6707 /*
6708 * A dedicated variable to avoid a garbage collection on abort.
6709 * `GC_find_leak` cannot be used for this purpose as otherwise
6710 * TSan finds a data race (between `GC_default_on_abort` and, e.g.,
6711 * `GC_finish_collection`).
6712 */
6713# define GC_skip_collect_atexit GC_arrays._skip_collect_atexit
6714 GC_bool _skip_collect_atexit;
6715# endif
6716#endif
6717
6718#if defined(NO_FIND_LEAK) && defined(SHORT_DBG_HDRS)
6719# define GC_debugging_initialized GC_arrays._debugging_initialized
6720 GC_bool _debugging_initialized;
6721# define GC_debugging_started FALSE
6722#else
6723# define GC_debugging_initialized GC_debugging_started
6724 /* `GC_debug_malloc()` has been called, once at least. */
6725# define GC_debugging_started GC_arrays._debugging_started
6726 GC_bool _debugging_started;
6727
6728# define GC_have_errors GC_arrays._have_errors
6729# ifdef AO_HAVE_store
6730 volatile AO_t _have_errors;
6731# else
6732 GC_bool _have_errors;
6733# endif
6734#endif
6735
6736#define GC_explicit_typing_initialized GC_arrays._explicit_typing_initialized
6737#ifdef AO_HAVE_load_acquire
6738 volatile AO_t _explicit_typing_initialized;
6739#else
6740 GC_bool _explicit_typing_initialized;
6741#endif
6742
6743 /* Indicate whether a full collection due to heap growth is needed. */
6744#define GC_need_full_gc GC_arrays._need_full_gc
6745 GC_bool _need_full_gc;
6746
6747#ifndef NO_CLOCK
6748 /*
6749 * Do performance measurements if set to true (e.g., accumulation of the
6750 * total time of full collections).
6751 */
6752# define GC_measure_performance GC_arrays._measure_performance
6753 GC_bool _measure_performance;
6754
6755 /*
6756 * Variables for world-stop average delay time statistic computation.
6757 * `GC_world_stopped_total_divisor` is incremented every world stop and
6758 * halved when reached its maximum (or upon `GC_world_stopped_total_time`
6759 * overflow). In milliseconds.
6760 */
6761 /* TODO: Store the nanosecond part. */
6762# define GC_world_stopped_total_time GC_arrays._world_stopped_total_time
6763# define GC_world_stopped_total_divisor GC_arrays._world_stopped_total_divisor
6764 unsigned _world_stopped_total_time;
6765 unsigned _world_stopped_total_divisor;
6766#endif
6767
6768#ifndef NO_FIND_LEAK
6769# define GC_n_leaked GC_arrays._n_leaked
6770 unsigned _n_leaked;
6771#endif
6772#ifndef SHORT_DBG_HDRS
6773# define GC_n_smashed GC_arrays._n_smashed
6774 unsigned _n_smashed;
6775#endif
6776
6777 /* Number of bytes in the accessible composite objects. */
6778#define GC_composite_in_use GC_arrays._composite_in_use
6779 word _composite_in_use;
6780
6781 /* Number of bytes in the accessible atomic objects. */
6782#define GC_atomic_in_use GC_arrays._atomic_in_use
6783 word _atomic_in_use;
6784
6785 /* GC number of latest successful `GC_expand_hp_inner()` call. */
6786#define GC_last_heap_growth_gc_no GC_arrays._last_heap_growth_gc_no
6787 word _last_heap_growth_gc_no;
6788
6789 /*
6790 * Number of bytes of memory reclaimed minus the number of bytes originally
6791 * on free lists that we had to drop. Protected by the allocator lock.
6792 */
6793#define GC_bytes_found GC_arrays._bytes_found
6794 GC_signed_word _bytes_found;
6795
6796#ifndef GC_GET_HEAP_USAGE_NOT_NEEDED
6797 /*
6798 * Number of bytes reclaimed before this collection cycle; used for
6799 * statistics only.
6800 */
6801# define GC_reclaimed_bytes_before_gc GC_arrays._reclaimed_bytes_before_gc
6802 word _reclaimed_bytes_before_gc;
6803#endif
6804
6805#ifdef USE_MUNMAP
6806# define GC_unmapped_bytes GC_arrays._unmapped_bytes
6807 word _unmapped_bytes;
6808#else
6809# define GC_unmapped_bytes 0
6810#endif
6811
6812#if defined(COUNT_UNMAPPED_REGIONS) && defined(USE_MUNMAP)
6813# define GC_num_unmapped_regions GC_arrays._num_unmapped_regions
6814 GC_signed_word _num_unmapped_regions;
6815#else
6816# define GC_num_unmapped_regions 0
6817#endif
6818
6819#define GC_all_nils GC_arrays._all_nils
6820 bottom_index *_all_nils;
6821
6822#define GC_scan_ptr GC_arrays._scan_ptr
6823 struct hblk *_scan_ptr;
6824
6825#ifdef PARALLEL_MARK
6826# define GC_main_local_mark_stack GC_arrays._main_local_mark_stack
6827 mse *_main_local_mark_stack;
6828
6829 /*
6830 * The lowest entry on mark stack that may not be empty.
6831 * Updated only by the initiating thread.
6832 */
6833# define GC_first_nonempty GC_arrays._first_nonempty
6834 volatile ptr_t _first_nonempty;
6835#endif
6836
6837#ifdef ENABLE_TRACE
6838# define GC_trace_ptr GC_arrays._trace_ptr
6839 ptr_t _trace_ptr;
6840#endif
6841
6842#if !defined(ALWAYS_SMALL_CLEAR_STACK) && !defined(STACK_NOT_SCANNED) \
6843 && !defined(THREADS)
6844 /*
6845 * Coolest stack pointer value from which we have already cleared
6846 * the stack.
6847 */
6848# define GC_min_sp GC_arrays._min_sp
6849 ptr_t _min_sp;
6850
6851 /*
6852 * The "hottest" stack pointer value we have seen recently.
6853 * Degrades over time.
6854 */
6855# define GC_high_water GC_arrays._high_water
6856 ptr_t _high_water;
6857#endif
6858
6859#if CPP_PTRSZ > CPP_WORDSZ
6860# define GC_noop_sink_ptr GC_arrays._noop_sink_ptr
6861 volatile ptr_t _noop_sink_ptr;
6862#endif
6863
6864#define GC_noop_sink GC_arrays._noop_sink
6865#if defined(AO_HAVE_store) && defined(THREAD_SANITIZER)
6866 volatile AO_t _noop_sink;
6867#else
6868 volatile word _noop_sink;
6869#endif
6870
6871#if !defined(SMALL_CONFIG) && !defined(GC_NO_FINALIZATION)
6872 /* Saved number of disappearing links for stats printing. */
6873# define GC_old_dl_entries GC_arrays._old_dl_entries
6874 size_t _old_dl_entries;
6875# ifndef GC_LONG_REFS_NOT_NEEDED
6876# define GC_old_ll_entries GC_arrays._old_ll_entries
6877 size_t _old_ll_entries;
6878# endif
6879#endif
6880
6881#define GC_mark_stack_size GC_arrays._mark_stack_size
6882 size_t _mark_stack_size;
6883
6884#define GC_mark_state GC_arrays._mark_state
6885 mark_state_t _mark_state; /*< initialized to `MS_NONE` (0) */
6886
6887#define GC_capacity_heap_sects GC_arrays._capacity_heap_sects
6888 size_t _capacity_heap_sects;
6889
6890#define GC_n_heap_sects GC_arrays._n_heap_sects
6891 size_t _n_heap_sects; /*< number of separately added heap sections */
6892
6893#ifdef ANY_MSWIN
6894# define GC_n_heap_bases GC_arrays._n_heap_bases
6895 size_t _n_heap_bases; /*< see `GC_heap_bases[]` */
6896#endif
6897
6898#ifdef USE_PROC_FOR_LIBRARIES
6899 /* Number of `GET_MEM`-allocated memory sections. */
6900# define GC_n_memory GC_arrays._n_memory
6901 word _n_memory;
6902#endif
6903
6904#ifdef GC_GCJ_SUPPORT
6905# define GC_last_finalized_no GC_arrays._last_finalized_no
6906# define GC_gcjobjfreelist GC_arrays._gcjobjfreelist
6907 word _last_finalized_no;
6908 ptr_t *_gcjobjfreelist;
6909#endif
6910
6911#define GC_fo_entries GC_arrays._fo_entries
6912 size_t _fo_entries;
6913
6914#ifndef GC_NO_FINALIZATION
6915# define GC_dl_hashtbl GC_arrays._dl_hashtbl
6916# define GC_fnlz_roots GC_arrays._fnlz_roots
6917# define GC_log_fo_table_size GC_arrays._log_fo_table_size
6918# ifndef GC_LONG_REFS_NOT_NEEDED
6919# define GC_ll_hashtbl GC_arrays._ll_hashtbl
6920 struct dl_hashtbl_s _ll_hashtbl;
6921# endif
6922 struct dl_hashtbl_s _dl_hashtbl;
6923 struct fnlz_roots_s _fnlz_roots;
6924 unsigned _log_fo_table_size;
6925
6926# ifndef GC_TOGGLE_REFS_NOT_NEEDED
6927# define GC_toggleref_arr GC_arrays._toggleref_arr
6928# define GC_toggleref_array_size GC_arrays._toggleref_array_size
6929# define GC_toggleref_array_capacity GC_arrays._toggleref_array_capacity
6930 union toggle_ref_u *_toggleref_arr;
6931 size_t _toggleref_array_size;
6932 size_t _toggleref_array_capacity;
6933# endif
6934#endif
6935
6936#ifdef TRACE_BUF
6937# define GC_trace_buf_pos GC_arrays._trace_buf_pos
6938 size_t _trace_buf_pos; /*< an index in the circular buffer */
6939#endif
6940
6941 /*
6942 * How many consecutive collection/expansion failures?
6943 * Reset by `GC_allochblk()`.
6944 */
6945#define GC_alloc_fail_count GC_arrays._alloc_fail_count
6946 unsigned _alloc_fail_count;
6947
6948#ifdef ENABLE_DISCLAIM
6949# define GC_finalized_kind GC_arrays._finalized_kind
6950 unsigned _finalized_kind;
6951#endif
6952
6953#ifndef NO_CLOCK
6954# define GC_full_gc_total_time GC_arrays._full_gc_total_time
6955# define GC_stopped_mark_total_time GC_arrays._stopped_mark_total_time
6956# define GC_full_gc_total_ns_frac GC_arrays._full_gc_total_ns_frac
6957# define GC_stopped_mark_total_ns_frac GC_arrays._stopped_mark_total_ns_frac
6958 unsigned long _full_gc_total_time; /*< in ms, may wrap */
6959 unsigned long _stopped_mark_total_time;
6960 unsigned32 _full_gc_total_ns_frac; /*< fraction of 1 ms */
6961 unsigned32 _stopped_mark_total_ns_frac;
6962#endif
6963
6964#ifdef GC_WIN32_THREADS
6965 /* Largest index in `dll_thread_table` that was ever used. */
6966# define GC_max_thread_index GC_arrays._max_thread_index
6967 volatile LONG _max_thread_index;
6968#endif
6969
6970 /* Total size of registered root sections. */
6971#define GC_root_size GC_arrays._root_size
6972 word _root_size;
6973
6974 /* `GC_static_roots[0..n_root_sets-1]` contains the valid root sets. */
6975#define n_root_sets GC_arrays._n_root_sets
6976 size_t _n_root_sets;
6977
6978#define GC_excl_table_entries GC_arrays._excl_table_entries
6979 size_t _excl_table_entries; /*< number of entries in use */
6980
6981#define GC_ed_size GC_arrays._ed_size
6982 size_t _ed_size; /*< current size of above arrays */
6983
6984#define GC_avail_descr GC_arrays._avail_descr
6985 size_t _avail_descr; /*< next available slot */
6986
6987#if defined(CAN_HANDLE_FORK) && defined(GC_PTHREADS)
6988 /* Value of `pthread_self()` of the thread which called `fork()`. */
6989# define GC_parent_pthread_self GC_arrays._parent_pthread_self
6990 pthread_t _parent_pthread_self;
6991#endif
6992
6993 /* Points to array of extended descriptors. */
6994#define GC_ext_descriptors GC_arrays._ext_descriptors
6995 typed_ext_descr_t *_ext_descriptors;
6996
6997 /*
6998 * Table of user-defined mark procedures. There is a small number
6999 * of these, which can be referenced by `DS_PROC` mark descriptors.
7000 * See `gc_mark.h` file.
7001 */
7002#define GC_mark_procs GC_arrays._mark_procs
7003 GC_mark_proc _mark_procs[GC_MAX_MARK_PROCS];
7004
7005 /*
7006 * `GC_valid_offsets[i]` implies
7007 * `GC_modws_valid_offsets[i % sizeof(ptr_t)]`.
7008 */
7009#define GC_modws_valid_offsets GC_arrays._modws_valid_offsets
7010 char _modws_valid_offsets[sizeof(ptr_t)];
7011
7012#ifdef MAKE_BACK_GRAPH
7013 /* Points to never-used `back_edges` space. */
7014# define GC_n_back_edge_structs GC_arrays._n_back_edge_structs
7015 int _n_back_edge_structs;
7016
7017# define GC_back_edge_space GC_arrays._back_edge_space
7018 struct back_edges_s *_back_edge_space;
7019
7020 /* Pointer to free list of deallocated `back_edges` structures. */
7021# define GC_avail_back_edges GC_arrays._avail_back_edges
7022 struct back_edges_s *_avail_back_edges;
7023
7024 /*
7025 * Table of objects that are currently on the depth-first search stack.
7026 * Only objects with in-degree one are in this table. Other objects are
7027 * identified using `HEIGHT_IN_PROGRESS`.
7028 */
7029 /* FIXME: This data structure needs improvement. */
7030# define GC_backgraph_in_progress_space GC_arrays._backgraph_in_progress_space
7031# define GC_backgraph_in_progress_size GC_arrays._backgraph_in_progress_size
7032# define GC_backgraph_n_in_progress GC_arrays._backgraph_n_in_progress
7033 ptr_t *_backgraph_in_progress_space;
7034 size_t _backgraph_in_progress_size;
7035 size_t _backgraph_n_in_progress;
7036
7037# define GC_backgraph_max_deepest_h GC_arrays._backgraph_max_deepest_h
7038# define GC_backgraph_deepest_height GC_arrays._backgraph_deepest_height
7039# define GC_backgraph_deepest_obj GC_arrays._backgraph_deepest_obj
7040 word _backgraph_max_deepest_h;
7041 word _backgraph_deepest_height;
7042 ptr_t _backgraph_deepest_obj;
7043#endif
7044
7045#ifdef GC_READ_ENV_FILE
7046 /*
7047 * The content of the `.gc.env` file with CR and LF replaced to '\0'.
7048 * `NULL` if the file is missing or empty. Otherwise, always ends
7049 * with '\0' (designating the end of the file).
7050 */
7051# define GC_envfile_content GC_arrays._envfile_content
7052 char *_envfile_content;
7053
7054 /* Length of `GC_envfile_content` (if non-`NULL`). */
7055# define GC_envfile_length GC_arrays._envfile_length
7056 size_t _envfile_length;
7057#endif
7058
7059#ifndef ANY_MSWIN
7060 /*
7061 * The hash table header. Used only to check whether a range
7062 * is already present.
7063 */
7064# define GC_root_index GC_arrays._root_index
7065 struct roots *_root_index[RT_SIZE];
7066#endif
7067
7068#if defined(SAVE_CALL_CHAIN) && !defined(DONT_SAVE_TO_LAST_STACK) \
7069 && (!defined(REDIRECT_MALLOC) || !defined(GC_HAVE_BUILTIN_BACKTRACE))
7070 /*
7071 * Stack at last garbage collection. Useful for debugging mysterious
7072 * object disappearances. In the multi-threaded case, we currently only
7073 * save the calling stack. Not supported in case of `malloc` redirection
7074 * because `backtrace()` may call `malloc()`.
7075 */
7076 struct callinfo _last_stack[NFRAMES];
7077# define SAVE_CALLERS_TO_LAST_STACK() GC_save_callers(GC_arrays._last_stack)
7078#else
7079# define SAVE_CALLERS_TO_LAST_STACK() (void)0
7080#endif
7081
7082 /* Free list for `NORMAL` objects. */
7083#define GC_objfreelist GC_arrays._objfreelist
7084 void *_objfreelist[MAXOBJGRANULES + 1];
7085
7086 /* Free list for atomic objects. */
7087#define GC_aobjfreelist GC_arrays._aobjfreelist
7088 void *_aobjfreelist[MAXOBJGRANULES + 1];
7089
7090 /*
7091 * Uncollectible but traced objects. Objects on this and `_auobjfreelist`
7092 * are always marked, except during garbage collections.
7093 */
7094#define GC_uobjfreelist GC_arrays._uobjfreelist
7095 void *_uobjfreelist[MAXOBJGRANULES + 1];
7096
7097#ifdef GC_ATOMIC_UNCOLLECTABLE
7098 /* Atomic uncollectible but traced objects. */
7099# define GC_auobjfreelist GC_arrays._auobjfreelist
7100 void *_auobjfreelist[MAXOBJGRANULES + 1];
7101#endif
7102
7103 /*
7104 * Number of granules to allocate when asked for a certain number of bytes
7105 * (plus `EXTRA_BYTES`). Should be accessed with the allocator lock held.
7106 */
7107#define GC_size_map GC_arrays._size_map
7108 size_t _size_map[MAXOBJBYTES + 1];
7109
7110#ifndef MARK_BIT_PER_OBJ
7111 /*
7112 * If the element is not `NULL`, then it points to a map of valid object
7113 * addresses. `GC_obj_map[lg][i]` is `i % lg`. This is now used purely
7114 * to replace a division in the marker by a table lookup.
7115 * `GC_obj_map[0]` is used for large objects and contains all nonzero
7116 * entries. This gets us out of the marker fast path without an extra test.
7117 */
7118# define GC_obj_map GC_arrays._obj_map
7119 hb_map_entry_t *_obj_map[MAXOBJGRANULES + 1];
7120
7121# define OBJ_MAP_LEN BYTES_TO_GRANULES(HBLKSIZE)
7122#endif
7123
7124#define VALID_OFFSET_SZ HBLKSIZE
7125 /*
7126 * A nonzero `GC_valid_offsets[i]` means `i` is registered as
7127 * a displacement.
7128 */
7129#define GC_valid_offsets GC_arrays._valid_offsets
7130 char _valid_offsets[VALID_OFFSET_SZ];
7131
7132#ifndef GC_DISABLE_INCREMENTAL
7133 /* Pages that were dirty at last `GC_read_dirty()` call. */
7134# define GC_grungy_pages GC_arrays._grungy_pages
7135 page_hash_table _grungy_pages;
7136
7137 /* Pages dirtied since last `GC_read_dirty()` call. */
7138# define GC_dirty_pages GC_arrays._dirty_pages
7139# ifdef MPROTECT_VDB
7140 volatile
7141# endif
7142 page_hash_table _dirty_pages;
7143#endif
7144
7145#if (defined(CHECKSUMS) && (defined(GWW_VDB) || defined(SOFT_VDB))) \
7146 || defined(PROC_VDB)
7147 /* A table to indicate the pages ever dirtied. */
7148# define GC_written_pages GC_arrays._written_pages
7149 page_hash_table _written_pages;
7150#endif
7151
7152 /* Heap segments potentially containing client objects. */
7153#define GC_heap_sects GC_arrays._heap_sects
7154 struct HeapSect *_heap_sects;
7155
7156#if defined(USE_PROC_FOR_LIBRARIES)
7157 /* All `GET_MEM`-allocated memory. Includes block headers and the like. */
7158# define GC_our_memory GC_arrays._our_memory
7159 struct HeapSect _our_memory[MAX_HEAP_SECTS];
7160#endif
7161
7162#ifdef ANY_MSWIN
7163 /* Start address of memory regions obtained from OS. */
7164# define GC_heap_bases GC_arrays._heap_bases
7165 ptr_t _heap_bases[MAX_HEAP_SECTS];
7166#endif
7167
7168#ifdef MSWINCE
7169 /* Committed lengths of memory regions obtained from OS. */
7170# define GC_heap_lengths GC_arrays._heap_lengths
7171 word _heap_lengths[MAX_HEAP_SECTS];
7172#endif
7173
7174#define GC_static_roots GC_arrays._static_roots
7175 struct roots _static_roots[MAX_ROOT_SETS];
7176
7177 /* Array of exclusions, ascending address order. */
7178#define GC_excl_table GC_arrays._excl_table
7179 struct exclusion _excl_table[MAX_EXCLUSIONS];
7180
7181 /*
7182 * The block header index. Each entry points to a `bottom_index` entity.
7183 * On a 32-bit machine, it points to the index for a set of the high-order
7184 * bits equal to the index. For longer addresses, we hash the high-order
7185 * bits to compute the index in `GC_top_index`, and each entry points to
7186 * a hash chain. The last entry in each chain is `GC_all_nils`.
7187 */
7188#define GC_top_index GC_arrays._top_index
7189 bottom_index *_top_index[TOP_SZ];
7190
7191#ifdef ECOS
7192# ifndef ECOS_GC_MEMORY_SIZE
7193# define ECOS_GC_MEMORY_SIZE (448 * 1024)
7194# endif
7195# define GC_ecos_brk_idx GC_arrays._ecos_brk_idx
7196# define GC_ecos_memory GC_arrays._ecos_memory
7197 size_t _ecos_brk_idx;
7198 char _ecos_memory[ECOS_GC_MEMORY_SIZE];
7199#endif
7200};
7201
7202GC_API_PRIV struct _GC_arrays GC_arrays;
7203#define beginGC_arrays ((ptr_t)(&GC_arrays))
7204#define endGC_arrays (beginGC_arrays + sizeof(GC_arrays))
7205
7206/* Object kinds. */
7207#ifndef MAXOBJKINDS
7208# ifdef SMALL_CONFIG
7209# define MAXOBJKINDS 16
7210# else
7211# define MAXOBJKINDS 24
7212# endif
7213#endif
7214GC_EXTERN struct obj_kind {
7215 /*
7216 * Array of free-list headers for this kind of object. Point either
7217 * to `GC_arrays` or to storage allocated with `GC_scratch_alloc()`.
7218 */
7219 void **ok_freelist;
7220
7221 /*
7222 * List headers for lists of blocks waiting to be swept.
7223 * Indexed by object size in granules.
7224 */
7225 struct hblk **ok_reclaim_list;
7226
7227 /* Descriptor template for objects in this block. */
7228 word ok_descriptor;
7229
7230 /*
7231 * Add object size in bytes to descriptor template to obtain descriptor.
7232 * Otherwise the template is used as is.
7233 */
7234 GC_bool ok_relocate_descr;
7235
7236 /* Clear objects before putting them on the free list. */
7237 GC_bool ok_init;
7238
7239#ifdef ENABLE_DISCLAIM
7240 /*
7241 * Mark from all, including unmarked, objects in block.
7242 * Used to protect objects reachable from reclaim notifiers.
7243 */
7244 GC_bool ok_mark_unconditionally;
7245
7246 /*
7247 * The disclaim procedure is called before `obj` is reclaimed, but
7248 * must also tolerate being called with object from free list.
7249 * A nonzero exit prevents object from being reclaimed.
7250 */
7251 int(GC_CALLBACK *ok_disclaim_proc)(void * /* `obj` */);
7252
7253# define OK_DISCLAIM_INITZ /* comma */ , FALSE, 0
7254#else
7255# define OK_DISCLAIM_INITZ /*< empty */
7256#endif
7257} GC_obj_kinds[MAXOBJKINDS];
7258
7259#define beginGC_obj_kinds ((ptr_t)(&GC_obj_kinds[0]))
7260#define endGC_obj_kinds (beginGC_obj_kinds + sizeof(GC_obj_kinds))
7261
7262/* The predefined kinds. */
7263#define PTRFREE GC_I_PTRFREE
7264#define NORMAL GC_I_NORMAL
7265#define UNCOLLECTABLE 2
7266#ifdef GC_ATOMIC_UNCOLLECTABLE
7267# define AUNCOLLECTABLE 3
7268# define IS_UNCOLLECTABLE(k) (((k) & ~1) == UNCOLLECTABLE)
7269# define GC_N_KINDS_INITIAL_VALUE 4
7270#else
7271# define IS_UNCOLLECTABLE(k) ((k) == UNCOLLECTABLE)
7272# define GC_N_KINDS_INITIAL_VALUE 3
7273#endif
7274
7275GC_EXTERN unsigned GC_n_kinds;
7276
7277/* May mean the allocation granularity size, not page size. */
7278GC_EXTERN size_t GC_page_size;
7279
7280#ifdef REAL_PAGESIZE_NEEDED
7281GC_EXTERN size_t GC_real_page_size;
7282#else
7283# define GC_real_page_size GC_page_size
7284#endif
7285
7286/*
7287 * Get heap memory from the OS.
7288 * Note that `sbrk`-like allocation is preferred, since it usually
7289 * makes it possible to merge consecutively allocated chunks.
7290 * It also avoids unintended recursion with `REDIRECT_MALLOC` macro
7291 * defined. `GET_MEM()` argument should be of `size_t` type and
7292 * have no side-effect. `GET_MEM()` returns `HBLKSIZE`-aligned chunk
7293 * (`NULL` means a failure). In case of `MMAP_SUPPORTED`, the argument
7294 * must also be a multiple of a physical page size.
7295 * `GET_MEM` is currently not assumed to retrieve zero-filled space.
7296 */
7297/* TODO: Take advantage of `GET_MEM()` returning a zero-filled space. */
7298#if defined(ANY_MSWIN) || defined(MSWIN_XBOX1) || defined(OS2)
7299GC_INNER void *GC_get_mem(size_t lb);
7300# define GET_MEM(lb) GC_get_mem(lb)
7301# if defined(CYGWIN32) && !defined(USE_WINALLOC)
7302# define NEED_UNIX_GET_MEM
7303# endif
7304#elif defined(DOS4GW) || defined(EMBOX) || defined(KOS) || defined(NEXT) \
7305 || defined(NONSTOP) || defined(RTEMS) || defined(__CC_ARM) \
7306 || (defined(SOLARIS) && !defined(USE_MMAP))
7307/* TODO: Use `page_alloc()` directly on Embox. */
7308# if defined(REDIRECT_MALLOC) && !defined(CPPCHECK)
7309# error Malloc redirection is unsupported
7310# endif
7311# define GET_MEM(lb) \
7312 ((void *)HBLKPTR((ptr_t)calloc(1, SIZET_SAT_ADD(lb, GC_page_size)) \
7313 + GC_page_size - 1))
7314#elif !defined(GET_MEM)
7315GC_INNER void *GC_unix_get_mem(size_t lb);
7316# define GET_MEM(lb) GC_unix_get_mem(lb)
7317# define NEED_UNIX_GET_MEM
7318#endif
7319
7320/*
7321 * Round up allocation size to a multiple of a page size.
7322 * `GC_setpagesize()` is assumed to be already invoked.
7323 */
7324#define ROUNDUP_PAGESIZE(lb) /*< `lb` should have no side-effect */ \
7325 (SIZET_SAT_ADD(lb, GC_page_size - 1) & ~(GC_page_size - 1))
7326
7327/*
7328 * Same as `ROUNDUP_PAGESIZE` but is used to make `GET_MEM()` argument
7329 * safe.
7330 */
7331#ifdef MMAP_SUPPORTED
7332# define ROUNDUP_PAGESIZE_IF_MMAP(lb) ROUNDUP_PAGESIZE(lb)
7333#else
7334# define ROUNDUP_PAGESIZE_IF_MMAP(lb) (lb)
7335#endif
7336
7337#ifdef ANY_MSWIN
7338GC_EXTERN SYSTEM_INFO GC_sysinfo;
7339
7340/*
7341 * Is `p` the start of either the `malloc` heap, or of one of the collector
7342 * heap sections?
7343 */
7344GC_INNER GC_bool GC_is_heap_base(const void *p);
7345#endif
7346
7347#ifdef GC_GCJ_SUPPORT
7348/* Note: `GC_hblkfreelist` and `GC_free_bytes` remain visible to GNU `gcj`. */
7349extern struct hblk *GC_hblkfreelist[];
7350extern word GC_free_bytes[];
7351#endif
7352
7353/* This is used by `GC_do_blocking()`. */
7354struct blocking_data {
7355 GC_fn_type fn;
7356 void *client_data; /*< and result */
7357};
7358
7359/* This is used by `GC_call_with_gc_active`, `GC_push_all_stack_sections`. */
7360struct GC_traced_stack_sect_s {
7361 ptr_t saved_stack_ptr;
7362#ifdef IA64
7363 ptr_t saved_backing_store_ptr;
7364 ptr_t backing_store_end;
7365#endif
7366 struct GC_traced_stack_sect_s *prev;
7367};
7368
7369#ifdef THREADS
7370/*
7371 * Process all "traced stack sections" - scan entire stack except for
7372 * frames belonging to the user functions invoked by `GC_do_blocking`.
7373 */
7374GC_INNER void
7375GC_push_all_stack_sections(ptr_t lo, ptr_t hi,
7376 struct GC_traced_stack_sect_s *traced_stack_sect);
7377
7378/*
7379 * The total size, in bytes, of all stacks.
7380 * Updated on every `GC_push_all_stacks()` call.
7381 */
7382GC_EXTERN word GC_total_stacksize;
7383
7384#else
7385/* Note: `NULL` value means we are not inside `GC_do_blocking()` call. */
7386GC_EXTERN ptr_t GC_blocked_sp;
7387
7388/*
7389 * Points to the "frame" data held in stack by the innermost
7390 * `GC_call_with_gc_active()`. `NULL` if no such "frame" active.
7391 */
7392GC_EXTERN struct GC_traced_stack_sect_s *GC_traced_stack_sect;
7393#endif /* !THREADS */
7394
7395#if defined(E2K) && defined(THREADS) || defined(IA64)
7396/*
7397 * The bottom of the register stack of the primordial thread.
7398 * E2K: holds the offset (`ps_ofs`) instead of a pointer.
7399 */
7400GC_EXTERN ptr_t GC_register_stackbottom;
7401#endif
7402
7403#ifdef IA64
7404/* Similar to `GC_push_all_stack_sections` but for IA-64 registers store. */
7405GC_INNER void GC_push_all_register_sections(
7406 ptr_t bs_lo, ptr_t bs_hi, GC_bool eager,
7407 struct GC_traced_stack_sect_s *traced_stack_sect);
7408#endif
7409
7410/*
7411 * Mark bit operations.
7412 *
7413 * The marks are in a reserved area of each heap block.
7414 * Each object or granule has one mark bit associated with it.
7415 * Only those corresponding to the beginning of an object are used.
7416 */
7417
7418/*
7419 * Retrieve, set, clear the `n`-th mark bit in a given heap block.
7420 * (Recall that bit `n` corresponds to `n`-th object or allocation granule
7421 * relative to the beginning of the block, including unused space.)
7422 */
7423
7424#ifdef USE_MARK_BYTES
7425# define mark_bit_from_hdr(hhdr, n) ((hhdr)->hb_marks[n])
7426# define set_mark_bit_from_hdr(hhdr, n) (void)((hhdr)->hb_marks[n] = 1)
7427# define clear_mark_bit_from_hdr(hhdr, n) (void)((hhdr)->hb_marks[n] = 0)
7428#else
7429/* Set mark bit correctly, even if mark bits may be concurrently accessed. */
7430# if defined(PARALLEL_MARK) || (defined(THREAD_SANITIZER) && defined(THREADS))
7431/*
7432 * Workaround TSan false positive: there is no race between
7433 * `mark_bit_from_hdr` and `set_mark_bit_from_hdr` when `n` is different
7434 * (alternatively, `USE_MARK_BYTES` could be used). If TSan is off, then
7435 * `AO_or()` is used only if we define `USE_MARK_BITS` macro explicitly.
7436 */
7437# define OR_WORD(addr, bits) AO_or(addr, bits)
7438# else
7439# define OR_WORD(addr, bits) (void)(*(addr) |= (bits))
7440# endif
7441# define mark_bit_from_hdr(hhdr, n) \
7442 (((hhdr)->hb_marks[divWORDSZ(n)] >> modWORDSZ(n)) & (word)1)
7443# define set_mark_bit_from_hdr(hhdr, n) \
7444 OR_WORD((hhdr)->hb_marks + divWORDSZ(n), (word)1 << modWORDSZ(n))
7445# define clear_mark_bit_from_hdr(hhdr, n) \
7446 (void)(((word *)CAST_AWAY_VOLATILE_PVOID((hhdr)->hb_marks))[divWORDSZ(n)] \
7447 &= ~((word)1 << modWORDSZ(n)))
7448#endif /* !USE_MARK_BYTES */
7449
7450#ifdef MARK_BIT_PER_OBJ
7451/*
7452 * Get the mark bit index corresponding to the given byte offset and
7453 * size (in bytes).
7454 */
7455# define MARK_BIT_NO(offset, sz) ((offset) / (sz))
7456
7457/* Spacing between useful mark bits. */
7458# define MARK_BIT_OFFSET(sz) 1
7459
7460/* Position of final, always set, mark bit. */
7461# define FINAL_MARK_BIT(sz) ((sz) > MAXOBJBYTES ? 1 : HBLK_OBJS(sz))
7462#else
7463# define MARK_BIT_NO(offset, sz) BYTES_TO_GRANULES(offset)
7464# define MARK_BIT_OFFSET(sz) BYTES_TO_GRANULES(sz)
7465# define FINAL_MARK_BIT(sz) \
7466 ((sz) > MAXOBJBYTES ? MARK_BITS_PER_HBLK \
7467 : BYTES_TO_GRANULES(HBLK_OBJS(sz) * (sz)))
7468#endif /* !MARK_BIT_PER_OBJ */
7469
7470/* Important internal collector routines. */
7471
7472/* Return the current stack pointer, approximately. */
7473GC_INNER ptr_t GC_approx_sp(void);
7474
7475/*
7476 * Same as `GC_approx_sp` but a macro. `sp` should be a local variable
7477 * of `volatile` `ptr_t` type.
7478 */
7479#if (defined(E2K) && defined(__clang__) \
7480 || (defined(S390) && __clang_major__ < 8)) \
7481 && !defined(CPPCHECK)
7482/*
7483 * Workaround some bugs in clang:
7484 * - "undefined reference to llvm.frameaddress" error (clang-9/e2k);
7485 * - a crash in SystemZTargetLowering of libLLVM-3.8 (s390).
7486 */
7487# define STORE_APPROX_SP_TO(sp) (void)(sp = (ptr_t)(&sp))
7488#elif defined(CPPCHECK) \
7489 || ((__GNUC__ >= 4 /* `GC_GNUC_PREREQ(4, 0)` */) \
7490 && !defined(STACK_NOT_SCANNED))
7491/* TODO: Use `GC_GNUC_PREREQ` after fixing a bug in cppcheck. */
7492/* Note: l-value is passed instead of pointer to `sp` (because of cppcheck). */
7493# define STORE_APPROX_SP_TO(sp) (void)(sp = (ptr_t)__builtin_frame_address(0))
7494#else
7495# define STORE_APPROX_SP_TO(sp) (void)(sp = (ptr_t)(&sp))
7496#endif
7497
7498/* Have we allocated enough to amortize a collection? */
7499GC_INNER GC_bool GC_should_collect(void);
7500
7501/*
7502 * Get the next block whose address is at least `h`. Returned block
7503 * is managed by the collector. The block must be in use unless
7504 * `allow_free` is TRUE. Return `NULL` if there is no such block.
7505 */
7506GC_INNER struct hblk *GC_next_block(struct hblk *h, GC_bool allow_free);
7507
7508/*
7509 * Get the last (highest address) block whose address is at most `h`.
7510 * Returned block is managed by the collector, but may or may not be in use.
7511 * Return `NULL` if there is no such block.
7512 */
7513GC_INNER struct hblk *GC_prev_block(struct hblk *h);
7514
7515GC_INNER void GC_mark_init(void);
7516
7517/*
7518 * Clear mark bits in all allocated heap blocks (i.e. for all heap objects).
7519 * This invalidates the marker invariant, and sets `GC_mark_state` to
7520 * reflect this. (This implicitly starts marking to reestablish the
7521 * invariant.)
7522 */
7523GC_INNER void GC_clear_marks(void);
7524
7525/*
7526 * Tell the marker that marked objects may point to unmarked ones, and
7527 * roots may point to unmarked objects. Reset mark stack.
7528 */
7529GC_INNER void GC_invalidate_mark_state(void);
7530
7531/*
7532 * Perform a small amount of marking. We try to touch roughly a page
7533 * of memory. Returns quickly if no collection is in progress.
7534 * Returns `TRUE` if we just finished a mark phase.
7535 * `cold_gc_frame` argument is an address inside a frame of the
7536 * collector that remains valid until all marking is complete;
7537 * `NULL` value indicates that it is OK to miss some register values.
7538 * In the case of an incremental collection, the world may be running.
7539 */
7540GC_INNER GC_bool GC_mark_some(ptr_t cold_gc_frame);
7541
7542/*
7543 * Initiate a garbage collection. Initiates a full collection if the
7544 * mark state is invalid; otherwise it is a partial one.
7545 */
7546GC_INNER void GC_initiate_gc(void);
7547
7548/*
7549 * Is a collection in progress? Note that this can return `TRUE` in
7550 * the non-incremental case, if a collection has been abandoned and
7551 * the mark state is now `MS_INVALID`.
7552 */
7553GC_INNER GC_bool GC_collection_in_progress(void);
7554
7555/*
7556 * Push contents of the symbol residing in the static roots area excluded
7557 * from scanning by the collector for a reason. Note: it should be used only
7558 * for symbols of relatively small size (containing one or several pointers).
7559 */
7560#define GC_PUSH_ALL_SYM(sym) GC_push_all_eager(&(sym), &(sym) + 1)
7561
7562/* Same as `GC_push_all` but consider interior pointers as valid. */
7563GC_INNER void GC_push_all_stack(ptr_t b, ptr_t t);
7564
7565#ifdef NO_VDB_FOR_STATIC_ROOTS
7566# define GC_push_conditional_static(b, t, all) \
7567 ((void)(all), GC_push_all(b, t))
7568#else
7569/*
7570 * Same as `GC_push_conditional` (does either of `GC_push_all` or
7571 * `GC_push_selected` depending on the third argument) but the caller
7572 * guarantees the region belongs to the registered static roots.
7573 */
7574GC_INNER void GC_push_conditional_static(void *b, void *t, GC_bool all);
7575#endif
7576
7577#if defined(WRAP_MARK_SOME) && defined(PARALLEL_MARK)
7578/*
7579 * Similar to `GC_push_conditional` but scans the whole region immediately.
7580 * `GC_mark_local` does not handle memory protection faults yet.
7581 * So, the static data regions are scanned immediately by `GC_push_roots`.
7582 */
7583GC_INNER void GC_push_conditional_eager(void *bottom, void *top, GC_bool all);
7584#endif
7585
7586/*
7587 * In the multi-threaded case, we push part of the current thread stack
7588 * with `GC_push_all_eager` when we push the registers. This gets the
7589 * callee-save registers that may disappear. The remainder of the stacks
7590 * are scheduled for scanning in `(*GC_push_other_roots)()`, which is
7591 * thread-package-specific.
7592 */
7593
7594/*
7595 * Push all or dirty roots. Call the mark routine (`GC_push_one` for
7596 * a single pointer, `GC_push_conditional` on groups of pointers) on every
7597 * top level accessible pointer. If not `all`, then arrange to push only
7598 * possibly altered values. `cold_gc_frame` is an address inside
7599 * a collector frame that remains valid until all marking is complete;
7600 * a `NULL` pointer indicates that it is OK to miss some register values.
7601 */
7602GC_INNER void GC_push_roots(GC_bool all, ptr_t cold_gc_frame);
7603
7604/*
7605 * Push system or application specific roots onto the mark stack.
7606 * In some environments (e.g. a multi-threaded one) this is predefined
7607 * to be nonzero. A client-supplied replacement should also call the
7608 * original function. Remains externally visible as used by some
7609 * well-known 3rd-party software (e.g., ECL) currently.
7610 */
7611GC_API_PRIV GC_push_other_roots_proc GC_push_other_roots;
7612
7613#ifdef THREADS
7614GC_INNER void GC_push_thread_structures(void);
7615#endif
7616
7617/*
7618 * A pointer set to `GC_push_typed_structures_proc` lazily so that we can
7619 * avoid linking in the typed allocation support if the latter is unused.
7620 */
7621GC_EXTERN void (*GC_push_typed_structures)(void);
7622
7623typedef void (*GC_with_callee_saves_func)(ptr_t arg, void *context);
7624
7625/*
7626 * Ensure that either registers are pushed, or callee-save registers are
7627 * somewhere on the stack, and then call `fn(arg, ctxt)`. `ctxt` is either
7628 * a pointer to a `ucontext_t` entity we generated, or `NULL`. Could be
7629 * called with or w/o the allocator lock held; could be called from a signal
7630 * handler as well.
7631 */
7632GC_INNER void GC_with_callee_saves_pushed(GC_with_callee_saves_func fn,
7633 ptr_t arg);
7634
7635#if defined(IA64) || defined(SPARC)
7636/*
7637 * Cause all stacked registers to be saved in memory. Return a pointer to
7638 * the top of the corresponding memory stack.
7639 */
7640ptr_t GC_save_regs_in_stack(void);
7641#endif
7642
7643#ifdef E2K
7644# include <asm/e2k_syswork.h>
7645# include <errno.h>
7646# include <sys/syscall.h>
7647
7648# if defined(CPPCHECK)
7649/*
7650 * Workaround "Uninitialized bs_lo" and "obsolete alloca() called"
7651 * false positive (FP) warnings.
7652 */
7653# define PS_ALLOCA_BUF(pbuf, sz) \
7654 (void)(GC_noop1_ptr(pbuf), *(pbuf) = (ptr_t)__builtin_alloca(sz))
7655# else
7656# define PS_ALLOCA_BUF(pbuf, sz) (void)(*(pbuf) = (ptr_t)alloca(sz))
7657# endif
7658
7659/*
7660 * Approximate size (in bytes) of the obtained procedure stack part
7661 * belonging to `syscall()` itself.
7662 */
7663# define PS_SYSCALL_TAIL_BYTES 0x100
7664
7665/*
7666 * Determine the current size of the whole procedure stack. The size
7667 * is valid only within the current function.
7668 */
7669# define GET_PROCEDURE_STACK_SIZE_INNER(psz_ull) \
7670 do { \
7671 *(psz_ull) = 0; /*< might be redundant */ \
7672 if (syscall(__NR_access_hw_stacks, E2K_GET_PROCEDURE_STACK_SIZE, NULL, \
7673 NULL, 0, psz_ull) \
7674 == -1) \
7675 ABORT_ARG1("Cannot get size of procedure stack", ": errno= %d", \
7676 errno); \
7677 GC_ASSERT(*(psz_ull) > 0 && *(psz_ull) % sizeof(ptr_t) == 0); \
7678 } while (0)
7679
7680# ifdef THREADS
7681# define PS_COMPUTE_ADJUSTED_OFS(padj_ps_ofs, ps_ofs, ofs_sz_ull) \
7682 do { \
7683 if ((ofs_sz_ull) <= (ps_ofs) /* `&& ofs_sz_ull > 0` */) \
7684 ABORT_ARG2("Incorrect size of procedure stack", \
7685 ": ofs= %lu, size= %lu", (unsigned long)(ps_ofs), \
7686 (unsigned long)(ofs_sz_ull)); \
7687 *(padj_ps_ofs) = (ps_ofs) > (unsigned)PS_SYSCALL_TAIL_BYTES \
7688 ? (ps_ofs) - (unsigned)PS_SYSCALL_TAIL_BYTES \
7689 : 0; \
7690 } while (0)
7691# else
7692/* A simplified variant of the above assuming `ps_ofs` is a zero const. */
7693# define PS_COMPUTE_ADJUSTED_OFS(padj_ps_ofs, ps_ofs, ofs_sz_ull) \
7694 do { \
7695 GC_STATIC_ASSERT((ps_ofs) == 0); \
7696 (void)(ofs_sz_ull); \
7697 *(padj_ps_ofs) = 0; \
7698 } while (0)
7699# endif /* !THREADS */
7700
7701/*
7702 * Copy procedure (register) stack to a stack-allocated buffer.
7703 * Usable from a signal handler. The buffer (`*pbuf`) is valid only
7704 * within the current function. `ps_ofs` designates the offset in the
7705 * procedure stack to copy the contents from. Note: this macro cannot
7706 * be changed to a function because `alloca()` and both `syscall()`
7707 * should be called in the context of the caller.
7708 */
7709# define GET_PROCEDURE_STACK_LOCAL(ps_ofs, pbuf, psz) \
7710 do { \
7711 unsigned long long ofs_sz_ull; \
7712 size_t adj_ps_ofs; \
7713 \
7714 GET_PROCEDURE_STACK_SIZE_INNER(&ofs_sz_ull); \
7715 PS_COMPUTE_ADJUSTED_OFS(&adj_ps_ofs, ps_ofs, ofs_sz_ull); \
7716 *(psz) = (size_t)ofs_sz_ull - adj_ps_ofs; \
7717 /* Allocate buffer on the stack; cannot return `NULL`. */ \
7718 PS_ALLOCA_BUF(pbuf, *(psz)); \
7719 /* Copy the procedure stack at the given offset to the buffer. */ \
7720 for (;;) { \
7721 ofs_sz_ull = adj_ps_ofs; \
7722 if (syscall(__NR_access_hw_stacks, E2K_READ_PROCEDURE_STACK_EX, \
7723 &ofs_sz_ull, *(pbuf), *(psz), NULL) \
7724 != -1) \
7725 break; \
7726 if (errno != EAGAIN) \
7727 ABORT_ARG2("Cannot read procedure stack", ": sz= %lu, errno= %d", \
7728 (unsigned long)(*(psz)), errno); \
7729 } \
7730 } while (0)
7731#endif /* E2K */
7732
7733#if defined(E2K) && defined(USE_PTR_HWTAG)
7734/* Load value and get tag of the target memory. */
7735# if defined(__ptr64__)
7736# define LOAD_TAGGED_VALUE(v, tag, p) \
7737 do { \
7738 ptr_t val; \
7739 __asm__ __volatile__("ldd, sm %[adr], 0x0, %[val]\n\t" \
7740 "gettagd %[val], %[tag]\n" \
7741 : [val] "=r"(val), [tag] "=r"(tag) \
7742 : [adr] "r"(p)); \
7743 v = val; \
7744 } while (0)
7745# elif !defined(CPPCHECK)
7746# error Unsupported -march for e2k target
7747# endif
7748
7749# define LOAD_PTR_OR_CONTINUE(v, p) \
7750 { \
7751 int tag LOCAL_VAR_INIT_OK; \
7752 LOAD_TAGGED_VALUE(v, tag, p); \
7753 if (tag != 0) \
7754 continue; \
7755 }
7756#elif defined(CHERI_PURECAP)
7757# define HAS_TAG_AND_PERM_LOAD(cap) \
7758 (cheri_tag_get(cap) != 0 && (cheri_perms_get(cap) & CHERI_PERM_LOAD) != 0)
7759
7760# define LOAD_PTR_OR_CONTINUE(v, p) \
7761 { \
7762 word base_addr; \
7763 v = *(ptr_t *)(p); \
7764 if (!HAS_TAG_AND_PERM_LOAD(v)) \
7765 continue; \
7766 base_addr = cheri_base_get(v); \
7767 if (ADDR(v) < base_addr || ADDR(v) >= base_addr + cheri_length_get(v)) \
7768 continue; \
7769 }
7770
7771# define CAPABILITY_COVERS_RANGE(cap, b_addr, e_addr) \
7772 (cheri_base_get(cap) <= (b_addr) \
7773 && cheri_base_get(cap) + cheri_length_get(cap) >= (e_addr))
7774# define SPANNING_CAPABILITY(cap, b_addr, e_addr) \
7775 (cheri_tag_get(cap) && CAPABILITY_COVERS_RANGE(cap, b_addr, e_addr) \
7776 && (cheri_perms_get(cap) & (CHERI_PERM_LOAD | CHERI_PERM_LOAD_CAP)) \
7777 != 0)
7778#else
7779# define LOAD_PTR_OR_CONTINUE(v, p) (void)(v = *(ptr_t *)(p))
7780#endif /* !CHERI_PURECAP */
7781
7782#if defined(DARWIN) && defined(THREADS)
7783/*
7784 * If `p` points to an object, mark it and push contents on the mark stack.
7785 * Pointer recognition test always accepts interior pointers, i.e. this is
7786 * appropriate for pointers found on the thread stack.
7787 */
7788void GC_push_one(word p);
7789#endif
7790
7791/*
7792 * Mark and push (i.e. gray) a single object `p` onto the main mark stack.
7793 * Consider `p` to be valid if it is an interior pointer. The object `p`
7794 * has passed a preliminary pointer validity test, but we do not definitely
7795 * know whether it is valid. Mark bits are not atomically updated; thus
7796 * this must be the only thread setting them.
7797 */
7798#if defined(PRINT_BLACK_LIST) || defined(KEEP_BACK_PTRS)
7799GC_INNER void GC_mark_and_push_stack(ptr_t p, ptr_t source);
7800#else
7801GC_INNER void GC_mark_and_push_stack(ptr_t p);
7802#endif
7803
7804/* Is the block with the given header containing no pointers? */
7805#define IS_PTRFREE(hhdr) (0 == (hhdr)->hb_descr)
7806
7807/* Clear all mark bits in the header. */
7808GC_INNER void GC_clear_hdr_marks(hdr *hhdr);
7809
7810/* Set all mark bits in the header. Used for uncollectible blocks. */
7811GC_INNER void GC_set_hdr_marks(hdr *hhdr);
7812
7813/* Set all mark bits associated with a free list. */
7814GC_INNER void GC_set_fl_marks(ptr_t);
7815
7816#if defined(GC_ASSERTIONS) && defined(THREAD_LOCAL_ALLOC)
7817/*
7818 * Check that all mark bits associated with a free list are set.
7819 * Abort if not.
7820 */
7821void GC_check_fl_marks(void **);
7822#endif
7823
7824/*
7825 * Add [`b`,`e`) to the root set. Adding the same interval a second
7826 * time is a moderately fast no-op, and hence benign. We do not handle
7827 * different but overlapping intervals efficiently. (But we do handle
7828 * them correctly.) `tmp` specifies that the interval may be deleted
7829 * before re-registering dynamic libraries.
7830 */
7831GC_INNER void GC_add_roots_inner(ptr_t b, ptr_t e, GC_bool tmp);
7832
7833#ifdef USE_PROC_FOR_LIBRARIES
7834/*
7835 * Remove given range from every static root which intersects with the range.
7836 * `GC_remove_tmp_roots` is assumed to be called before this function is
7837 * called (repeatedly) by `GC_register_map_entries`.
7838 */
7839GC_INNER void GC_remove_roots_subregion(ptr_t b, ptr_t e);
7840#endif
7841
7842/*
7843 * Inform the collector that a certain section of statically allocated
7844 * memory contains no pointers to garbage-collected memory.
7845 * The range boundaries should be properly aligned and valid.
7846 */
7847GC_INNER void GC_exclude_static_roots_inner(ptr_t start, ptr_t finish);
7848
7849#if defined(ANY_MSWIN) || defined(DYNAMIC_LOADING)
7850/* Add dynamic library data sections to the root set. */
7851GC_INNER void GC_register_dynamic_libraries(void);
7852#endif
7853
7854/*
7855 * Remove and re-register dynamic libraries if we are configured to do
7856 * that at each collection.
7857 */
7858GC_INNER void GC_cond_register_dynamic_libraries(void);
7859
7860/* Machine-dependent startup routines. */
7861
7862/*
7863 * Get the cold end of the stack of the primordial thread. This is always
7864 * called from the main (primordial) thread.
7865 */
7866GC_INNER ptr_t GC_get_main_stack_base(void);
7867
7868#ifdef IA64
7869/* Get the cold end of register stack. */
7870GC_INNER ptr_t GC_get_register_stack_base(void);
7871#endif
7872
7873GC_INNER void GC_register_data_segments(void);
7874
7875#ifdef THREADS
7876/* Both are invoked from `GC_init()` only. */
7877GC_INNER void GC_thr_init(void);
7878
7879/*
7880 * Perform all initializations, including those that may require allocation,
7881 * e.g. initialize thread-local free lists if used. Called by `GC_init()`.
7882 */
7883GC_INNER void GC_init_parallel(void);
7884
7885# ifndef DONT_USE_ATEXIT
7886GC_INNER GC_bool GC_is_main_thread(void);
7887# endif
7888#else
7889# ifdef TRACE_BUF
7890void GC_add_trace_entry(const char *caller_fn_name, ptr_t arg1, ptr_t arg2);
7891# endif
7892#endif /* !THREADS */
7893
7894#ifdef NO_BLACK_LISTING
7895# define GC_bl_init() (void)0
7896/* Do not define `GC_bl_init_no_interiors()`. */
7897# define GC_ADD_TO_BLACK_LIST_NORMAL(p, source) ((void)(p))
7898# define GC_ADD_TO_BLACK_LIST_STACK(p, source) ((void)(p))
7899# define GC_promote_black_lists() (void)0
7900# define GC_unpromote_black_lists() (void)0
7901#else
7902
7903/*
7904 * If we need a block of `n` bytes, and we have a block of `n + BL_LIMIT`
7905 * bytes available, and `n` is greater than `BL_LIMIT`, but all possible
7906 * positions in it are black-listed, we just use it anyway (and print
7907 * a warning, if warnings are enabled). This risks subsequently leaking
7908 * the block due to a false reference. But not using the block risks
7909 * unreasonable immediate heap growth.
7910 */
7911# define BL_LIMIT GC_black_list_spacing
7912
7913/*
7914 * Average number of bytes between black-listed blocks. Approximate.
7915 * Counts only blocks that are "stack black-listed", i.e. that are
7916 * problematic in the interior of an object.
7917 */
7918GC_EXTERN word GC_black_list_spacing;
7919
7920/*
7921 * The interval between unsuppressed warnings about repeated allocation
7922 * of a very large block.
7923 */
7924GC_EXTERN long GC_large_alloc_warn_interval;
7925
7926/* Initialize the black listing mechanism. */
7927GC_INNER void GC_bl_init(void);
7928GC_INNER void GC_bl_init_no_interiors(void);
7929
7930# ifdef PRINT_BLACK_LIST
7931/*
7932 * Register bits as a possible future false reference from the heap
7933 * or static data. The argument `p` is not a valid pointer reference,
7934 * but it falls inside the plausible heap bounds.
7935 */
7936GC_INNER void GC_add_to_black_list_normal(ptr_t p, ptr_t source);
7937# define GC_ADD_TO_BLACK_LIST_NORMAL(p, source) \
7938 if (GC_all_interior_pointers) { \
7939 GC_add_to_black_list_stack(p, source); \
7940 } else \
7941 GC_add_to_black_list_normal(p, source)
7942GC_INNER void GC_add_to_black_list_stack(ptr_t p, ptr_t source);
7943# define GC_ADD_TO_BLACK_LIST_STACK(p, source) \
7944 GC_add_to_black_list_stack(p, source)
7945# else
7946GC_INNER void GC_add_to_black_list_normal(ptr_t p);
7947# define GC_ADD_TO_BLACK_LIST_NORMAL(p, source) \
7948 if (GC_all_interior_pointers) { \
7949 GC_add_to_black_list_stack(p); \
7950 } else \
7951 GC_add_to_black_list_normal(p)
7952GC_INNER void GC_add_to_black_list_stack(ptr_t p);
7953# define GC_ADD_TO_BLACK_LIST_STACK(p, source) GC_add_to_black_list_stack(p)
7954# endif /* PRINT_BLACK_LIST */
7955
7956/*
7957 * Declare an end to a black listing phase. (I.e. signal the completion of
7958 * a collection.) Turn the incomplete black lists into new black lists, etc.
7959 */
7960GC_INNER void GC_promote_black_lists(void);
7961
7962/*
7963 * Approximately undo the effect of `GC_promote_black_lists()`.
7964 * This actually loses some information, but only in a reasonably safe way.
7965 */
7966GC_INNER void GC_unpromote_black_lists(void);
7967#endif
7968
7969/*
7970 * The collector internal memory allocation for small objects.
7971 * Deallocation is not possible. May return `NULL`.
7972 */
7973GC_INNER ptr_t GC_scratch_alloc(size_t bytes);
7974
7975#ifdef GWW_VDB
7976/* `GC_scratch_recycle_no_gww()` is not used. */
7977#else
7978# define GC_scratch_recycle_no_gww GC_scratch_recycle_inner
7979#endif
7980/* Reuse the memory region by the heap. */
7981GC_INNER void GC_scratch_recycle_inner(void *ptr, size_t sz);
7982
7983#ifndef MARK_BIT_PER_OBJ
7984/*
7985 * Add a heap block map for objects of a size in granules to `GC_obj_map`.
7986 * A size of zero is used for large objects. Returns `FALSE` on failure.
7987 */
7988GC_INNER GC_bool GC_add_map_entry(size_t lg);
7989#endif
7990
7991/*
7992 * Same as `GC_register_displacement` but assuming the allocator lock
7993 * is already held.
7994 */
7995GC_INNER void GC_register_displacement_inner(size_t offset);
7996
7997/*
7998 * Allocate a new heap block for small objects of size `lg` (in granules)
7999 * and `kind`. Add all of the block's objects to the free list for objects
8000 * of that size. Set all mark bits if objects are uncollectible.
8001 * Will fail to do anything if out of memory.
8002 */
8003GC_INNER void GC_new_hblk(size_t lg, int kind);
8004
8005/*
8006 * Build a free list for objects of size `lg` (in granules) inside heap
8007 * block `h`. Clear objects inside `h` if `clear` argument is set.
8008 * Add `list` to the end of the free list we build. Return the new
8009 * free list. Normally called by `GC_new_hblk()`, but this could also
8010 * be called without the allocator lock, if we ensure that there is no
8011 * concurrent collection which might reclaim objects that we have not
8012 * yet allocated.
8013 */
8014GC_INNER ptr_t GC_build_fl(struct hblk *h, ptr_t list, size_t lg,
8015 GC_bool clear);
8016
8017/*
8018 * Allocate (and return pointer to) a heap block for objects of the
8019 * given size and alignment (in bytes), searching over the appropriate
8020 * free block lists; inform the marker that the found block is valid
8021 * for objects of the indicated size. Assumes (as implied by the argument
8022 * name) that `EXTRA_BYTES` value is already added to the size, if needed.
8023 * The client is responsible for clearing the block, if needed.
8024 * Note: we set `GC_obj_map` field in the header correctly; the caller
8025 * is responsible for building an object's free list in the block.
8026 */
8027GC_INNER struct hblk *GC_allochblk(size_t lb_adjusted, int kind,
8028 unsigned flags, size_t align_m1);
8029
8030/*
8031 * Deallocate (free) a heap block and mark it as invalid. Coalesce it
8032 * with its neighbors if possible. All mark words are assumed to be cleared.
8033 */
8034GC_INNER void GC_freehblk(struct hblk *p);
8035
8036/* Miscellaneous GC routines. */
8037
8038/*
8039 * This explicitly increases the size of the heap. It is used internally,
8040 * but may also be invoked from `GC_expand_hp` by client. The argument is
8041 * in units of `HBLKSIZE`. (An argument of zero is treated as 1.)
8042 * Returns `FALSE` on failure.
8043 */
8044GC_INNER GC_bool GC_expand_hp_inner(word n);
8045
8046/*
8047 * Restore unmarked objects to free lists, or (if `abort_if_found` is `TRUE`)
8048 * report them. (I.e. perform `GC_reclaim_block()` on the entire heap,
8049 * after first clearing small-object free lists if we are not just looking
8050 * for leaks.) Sweeping of small object pages is largely deferred.
8051 */
8052GC_INNER void GC_start_reclaim(GC_bool abort_if_found);
8053
8054/*
8055 * Sweep blocks of the indicated object size (in granules) and kind
8056 * until either the appropriate nonempty free list is found, or there
8057 * are no more blocks to sweep.
8058 */
8059GC_INNER void GC_continue_reclaim(size_t lg, int kind);
8060
8061/*
8062 * Reclaim all small blocks waiting to be reclaimed. Abort and return
8063 * `FALSE` when/if `(*stop_func)()` returns `TRUE`. If this returns `TRUE`,
8064 * then it is safe to restart the world with incorrectly cleared mark bits.
8065 * If `ignore_old`, then reclaim only blocks that have been reclaimed
8066 * recently, and discard the rest. `stop_func` may be 0.
8067 */
8068GC_INNER GC_bool GC_reclaim_all(GC_stop_func stop_func, GC_bool ignore_old);
8069
8070/*
8071 * Generic procedure to rebuild a free list in `hbp` with header `hhdr`,
8072 * with objects of size `sz` bytes. Add `list` to the end of the free list.
8073 * Add the number of reclaimed bytes to `*pcount`. Note: it could be called
8074 * directly from `GC_malloc_many`.
8075 */
8076GC_INNER ptr_t GC_reclaim_generic(struct hblk *hbp, hdr *hhdr, size_t sz,
8077 GC_bool init, ptr_t list, word *pcount);
8078
8079/*
8080 * Is given heap block completely unmarked (i.e. contains no marked objects)?
8081 * This does not require the block to be in physical memory.
8082 */
8083GC_INNER GC_bool GC_block_empty(const hdr *hhdr);
8084
8085/* Always returns 0 (`FALSE`). */
8086GC_INNER int GC_CALLBACK GC_never_stop_func(void);
8087
8088/*
8089 * Stop-the-world garbage collection. The caller must have acquired
8090 * the allocator lock. If `stop_func` is not `GC_never_stop_func`, then
8091 * abort if `stop_func` returns `TRUE`. Return `TRUE` if we successfully
8092 * completed the collection (otherwise the collection is aborted).
8093 */
8094GC_INNER GC_bool GC_try_to_collect_inner(GC_stop_func stop_func);
8095
8096#define GC_gcollect_inner() (void)GC_try_to_collect_inner(GC_never_stop_func)
8097
8098#ifdef THREADS
8099/*
8100 * We may currently be in thread creation or destruction. Only set to `TRUE`
8101 * while the allocator lock is held. When set, it is OK to run the garbage
8102 * collection from an unknown thread. Protected by the allocator lock.
8103 */
8104GC_EXTERN GC_bool GC_in_thread_creation;
8105#endif
8106
8107/*
8108 * Do `n_blocks` units of a garbage collection work, if appropriate.
8109 * A unit is an amount appropriate for `HBLKSIZE` bytes of allocation.
8110 */
8111GC_INNER void GC_collect_a_little_inner(size_t n_blocks);
8112
8113GC_INNER void *GC_malloc_kind_aligned_global(size_t lb, int kind,
8114 size_t align_m1);
8115
8116GC_INNER void *GC_generic_malloc_aligned(size_t lb, int kind, unsigned flags,
8117 size_t align_m1);
8118
8119/*
8120 * Allocate an object of the given `kind` but assuming the allocator
8121 * lock is already held. Should not be used to directly allocate
8122 * objects requiring special handling on allocation. `flags` argument
8123 * should be 0 or `IGNORE_OFF_PAGE`; in the latter case the client
8124 * guarantees there will always be a pointer to the beginning (i.e.
8125 * within the first `hblk`) of the object while it is live.
8126 */
8127GC_INNER void *GC_generic_malloc_inner(size_t lb, int kind, unsigned flags);
8128
8129/*
8130 * Collect or expand heap in an attempt make the indicated number of
8131 * free blocks available. Should be called until the blocks are
8132 * available (setting `retry` value to `TRUE` unless this is the first
8133 * call in a loop) or until it fails by returning `FALSE`. The `flags`
8134 * argument should be `IGNORE_OFF_PAGE` or 0.
8135 */
8136GC_INNER GC_bool GC_collect_or_expand(word needed_blocks, unsigned flags,
8137 GC_bool retry);
8138
8139/*
8140 * Make the indicated object free list nonempty, and return its head (the
8141 * first object on the free list). The object must be removed from the free
8142 * list by the caller. The size is in granules.
8143 */
8144GC_INNER ptr_t GC_allocobj(size_t lg, int kind);
8145
8146#ifdef GC_ADD_CALLER
8147/*
8148 * `GC_DBG_EXTRAS` is used by the collector debug API functions (unlike
8149 * `GC_EXTRAS` used by the debug API macros) thus `GC_RETURN_ADDR_PARENT`
8150 * (pointing to client caller) should be used if possible.
8151 */
8152# ifdef GC_HAVE_RETURN_ADDR_PARENT
8153# define GC_DBG_EXTRAS GC_RETURN_ADDR_PARENT, NULL, 0
8154# else
8155# define GC_DBG_EXTRAS GC_RETURN_ADDR, NULL, 0
8156# endif
8157#else
8158# define GC_DBG_EXTRAS "unknown", 0
8159#endif /* !GC_ADD_CALLER */
8160
8161#ifdef GC_COLLECT_AT_MALLOC
8162/*
8163 * Parameter to force collection at every `malloc` of size greater or
8164 * equal to the given value. This might be handy during debugging.
8165 * Note: this variable is visible outside for debugging purpose.
8166 */
8167extern size_t GC_dbg_collect_at_malloc_min_lb;
8168
8169# define GC_DBG_COLLECT_AT_MALLOC(lb) \
8170 (void)((lb) >= GC_dbg_collect_at_malloc_min_lb ? (GC_gcollect(), 0) : 0)
8171#else
8172# define GC_DBG_COLLECT_AT_MALLOC(lb) (void)0
8173#endif /* !GC_COLLECT_AT_MALLOC */
8174
8175/* Allocation routines that bypass the thread-local cache. */
8176
8177#if defined(THREAD_LOCAL_ALLOC) && defined(GC_GCJ_SUPPORT)
8178/*
8179 * Allocate an object, clear it, and store the pointer to the type
8180 * structure ("vtable" in `gcj`). This adds a byte at the end of the
8181 * object if `GC_malloc` would.
8182 */
8183GC_INNER void *GC_core_gcj_malloc(size_t lb, const void *vtable_ptr,
8184 unsigned flags);
8185#endif
8186
8187GC_INNER void GC_init_headers(void);
8188
8189/*
8190 * Install a header for block `h`. Return `NULL` on failure, or the
8191 * uninitialized header otherwise.
8192 */
8193GC_INNER hdr *GC_install_header(struct hblk *h);
8194
8195/*
8196 * Set up forwarding counts for block `h` of size `sz`. Return `FALSE`
8197 * on failure.
8198 */
8199GC_INNER GC_bool GC_install_counts(struct hblk *h, size_t sz);
8200
8201/* Remove the header for block `h`. */
8202GC_INNER void GC_remove_header(struct hblk *h);
8203
8204/* Remove forwarding counts for `h`. */
8205GC_INNER void GC_remove_counts(struct hblk *h, size_t sz);
8206
8207/* A non-macro variant of the header location routine. */
8208GC_INNER hdr *GC_find_header(const void *h);
8209
8210/*
8211 * Get `HBLKSIZE`-aligned heap memory chunk from the OS and add the
8212 * chunk to `GC_our_memory`. Return `NULL` if out of memory.
8213 */
8214GC_INNER ptr_t GC_os_get_mem(size_t bytes);
8215
8216#if defined(NO_FIND_LEAK) && defined(SHORT_DBG_HDRS)
8217# define GC_print_all_errors() (void)0
8218# define GC_check_heap() (void)0
8219# define GC_print_all_smashed() (void)0
8220#else
8221/*
8222 * Print smashed and leaked objects, if any. Clear the lists of such
8223 * objects. Called without the allocator lock held.
8224 */
8225GC_INNER void GC_print_all_errors(void);
8226
8227/*
8228 * Check that all objects in the heap with debugging info are intact.
8229 * Add any that are not to `GC_smashed` list.
8230 */
8231GC_EXTERN void (*GC_check_heap)(void);
8232
8233/* Print `GC_smashed` list if it is not empty. Then clear the list. */
8234GC_EXTERN void (*GC_print_all_smashed)(void);
8235#endif
8236
8237/*
8238 * If possible, print (using `GC_err_printf()`) a more detailed
8239 * description (terminated with "\n") of the object referred to by `p`.
8240 */
8241GC_EXTERN void (*GC_print_heap_obj)(ptr_t p);
8242
8243GC_INNER void GC_default_print_heap_obj_proc(ptr_t p);
8244
8245#if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG)
8246/*
8247 * Print an address map of the process. The caller should hold the
8248 * allocator lock.
8249 */
8250void GC_print_address_map(void);
8251#endif
8252
8253#ifdef NO_FIND_LEAK
8254# define GC_find_leak_inner FALSE
8255#else
8256# define GC_find_leak_inner GC_find_leak
8257# ifndef SHORT_DBG_HDRS
8258/*
8259 * Do not immediately deallocate object on `free()` in the find-leak mode,
8260 * just mark it as freed (and deallocate it after collection).
8261 */
8262GC_EXTERN GC_bool GC_findleak_delay_free;
8263# endif
8264#endif /* !NO_FIND_LEAK */
8265
8266#if defined(NO_FIND_LEAK) && defined(SHORT_DBG_HDRS)
8267# define get_have_errors() FALSE
8268#elif defined(AO_HAVE_store)
8269# define GC_SET_HAVE_ERRORS() AO_store(&GC_have_errors, (AO_t)TRUE)
8270# define get_have_errors() \
8271 ((GC_bool)AO_load(&GC_have_errors)) /*< no barrier */
8272#else
8273# define GC_SET_HAVE_ERRORS() (void)(GC_have_errors = TRUE)
8274/*
8275 * We saw a smashed or leaked object. Call error printing routine
8276 * occasionally. It is OK to read it not acquiring the allocator lock.
8277 * Once set to `TRUE`, it is never cleared.
8278 */
8279# define get_have_errors() GC_have_errors
8280#endif /* !AO_HAVE_store */
8281
8282#define VERBOSE 2
8283#if !defined(NO_CLOCK) || !defined(SMALL_CONFIG)
8284/*
8285 * Value of 1 generates basic collector log; `VERBOSE` generates additional
8286 * messages.
8287 */
8288GC_EXTERN int GC_print_stats;
8289#else /* SMALL_CONFIG */
8290/*
8291 * Defined as a macro to aid the compiler to remove the relevant message
8292 * character strings from the executable (with a particular level of
8293 * optimizations).
8294 */
8295# define GC_print_stats 0
8296#endif
8297
8298#ifdef KEEP_BACK_PTRS
8299/* Number of random backtraces to generate for each collection. */
8300GC_EXTERN long GC_backtraces;
8301#endif
8302
8303/*
8304 * A trivial (linear congruential) pseudo-random numbers generator,
8305 * safe for the concurrent usage.
8306 */
8307#define GC_RAND_MAX ((int)(~0U >> 1))
8308#if defined(AO_HAVE_store) && defined(THREAD_SANITIZER)
8309# define GC_RAND_STATE_T volatile AO_t
8310# define GC_RAND_NEXT(pseed) GC_rand_next(pseed)
8311GC_INLINE int
8312GC_rand_next(GC_RAND_STATE_T *pseed)
8313{
8314 AO_t next = (AO_t)((AO_load(pseed) * (unsigned32)1103515245UL + 12345)
8315 & (unsigned32)((unsigned)GC_RAND_MAX));
8316 AO_store(pseed, next);
8317 return (int)next;
8318}
8319#else
8320# define GC_RAND_STATE_T unsigned32
8321# define GC_RAND_NEXT(pseed) /*< overflow and race are OK */ \
8322 (int)(*(pseed) = (*(pseed) * (unsigned32)1103515245UL + 12345) \
8323 & (unsigned32)((unsigned)GC_RAND_MAX))
8324#endif
8325
8326#ifdef MAKE_BACK_GRAPH
8327GC_EXTERN GC_bool GC_print_back_height;
8328void GC_print_back_graph_stats(void);
8329#endif
8330
8331#ifdef THREADS
8332/*
8333 * Explicitly deallocate the object when we already hold the allocator lock.
8334 * Only used for internally allocated objects.
8335 */
8336GC_INNER void GC_free_inner(void *p);
8337#endif
8338
8339#ifdef VALGRIND_TRACKING
8340# define FREE_PROFILER_HOOK(p) GC_free_profiler_hook(p)
8341#else
8342# define FREE_PROFILER_HOOK(p) (void)(p)
8343#endif
8344
8345/*
8346 * Macros used for collector internal allocation. These assume the
8347 * allocator lock is held.
8348 */
8349#ifdef DBG_HDRS_ALL
8350
8351/*
8352 * An allocation function for internal use. Normally internally allocated
8353 * objects do not have debug information. But in this case, we need to make
8354 * sure that all objects have debug headers.
8355 */
8356GC_INNER void *GC_debug_generic_malloc_inner(size_t lb, int kind,
8357 unsigned flags);
8358
8359# define GC_INTERNAL_MALLOC(lb, k) GC_debug_generic_malloc_inner(lb, k, 0)
8360# define GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE(lb, k) \
8361 GC_debug_generic_malloc_inner(lb, k, IGNORE_OFF_PAGE)
8362# ifdef THREADS
8363/* Used internally; we assume it is called correctly. */
8364GC_INNER void GC_debug_free_inner(void *p);
8365
8366# define GC_INTERNAL_FREE GC_debug_free_inner
8367# else
8368# define GC_INTERNAL_FREE GC_debug_free
8369# endif
8370#else
8371# define GC_INTERNAL_MALLOC(lb, k) GC_generic_malloc_inner(lb, k, 0)
8372# define GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE(lb, k) \
8373 GC_generic_malloc_inner(lb, k, IGNORE_OFF_PAGE)
8374# ifdef THREADS
8375# define GC_INTERNAL_FREE GC_free_inner
8376# else
8377# define GC_INTERNAL_FREE GC_free
8378# endif
8379#endif /* !DBG_HDRS_ALL */
8380
8381/* Memory unmapping routines. */
8382#ifdef USE_MUNMAP
8383
8384/*
8385 * Unmap blocks that have not been recently touched. This is the only
8386 * way blocks are ever unmapped.
8387 */
8388GC_INNER void GC_unmap_old(unsigned threshold);
8389
8390/*
8391 * Merge all unmapped blocks that are adjacent to other free blocks.
8392 * This may involve remapping, since all blocks are either fully mapped
8393 * or fully unmapped. Returns `TRUE` if at least one block was merged.
8394 */
8395GC_INNER GC_bool GC_merge_unmapped(void);
8396
8397GC_INNER void GC_unmap(ptr_t start, size_t bytes);
8398GC_INNER void GC_remap(ptr_t start, size_t bytes);
8399
8400/*
8401 * Two adjacent blocks have already been unmapped and are about to be merged.
8402 * Unmap the whole block. This typically requires that we unmap a small
8403 * section in the middle that was not previously unmapped due to alignment
8404 * constraints.
8405 */
8406GC_INNER void GC_unmap_gap(ptr_t start1, size_t bytes1, ptr_t start2,
8407 size_t bytes2);
8408#endif
8409
8410#ifdef CAN_HANDLE_FORK
8411/*
8412 * Fork-handling mode:
8413 * - 0 means no `fork` handling is requested (but client could anyway
8414 * call `fork()` provided it is surrounded with `GC_atfork_prepare`,
8415 * `GC_atfork_parent`, `GC_atfork_child` calls);
8416 * - (-1) means the collector tries to use `pthread_at_fork()` if it is
8417 * available (if it succeeds, then `GC_handle_fork` value is changed to
8418 * one), a portable client should nonetheless surround `fork()` with
8419 * `GC_atfork_prepare()` and the accompanying routines (for the case
8420 * of `pthread_at_fork()` failure or absence);
8421 * - 1 (or other values) means client fully relies on `pthread_at_fork`
8422 * (so if it is missing or failed, then `abort` occurs in `GC_init()`),
8423 * `GC_atfork_prepare` and the accompanying routines are no-op in such
8424 * a case.
8425 *
8426 * Note: the value is examined by `GC_thr_init`.
8427 */
8428GC_EXTERN int GC_handle_fork;
8429
8430# ifdef THREADS
8431# if defined(SOLARIS) && !defined(_STRICT_STDC)
8432/* Update `pthreads` id in the child process right after `fork`. */
8433GC_INNER void GC_stackbase_info_update_after_fork(void);
8434# else
8435# define GC_stackbase_info_update_after_fork() (void)0
8436# endif
8437# endif
8438#endif /* CAN_HANDLE_FORK */
8439
8440#ifdef NO_MANUAL_VDB
8441# define GC_manual_vdb FALSE
8442# define GC_auto_incremental GC_incremental
8443# define GC_dirty(p) (void)(p)
8444# define REACHABLE_AFTER_DIRTY(p) (void)(p)
8445#else
8446/*
8447 * The incremental collection is in the manual VDB mode.
8448 * Assumes `GC_incremental` is `TRUE`. Should not be modified once
8449 * `GC_incremental` is set to `TRUE`.
8450 */
8451GC_EXTERN GC_bool GC_manual_vdb;
8452
8453# define GC_auto_incremental (GC_incremental && !GC_manual_vdb)
8454
8455/*
8456 * Manually mark the page containing `p` as dirty. Logically, this
8457 * dirties the entire object. Does not require locking.
8458 * Exported and marked as `noinline` for the purpose of some clients that
8459 * need to patch the symbol when using write barrier validation.
8460 */
8461GC_API_PATCHABLE void GC_dirty_inner(const void *p);
8462
8463# define GC_dirty(p) (GC_manual_vdb ? GC_dirty_inner(p) : (void)0)
8464# define REACHABLE_AFTER_DIRTY(p) GC_reachable_here(p)
8465#endif /* !NO_MANUAL_VDB */
8466
8467#ifdef GC_DISABLE_INCREMENTAL
8468# define GC_incremental FALSE
8469#else
8470/*
8471 * Using incremental/generational collection. Assumes dirty bits are
8472 * being maintained.
8473 */
8474GC_EXTERN GC_bool GC_incremental;
8475
8476/* Virtual dirty bit (VDB) implementations; each one exports the following. */
8477
8478/*
8479 * Initialize the virtual dirty bit implementation. Returns `TRUE` if
8480 * virtual dirty bits are maintained (otherwise it is OK to be called again
8481 * if the client calls `GC_enable_incremental()` once more).
8482 */
8483GC_INNER GC_bool GC_dirty_init(void);
8484
8485/*
8486 * Retrieve system dirty bits for the heap to a local buffer (unless
8487 * `output_unneeded`). The caller should set `output_unneeded` to indicate
8488 * that reading of the retrieved dirty bits is not planned till the next
8489 * retrieval. Restore the systems notion of which pages are dirty.
8490 * We assume that either the world is stopped or it is OK to lose dirty bits
8491 * while it is happening (`GC_enable_incremental()` is the caller and
8492 * `output_unneeded` is `TRUE` at least if the multi-threading support is on).
8493 */
8494GC_INNER void GC_read_dirty(GC_bool output_unneeded);
8495
8496/*
8497 * Is the `HBLKSIZE`-sized page at `h` marked dirty in the local buffer?
8498 * If the actual page size is different, this returns `TRUE` if any of
8499 * the pages overlapping `h` are dirty. This routine may err on the side
8500 * of labeling pages as dirty (and this implementation does).
8501 */
8502GC_INNER GC_bool GC_page_was_dirty(struct hblk *h);
8503
8504/*
8505 * Block `h` is about to be written or allocated shortly. Ensure that
8506 * all pages containing any part of the `nblocks` `hblk` entities starting
8507 * at `h` are no longer write-protected (by the virtual dirty bit
8508 * implementation). I.e., this is a call that:
8509 * - hints that [`h`, `h + nblocks`) is about to be written;
8510 * - guarantees that protection is removed;
8511 * - may speed up some virtual dirty bit implementations;
8512 * - may be essential if we need to ensure that pointer-free system
8513 * call buffers in the heap are not protected.
8514 */
8515GC_INNER void GC_remove_protection(struct hblk *h, size_t nblocks,
8516 GC_bool is_ptrfree);
8517
8518# if !defined(NO_VDB_FOR_STATIC_ROOTS) && !defined(PROC_VDB)
8519/* Is VDB working for static roots? */
8520GC_INNER GC_bool GC_is_vdb_for_static_roots(void);
8521# endif
8522
8523# ifdef CAN_HANDLE_FORK
8524# if defined(PROC_VDB) || defined(SOFT_VDB) \
8525 || (defined(MPROTECT_VDB) && defined(DARWIN) && defined(THREADS))
8526/*
8527 * Update pid-specific resources (like `/proc` file descriptors) needed
8528 * by the dirty bits implementation after `fork` in the child process.
8529 */
8530GC_INNER void GC_dirty_update_child(void);
8531# else
8532# define GC_dirty_update_child() (void)0
8533# endif
8534# endif /* CAN_HANDLE_FORK */
8535
8536# if defined(MPROTECT_VDB) && defined(DARWIN)
8537EXTERN_C_END
8538# include <pthread.h>
8539EXTERN_C_BEGIN
8540# ifdef THREADS
8541GC_INNER int GC_inner_pthread_create(pthread_t *t,
8542 GC_PTHREAD_CREATE_CONST pthread_attr_t *a,
8543 void *(*fn)(void *), void *arg);
8544# else
8545# define GC_inner_pthread_create pthread_create
8546# endif
8547# endif
8548#endif /* !GC_DISABLE_INCREMENTAL */
8549
8550#if defined(COUNT_PROTECTED_REGIONS) && defined(MPROTECT_VDB)
8551/*
8552 * Do actions on heap growth, if needed, to prevent hitting the OS kernel
8553 * limit on the VM map regions.
8554 */
8555GC_INNER void GC_handle_protected_regions_limit(void);
8556#else
8557# define GC_handle_protected_regions_limit() (void)0
8558#endif
8559
8560/* Same as `GC_base` but accepts and returns a pointer to `const` object. */
8561#define GC_base_C(p) ((const void *)GC_base(GC_CAST_AWAY_CONST_PVOID(p)))
8562
8563/* Some debugging print routines. */
8564void GC_print_block_list(void);
8565void GC_print_hblkfreelist(void);
8566void GC_print_heap_sects(void);
8567void GC_print_static_roots(void);
8568
8569#ifdef KEEP_BACK_PTRS
8570/*
8571 * Store back pointer to `source` in `dest`, if that appears to be
8572 * possible. This is not completely safe, since we may mistakenly
8573 * conclude that `dest` has a debugging wrapper. But the error
8574 * probability is very small, and this should not be used in
8575 * production code. We assume that `dest` is the real base pointer.
8576 * `source` should usually be a pointer to the interior of an object.
8577 */
8578GC_INNER void GC_store_back_pointer(ptr_t source, ptr_t dest);
8579
8580GC_INNER void GC_marked_for_finalization(ptr_t dest);
8581# define GC_STORE_BACK_PTR(source, dest) GC_store_back_pointer(source, dest)
8582# define GC_MARKED_FOR_FINALIZATION(dest) GC_marked_for_finalization(dest)
8583#else
8584# define GC_STORE_BACK_PTR(source, dest) (void)(source)
8585# define GC_MARKED_FOR_FINALIZATION(dest)
8586#endif /* !KEEP_BACK_PTRS */
8587
8588/* Make arguments appear live to compiler. */
8589void GC_noop6(word, word, word, word, word, word);
8590
8591#ifndef GC_ATTR_FORMAT_PRINTF
8592# if GC_GNUC_PREREQ(3, 0)
8593# define GC_ATTR_FORMAT_PRINTF(spec_argnum, first_checked) \
8594 __attribute__((__format__(__printf__, spec_argnum, first_checked)))
8595# else
8596# define GC_ATTR_FORMAT_PRINTF(spec_argnum, first_checked)
8597# endif
8598#endif
8599
8600/* Logging and diagnostic output. */
8601
8602/*
8603 * `GC_printf` is used typically on client explicit print requests.
8604 * A variant of `printf` that does not allocate, 1 KB total output length.
8605 * (It uses `sprintf()` internally; hopefully the latter does not allocate
8606 * memory for `long` arguments.) For all `GC_*_printf` routines,
8607 * it is recommended to put "\n" at the end of `format` string (for the
8608 * output atomicity).
8609 */
8610GC_API_PRIV void GC_printf(const char *format, ...)
8611 GC_ATTR_FORMAT_PRINTF(1, 2);
8612GC_API_PRIV void GC_err_printf(const char *format, ...)
8613 GC_ATTR_FORMAT_PRINTF(1, 2);
8614
8615/*
8616 * The basic logging routine. Typically, it is called directly only inside
8617 * various `DEBUG_*` blocks.
8618 */
8619GC_API_PRIV void GC_log_printf(const char *format, ...)
8620 GC_ATTR_FORMAT_PRINTF(1, 2);
8621
8622#ifndef GC_ANDROID_LOG
8623# define GC_PRINT_STATS_FLAG (GC_print_stats != 0)
8624# define GC_INFOLOG_PRINTF GC_COND_LOG_PRINTF
8625/*
8626 * The "verbose" logging routine which is called only if `GC_print_stats`
8627 * is `VERBOSE`.
8628 */
8629# define GC_verbose_log_printf GC_log_printf
8630#else
8631extern GC_bool GC_quiet;
8632# define GC_PRINT_STATS_FLAG (!GC_quiet)
8633/* `INFO`/`DBG` loggers are enabled even if `GC_print_stats` is off. */
8634# ifndef GC_INFOLOG_PRINTF
8635# define GC_INFOLOG_PRINTF \
8636 if (GC_quiet) { \
8637 } else \
8638 GC_info_log_printf
8639# endif
8640GC_INNER void GC_info_log_printf(const char *format, ...)
8641 GC_ATTR_FORMAT_PRINTF(1, 2);
8642GC_INNER void GC_verbose_log_printf(const char *format, ...)
8643 GC_ATTR_FORMAT_PRINTF(1, 2);
8644#endif /* GC_ANDROID_LOG */
8645
8646#if defined(SMALL_CONFIG) || defined(GC_ANDROID_LOG)
8647# define GC_ERRINFO_PRINTF GC_INFOLOG_PRINTF
8648#else
8649# define GC_ERRINFO_PRINTF GC_log_printf
8650#endif
8651
8652/*
8653 * Convenient wrapper macros over `GC_log_printf()` and
8654 * `GC_verbose_log_printf()`.
8655 */
8656#define GC_COND_LOG_PRINTF \
8657 if (LIKELY(!GC_print_stats)) { \
8658 } else \
8659 GC_log_printf
8660#define GC_VERBOSE_LOG_PRINTF \
8661 if (LIKELY(GC_print_stats != VERBOSE)) { \
8662 } else \
8663 GC_verbose_log_printf
8664#ifndef GC_DBGLOG_PRINTF
8665# define GC_DBGLOG_PRINTF \
8666 if (!GC_PRINT_STATS_FLAG) { \
8667 } else \
8668 GC_log_printf
8669#endif
8670
8671/* Write `s` to `stderr`, but do not buffer, do not add newlines, do not... */
8672void GC_err_puts(const char *s);
8673
8674/*
8675 * A handy macro for logging size values (of `word` type) in KiB, rounding
8676 * to nearest value.
8677 */
8678#define TO_KiB_UL(v) ((unsigned long)(((v) + ((1 << 9) - 1)) >> 10))
8679
8680#ifdef USE_MUNMAP
8681GC_EXTERN unsigned GC_unmap_threshold; /*< defined in `alloc.c` file */
8682
8683/*
8684 * Force memory unmapping on every collection. Has no effect on
8685 * implicitly-initiated collections.
8686 */
8687GC_EXTERN GC_bool GC_force_unmap_on_gcollect;
8688#endif
8689
8690#ifdef MSWIN32
8691GC_EXTERN GC_bool GC_no_win32_dlls; /*< defined in `os_dep.c` file */
8692
8693/* Is this a Windows NT derivative (i.e. NT, Win2K, XP or later)? */
8694GC_EXTERN GC_bool GC_wnt;
8695#endif
8696
8697#ifdef THREADS
8698# if (defined(MSWIN32) && !defined(CONSOLE_LOG)) || defined(MSWINCE)
8699GC_EXTERN CRITICAL_SECTION GC_write_cs;
8700# ifdef GC_ASSERTIONS
8701/*
8702 * Set to `TRUE` only if `GC_stop_world()` has acquired `GC_write_cs`.
8703 * Protected by `GC_write_cs`.
8704 */
8705GC_EXTERN GC_bool GC_write_disabled;
8706# endif
8707# endif /* MSWIN32 || MSWINCE */
8708# ifdef NEED_FAULT_HANDLER_LOCK
8709/*
8710 * Acquire the spin lock we use to update dirty bits. Threads should
8711 * not get stopped holding it. But we may acquire and release it during
8712 * `GC_remove_protection()` call.
8713 */
8714# define GC_acquire_dirty_lock() \
8715 do { /* Empty. */ \
8716 } while (AO_test_and_set_acquire(&GC_fault_handler_lock) == AO_TS_SET)
8717# define GC_release_dirty_lock() AO_CLEAR(&GC_fault_handler_lock)
8718# else
8719# define GC_acquire_dirty_lock() (void)0
8720# define GC_release_dirty_lock() (void)0
8721# endif
8722# ifdef MSWINCE
8723GC_EXTERN GC_bool GC_dont_query_stack_min;
8724# endif
8725#elif defined(IA64)
8726/* Value returned from register flushing routine (`ar.bsp`). */
8727GC_EXTERN ptr_t GC_save_regs_ret_val;
8728#endif /* !THREADS */
8729
8730#ifdef THREAD_LOCAL_ALLOC
8731GC_EXTERN GC_bool GC_world_stopped; /*< defined in `alloc.c` file */
8732
8733/*
8734 * We must explicitly mark `ptrfree` and `gcj` free lists, since the
8735 * free list links would not otherwise be found. We also set them in
8736 * the normal free lists, since that involves touching less memory than
8737 * if we scanned them normally.
8738 */
8739GC_INNER void GC_mark_thread_local_free_lists(void);
8740#endif
8741
8742#if defined(GLIBC_2_19_TSX_BUG) && defined(GC_PTHREADS_PARAMARK)
8743/* Parse string like `<major>[.<minor>[<tail>]]` and return `major` value. */
8744GC_INNER int GC_parse_version(int *pminor, const char *pverstr);
8745#endif
8746
8747#if defined(MPROTECT_VDB) && defined(GWW_VDB)
8748/*
8749 * Returns `TRUE` if `GetWriteWatch()` is available. May be called
8750 * repeatedly. May be called with or without the allocator lock held.
8751 */
8752GC_INNER GC_bool GC_gww_dirty_init(void);
8753#endif
8754
8755#if defined(CHECKSUMS) || defined(PROC_VDB)
8756/* Could any valid GC heap pointer ever have been written to this page? */
8757GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk *h);
8758#endif
8759
8760#ifndef GC_NO_DEINIT
8761GC_INNER void GC_reset_freelist(void);
8762GC_INNER void GC_reset_obj_kinds(void);
8763# ifdef CHECKSUMS
8764void GC_reset_check_page(void);
8765# endif
8766# ifdef THREADS
8767GC_INNER void GC_reset_threads(void);
8768# endif
8769# ifdef THREAD_LOCAL_ALLOC
8770GC_INNER void GC_reset_thread_local_initialization(void);
8771# endif
8772#endif
8773
8774#ifdef CHECKSUMS
8775# ifdef MPROTECT_VDB
8776void GC_record_fault(struct hblk *h);
8777# endif
8778void GC_check_dirty(void);
8779#endif
8780
8781GC_INNER void GC_setpagesize(void);
8782
8783GC_INNER void GC_initialize_offsets(void);
8784
8785#if defined(REDIR_MALLOC_AND_LINUXTHREADS) \
8786 && !defined(REDIRECT_MALLOC_IN_HEADER)
8787GC_INNER void GC_init_lib_bounds(void);
8788#else
8789# define GC_init_lib_bounds() (void)0
8790#endif
8791
8792#ifdef REDIR_MALLOC_AND_LINUXTHREADS
8793/*
8794 * Find the text (code) mapping for the library whose name, after
8795 * stripping the directory part, starts with `nm`.
8796 */
8797GC_INNER GC_bool GC_text_mapping(const char *nm, ptr_t *startp, ptr_t *endp);
8798#endif
8799
8800#if defined(USE_WINALLOC) && !defined(REDIRECT_MALLOC)
8801GC_INNER void GC_add_current_malloc_heap(void);
8802#endif
8803
8804#ifdef MAKE_BACK_GRAPH
8805/*
8806 * Rebuild the representation of the backward reachability graph.
8807 * Does not examine mark bits. Could be called before collection.
8808 */
8809GC_INNER void GC_build_back_graph(void);
8810
8811GC_INNER void GC_traverse_back_graph(void);
8812#endif
8813
8814#ifdef MSWIN32
8815GC_INNER void GC_init_win32(void);