Initial project import
This commit is contained in:
commit
23f2d29e32
11957 files changed
+1754577
No files matched your search
+50
@@ -0,0 +1,50 @@
|
||||
The libgc source is distributed here as an amalgamation (https://sqlite.org/amalgamation.html).
|
||||
This means that, rather than mirroring the entire bdwgc repo here, the amalgamate tool
|
||||
was used to bundle all C files and local includes together into a single C file, which is
|
||||
much easier to handle. This helps keep the V source distribution small, can reduce compile
|
||||
times by 3%-15%, and can help C compilers generate more optimized code.
|
||||
|
||||
For generating the libgc amalgamation, the following commands were used:
|
||||
|
||||
git clone https://github.com/ivmai/bdwgc.git
|
||||
cd bdwgc
|
||||
./autogen.sh
|
||||
./configure --enable-threads=pthreads \
|
||||
--enable-static \
|
||||
--enable-shared=no \
|
||||
--enable-thread-local-alloc=no \
|
||||
--enable-parallel-mark \
|
||||
--enable-single-obj-compilation \
|
||||
--enable-gc-debug
|
||||
|
||||
../../../cmd/tools/amalgamate -o ../gc.c \
|
||||
-b atomic_ops.h \
|
||||
-b gc/gc.h \
|
||||
-b gc/gc_backptr.h \
|
||||
-b gc/gc_disclaim.h \
|
||||
-b gc/gc_gcj.h \
|
||||
-b gc/gc_inline.h \
|
||||
-b gc/gc_mark.h \
|
||||
-b gc/gc_pthread_redirects.h \
|
||||
-b gc/gc_tiny_fl.h \
|
||||
-b gc/gc_typed.h \
|
||||
-b gc/javaxfc.h \
|
||||
-b il/PCR_IL.h \
|
||||
-b mm/PCR_MM.h \
|
||||
-b psp2-support.h \
|
||||
-b stubinfo.h \
|
||||
-b th/PCR_ThCtl.h \
|
||||
-b vd/PCR_VD.h \
|
||||
-s include \
|
||||
-s include/private \
|
||||
extra/gc.c
|
||||
|
||||
The updated header files are then copied into the include/gc directory. We can delete
|
||||
include/gc/gc_cpp.h since this header is not needed by V. And, we can remove the git
|
||||
repo for bdwgc.
|
||||
|
||||
cp include/gc/*.h ../include/gc
|
||||
cd ..
|
||||
rm include/gc/gc_cpp.h
|
||||
rm -rf bdwgc
|
||||
|
||||
Vendored
+45849
File diff suppressed because it is too large.
Load diff
+16
@@ -0,0 +1,16 @@
|
||||
/* This file is installed for backward compatibility. */
|
||||
#include "gc/gc.h"
|
||||
|
||||
/* Fix for vlang/v#27179: the original version of this file cast the
|
||||
* pointer argument to V's `u64` type, which makes the header illegal
|
||||
* to include from standalone C (any C shim doing `#include <gc.h>`
|
||||
* via V's -I@VEXEROOT/thirdparty/libgc/include path would fail with
|
||||
* "unknown type: u64"). `GC_word` is the libgc-defined type that
|
||||
* `GC_noop1` actually takes (gc/gc.h, typedef'd to uintptr_t on most
|
||||
* platforms) — using it makes this header valid both from V code and
|
||||
* from plain C shims. */
|
||||
#ifndef _MSC_VER
|
||||
__attribute__ ((weak)) GC_API void GC_CALL GC_noop1_ptr(volatile void *p) {
|
||||
GC_noop1((GC_word)p);
|
||||
}
|
||||
#endif
|
||||
+426
@@ -0,0 +1,426 @@
|
||||
/*
|
||||
* Copyright (c) 1993-1994 by Xerox Corporation. All rights reserved.
|
||||
*
|
||||
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
||||
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
||||
*
|
||||
* Permission is hereby granted to use or copy this program
|
||||
* for any purpose, provided the above notices are retained on all copies.
|
||||
* Permission to modify the code and to distribute modified code is granted,
|
||||
* provided the above notices are retained, and a notice that the code was
|
||||
* modified is included with the above copyright notice.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Cords are immutable character strings. A number of operations on long
|
||||
* cords are much more efficient than their counterpart in platform
|
||||
* `strings.h` file. In particular, concatenation takes constant time
|
||||
* independent of the length of the arguments. (Cords are represented as
|
||||
* trees, with internal nodes representing concatenation and leaves
|
||||
* consisting of either C strings or a functional description of the string.)
|
||||
*
|
||||
* The following are reasonable applications of cords. They would perform
|
||||
* unacceptably if C strings were used:
|
||||
* - A compiler that produces assembly language output by repeatedly
|
||||
* concatenating instructions onto a cord representing the output file;
|
||||
* - A text editor that converts the input file to a cord, and then
|
||||
* performs editing operations by producing a new cord representing the
|
||||
* file after each character change (and keeping the old ones in an edit
|
||||
* history).
|
||||
*
|
||||
* For optimal performance, cords should be built by concatenating short
|
||||
* sections. This interface is designed for maximum compatibility with
|
||||
* C strings. ASCII NUL characters may be embedded in cords using
|
||||
* `CORD_from_fn`. This is handled correctly, but `CORD_to_char_star` will
|
||||
* produce a string with embedded NUL characters when given such a cord.
|
||||
*
|
||||
* This interface is fairly big, largely for performance reasons.
|
||||
* The most basic constants, functions and types:
|
||||
*
|
||||
* - `CORD` - the type of a cord;
|
||||
* - `CORD_EMPTY` - empty cord;
|
||||
* - `CORD_len(cord)` - length of a cord;
|
||||
* - `CORD_cat(cord1, cord2)` - concatenation of two cords;
|
||||
* - `CORD_substr(cord, start, len)` - substring (or subcord);
|
||||
* - `CORD_pos i; CORD_FOR(i, cord) { ... CORD_pos_fetch(i) ... }` - examine
|
||||
* each character in a cord (`CORD_pos_fetch(i)` is the `char`);
|
||||
* - `CORD_fetch(i)` - retrieve `i`'th character (slowly);
|
||||
* - `CORD_cmp(cord1, cord2)` - compare two cords;
|
||||
* - `CORD_from_file(FILE *f)` - turn a read-only file into a cord;
|
||||
* - `CORD_to_char_star(cord)` - convert to C string (non-`NULL` C constant
|
||||
* strings are cords);
|
||||
* - `CORD_printf(CORD format, ...)` and friends - cord's variant of
|
||||
* `printf` (use "%r" for cords).
|
||||
*/
|
||||
|
||||
#ifndef CORD_H
|
||||
#define CORD_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(GC_DLL) && !defined(CORD_NOT_DLL) && !defined(CORD_API)
|
||||
/* Same as for `GC_API` in `gc_config_macros.h` file. */
|
||||
# ifdef CORD_BUILD
|
||||
# if defined(__MINGW32__) && !defined(__cplusplus) || defined(__CEGCC__)
|
||||
# define CORD_API __declspec(dllexport)
|
||||
# elif defined(_MSC_VER) || defined(__DMC__) || defined(__BORLANDC__) \
|
||||
|| defined(__CYGWIN__) || defined(__MINGW32__) \
|
||||
|| defined(__WATCOMC__)
|
||||
# define CORD_API extern __declspec(dllexport)
|
||||
# elif defined(__GNUC__) && !defined(GC_NO_VISIBILITY) \
|
||||
&& (__GNUC__ >= 4 || defined(GC_VISIBILITY_HIDDEN_SET))
|
||||
/* Only matters if used in conjunction with `-fvisibility=hidden` option. */
|
||||
# define CORD_API extern __attribute__((__visibility__("default")))
|
||||
# endif
|
||||
# else /* !CORD_BUILD */
|
||||
# if defined(__BORLANDC__) || defined(__CEGCC__) || defined(__CYGWIN__) \
|
||||
|| defined(__DMC__) || defined(_MSC_VER)
|
||||
# define CORD_API __declspec(dllimport)
|
||||
# elif defined(__MINGW32__) || defined(__WATCOMC__)
|
||||
# define CORD_API extern __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
#endif /* GC_DLL */
|
||||
|
||||
#ifndef CORD_API
|
||||
# define CORD_API extern
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Cords have type `const char *`. This is cheating quite a bit, and not
|
||||
* 100% portable. But it means that nonempty character string constants
|
||||
* may be used as cords directly, provided the string is never modified in
|
||||
* place. The empty cord is represented by, and can be written as, `NULL`.
|
||||
*/
|
||||
typedef const char *CORD;
|
||||
|
||||
/** An empty cord is always represented as nil. */
|
||||
#define CORD_EMPTY 0
|
||||
|
||||
/** Is a nonempty cord represented as a C string? */
|
||||
#define CORD_IS_STRING(s) (*(s) != '\0')
|
||||
|
||||
/**
|
||||
* Concatenate two cords. If the arguments are C strings, they may not
|
||||
* be subsequently altered.
|
||||
*/
|
||||
CORD_API CORD CORD_cat(CORD, CORD);
|
||||
|
||||
/**
|
||||
* Concatenate a cord and a C string with known length. Except for the
|
||||
* empty string case, this is a special case of `CORD_cat`. Since the
|
||||
* length is known, it can be faster. The string `y` is shared with
|
||||
* the resulting cord. Hence it should not be altered by the caller.
|
||||
*/
|
||||
CORD_API CORD CORD_cat_char_star(CORD /* `x` */, const char * /* `y` */,
|
||||
size_t /* `y_len` */);
|
||||
|
||||
/** Compute the length of a cord. */
|
||||
CORD_API size_t CORD_len(CORD);
|
||||
|
||||
/** Cords may be represented by functions defining the `i`-th character. */
|
||||
typedef char (*CORD_fn)(size_t /* `i` */, void * /* `client_data` */);
|
||||
|
||||
/** Turn a functional description into a cord. */
|
||||
CORD_API CORD CORD_from_fn(CORD_fn, void * /* `client_data` */,
|
||||
size_t /* `len` */);
|
||||
|
||||
/**
|
||||
* Return the substring (subcord really) of `x` with length at most `n`,
|
||||
* starting at position `i`. (The initial character has position zero.)
|
||||
*/
|
||||
CORD_API CORD CORD_substr(CORD, size_t /* `i` */, size_t /* `n` */);
|
||||
|
||||
/**
|
||||
* Return the argument, but rebalanced to allow more efficient
|
||||
* character retrieval, substring operations, and comparisons.
|
||||
* This is useful only for cords that were built using repeated
|
||||
* concatenation. Guarantees log time access to the result, unless
|
||||
* the argument was obtained through a large number of repeated
|
||||
* substring operations or the embedded functional descriptions take
|
||||
* longer to evaluate. May reallocate significant parts of the cord.
|
||||
* The argument is not modified; only the result is balanced.
|
||||
*/
|
||||
CORD_API CORD CORD_balance(CORD);
|
||||
|
||||
/*
|
||||
* The following traverse a cord by applying a function to each
|
||||
* character. This is occasionally appropriate, especially where
|
||||
* speed is crucial. But, since C does not have nested functions,
|
||||
* clients of this sort of traversal are clumsy to write. Consider
|
||||
* the functions that operate on cord positions instead.
|
||||
*/
|
||||
|
||||
/** Function to iteratively apply to individual characters in cord. */
|
||||
typedef int (*CORD_iter_fn)(char, void * /* `client_data` */);
|
||||
|
||||
/**
|
||||
* Function to apply to substrings of a cord. Each substring is
|
||||
* a C character string, not a general cord.
|
||||
*/
|
||||
typedef int (*CORD_batched_iter_fn)(const char *, void * /* `client_data` */);
|
||||
|
||||
#define CORD_NO_FN ((CORD_batched_iter_fn)0)
|
||||
|
||||
/**
|
||||
* Apply `f1` to each character in the cord, in ascending order, starting at
|
||||
* position `i`. If `f2` is not `CORD_NO_FN`, then multiple calls to `f1`
|
||||
* may be replaced by a single call to `f2`. The latter is provided only
|
||||
* to allow some optimization by the client. This terminates when the right
|
||||
* end of this string is reached, or when `f1` or `f2` return a nonzero value.
|
||||
* In the latter case this function returns a nonzero value; otherwise
|
||||
* it returns 0. The specified value of `i` must be less than `CORD_len(x)`.
|
||||
*/
|
||||
CORD_API int CORD_iter5(CORD, size_t /* `i` */, CORD_iter_fn /* `f1` */,
|
||||
CORD_batched_iter_fn /* `f2` */,
|
||||
void * /* `client_data` */);
|
||||
|
||||
/** A simpler variant of `CORD_iter5` that starts at 0, and without `f2`. */
|
||||
CORD_API int CORD_iter(CORD, CORD_iter_fn /* `f1` */,
|
||||
void * /* `client_data` */);
|
||||
#define CORD_iter(x, f1, cd) CORD_iter5(x, 0, f1, CORD_NO_FN, cd)
|
||||
|
||||
/**
|
||||
* Similar to `CORD_iter5`, but end-to-beginning. No provisions for
|
||||
* `CORD_batched_iter_fn`.
|
||||
*/
|
||||
CORD_API int CORD_riter4(CORD, size_t /* `i` */, CORD_iter_fn /* `f1` */,
|
||||
void * /* `client_data` */);
|
||||
|
||||
/** A simpler variant of `CORD_riter4` that starts at the end. */
|
||||
CORD_API int CORD_riter(CORD, CORD_iter_fn /* `f1` */,
|
||||
void * /* `client_data` */);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Functions that operate on cord positions. The easy way to traverse cords.
|
||||
* A cord position is logically a pair consisting of a cord and an index
|
||||
* into that cord. But it is much faster to retrieve a character based on
|
||||
* a position than on an index. Unfortunately, positions are big (order of
|
||||
* a few 100 bytes), so allocate them with caution. Things in `cord_pos.h`
|
||||
* file should be treated as opaque, except as described below. Also, note
|
||||
* that `CORD_pos_fetch`, `CORD_next` and `CORD_prev` have both macro and
|
||||
* function definitions. The former may evaluate their argument more than
|
||||
* once.
|
||||
*/
|
||||
#include "cord_pos.h"
|
||||
|
||||
/*
|
||||
* Visible definitions from above:
|
||||
* - `typedef <OPAQUE_but_fairly_big> CORD_pos[1]`;
|
||||
* - `CORD CORD_pos_to_cord(CORD_pos p)` - extract the cord from
|
||||
* a position;
|
||||
* - `size_t CORD_pos_to_index(CORD_pos p)` - extract the current index
|
||||
* from a position;
|
||||
* - `char CORD_pos_fetch(CORD_pos p)` - fetch the character located at
|
||||
* the given position;
|
||||
* - `void CORD_set_pos(CORD_pos p, CORD x, size_t i)` - initialize the
|
||||
* position to refer to the given cord and index;
|
||||
* - `void CORD_next(CORD_pos p)` - advance the position to the next
|
||||
* character;
|
||||
* - `void CORD_prev(CORD_pos p)` - move the position to the preceding
|
||||
* character;
|
||||
* - `int CORD_pos_valid(CORD_pos p)` - check whether the position is
|
||||
* valid, i.e. inside the cord.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define CORD_FOR(pos, cord) \
|
||||
for (CORD_set_pos(pos, cord, 0); CORD_pos_valid(pos); CORD_next(pos))
|
||||
|
||||
/**
|
||||
* An out-of-memory handler to call. Zero value means do nothing special,
|
||||
* just abort. Use of the setter and getter is preferred over the direct
|
||||
* access to the global variable.
|
||||
*/
|
||||
typedef void (*CORD_oom_fn_t)(void);
|
||||
CORD_API void CORD_set_oom_fn(CORD_oom_fn_t);
|
||||
CORD_API CORD_oom_fn_t CORD_get_oom_fn(void);
|
||||
#ifndef CORD_DONT_DECLARE_OOM_FN
|
||||
CORD_API CORD_oom_fn_t CORD_oom_fn;
|
||||
#endif
|
||||
#ifdef CORD_BUILD
|
||||
/* no export */ void CORD__call_oom_fn(void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Dump the representation of `x` to `stdout` in an implementation
|
||||
* defined manner. Intended for debugging only.
|
||||
*/
|
||||
CORD_API void CORD_dump(CORD /* `x` */);
|
||||
|
||||
/*
|
||||
* The following could easily be implemented by the client. They are
|
||||
* provided by the cord library for convenience.
|
||||
*/
|
||||
|
||||
/** Concatenate a character to the end of a cord. */
|
||||
CORD_API CORD CORD_cat_char(CORD, char);
|
||||
|
||||
/** Concatenate `n` cords. */
|
||||
CORD_API CORD CORD_catn(int /* `n` */, /* `CORD` */...);
|
||||
|
||||
/** Return the character in `CORD_substr(x, i, 1)`. */
|
||||
CORD_API char CORD_fetch(CORD /* `x` */, size_t /* `i` */);
|
||||
|
||||
/**
|
||||
* Return a negative value, zero, or a positive value, depending on
|
||||
* whether `x < y`, `x == y`, or `x > y`, respectively.
|
||||
*/
|
||||
CORD_API int CORD_cmp(CORD /* `x` */, CORD /* `y` */);
|
||||
|
||||
/**
|
||||
* A generalization that takes both starting positions for the comparison,
|
||||
* and a limit on the number of characters to be compared.
|
||||
*/
|
||||
CORD_API int CORD_ncmp(CORD /* `x` */, size_t /* `x_start` */, CORD /* `y` */,
|
||||
size_t /* `y_start` */, size_t /* `len` */);
|
||||
|
||||
/**
|
||||
* Find the first occurrence of `s` in `x` at position `start` or later.
|
||||
* Return the position of the first character of `s` in `x`, or
|
||||
* `CORD_NOT_FOUND` if there is none.
|
||||
*/
|
||||
CORD_API size_t CORD_str(CORD /* `x` */, size_t /* `start` */, CORD /* `s` */);
|
||||
|
||||
/**
|
||||
* Return a cord consisting of `i` copies of `c`. Dangerous in
|
||||
* conjunction with `CORD_to_char_star`. `c` could be a NUL character.
|
||||
* The resulting representation takes constant space, independent of `i`.
|
||||
*/
|
||||
CORD_API CORD CORD_chars(char /* `c` */, size_t /* `i` */);
|
||||
|
||||
#define CORD_nul(i) CORD_chars('\0', i)
|
||||
|
||||
/**
|
||||
* Turn a file `f` into cord. The file must be seekable. Its contents
|
||||
* must remain constant. The file may be accessed as an immediate
|
||||
* result of this call and/or as a result of subsequent accesses to
|
||||
* the cord. Short files are likely to be immediately read, but
|
||||
* long files are likely to be read on demand, possibly relying on
|
||||
* `stdio` for buffering. We must have exclusive access to the
|
||||
* descriptor `f`, i.e. we may read it at any time, and expect the file
|
||||
* pointer to be where we left it. Normally this should be invoked as
|
||||
* `CORD_from_file(fopen(...))`. The latter (`CORD_from_file`)
|
||||
* arranges to close the file descriptor when it is no longer needed
|
||||
* (e.g. when the result becomes inaccessible). The file `f` must be
|
||||
* such that `ftell` reflects the actual character position in the
|
||||
* file, i.e. the number of characters that can be or were read with
|
||||
* `fread`. On UNIX systems this is always true. On Windows systems,
|
||||
* `f` must be opened in binary mode.
|
||||
*/
|
||||
CORD_API CORD CORD_from_file(FILE * /* `f` */);
|
||||
|
||||
/**
|
||||
* Equivalent to `CORD_from_file`, except that the entire file will be
|
||||
* read and the file pointer will be closed immediately. The binary mode
|
||||
* restriction of `CORD_from_file` does not apply.
|
||||
*/
|
||||
CORD_API CORD CORD_from_file_eager(FILE *);
|
||||
|
||||
/**
|
||||
* Equivalent to `CORD_from_file`, except that the file will be read on
|
||||
* demand. The binary mode restriction applies.
|
||||
*/
|
||||
CORD_API CORD CORD_from_file_lazy(FILE *);
|
||||
|
||||
/**
|
||||
* Turn a cord into a C string. The result shares no structure with `x`,
|
||||
* and is thus modifiable.
|
||||
*/
|
||||
CORD_API char *CORD_to_char_star(CORD /* `x` */);
|
||||
|
||||
/**
|
||||
* Turn a C string into a `CORD`. The C string is copied, and so may
|
||||
* subsequently be modified.
|
||||
*/
|
||||
CORD_API CORD CORD_from_char_star(const char *);
|
||||
|
||||
/**
|
||||
* Identical to `CORD_from_char_star`, but the result may share structure
|
||||
* with the argument and is thus not modifiable.
|
||||
*/
|
||||
CORD_API const char *CORD_to_const_char_star(CORD);
|
||||
|
||||
/**
|
||||
* Write a cord to a file, starting at the current position.
|
||||
* No trailing NUL characters and newlines are added. Returns `EOF`
|
||||
* if a write error occurs, 1 otherwise.
|
||||
*/
|
||||
CORD_API int CORD_put(CORD, FILE *);
|
||||
|
||||
/** "Not found" result for `CORD_chr()` and `CORD_rchr()`. */
|
||||
#define CORD_NOT_FOUND ((size_t)(-1))
|
||||
|
||||
/**
|
||||
* A vague analog of `strchr`. Returns the position (an integer, not
|
||||
* a pointer) of the first occurrence of `char` `c` inside `x` at
|
||||
* position `i` or later. The value `i` must be less than `CORD_len(x)`.
|
||||
*/
|
||||
CORD_API size_t CORD_chr(CORD /* `x` */, size_t /* `i` */, int /* `c` */);
|
||||
|
||||
/**
|
||||
* A vague analog of `strrchr`. Returns index of the last occurrence
|
||||
* of `char` `c` inside `x` at position `i` or earlier. The value `i` must
|
||||
* be less than `CORD_len(x)`.
|
||||
*/
|
||||
CORD_API size_t CORD_rchr(CORD /* `x` */, size_t /* `i` */, int /* `c` */);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#ifndef CORD_NO_IO
|
||||
|
||||
# include <stdarg.h>
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
/**
|
||||
* The following ones provide functionality similar to the ANSI C functions
|
||||
* with corresponding names, but with the following additions and changes:
|
||||
* 1. A "%r" conversion specification specifies a `CORD` argument.
|
||||
* Field width, precision, etc. have the same semantics as for "%s".
|
||||
* (Note that "%c", "%C", and "%S" were already taken.)
|
||||
* 2. The format string is represented as a `CORD`.
|
||||
* 3. `CORD_sprintf` and `CORD_vsprintf` assign the result through
|
||||
* the 1st argument. Unlike their ANSI C variants, there is no need
|
||||
* to guess the correct buffer size.
|
||||
* 4. Most of the conversions are implemented through the native
|
||||
* `vsprintf`. Hence they are usually no faster, and idiosyncrasies
|
||||
* of the native `printf` are preserved. However, `CORD` arguments
|
||||
* to `CORD_sprintf`, `CORD_vsprintf` are *not* copied; the result
|
||||
* shares the original structure. This may make them very efficient
|
||||
* in some unusual applications. The format string is copied.
|
||||
*
|
||||
* The functions return the number of characters generated or -1 on error.
|
||||
* This complies with the ANSI standard, but is inconsistent with some
|
||||
* older implementations of `sprintf`.
|
||||
*/
|
||||
CORD_API int CORD_sprintf(CORD * /* `out` */, CORD /* `format` */, ...);
|
||||
CORD_API int CORD_vsprintf(CORD * /* `out` */, CORD /* `format` */, va_list);
|
||||
CORD_API int CORD_fprintf(FILE *, CORD /* `format` */, ...);
|
||||
CORD_API int CORD_vfprintf(FILE *, CORD /* `format` */, va_list);
|
||||
CORD_API int CORD_printf(CORD /* `format` */, ...);
|
||||
CORD_API int CORD_vprintf(CORD /* `format` */, va_list);
|
||||
|
||||
# ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
# endif
|
||||
|
||||
#endif /* CORD_NO_IO */
|
||||
|
||||
#endif /* CORD_H */
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (c) 1993-1994 by Xerox Corporation. All rights reserved.
|
||||
*
|
||||
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
||||
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
||||
*
|
||||
* Permission is hereby granted to use or copy this program
|
||||
* for any purpose, provided the above notices are retained on all copies.
|
||||
* Permission to modify the code and to distribute modified code is granted,
|
||||
* provided the above notices are retained, and a notice that the code was
|
||||
* modified is included with the above copyright notice.
|
||||
*/
|
||||
|
||||
/* This should never be included directly; included only from `cord.h` file. */
|
||||
#if !defined(CORD_POSITION_H) && defined(CORD_H)
|
||||
# define CORD_POSITION_H
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
/*
|
||||
* The representation of `CORD_position`. This is private to the
|
||||
* implementation, but the size is known to clients. Also the implementation
|
||||
* of some exported macros relies on it. Do not use anything defined here
|
||||
* and not in `cord.h` file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The maximum depth of a balanced cord plus one. We do not let cords get
|
||||
* deeper than this maximum.
|
||||
*/
|
||||
# define CORD_MAX_DEPTH 48
|
||||
|
||||
struct CORD_pe {
|
||||
CORD pe_cord;
|
||||
size_t pe_start_pos;
|
||||
};
|
||||
|
||||
/**
|
||||
* A structure describing an entry on the path from the root to current
|
||||
* position.
|
||||
*/
|
||||
typedef struct CORD_Pos {
|
||||
size_t cur_pos;
|
||||
|
||||
int path_len;
|
||||
|
||||
/* `path_len` is `CORD_POS_INVALID` if and only if position is invalid. */
|
||||
# define CORD_POS_INVALID 0x55555555
|
||||
|
||||
/*
|
||||
* Current leaf, if it is a string. If the current leaf is a function,
|
||||
* then this may point to `function_buf` containing the next few characters.
|
||||
* Always points to a valid string containing the current character
|
||||
* unless `cur_end` is zero.
|
||||
*/
|
||||
const char *cur_leaf;
|
||||
|
||||
/* Start position of `cur_leaf`. */
|
||||
size_t cur_start;
|
||||
|
||||
/* Ending position of `cur_leaf`; zero if `cur_leaf` is invalid. */
|
||||
size_t cur_end;
|
||||
|
||||
/*
|
||||
* `path[path_len]` is the leaf corresponding to `cur_pos`;
|
||||
* `path[0].pe_cord` is the cord we point to.
|
||||
*/
|
||||
struct CORD_pe path[CORD_MAX_DEPTH + 1];
|
||||
|
||||
# define CORD_FUNCTION_BUF_SZ 8
|
||||
|
||||
/* Space for next few chars from function node. */
|
||||
char function_buf[CORD_FUNCTION_BUF_SZ];
|
||||
} CORD_pos[1];
|
||||
|
||||
/** Extract the cord from a position. */
|
||||
CORD_API CORD CORD_pos_to_cord(CORD_pos);
|
||||
|
||||
/** Extract the current index from a position. */
|
||||
CORD_API size_t CORD_pos_to_index(CORD_pos);
|
||||
|
||||
/** Fetch the character located at the given position. */
|
||||
CORD_API char CORD_pos_fetch(CORD_pos);
|
||||
|
||||
/**
|
||||
* Initialize the position to refer to the given cord and `index`.
|
||||
* Note that this is the most expensive function on positions.
|
||||
*/
|
||||
CORD_API void CORD_set_pos(CORD_pos, CORD, size_t /* `index` */);
|
||||
|
||||
/**
|
||||
* Advance the position to the next character. `p` must be initialized
|
||||
* and valid. Invalidates `p` if past end.
|
||||
*/
|
||||
CORD_API void CORD_next(CORD_pos /* `p` */);
|
||||
|
||||
/**
|
||||
* Move the position to the preceding character. `p` must be initialized
|
||||
* and valid. Invalidates `p` if past beginning.
|
||||
*/
|
||||
CORD_API void CORD_prev(CORD_pos /* `p` */);
|
||||
|
||||
/** Is the position valid, i.e. inside the cord? */
|
||||
CORD_API int CORD_pos_valid(CORD_pos);
|
||||
|
||||
CORD_API char CORD__pos_fetch(CORD_pos);
|
||||
CORD_API void CORD__next(CORD_pos);
|
||||
CORD_API void CORD__prev(CORD_pos);
|
||||
|
||||
# define CORD_pos_fetch(p) \
|
||||
((p)[0].cur_end != 0 ? (p)[0].cur_leaf[(p)[0].cur_pos - (p)[0].cur_start] \
|
||||
: CORD__pos_fetch(p))
|
||||
|
||||
# define CORD_next(p) \
|
||||
((p)[0].cur_pos + 1 < (p)[0].cur_end ? (p)[0].cur_pos++ \
|
||||
: (CORD__next(p), 0U))
|
||||
|
||||
# define CORD_prev(p) \
|
||||
((p)[0].cur_end != 0 && (p)[0].cur_pos > (p)[0].cur_start \
|
||||
? (p)[0].cur_pos-- \
|
||||
: (CORD__prev(p), 0U))
|
||||
|
||||
# define CORD_pos_to_index(p) ((p)[0].cur_pos)
|
||||
|
||||
# define CORD_pos_to_cord(p) ((p)[0].path[0].pe_cord)
|
||||
|
||||
# define CORD_pos_valid(p) ((p)[0].path_len != CORD_POS_INVALID)
|
||||
|
||||
/* Some grubby stuff for performance-critical friends. */
|
||||
|
||||
/** Number of characters in cache. A non-positive value means none. */
|
||||
# define CORD_pos_chars_left(p) ((long)(p)[0].cur_end - (long)(p)[0].cur_pos)
|
||||
|
||||
/**
|
||||
* Advance position by `n` characters; `n` should be positive and less
|
||||
* than `CORD_pos_chars_left(p)`.
|
||||
*/
|
||||
# define CORD_pos_advance(p, n) \
|
||||
((p)[0].cur_pos += (n) - (size_t)1, CORD_next(p))
|
||||
|
||||
/** Address of the current character in cache. */
|
||||
# define CORD_pos_cur_char_addr(p) \
|
||||
((p)[0].cur_leaf + ((p)[0].cur_pos - (p)[0].cur_start))
|
||||
|
||||
# ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
# endif
|
||||
|
||||
#endif
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 1993-1994 by Xerox Corporation. All rights reserved.
|
||||
*
|
||||
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
||||
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
||||
*
|
||||
* Permission is hereby granted to use or copy this program
|
||||
* for any purpose, provided the above notices are retained on all copies.
|
||||
* Permission to modify the code and to distribute modified code is granted,
|
||||
* provided the above notices are retained, and a notice that the code was
|
||||
* modified is included with the above copyright notice.
|
||||
*/
|
||||
|
||||
#ifndef EC_H
|
||||
#define EC_H
|
||||
|
||||
#ifndef CORD_H
|
||||
# include "cord.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Extensible cords are strings that may be destructively appended to.
|
||||
* They allow fast construction of cords from characters that are being
|
||||
* read from a stream.
|
||||
*
|
||||
* A client might look like:
|
||||
* ```
|
||||
* CORD_ec x;
|
||||
* CORD result;
|
||||
* char c;
|
||||
* FILE *f;
|
||||
*
|
||||
* CORD_ec_init(x);
|
||||
* while (...) {
|
||||
* c = getc(f);
|
||||
* ...
|
||||
* CORD_ec_append(x, c);
|
||||
* }
|
||||
* result = CORD_balance(CORD_ec_to_cord(x));
|
||||
* ```
|
||||
*
|
||||
* If a C string is desired as the final result, the call to `CORD_balance`
|
||||
* may be replaced by a call to `CORD_to_char_star`.
|
||||
*/
|
||||
|
||||
#ifndef CORD_BUFSZ
|
||||
# define CORD_BUFSZ 128
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This structure represents the concatenation of `ec_cord` with
|
||||
* `ec_buf[0 .. ec_bufptr - ec_buf - 1]`.
|
||||
*/
|
||||
typedef struct CORD_ec_struct {
|
||||
CORD ec_cord;
|
||||
char *ec_bufptr;
|
||||
char ec_buf[CORD_BUFSZ + 1];
|
||||
} CORD_ec[1];
|
||||
|
||||
/** Flush the buffer part of the extended cord into extensible cord. */
|
||||
CORD_API void CORD_ec_flush_buf(CORD_ec);
|
||||
|
||||
/** Convert an extensible cord to a cord. */
|
||||
#define CORD_ec_to_cord(x) (CORD_ec_flush_buf(x), (x)[0].ec_cord)
|
||||
|
||||
/** Initialize an extensible cord. */
|
||||
#define CORD_ec_init(x) \
|
||||
((x)[0].ec_cord = 0, (void)((x)[0].ec_bufptr = (x)[0].ec_buf))
|
||||
|
||||
/** Append a character to an extensible cord. */
|
||||
#define CORD_ec_append(x, c) \
|
||||
((void)((x)[0].ec_bufptr == (x)[0].ec_buf + CORD_BUFSZ \
|
||||
? (CORD_ec_flush_buf(x), 0) \
|
||||
: 0), \
|
||||
(void)(*(x)[0].ec_bufptr++ = (c)))
|
||||
|
||||
/**
|
||||
* Append a cord to an extensible cord. Structure remains shared with
|
||||
* the original.
|
||||
*/
|
||||
CORD_API void CORD_ec_append_cord(CORD_ec, CORD);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* EC_H */
|
||||
+2826
File diff suppressed because it is too large.
Load diff
+480
@@ -0,0 +1,480 @@
|
||||
/*
|
||||
* Copyright (c) 1996-1997 Silicon Graphics Computer Systems, Inc.
|
||||
* Copyright (c) 2002 Hewlett-Packard Company
|
||||
*
|
||||
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
||||
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
||||
*
|
||||
* Permission is hereby granted to use or copy this program
|
||||
* for any purpose, provided the above notices are retained on all copies.
|
||||
* Permission to modify the code and to distribute modified code is granted,
|
||||
* provided the above notices are retained, and a notice that the code was
|
||||
* modified is included with the above copyright notice.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This implements standard-conforming allocators that interact with
|
||||
* the garbage collector. `gc_allocator<T>` allocates garbage-collectible
|
||||
* objects of type `T`. `traceable_allocator<T>` allocates objects that
|
||||
* are not themselves garbage-collected ones, but are scanned by the
|
||||
* collector for pointers to collectible objects. `traceable_allocator<T>`
|
||||
* should be used for explicitly managed STL containers that may point to
|
||||
* collectible objects.
|
||||
*
|
||||
* This code was derived from an earlier version of the GNU C++ standard
|
||||
* library, which itself was derived from the SGI STL implementation.
|
||||
*
|
||||
* Ignore-off-page allocator: George T. Talbot
|
||||
*/
|
||||
|
||||
#ifndef GC_ALLOCATOR_H
|
||||
#define GC_ALLOCATOR_H
|
||||
|
||||
#include "gc.h"
|
||||
|
||||
#include <new> // for placement `new` and `bad_alloc`
|
||||
|
||||
#ifdef GC_NAMESPACE_ALLOCATOR
|
||||
namespace boehmgc
|
||||
{
|
||||
#endif
|
||||
|
||||
#if !defined(GC_NO_MEMBER_TEMPLATES) && defined(_MSC_VER) && _MSC_VER <= 1200
|
||||
// MSVC++ 6.0 do not support member templates.
|
||||
# define GC_NO_MEMBER_TEMPLATES
|
||||
#endif
|
||||
|
||||
#if defined(GC_NEW_ABORTS_ON_OOM) || defined(_LIBCPP_NO_EXCEPTIONS)
|
||||
# define GC_ALLOCATOR_THROW_OR_ABORT() GC_abort_on_oom()
|
||||
#else
|
||||
# define GC_ALLOCATOR_THROW_OR_ABORT() throw std::bad_alloc()
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
# define GC_ALCTR_PTRDIFF_T std::ptrdiff_t
|
||||
# define GC_ALCTR_SIZE_T std::size_t
|
||||
#else
|
||||
# define GC_ALCTR_PTRDIFF_T ptrdiff_t
|
||||
# define GC_ALCTR_SIZE_T size_t
|
||||
#endif
|
||||
|
||||
// First some helpers to allow us to dispatch on whether or not a type
|
||||
// is known to be pointer-free. These are private, except that the client
|
||||
// may invoke the `GC_DECLARE_PTRFREE` macro.
|
||||
|
||||
struct GC_true_type {
|
||||
};
|
||||
struct GC_false_type {
|
||||
};
|
||||
|
||||
template <class GC_tp> struct GC_type_traits {
|
||||
GC_false_type GC_is_ptr_free;
|
||||
};
|
||||
|
||||
#define GC_DECLARE_PTRFREE(T) \
|
||||
template <> struct GC_type_traits<T> { \
|
||||
GC_true_type GC_is_ptr_free; \
|
||||
}
|
||||
|
||||
GC_DECLARE_PTRFREE(char);
|
||||
GC_DECLARE_PTRFREE(signed char);
|
||||
GC_DECLARE_PTRFREE(unsigned char);
|
||||
GC_DECLARE_PTRFREE(signed short);
|
||||
GC_DECLARE_PTRFREE(unsigned short);
|
||||
GC_DECLARE_PTRFREE(signed int);
|
||||
GC_DECLARE_PTRFREE(unsigned int);
|
||||
GC_DECLARE_PTRFREE(signed long);
|
||||
GC_DECLARE_PTRFREE(unsigned long);
|
||||
GC_DECLARE_PTRFREE(float);
|
||||
GC_DECLARE_PTRFREE(double);
|
||||
GC_DECLARE_PTRFREE(long double);
|
||||
// The client may want to add others.
|
||||
|
||||
// In the following `GC_Tp` is `GC_true_type` if we are allocating
|
||||
// a pointer-free object.
|
||||
template <class GC_Tp>
|
||||
inline void *
|
||||
GC_selective_alloc(GC_ALCTR_SIZE_T n, GC_Tp, bool ignore_off_page)
|
||||
{
|
||||
void *obj = ignore_off_page ? GC_MALLOC_IGNORE_OFF_PAGE(n) : GC_MALLOC(n);
|
||||
if (0 == obj)
|
||||
GC_ALLOCATOR_THROW_OR_ABORT();
|
||||
return obj;
|
||||
}
|
||||
|
||||
#if !defined(__WATCOMC__)
|
||||
// Note: template-id not supported in this context by Watcom compiler.
|
||||
template <>
|
||||
inline void *
|
||||
GC_selective_alloc<GC_true_type>(GC_ALCTR_SIZE_T n, GC_true_type,
|
||||
bool ignore_off_page)
|
||||
{
|
||||
void *obj = ignore_off_page ? GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(n)
|
||||
: GC_MALLOC_ATOMIC(n);
|
||||
if (0 == obj)
|
||||
GC_ALLOCATOR_THROW_OR_ABORT();
|
||||
return obj;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Now the public `gc_allocator<T>` class.
|
||||
template <class GC_Tp> class gc_allocator
|
||||
{
|
||||
public:
|
||||
typedef GC_ALCTR_SIZE_T size_type;
|
||||
typedef GC_ALCTR_PTRDIFF_T difference_type;
|
||||
typedef GC_Tp *pointer;
|
||||
typedef const GC_Tp *const_pointer;
|
||||
typedef GC_Tp &reference;
|
||||
typedef const GC_Tp &const_reference;
|
||||
typedef GC_Tp value_type;
|
||||
|
||||
template <class GC_Tp1> struct rebind {
|
||||
typedef gc_allocator<GC_Tp1> other;
|
||||
};
|
||||
|
||||
GC_CONSTEXPR
|
||||
gc_allocator() GC_NOEXCEPT
|
||||
{
|
||||
// Empty.
|
||||
}
|
||||
|
||||
GC_CONSTEXPR
|
||||
gc_allocator(const gc_allocator &) GC_NOEXCEPT
|
||||
{
|
||||
// Empty.
|
||||
}
|
||||
|
||||
#ifndef GC_NO_MEMBER_TEMPLATES
|
||||
template <class GC_Tp1>
|
||||
GC_ATTR_EXPLICIT GC_CONSTEXPR
|
||||
gc_allocator(const gc_allocator<GC_Tp1> &) GC_NOEXCEPT
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
GC_CONSTEXPR ~gc_allocator() GC_NOEXCEPT {}
|
||||
|
||||
GC_CONSTEXPR pointer
|
||||
address(reference GC_x) const
|
||||
{
|
||||
return &GC_x;
|
||||
}
|
||||
|
||||
GC_CONSTEXPR const_pointer
|
||||
address(const_reference GC_x) const
|
||||
{
|
||||
return &GC_x;
|
||||
}
|
||||
|
||||
// `GC_n` is permitted to be 0. The C++ standard says nothing about what
|
||||
// the return value is when `GC_n` is zero.
|
||||
GC_CONSTEXPR GC_Tp *
|
||||
allocate(size_type GC_n, const void * = 0)
|
||||
{
|
||||
GC_type_traits<GC_Tp> traits;
|
||||
return static_cast<GC_Tp *>(GC_selective_alloc(
|
||||
GC_n * sizeof(GC_Tp), traits.GC_is_ptr_free, false));
|
||||
}
|
||||
|
||||
GC_CONSTEXPR void
|
||||
deallocate(pointer __p, size_type /* `GC_n` */) GC_NOEXCEPT
|
||||
{
|
||||
GC_FREE(__p);
|
||||
}
|
||||
|
||||
GC_CONSTEXPR size_type
|
||||
max_size() const GC_NOEXCEPT
|
||||
{
|
||||
return static_cast<GC_ALCTR_SIZE_T>(-1) / sizeof(GC_Tp);
|
||||
}
|
||||
|
||||
GC_CONSTEXPR void
|
||||
construct(pointer __p, const GC_Tp &__val)
|
||||
{
|
||||
new (__p) GC_Tp(__val);
|
||||
}
|
||||
|
||||
GC_CONSTEXPR void
|
||||
destroy(pointer __p)
|
||||
{
|
||||
__p->~GC_Tp();
|
||||
}
|
||||
};
|
||||
|
||||
template <> class gc_allocator<void>
|
||||
{
|
||||
public:
|
||||
typedef GC_ALCTR_SIZE_T size_type;
|
||||
typedef GC_ALCTR_PTRDIFF_T difference_type;
|
||||
typedef void *pointer;
|
||||
typedef const void *const_pointer;
|
||||
typedef void value_type;
|
||||
|
||||
template <class GC_Tp1> struct rebind {
|
||||
typedef gc_allocator<GC_Tp1> other;
|
||||
};
|
||||
};
|
||||
|
||||
template <class GC_T1, class GC_T2>
|
||||
GC_CONSTEXPR inline bool
|
||||
operator==(const gc_allocator<GC_T1> &,
|
||||
const gc_allocator<GC_T2> &) GC_NOEXCEPT
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class GC_T1, class GC_T2>
|
||||
GC_CONSTEXPR inline bool
|
||||
operator!=(const gc_allocator<GC_T1> &,
|
||||
const gc_allocator<GC_T2> &) GC_NOEXCEPT
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now the public `gc_allocator_ignore_off_page<T>` class.
|
||||
template <class GC_Tp> class gc_allocator_ignore_off_page
|
||||
{
|
||||
public:
|
||||
typedef GC_ALCTR_SIZE_T size_type;
|
||||
typedef GC_ALCTR_PTRDIFF_T difference_type;
|
||||
typedef GC_Tp *pointer;
|
||||
typedef const GC_Tp *const_pointer;
|
||||
typedef GC_Tp &reference;
|
||||
typedef const GC_Tp &const_reference;
|
||||
typedef GC_Tp value_type;
|
||||
|
||||
template <class GC_Tp1> struct rebind {
|
||||
typedef gc_allocator_ignore_off_page<GC_Tp1> other;
|
||||
};
|
||||
|
||||
GC_CONSTEXPR
|
||||
gc_allocator_ignore_off_page() GC_NOEXCEPT
|
||||
{
|
||||
// Empty.
|
||||
}
|
||||
|
||||
GC_CONSTEXPR
|
||||
gc_allocator_ignore_off_page(const gc_allocator_ignore_off_page &)
|
||||
GC_NOEXCEPT
|
||||
{
|
||||
// Empty.
|
||||
}
|
||||
|
||||
#ifndef GC_NO_MEMBER_TEMPLATES
|
||||
template <class GC_Tp1>
|
||||
GC_ATTR_EXPLICIT GC_CONSTEXPR
|
||||
gc_allocator_ignore_off_page(const gc_allocator_ignore_off_page<GC_Tp1> &)
|
||||
GC_NOEXCEPT
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
GC_CONSTEXPR ~gc_allocator_ignore_off_page() GC_NOEXCEPT {}
|
||||
|
||||
GC_CONSTEXPR pointer
|
||||
address(reference GC_x) const
|
||||
{
|
||||
return &GC_x;
|
||||
}
|
||||
|
||||
GC_CONSTEXPR const_pointer
|
||||
address(const_reference GC_x) const
|
||||
{
|
||||
return &GC_x;
|
||||
}
|
||||
|
||||
// `GC_n` is permitted to be 0. The C++ standard says nothing about what
|
||||
// the return value is when `GC_n` is zero.
|
||||
GC_CONSTEXPR GC_Tp *
|
||||
allocate(size_type GC_n, const void * = 0)
|
||||
{
|
||||
GC_type_traits<GC_Tp> traits;
|
||||
return static_cast<GC_Tp *>(
|
||||
GC_selective_alloc(GC_n * sizeof(GC_Tp), traits.GC_is_ptr_free, true));
|
||||
}
|
||||
|
||||
GC_CONSTEXPR void
|
||||
deallocate(pointer __p, size_type /* `GC_n` */) GC_NOEXCEPT
|
||||
{
|
||||
GC_FREE(__p);
|
||||
}
|
||||
|
||||
GC_CONSTEXPR size_type
|
||||
max_size() const GC_NOEXCEPT
|
||||
{
|
||||
return static_cast<GC_ALCTR_SIZE_T>(-1) / sizeof(GC_Tp);
|
||||
}
|
||||
|
||||
GC_CONSTEXPR void
|
||||
construct(pointer __p, const GC_Tp &__val)
|
||||
{
|
||||
new (__p) GC_Tp(__val);
|
||||
}
|
||||
|
||||
GC_CONSTEXPR void
|
||||
destroy(pointer __p)
|
||||
{
|
||||
__p->~GC_Tp();
|
||||
}
|
||||
};
|
||||
|
||||
template <> class gc_allocator_ignore_off_page<void>
|
||||
{
|
||||
public:
|
||||
typedef GC_ALCTR_SIZE_T size_type;
|
||||
typedef GC_ALCTR_PTRDIFF_T difference_type;
|
||||
typedef void *pointer;
|
||||
typedef const void *const_pointer;
|
||||
typedef void value_type;
|
||||
|
||||
template <class GC_Tp1> struct rebind {
|
||||
typedef gc_allocator_ignore_off_page<GC_Tp1> other;
|
||||
};
|
||||
};
|
||||
|
||||
template <class GC_T1, class GC_T2>
|
||||
GC_CONSTEXPR inline bool
|
||||
operator==(const gc_allocator_ignore_off_page<GC_T1> &,
|
||||
const gc_allocator_ignore_off_page<GC_T2> &) GC_NOEXCEPT
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class GC_T1, class GC_T2>
|
||||
GC_CONSTEXPR inline bool
|
||||
operator!=(const gc_allocator_ignore_off_page<GC_T1> &,
|
||||
const gc_allocator_ignore_off_page<GC_T2> &) GC_NOEXCEPT
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// And the public `traceable_allocator<T>` class.
|
||||
|
||||
// Note that we currently do not specialize the pointer-free case,
|
||||
// since a pointer-free traceable container does not make that much sense,
|
||||
// though it could become an issue due to abstraction boundaries.
|
||||
|
||||
template <class GC_Tp> class traceable_allocator
|
||||
{
|
||||
public:
|
||||
typedef GC_ALCTR_SIZE_T size_type;
|
||||
typedef GC_ALCTR_PTRDIFF_T difference_type;
|
||||
typedef GC_Tp *pointer;
|
||||
typedef const GC_Tp *const_pointer;
|
||||
typedef GC_Tp &reference;
|
||||
typedef const GC_Tp &const_reference;
|
||||
typedef GC_Tp value_type;
|
||||
|
||||
template <class GC_Tp1> struct rebind {
|
||||
typedef traceable_allocator<GC_Tp1> other;
|
||||
};
|
||||
|
||||
GC_CONSTEXPR
|
||||
traceable_allocator() GC_NOEXCEPT
|
||||
{
|
||||
// Empty.
|
||||
}
|
||||
|
||||
GC_CONSTEXPR
|
||||
traceable_allocator(const traceable_allocator &) GC_NOEXCEPT
|
||||
{
|
||||
// Empty.
|
||||
}
|
||||
|
||||
#ifndef GC_NO_MEMBER_TEMPLATES
|
||||
template <class GC_Tp1>
|
||||
GC_ATTR_EXPLICIT GC_CONSTEXPR
|
||||
traceable_allocator(const traceable_allocator<GC_Tp1> &) GC_NOEXCEPT
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
GC_CONSTEXPR ~traceable_allocator() GC_NOEXCEPT {}
|
||||
|
||||
GC_CONSTEXPR pointer
|
||||
address(reference GC_x) const
|
||||
{
|
||||
return &GC_x;
|
||||
}
|
||||
|
||||
GC_CONSTEXPR const_pointer
|
||||
address(const_reference GC_x) const
|
||||
{
|
||||
return &GC_x;
|
||||
}
|
||||
|
||||
// `GC_n` is permitted to be 0. The C++ standard says nothing about what
|
||||
// the return value is when `GC_n` is zero.
|
||||
GC_CONSTEXPR GC_Tp *
|
||||
allocate(size_type GC_n, const void * = 0)
|
||||
{
|
||||
void *obj = GC_MALLOC_UNCOLLECTABLE(GC_n * sizeof(GC_Tp));
|
||||
if (0 == obj)
|
||||
GC_ALLOCATOR_THROW_OR_ABORT();
|
||||
return static_cast<GC_Tp *>(obj);
|
||||
}
|
||||
|
||||
GC_CONSTEXPR void
|
||||
deallocate(pointer __p, size_type /* `GC_n` */) GC_NOEXCEPT
|
||||
{
|
||||
GC_FREE(__p);
|
||||
}
|
||||
|
||||
GC_CONSTEXPR size_type
|
||||
max_size() const GC_NOEXCEPT
|
||||
{
|
||||
return static_cast<GC_ALCTR_SIZE_T>(-1) / sizeof(GC_Tp);
|
||||
}
|
||||
|
||||
GC_CONSTEXPR void
|
||||
construct(pointer __p, const GC_Tp &__val)
|
||||
{
|
||||
new (__p) GC_Tp(__val);
|
||||
}
|
||||
|
||||
GC_CONSTEXPR void
|
||||
destroy(pointer __p)
|
||||
{
|
||||
__p->~GC_Tp();
|
||||
}
|
||||
};
|
||||
|
||||
template <> class traceable_allocator<void>
|
||||
{
|
||||
public:
|
||||
typedef GC_ALCTR_SIZE_T size_type;
|
||||
typedef GC_ALCTR_PTRDIFF_T difference_type;
|
||||
typedef void *pointer;
|
||||
typedef const void *const_pointer;
|
||||
typedef void value_type;
|
||||
|
||||
template <class GC_Tp1> struct rebind {
|
||||
typedef traceable_allocator<GC_Tp1> other;
|
||||
};
|
||||
};
|
||||
|
||||
template <class GC_T1, class GC_T2>
|
||||
GC_CONSTEXPR inline bool
|
||||
operator==(const traceable_allocator<GC_T1> &,
|
||||
const traceable_allocator<GC_T2> &) GC_NOEXCEPT
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class GC_T1, class GC_T2>
|
||||
GC_CONSTEXPR inline bool
|
||||
operator!=(const traceable_allocator<GC_T1> &,
|
||||
const traceable_allocator<GC_T2> &) GC_NOEXCEPT
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#undef GC_ALCTR_PTRDIFF_T
|
||||
#undef GC_ALCTR_SIZE_T
|
||||
|
||||
#ifdef GC_NAMESPACE_ALLOCATOR
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GC_ALLOCATOR_H */
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 1994 by Xerox Corporation. All rights reserved.
|
||||
* Copyright (c) 1996 by Silicon Graphics. All rights reserved.
|
||||
* Copyright (c) 1998 by Fergus Henderson. All rights reserved.
|
||||
* Copyright (c) 2000-2009 by Hewlett-Packard Development Company.
|
||||
* All rights reserved.
|
||||
*
|
||||
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
||||
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
||||
*
|
||||
* Permission is hereby granted to use or copy this program
|
||||
* for any purpose, provided the above notices are retained on all copies.
|
||||
* Permission to modify the code and to distribute modified code is granted,
|
||||
* provided the above notices are retained, and a notice that the code was
|
||||
* modified is included with the above copyright notice.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is a simple API to implement pointer back tracing, i.e.
|
||||
* to answer questions such as "who is pointing to this" or
|
||||
* "why is this object being retained by the collector".
|
||||
* Most of these calls yield useful information on only after
|
||||
* a garbage collection. Usually the client will first force
|
||||
* a full collection and then gather information, preferably
|
||||
* before much intervening allocation.
|
||||
* The implementation of the interface is only about 99.9999%
|
||||
* correct. It is intended to be good enough for profiling,
|
||||
* but is not intended to be used with production code.
|
||||
* Results are likely to be much more useful if all allocation
|
||||
* is accomplished through the debugging allocators.
|
||||
*/
|
||||
|
||||
/* The implementation idea is due to A. Demers. */
|
||||
|
||||
#ifndef GC_BACKPTR_H
|
||||
#define GC_BACKPTR_H
|
||||
|
||||
#ifndef GC_H
|
||||
# include "gc.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
/** No reference info available. */
|
||||
GC_UNREFERENCED,
|
||||
/** `dest` is not allocated with a debug allocation routine. */
|
||||
GC_NO_SPACE,
|
||||
/** Referenced directly by root `*base_p`. */
|
||||
GC_REFD_FROM_ROOT,
|
||||
/** Referenced from a register, i.e. a root without an address. */
|
||||
GC_REFD_FROM_REG,
|
||||
/** Referenced from another heap object. */
|
||||
GC_REFD_FROM_HEAP,
|
||||
/** Finalizable and hence accessible. */
|
||||
GC_FINALIZER_REFD
|
||||
} GC_ref_kind;
|
||||
|
||||
/**
|
||||
* Store information about the source object referencing `dest` in
|
||||
* `*base_p` and `*offset_p`. If multiple objects or roots point to
|
||||
* `dest`, then the one reported will be the last one used by the
|
||||
* garbage collector to trace the object. If the source is root, then
|
||||
* `*base_p` is the address and `*offset_p` is zero. If the source is
|
||||
* a heap object, then `*base_p` is non-`NULL` and `*offset_p` is the
|
||||
* offset. `dest` can be any address within a heap object.
|
||||
* The allocator lock is not acquired by design (despite of the
|
||||
* possibility of a race); anyway the function should not be used in
|
||||
* production code.
|
||||
*/
|
||||
GC_API GC_ref_kind GC_CALL GC_get_back_ptr_info(void * /* `dest` */,
|
||||
void ** /* `base_p` */,
|
||||
size_t * /* `offset_p` */)
|
||||
GC_ATTR_NONNULL(1);
|
||||
|
||||
/**
|
||||
* Generate a random heap address. The resulting address is
|
||||
* in the heap, but not necessarily inside a valid object.
|
||||
* The caller should hold the allocator lock.
|
||||
*/
|
||||
GC_API void *GC_CALL GC_generate_random_heap_address(void);
|
||||
|
||||
/**
|
||||
* Generate a random address inside a valid marked heap object.
|
||||
* The caller should hold the allocator lock.
|
||||
*/
|
||||
GC_API void *GC_CALL GC_generate_random_valid_address(void);
|
||||
|
||||
/**
|
||||
* Force a garbage collection and generate a backtrace from a random
|
||||
* heap address. This uses the collector logging mechanism (`GC_printf`)
|
||||
* to produce output. It can often be called from a debugger.
|
||||
*/
|
||||
GC_API void GC_CALL GC_generate_random_backtrace(void);
|
||||
|
||||
/**
|
||||
* Print a backtrace from a specific address. The client should call
|
||||
* `GC_gcollect()` right before the invocation. Used e.g. by
|
||||
* `GC_generate_random_backtrace()`.
|
||||
*/
|
||||
GC_API void GC_CALL GC_print_backtrace(void *) GC_ATTR_NONNULL(1);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* GC_BACKPTR_H */
|
||||
@@ -0,0 +1,548 @@
|
||||
/*
|
||||
* Copyright (c) 1994 by Xerox Corporation. All rights reserved.
|
||||
* Copyright (c) 1996 by Silicon Graphics. All rights reserved.
|
||||
* Copyright (c) 1998 by Fergus Henderson. All rights reserved.
|
||||
* Copyright (c) 2000-2009 by Hewlett-Packard Development Company.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2008-2025 Ivan Maidanski
|
||||
*
|
||||
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
||||
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
||||
*
|
||||
* Permission is hereby granted to use or copy this program
|
||||
* for any purpose, provided the above notices are retained on all copies.
|
||||
* Permission to modify the code and to distribute modified code is granted,
|
||||
* provided the above notices are retained, and a notice that the code was
|
||||
* modified is included with the above copyright notice.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This should never be included directly; it is included only from
|
||||
* `gc.h` file. We separate it only to make `gc.h` file more suitable
|
||||
* as documentation.
|
||||
*/
|
||||
#if defined(GC_H)
|
||||
|
||||
/* Convenient internal macro to test version of gcc. */
|
||||
# if defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||
# define GC_GNUC_PREREQ(major, minor) \
|
||||
((__GNUC__ << 8) + __GNUC_MINOR__ >= ((major) << 8) + (minor))
|
||||
# else
|
||||
# define GC_GNUC_PREREQ(major, minor) 0 /*< false */
|
||||
# endif
|
||||
|
||||
/*
|
||||
* A macro to define integer types of a pointer size. There seems to
|
||||
* be no way to do this even semi-portably. The following is probably
|
||||
* no better/worse than almost anything else.
|
||||
* The ANSI standard suggests that `size_t` and `ptrdiff_t` might be
|
||||
* better choices. But those had incorrect definitions on some older
|
||||
* systems; notably `typedef int size_t` is wrong.
|
||||
*/
|
||||
# ifdef _WIN64
|
||||
# if defined(__int64) && !defined(CPPCHECK)
|
||||
# define GC_SIGNEDWORD __int64
|
||||
# else
|
||||
# define GC_SIGNEDWORD long long
|
||||
# endif
|
||||
# else
|
||||
# define GC_SIGNEDWORD long
|
||||
# endif
|
||||
# define GC_UNSIGNEDWORD unsigned GC_SIGNEDWORD
|
||||
|
||||
/* Size of a pointer in bytes. */
|
||||
# if defined(__SIZEOF_POINTER__)
|
||||
# define GC_SIZEOF_PTR __SIZEOF_POINTER__
|
||||
# elif defined(__LP64__) || defined(_LP64) || defined(_WIN64) \
|
||||
|| defined(__alpha__) || defined(__arch64__) || defined(__powerpc64__) \
|
||||
|| defined(__s390x__) || defined(__sparcv9) \
|
||||
|| (defined(__x86_64__) && !defined(__ILP32__))
|
||||
# define GC_SIZEOF_PTR 8
|
||||
# else
|
||||
# define GC_SIZEOF_PTR 4
|
||||
# endif
|
||||
|
||||
/*
|
||||
* The return type of `GC_get_version()`. A 32-bit unsigned integer
|
||||
* or longer.
|
||||
*/
|
||||
# define GC_VERSION_VAL_T unsigned
|
||||
|
||||
/*
|
||||
* Some tests for old macros. These violate our namespace rules and
|
||||
* are deprecated. Use the `GC_` names instead.
|
||||
*/
|
||||
# if defined(SOLARIS_THREADS) || defined(_SOLARIS_THREADS) \
|
||||
|| defined(_SOLARIS_PTHREADS) || defined(GC_SOLARIS_PTHREADS)
|
||||
/*
|
||||
* We no longer support old style Solaris threads.
|
||||
* `GC_SOLARIS_THREADS` now means `pthreads`.
|
||||
*/
|
||||
# ifndef GC_SOLARIS_THREADS
|
||||
# define GC_SOLARIS_THREADS
|
||||
# endif
|
||||
# endif
|
||||
# if defined(IRIX_THREADS)
|
||||
# define GC_IRIX_THREADS
|
||||
# endif
|
||||
# if defined(DGUX_THREADS) && !defined(GC_DGUX386_THREADS)
|
||||
# define GC_DGUX386_THREADS
|
||||
# endif
|
||||
# if defined(AIX_THREADS)
|
||||
# define GC_AIX_THREADS
|
||||
# endif
|
||||
# if defined(HPUX_THREADS)
|
||||
# define GC_HPUX_THREADS
|
||||
# endif
|
||||
# if defined(OSF1_THREADS)
|
||||
# define GC_OSF1_THREADS
|
||||
# endif
|
||||
# if defined(LINUX_THREADS)
|
||||
# define GC_LINUX_THREADS
|
||||
# endif
|
||||
# if defined(WIN32_THREADS)
|
||||
# define GC_WIN32_THREADS
|
||||
# endif
|
||||
# if defined(RTEMS_THREADS)
|
||||
# define GC_RTEMS_PTHREADS
|
||||
# endif
|
||||
# if defined(USE_LD_WRAP)
|
||||
# define GC_USE_LD_WRAP
|
||||
# endif
|
||||
|
||||
# if defined(GC_WIN32_PTHREADS) && !defined(GC_WIN32_THREADS)
|
||||
/* Using pthreads-win32 library (or other Win32 implementation). */
|
||||
# define GC_WIN32_THREADS
|
||||
# endif
|
||||
|
||||
# if defined(GC_AIX_THREADS) || defined(GC_DARWIN_THREADS) \
|
||||
|| defined(GC_DGUX386_THREADS) || defined(GC_FREEBSD_THREADS) \
|
||||
|| defined(GC_HPUX_THREADS) || defined(GC_IRIX_THREADS) \
|
||||
|| defined(GC_LINUX_THREADS) || defined(GC_NETBSD_THREADS) \
|
||||
|| defined(GC_OPENBSD_THREADS) || defined(GC_OSF1_THREADS) \
|
||||
|| defined(GC_SOLARIS_THREADS) || defined(GC_WIN32_THREADS) \
|
||||
|| defined(GC_RTEMS_PTHREADS)
|
||||
# ifndef GC_THREADS
|
||||
# define GC_THREADS
|
||||
# endif
|
||||
# elif defined(GC_THREADS)
|
||||
# if defined(__linux__) || defined(__native_client__)
|
||||
# define GC_LINUX_THREADS
|
||||
# elif defined(__OpenBSD__)
|
||||
# define GC_OPENBSD_THREADS
|
||||
# elif defined(_PA_RISC1_1) || defined(_PA_RISC2_0) || defined(hppa) \
|
||||
|| defined(__HPPA) || (defined(__ia64) && defined(_HPUX_SOURCE))
|
||||
# define GC_HPUX_THREADS
|
||||
# elif defined(__HAIKU__)
|
||||
# define GC_HAIKU_THREADS
|
||||
# elif (defined(__DragonFly__) || defined(__FreeBSD_kernel__) \
|
||||
|| defined(__FreeBSD__)) \
|
||||
&& !defined(GC_NO_FREEBSD)
|
||||
# define GC_FREEBSD_THREADS
|
||||
# elif defined(__NetBSD__)
|
||||
# define GC_NETBSD_THREADS
|
||||
# elif defined(__alpha) || defined(__alpha__) /*< not Linux, not xBSD */
|
||||
# define GC_OSF1_THREADS
|
||||
# elif (defined(mips) || defined(__mips) || defined(_mips)) \
|
||||
&& !(defined(nec_ews) || defined(_nec_ews) || defined(ultrix) \
|
||||
|| defined(__ultrix))
|
||||
# define GC_IRIX_THREADS
|
||||
# elif defined(__sparc) /* `&& !defined(__linux__)` */ \
|
||||
|| ((defined(sun) || defined(__sun)) \
|
||||
&& (defined(i386) || defined(__i386__) || defined(__amd64) \
|
||||
|| defined(__amd64__)))
|
||||
# define GC_SOLARIS_THREADS
|
||||
# elif defined(__APPLE__) && defined(__MACH__)
|
||||
# define GC_DARWIN_THREADS
|
||||
# endif
|
||||
# if defined(DGUX) && (defined(i386) || defined(__i386__))
|
||||
# define GC_DGUX386_THREADS
|
||||
# endif
|
||||
# if defined(_AIX)
|
||||
# define GC_AIX_THREADS
|
||||
# endif
|
||||
# if (defined(_WIN32) || defined(_MSC_VER) || defined(__BORLANDC__) \
|
||||
|| defined(__CYGWIN32__) || defined(__CYGWIN__) \
|
||||
|| defined(__CEGCC__) || defined(_WIN32_WCE) \
|
||||
|| defined(__MINGW32__)) \
|
||||
&& !defined(GC_WIN32_THREADS)
|
||||
/* Either POSIX or native Win32 threads. */
|
||||
# define GC_WIN32_THREADS
|
||||
# endif
|
||||
# if defined(__rtems__) && (defined(i386) || defined(__i386__))
|
||||
# define GC_RTEMS_PTHREADS
|
||||
# endif
|
||||
# endif /* GC_THREADS */
|
||||
|
||||
# undef GC_PTHREADS
|
||||
# if (!defined(GC_WIN32_THREADS) || defined(GC_WIN32_PTHREADS) \
|
||||
|| defined(__CYGWIN32__) || defined(__CYGWIN__)) \
|
||||
&& defined(GC_THREADS) && !defined(NN_PLATFORM_CTR) \
|
||||
&& !defined(NN_BUILD_TARGET_PLATFORM_NX)
|
||||
/* POSIX threads (`pthreads`). */
|
||||
# define GC_PTHREADS
|
||||
# endif
|
||||
|
||||
# if !defined(_PTHREADS) && defined(GC_NETBSD_THREADS)
|
||||
# define _PTHREADS
|
||||
# endif
|
||||
|
||||
# if defined(GC_DGUX386_THREADS) && !defined(_POSIX4A_DRAFT10_SOURCE)
|
||||
# define _POSIX4A_DRAFT10_SOURCE 1
|
||||
# endif
|
||||
|
||||
# if !defined(_REENTRANT) && defined(GC_PTHREADS) \
|
||||
&& !defined(GC_WIN32_THREADS)
|
||||
/*
|
||||
* Better late than never. This fails if system headers that depend
|
||||
* on this were previously included.
|
||||
*/
|
||||
# define _REENTRANT 1
|
||||
# endif
|
||||
|
||||
# if defined(__clang__) && defined(__CYGWIN__) && defined(GC_THREADS) \
|
||||
&& defined(__LP64__)
|
||||
/*
|
||||
* Workaround "__stdcall__ ignored for this target" clang warning.
|
||||
* Note: `__stdcall` is defined implicitly based on `__stdcall__`.
|
||||
*/
|
||||
# define __stdcall__ /*< empty */
|
||||
# endif
|
||||
|
||||
# define __GC
|
||||
# if !defined(_WIN32_WCE) || defined(__GNUC__)
|
||||
# include <stddef.h>
|
||||
# if defined(__MINGW32__) && !defined(_WIN32_WCE) \
|
||||
|| defined(__CHERI_PURE_CAPABILITY__)
|
||||
# include <stdint.h>
|
||||
/*
|
||||
* We mention `uintptr_t`. Perhaps this should be included in pure
|
||||
* MS environments as well.
|
||||
*/
|
||||
# endif
|
||||
# else
|
||||
/* Yet more kludges for WinCE. */
|
||||
# include <stdlib.h> /*< for `size_t` */
|
||||
# ifndef _PTRDIFF_T_DEFINED
|
||||
/* `ptrdiff_t` is not defined. */
|
||||
# define _PTRDIFF_T_DEFINED
|
||||
typedef long ptrdiff_t;
|
||||
# endif
|
||||
# endif /* _WIN32_WCE */
|
||||
|
||||
# if !defined(GC_NOT_DLL) && !defined(GC_DLL) \
|
||||
&& ((defined(_DLL) && !defined(__GNUC__)) \
|
||||
|| (defined(DLL_EXPORT) && defined(GC_BUILD)))
|
||||
# define GC_DLL
|
||||
# endif
|
||||
|
||||
# if defined(GC_DLL) && !defined(GC_API)
|
||||
|
||||
# if defined(__CEGCC__)
|
||||
# if defined(GC_BUILD)
|
||||
# define GC_API __declspec(dllexport)
|
||||
# else
|
||||
# define GC_API __declspec(dllimport)
|
||||
# endif
|
||||
|
||||
# elif defined(__MINGW32__)
|
||||
# if defined(__cplusplus) && defined(GC_BUILD)
|
||||
# define GC_API extern __declspec(dllexport)
|
||||
# elif defined(GC_BUILD) || defined(__MINGW32_DELAY_LOAD__)
|
||||
# define GC_API __declspec(dllexport)
|
||||
# else
|
||||
# define GC_API extern __declspec(dllimport)
|
||||
# endif
|
||||
|
||||
# elif defined(_MSC_VER) || defined(__DMC__) || defined(__BORLANDC__) \
|
||||
|| defined(__CYGWIN__)
|
||||
# ifdef GC_BUILD
|
||||
# define GC_API extern __declspec(dllexport)
|
||||
# else
|
||||
# define GC_API __declspec(dllimport)
|
||||
# endif
|
||||
|
||||
# elif defined(__WATCOMC__)
|
||||
# ifdef GC_BUILD
|
||||
# define GC_API extern __declspec(dllexport)
|
||||
# else
|
||||
# define GC_API extern __declspec(dllimport)
|
||||
# endif
|
||||
|
||||
# elif defined(__SYMBIAN32__)
|
||||
# ifdef GC_BUILD
|
||||
# define GC_API extern EXPORT_C
|
||||
# else
|
||||
# define GC_API extern IMPORT_C
|
||||
# endif
|
||||
|
||||
# elif defined(__GNUC__)
|
||||
/* Only matters if used in conjunction with `-fvisibility=hidden` option. */
|
||||
# if defined(GC_BUILD) && !defined(GC_NO_VISIBILITY) \
|
||||
&& (GC_GNUC_PREREQ(4, 0) || defined(GC_VISIBILITY_HIDDEN_SET))
|
||||
# define GC_API extern __attribute__((__visibility__("default")))
|
||||
# endif
|
||||
# endif
|
||||
# endif /* GC_DLL */
|
||||
|
||||
# ifndef GC_API
|
||||
# define GC_API extern
|
||||
# endif
|
||||
|
||||
# ifndef GC_CALL
|
||||
# define GC_CALL
|
||||
# endif
|
||||
|
||||
# ifndef GC_CALLBACK
|
||||
# define GC_CALLBACK GC_CALL
|
||||
# endif
|
||||
|
||||
# ifndef GC_ATTR_MALLOC
|
||||
/*
|
||||
* `malloc` attribute should be used for all `malloc`-like functions
|
||||
* (to tell the compiler that a function may be treated as if any
|
||||
* non-`NULL` pointer it returns cannot alias any other pointer valid
|
||||
* when the function returns). If the client code violates this rule
|
||||
* by using custom `GC_oom_func`, then the client should define
|
||||
* `GC_OOM_FUNC_RETURNS_ALIAS` macro.
|
||||
*/
|
||||
# ifdef GC_OOM_FUNC_RETURNS_ALIAS
|
||||
# define GC_ATTR_MALLOC /*< empty */
|
||||
# elif GC_GNUC_PREREQ(3, 1)
|
||||
# define GC_ATTR_MALLOC __attribute__((__malloc__))
|
||||
# elif defined(_MSC_VER) && (_MSC_VER >= 1900) && !defined(__EDG__)
|
||||
# define GC_ATTR_MALLOC \
|
||||
__declspec(allocator) __declspec(noalias) __declspec(restrict)
|
||||
# elif defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
# define GC_ATTR_MALLOC __declspec(noalias) __declspec(restrict)
|
||||
# else
|
||||
# define GC_ATTR_MALLOC
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef GC_ATTR_ALLOC_SIZE
|
||||
/* `alloc_size` attribute improves `__builtin_object_size` correctness. */
|
||||
# undef GC_ATTR_CALLOC_SIZE
|
||||
# ifdef __clang__
|
||||
# if __has_attribute(__alloc_size__)
|
||||
# define GC_ATTR_ALLOC_SIZE(argnum) \
|
||||
__attribute__((__alloc_size__(argnum)))
|
||||
# define GC_ATTR_CALLOC_SIZE(n, s) __attribute__((__alloc_size__(n, s)))
|
||||
# else
|
||||
# define GC_ATTR_ALLOC_SIZE(argnum) /*< empty */
|
||||
# endif
|
||||
# elif GC_GNUC_PREREQ(4, 3) && !defined(__ICC)
|
||||
# define GC_ATTR_ALLOC_SIZE(argnum) \
|
||||
__attribute__((__alloc_size__(argnum)))
|
||||
# define GC_ATTR_CALLOC_SIZE(n, s) __attribute__((__alloc_size__(n, s)))
|
||||
# else
|
||||
# define GC_ATTR_ALLOC_SIZE(argnum) /*< empty */
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef GC_ATTR_CALLOC_SIZE
|
||||
# define GC_ATTR_CALLOC_SIZE(n, s) /*< empty */
|
||||
# endif
|
||||
|
||||
# ifndef GC_ATTR_NONNULL
|
||||
# if GC_GNUC_PREREQ(4, 0)
|
||||
# define GC_ATTR_NONNULL(argnum) __attribute__((__nonnull__(argnum)))
|
||||
# else
|
||||
# define GC_ATTR_NONNULL(argnum) /*< empty */
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef GC_ATTR_CONST
|
||||
# if GC_GNUC_PREREQ(4, 0)
|
||||
# define GC_ATTR_CONST __attribute__((__const__))
|
||||
# else
|
||||
# define GC_ATTR_CONST /*< empty */
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef GC_ATTR_DEPRECATED
|
||||
# ifdef GC_BUILD
|
||||
# undef GC_ATTR_DEPRECATED
|
||||
# define GC_ATTR_DEPRECATED /*< empty */
|
||||
# elif GC_GNUC_PREREQ(4, 0)
|
||||
# define GC_ATTR_DEPRECATED __attribute__((__deprecated__))
|
||||
# elif defined(_MSC_VER) && _MSC_VER >= 1200
|
||||
# define GC_ATTR_DEPRECATED __declspec(deprecated)
|
||||
# else
|
||||
# define GC_ATTR_DEPRECATED /*< empty */
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef GC_ATTR_NORETURN
|
||||
# if GC_GNUC_PREREQ(2, 7)
|
||||
# define GC_ATTR_NORETURN __attribute__((__noreturn__))
|
||||
# elif defined(_MSC_VER) && _MSC_VER >= 1310 /*< VS 2003+ */
|
||||
# define GC_ATTR_NORETURN __declspec(noreturn)
|
||||
# elif defined(__NORETURN) /*< used in Solaris */
|
||||
# define GC_ATTR_NORETURN __NORETURN
|
||||
# else
|
||||
# define GC_ATTR_NORETURN /*< empty */
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if defined(__sgi) && !defined(__GNUC__) && _COMPILER_VERSION >= 720
|
||||
# define GC_ADD_CALLER
|
||||
# define GC_RETURN_ADDR ((GC_return_addr_t)__return_address)
|
||||
# endif
|
||||
|
||||
# if defined(__linux__) || defined(__GLIBC__)
|
||||
# if !defined(__native_client__)
|
||||
# include <features.h>
|
||||
# endif
|
||||
# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 || __GLIBC__ > 2) \
|
||||
&& !defined(__ia64__) && !defined(GC_MISSING_EXECINFO_H) \
|
||||
&& !defined(GC_HAVE_BUILTIN_BACKTRACE)
|
||||
# define GC_HAVE_BUILTIN_BACKTRACE
|
||||
# endif
|
||||
# if defined(__i386__) || defined(__amd64__) || defined(__x86_64__)
|
||||
# define GC_CAN_SAVE_CALL_STACKS
|
||||
# endif
|
||||
# endif /* GLIBC */
|
||||
|
||||
# if defined(_MSC_VER) && (_MSC_VER >= 1200 /* v12.0+ (MSVC 6.0+) */) \
|
||||
&& !defined(_M_ARM) && !defined(_M_ARM64) && !defined(_AMD64_) \
|
||||
&& !defined(_M_X64) && !defined(_WIN32_WCE) \
|
||||
&& !defined(GC_HAVE_NO_BUILTIN_BACKTRACE) \
|
||||
&& !defined(GC_HAVE_BUILTIN_BACKTRACE)
|
||||
# define GC_HAVE_BUILTIN_BACKTRACE
|
||||
# endif
|
||||
|
||||
# if defined(GC_HAVE_BUILTIN_BACKTRACE) && !defined(GC_CAN_SAVE_CALL_STACKS) \
|
||||
|| defined(__sparc)
|
||||
# define GC_CAN_SAVE_CALL_STACKS
|
||||
# endif
|
||||
|
||||
/*
|
||||
* If we are on a platform on which we cannot save call stacks, but
|
||||
* gcc is normally used, we go ahead and define `GC_ADD_CALLER` macro.
|
||||
* We make this decision independent of whether gcc is actually being
|
||||
* used, in order to keep the interface consistent, and allow mixing
|
||||
* of compilers.
|
||||
* This may also be desirable if it is possible but expensive to
|
||||
* retrieve the call chain.
|
||||
*/
|
||||
# if (defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__) \
|
||||
|| defined(__FreeBSD_kernel__) || defined(__HAIKU__) \
|
||||
|| defined(__NetBSD__) || defined(__OpenBSD__) \
|
||||
|| defined(HOST_ANDROID) || defined(__ANDROID__)) \
|
||||
&& !defined(GC_CAN_SAVE_CALL_STACKS)
|
||||
# define GC_ADD_CALLER
|
||||
# if GC_GNUC_PREREQ(2, 95)
|
||||
/*
|
||||
* gcc knows how to retrieve return address, but we do not know how to
|
||||
* generate call stacks.
|
||||
*/
|
||||
# define GC_RETURN_ADDR ((GC_return_addr_t)__builtin_return_address(0))
|
||||
# if GC_GNUC_PREREQ(4, 0) \
|
||||
&& (defined(__i386__) || defined(__amd64__) \
|
||||
|| defined(__x86_64__) /* and probably others... */) \
|
||||
&& !defined(GC_NO_RETURN_ADDR_PARENT)
|
||||
# define GC_HAVE_RETURN_ADDR_PARENT
|
||||
# define GC_RETURN_ADDR_PARENT \
|
||||
((GC_return_addr_t)__builtin_extract_return_addr( \
|
||||
__builtin_return_address(1)))
|
||||
/*
|
||||
* Note: a compiler might complain that calling `__builtin_return_address`
|
||||
* with a nonzero argument is unsafe.
|
||||
*/
|
||||
# endif
|
||||
# else
|
||||
/* Just pass 0 for gcc compatibility. */
|
||||
# define GC_RETURN_ADDR ((GC_return_addr_t)0)
|
||||
# endif
|
||||
# endif /* !GC_CAN_SAVE_CALL_STACKS */
|
||||
|
||||
# ifdef GC_PTHREADS
|
||||
|
||||
# if (defined(GC_DARWIN_THREADS) || defined(GC_WIN32_PTHREADS) \
|
||||
|| defined(__native_client__) || defined(GC_RTEMS_PTHREADS)) \
|
||||
&& !defined(GC_NO_DLOPEN)
|
||||
/* Either there is no `dlopen()` or we do not need to intercept it. */
|
||||
# define GC_NO_DLOPEN
|
||||
# endif
|
||||
|
||||
# if (defined(GC_DARWIN_THREADS) || defined(GC_WIN32_PTHREADS) \
|
||||
|| defined(__native_client__)) \
|
||||
&& !defined(GC_NO_PTHREAD_SIGMASK)
|
||||
/* Either there is no `pthread_sigmask()` or no need to intercept it. */
|
||||
# define GC_NO_PTHREAD_SIGMASK
|
||||
# endif
|
||||
|
||||
# if defined(__native_client__)
|
||||
/*
|
||||
* At present, NaCl `pthread_create()` prototype does not have
|
||||
* `const` for its `attr` argument; also, NaCl `pthread_exit()` one
|
||||
* does not have `noreturn` attribute.
|
||||
*/
|
||||
# ifndef GC_PTHREAD_CREATE_CONST
|
||||
# define GC_PTHREAD_CREATE_CONST /*< empty */
|
||||
# endif
|
||||
# ifndef GC_HAVE_PTHREAD_EXIT
|
||||
# define GC_HAVE_PTHREAD_EXIT
|
||||
# define GC_PTHREAD_EXIT_ATTRIBUTE /*< empty */
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if !defined(GC_HAVE_PTHREAD_EXIT) \
|
||||
&& ((defined(GC_LINUX_THREADS) && !defined(HOST_ANDROID) \
|
||||
&& !defined(__ANDROID__)) \
|
||||
|| defined(GC_SOLARIS_THREADS) || defined(__COSMOPOLITAN__))
|
||||
/* Intercept `pthread_exit()` where available and needed. */
|
||||
# define GC_HAVE_PTHREAD_EXIT
|
||||
# define GC_PTHREAD_EXIT_ATTRIBUTE GC_ATTR_NORETURN
|
||||
# endif
|
||||
|
||||
# if (!defined(GC_HAVE_PTHREAD_EXIT) || defined(__native_client__)) \
|
||||
&& !defined(GC_NO_PTHREAD_CANCEL)
|
||||
/* Either there is no `pthread_cancel()` or no need to intercept it. */
|
||||
# define GC_NO_PTHREAD_CANCEL
|
||||
# endif
|
||||
|
||||
# endif /* GC_PTHREADS */
|
||||
|
||||
# ifdef __cplusplus
|
||||
|
||||
# ifndef GC_ATTR_EXPLICIT
|
||||
# if __cplusplus >= 201103L && !defined(__clang__) \
|
||||
|| _MSVC_LANG >= 201103L || defined(CPPCHECK)
|
||||
# define GC_ATTR_EXPLICIT explicit
|
||||
# else
|
||||
# define GC_ATTR_EXPLICIT /*< empty */
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef GC_NOEXCEPT
|
||||
# if defined(__DMC__) \
|
||||
|| (defined(__BORLANDC__) \
|
||||
&& (defined(_RWSTD_NO_EXCEPTIONS) \
|
||||
|| defined(_RWSTD_NO_EX_SPEC))) \
|
||||
|| (defined(_MSC_VER) && defined(_HAS_EXCEPTIONS) \
|
||||
&& !_HAS_EXCEPTIONS) \
|
||||
|| (defined(__WATCOMC__) && !defined(_CPPUNWIND))
|
||||
# define GC_NOEXCEPT /*< empty */
|
||||
# ifndef GC_NEW_ABORTS_ON_OOM
|
||||
# define GC_NEW_ABORTS_ON_OOM
|
||||
# endif
|
||||
# elif __cplusplus >= 201103L || _MSVC_LANG >= 201103L
|
||||
# define GC_NOEXCEPT noexcept
|
||||
# else
|
||||
# define GC_NOEXCEPT throw()
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef GC_CONSTEXPR
|
||||
# if __cplusplus >= 202002L
|
||||
# define GC_CONSTEXPR constexpr
|
||||
# else
|
||||
# define GC_CONSTEXPR /*< empty */
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2007-2011 by Hewlett-Packard Company. All rights reserved.
|
||||
*
|
||||
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
||||
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
||||
*
|
||||
* Permission is hereby granted to use or copy this program
|
||||
* for any purpose, provided the above notices are retained on all copies.
|
||||
* Permission to modify the code and to distribute modified code is granted,
|
||||
* provided the above notices are retained, and a notice that the code was
|
||||
* modified is included with the above copyright notice.
|
||||
*/
|
||||
|
||||
#ifndef GC_DISCLAIM_H
|
||||
#define GC_DISCLAIM_H
|
||||
|
||||
#include "gc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This API is defined only if the library has been suitably compiled
|
||||
* (i.e. with `ENABLE_DISCLAIM` macro defined).
|
||||
*/
|
||||
|
||||
/**
|
||||
* Prepare the object kind used by `GC_finalized_malloc`. Call it from
|
||||
* your initialization code or, at least, at some point before using
|
||||
* finalized allocations. The function is thread-safe.
|
||||
*/
|
||||
GC_API void GC_CALL GC_init_finalized_malloc(void);
|
||||
|
||||
/** Type of a disclaim callback. Called with the allocator lock held. */
|
||||
typedef int(GC_CALLBACK *GC_disclaim_proc)(void * /* `obj` */);
|
||||
|
||||
/**
|
||||
* Register `proc` to be called on each object (of given `kind`) ready
|
||||
* to be reclaimed. If `proc()` returns a nonzero value, the
|
||||
* collector will not reclaim the object on this collection cycle
|
||||
* (`proc()` should not try to resurrect the object otherwise); objects
|
||||
* reachable from `proc()` (including the referred closure object) will
|
||||
* be protected from collection if `mark_from_all` is nonzero, but at
|
||||
* the expense that long chains of objects will take many cycles to
|
||||
* reclaim. Any call to `GC_free()` deallocates the object (pointed by
|
||||
* the argument) without inquiring `proc()`. Acquires the allocator lock.
|
||||
* No-op in the find-leak mode.
|
||||
*/
|
||||
GC_API void GC_CALL GC_register_disclaim_proc(int /* `kind` */,
|
||||
GC_disclaim_proc /* `proc` */,
|
||||
int /* `mark_from_all` */);
|
||||
|
||||
/** The finalizer closure used by `GC_finalized_malloc`. */
|
||||
struct GC_finalizer_closure {
|
||||
GC_finalization_proc proc;
|
||||
void *cd;
|
||||
};
|
||||
|
||||
/**
|
||||
* Allocate an object which is to be finalized by the given closure.
|
||||
* This uses a dedicated object kind with a disclaim procedure, and
|
||||
* is more efficient than `GC_register_finalizer` and friends.
|
||||
* `GC_init_finalized_malloc` must be called before using this.
|
||||
* The collector will reclaim the object during this collection cycle
|
||||
* (thus, `fc->proc()` should not try to resurrect the object).
|
||||
* The other objects reachable from `fc->proc()` (including the closure
|
||||
* object in case it is a heap-allocated one) will be protected from
|
||||
* collection. Note that `GC_size()` (applied to such allocated object)
|
||||
* returns a value slightly bigger than the specified allocation size,
|
||||
* and that `GC_base()` result points to a "pointer-sized" word prior
|
||||
* to the start of the allocated object.
|
||||
* The disclaim procedure is not invoked in the find-leak mode.
|
||||
* There is no debugging variant of this allocation function.
|
||||
*/
|
||||
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
|
||||
GC_finalized_malloc(size_t /* `size` */,
|
||||
const struct GC_finalizer_closure * /* `fc` */)
|
||||
GC_ATTR_NONNULL(2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
|
||||
* Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
|
||||
* Copyright 1996-1999 by Silicon Graphics. All rights reserved.
|
||||
* Copyright 1999 by Hewlett-Packard Company. All rights reserved.
|
||||
*
|
||||
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
||||
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
||||
*
|
||||
* Permission is hereby granted to use or copy this program
|
||||
* for any purpose, provided the above notices are retained on all copies.
|
||||
* Permission to modify the code and to distribute modified code is granted,
|
||||
* provided the above notices are retained, and a notice that the code was
|
||||
* modified is included with the above copyright notice.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file assumes the collector has been compiled with `GC_GCJ_SUPPORT`
|
||||
* macro defined.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We allocate objects whose first element contains a pointer to a structure
|
||||
* describing the object type. This structure contains a garbage collector
|
||||
* mark descriptor at offset `GC_GCJ_MARK_DESCR_OFFSET`.
|
||||
* Alternatively, the objects may be marked by the mark procedure passed
|
||||
* to `GC_init_gcj_malloc_mp()`.
|
||||
*/
|
||||
|
||||
#ifndef GC_GCJ_H
|
||||
#define GC_GCJ_H
|
||||
|
||||
#ifndef GC_H
|
||||
# include "gc.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The offset of the garbage collector mark descriptor inside the
|
||||
* structure describing the object type ("vtable"). `gcj` keeps the
|
||||
* mark descriptor as the second "pointer-sized" word of "vtable".
|
||||
* Probably this needs to be adjusted for other clients. It is assumed
|
||||
* that this offset is not smaller than the size of a pointer (the
|
||||
* assumption allows objects on the free list to be marked normally).
|
||||
*/
|
||||
#ifndef GC_GCJ_MARK_DESCR_OFFSET
|
||||
# define GC_GCJ_MARK_DESCR_OFFSET GC_SIZEOF_PTR
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This function must be called before the `gcj` allocators are invoked.
|
||||
* `mp_index` and `mp` are the index and mark procedure (see `gc_mark.h`
|
||||
* file), respectively, for the allocated objects. `mp` will be used to
|
||||
* build the descriptor for objects allocated through the debugging
|
||||
* interface; it will be invoked on all such objects with an `env` value
|
||||
* of 1. The client may choose to use the same mark procedure (`mp`) for
|
||||
* some of its generated mark descriptors. In that case, it should use
|
||||
* a different `env` value to detect the presence or absence of the debug
|
||||
* header. `mp` is really of type `GC_mark_proc`, as defined in `gc_mark.h`
|
||||
* file; we do not want to include that here for namespace pollution reasons.
|
||||
* Passing in `mp_index` here instead of having `GC_init_gcj_malloc()`
|
||||
* internally call `GC_new_proc()` is quite ugly, but in typical usage
|
||||
* scenarios a compiler also has to know about `mp_index`, so generating it
|
||||
* dynamically is not acceptable. The `mp_index` will typically be
|
||||
* an integer less than `RESERVED_MARK_PROCS`, so that it does not collide
|
||||
* with indices allocated by `GC_new_proc()`. If the application needs
|
||||
* no other reserved indices, zero (`GC_GCJ_RESERVED_MARK_PROC_INDEX` in
|
||||
* `gc_mark.h` file) is an obvious choice. Deprecated, portable clients
|
||||
* should include `gc_mark.h` file and use `GC_init_gcj_malloc_mp()` instead.
|
||||
*/
|
||||
GC_API GC_ATTR_DEPRECATED void GC_CALL GC_init_gcj_malloc(int /* `mp_index` */,
|
||||
void * /* `mp` */);
|
||||
|
||||
/**
|
||||
* Allocate an object, clear it, and store the pointer to the type
|
||||
* structure ("vtable" in `gcj`). This adds a byte at the end of the
|
||||
* object if `GC_malloc()` would. In case of out of memory,
|
||||
* `GC_oom_fn()` is called and its result is returned.
|
||||
*/
|
||||
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
|
||||
GC_gcj_malloc(size_t /* `lb` */, const void * /* `vtable_ptr` */);
|
||||
|
||||
/**
|
||||
* Similar to `GC_gcj_malloc`, but add the debug info. This is allocated
|
||||
* with `GC_gcj_debug_kind`.
|
||||
*/
|
||||
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
|
||||
GC_debug_gcj_malloc(size_t /* `lb` */, const void * /* `vtable_ptr` */,
|
||||
GC_EXTRA_PARAMS);
|
||||
|
||||
/**
|
||||
* Similar to `GC_gcj_malloc`, but assumes that a pointer to near the
|
||||
* beginning (i.e. within the first heap block) of the allocated object
|
||||
* is always maintained.
|
||||
*/
|
||||
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
|
||||
GC_gcj_malloc_ignore_off_page(size_t /* `lb` */,
|
||||
const void * /* `vtable_ptr` */);
|
||||
|
||||
/**
|
||||
* The kind numbers of normal and debug `gcj` objects. Useful only for
|
||||
* debug support, we hope.
|
||||
*/
|
||||
GC_API int GC_gcj_kind;
|
||||
GC_API int GC_gcj_debug_kind;
|
||||
|
||||
#ifdef GC_DEBUG
|
||||
# define GC_GCJ_MALLOC(s, d) GC_debug_gcj_malloc(s, d, GC_EXTRAS)
|
||||
# define GC_GCJ_MALLOC_IGNORE_OFF_PAGE(s, d) GC_GCJ_MALLOC(s, d)
|
||||
#else
|
||||
# define GC_GCJ_MALLOC(s, d) GC_gcj_malloc(s, d)
|
||||
# define GC_GCJ_MALLOC_IGNORE_OFF_PAGE(s, d) \
|
||||
GC_gcj_malloc_ignore_off_page(s, d)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* GC_GCJ_H */
|
||||
+261
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
|
||||
* Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
|
||||
* Copyright (c) 2005 Hewlett-Packard Development Company, L.P.
|
||||
* Copyright (c) 2008-2025 Ivan Maidanski
|
||||
*
|
||||
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
||||
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
||||
*
|
||||
* Permission is hereby granted to use or copy this program
|
||||
* for any purpose, provided the above notices are retained on all copies.
|
||||
* Permission to modify the code and to distribute modified code is granted,
|
||||
* provided the above notices are retained, and a notice that the code was
|
||||
* modified is included with the above copyright notice.
|
||||
*/
|
||||
|
||||
#ifndef GC_INLINE_H
|
||||
#define GC_INLINE_H
|
||||
|
||||
/*
|
||||
* *Warning*: Note that for these routines, it is the client`s responsibility
|
||||
* to add the extra byte at the end to deal with one-past-the-end pointers.
|
||||
* In the standard collector configuration, the collector assumes that such
|
||||
* a byte has been added, and hence does not trace the last "pointer-sized"
|
||||
* word in the resulting object. This is not an issue if
|
||||
* `GC_get_all_interior_pointers()` returns zero or if
|
||||
* `GC_get_dont_add_byte_at_end()` returns 1. This interface is most useful
|
||||
* for compilers that generate C code. It is also used internally for
|
||||
* thread-local allocation. A manual use is hereby discouraged.
|
||||
* Multi-threaded clients should include `atomic_ops.h` file (or similar)
|
||||
* before this header. There is no debugging variant of this allocation API.
|
||||
*/
|
||||
|
||||
#include "gc.h"
|
||||
#include "gc_tiny_fl.h"
|
||||
|
||||
#if GC_GNUC_PREREQ(3, 0) || defined(__clang__)
|
||||
/* Equivalent to `(expr)`, but predict that usually `expr == outcome`. */
|
||||
# define GC_EXPECT(expr, outcome) __builtin_expect(expr, outcome)
|
||||
#else
|
||||
# define GC_EXPECT(expr, outcome) (expr)
|
||||
#endif
|
||||
|
||||
#ifndef GC_ASSERT
|
||||
# ifdef NDEBUG
|
||||
# define GC_ASSERT(expr) (void)0
|
||||
# else
|
||||
# include <assert.h>
|
||||
# define GC_ASSERT(expr) assert(expr)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef GC_PREFETCH_FOR_WRITE
|
||||
# if (GC_GNUC_PREREQ(3, 0) || defined(__clang__)) \
|
||||
&& !defined(GC_NO_PREFETCH_FOR_WRITE)
|
||||
# define GC_PREFETCH_FOR_WRITE(x) __builtin_prefetch((x), 1 /* write */)
|
||||
# elif defined(_MSC_VER) && !defined(GC_NO_PREFETCH_FOR_WRITE) \
|
||||
&& (defined(_M_IX86) || defined(_M_X64)) && !defined(_CHPE_ONLY_) \
|
||||
&& (_MSC_VER >= 1900 /* VS 2015+ */)
|
||||
# include <intrin.h>
|
||||
# define GC_PREFETCH_FOR_WRITE(x) _m_prefetchw(x)
|
||||
/* TODO: Support also `_M_ARM` (`__prefetchw`). */
|
||||
# else
|
||||
# define GC_PREFETCH_FOR_WRITE(x) (void)0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Object kinds (exposed to public). */
|
||||
#define GC_I_PTRFREE 0
|
||||
#define GC_I_NORMAL 1
|
||||
|
||||
/**
|
||||
* Determine if the collector has been configured not to pad the
|
||||
* allocated objects even in the all-interior-pointers mode.
|
||||
* Meaningful only if `GC_get_all_interior_pointers()` returns 1.
|
||||
*/
|
||||
GC_API int GC_CALL GC_get_dont_add_byte_at_end(void);
|
||||
|
||||
/**
|
||||
* Return a list of one or more objects of the indicated size, linked
|
||||
* through the first pointer in each object. This has the advantage
|
||||
* that it acquires the allocator lock only once, and may greatly
|
||||
* reduce time wasted contending for the allocator lock. Typical usage
|
||||
* would be in a thread that requires many items of the same size.
|
||||
* It would keep its own free list in a thread-local storage, and call
|
||||
* `GC_malloc_many()` or friends to replenish it. (We do not round up
|
||||
* object sizes, since a call indicates the intention to consume many
|
||||
* objects of exactly this size.) We assume that the size is nonzero
|
||||
* and a multiple of `GC_GRANULE_BYTES`, and that the size already
|
||||
* includes the value returned by `GC_get_all_interior_pointers()`
|
||||
* (unless `GC_get_dont_add_byte_at_end()` returns a nonzero value).
|
||||
* We return the free-list by assigning it to `*result`, since it is
|
||||
* not safe to return a linked list of pointer-free objects, since the
|
||||
* collector would not retain the entire list if it were invoked just
|
||||
* as we were returning; the client must make sure that `*result` is
|
||||
* traced even if objects are pointer-free. Note also that the client
|
||||
* should usually clear the link field.
|
||||
*/
|
||||
GC_API void GC_CALL GC_generic_malloc_many(size_t /* `lb_adjusted` */,
|
||||
int /* `kind` */,
|
||||
void ** /* `result` */);
|
||||
|
||||
/**
|
||||
* A generalized variant of `GC_malloc` and `GC_malloc_atomic`.
|
||||
* Uses appropriately the thread-local (if available) or the global
|
||||
* free-list of the specified `kind`.
|
||||
*/
|
||||
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
|
||||
GC_malloc_kind(size_t /* `lb` */, int /* `kind` */);
|
||||
|
||||
#ifdef GC_THREADS
|
||||
/* Same as `GC_malloc_kind` but uses only the global free-list. */
|
||||
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
|
||||
GC_malloc_kind_global(size_t /* `lb` */, int /* `kind` */);
|
||||
#else
|
||||
# define GC_malloc_kind_global GC_malloc_kind
|
||||
#endif
|
||||
|
||||
/*
|
||||
* An internal macro to update the free-list pointer atomically
|
||||
* (if the AO primitives are available) to avoid race with the marker.
|
||||
*/
|
||||
#if !defined(GC_THREADS) || !defined(AO_HAVE_store)
|
||||
# define GC_FAST_M_AO_STORE(my_fl, next) (void)(*(my_fl) = (next))
|
||||
#elif defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ > __SIZEOF_SIZE_T__)
|
||||
/*
|
||||
* Directly use the gcc atomic intrinsic as the size of a pointer is
|
||||
* bigger than that of `AO_t`.
|
||||
*/
|
||||
# define GC_FAST_M_AO_STORE(my_fl, next) \
|
||||
__atomic_store_n(my_fl, next, __ATOMIC_RELAXED)
|
||||
#else
|
||||
# define GC_FAST_M_AO_STORE(my_fl, next) \
|
||||
AO_store((volatile AO_t *)(my_fl), (size_t)(next))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The ultimately general inline allocation macro. Allocate an object
|
||||
* of size `lg` (in granules), putting the resulting pointer in `result`.
|
||||
* `tiny_fl` is a "tiny" free-list array, which will be used first,
|
||||
* if the size is appropriate. If `lg` argument is too large, then we
|
||||
* allocate with `default_expr` instead. If we need to refill the free
|
||||
* list, we use `GC_generic_malloc_many()` with the indicated kind `k`.
|
||||
* `tiny_fl` should be an array of `GC_TINY_FREELISTS` `void` pointers.
|
||||
* If `num_direct` is nonzero, and the individual free-list pointers are
|
||||
* initialized to `(void *)1`, then we allocate `num_direct` granules
|
||||
* directly using `GC_generic_malloc_many()` before putting multiple
|
||||
* objects into the `tiny_fl` entry. If `num_direct` is zero, then the
|
||||
* free lists may also be initialized to `NULL`. Note that we use the
|
||||
* zeroth free list to hold objects of 1 granule in size that are used to
|
||||
* satisfy size 0 allocation requests. We rely on much of this hopefully
|
||||
* getting optimized away in the case of `num_direct` is 0. Particularly,
|
||||
* if `lg` argument is constant, this should generate a small amount of code.
|
||||
*/
|
||||
#define GC_FAST_MALLOC_GRANS(result, lg, tiny_fl, num_direct, k, \
|
||||
default_expr, init) \
|
||||
do { \
|
||||
if (GC_EXPECT((lg) >= GC_TINY_FREELISTS, 0)) { \
|
||||
result = (default_expr); \
|
||||
} else { \
|
||||
void **my_fl = (tiny_fl) + (lg); \
|
||||
void *my_entry = *my_fl; \
|
||||
void *next; \
|
||||
\
|
||||
for (;;) { \
|
||||
if (GC_EXPECT((GC_word)(GC_uintptr_t)my_entry \
|
||||
> (num_direct) + GC_TINY_FREELISTS + 1, \
|
||||
1)) { \
|
||||
next = *(void **)(my_entry); \
|
||||
result = my_entry; \
|
||||
GC_FAST_M_AO_STORE(my_fl, next); \
|
||||
init; \
|
||||
GC_PREFETCH_FOR_WRITE(next); \
|
||||
if ((k) != GC_I_PTRFREE) { \
|
||||
GC_end_stubborn_change(my_fl); \
|
||||
GC_reachable_here(next); \
|
||||
} \
|
||||
GC_ASSERT(GC_size(result) >= GC_RAW_BYTES_FROM_INDEX(lg)); \
|
||||
GC_ASSERT((k) == GC_I_PTRFREE \
|
||||
|| 0 /* `NULL` */ == ((void **)result)[1]); \
|
||||
break; \
|
||||
} \
|
||||
/* Entry contains counter or `NULL`. */ \
|
||||
if ((GC_signed_word)(GC_uintptr_t)my_entry \
|
||||
- (GC_signed_word)(num_direct) \
|
||||
<= 0 /*< `(GC_uintptr_t)my_entry <= num_direct` */ \
|
||||
&& my_entry != 0 /* NULL */) { \
|
||||
/* Small counter value, not `NULL`. */ \
|
||||
GC_FAST_M_AO_STORE(my_fl, (char *)my_entry + (lg) + 1); \
|
||||
result = (default_expr); \
|
||||
break; \
|
||||
} else { \
|
||||
/* Large counter or `NULL`. */ \
|
||||
size_t lb_adj = GC_RAW_BYTES_FROM_INDEX(0 == (lg) ? 1 : (lg)); \
|
||||
\
|
||||
GC_generic_malloc_many(lb_adj, k, my_fl); \
|
||||
my_entry = *my_fl; \
|
||||
if (0 /* `NULL` */ == my_entry) { \
|
||||
result = (*GC_get_oom_fn())(lb_adj); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Allocate `n` "pointer-sized" words. The allocation size is rounded
|
||||
* up to a granule size. The pointer is stored to `result`.
|
||||
* Should not be used unless `GC_get_all_interior_pointers()` returns zero
|
||||
* or if `GC_get_dont_add_byte_at_end()` returns 1. Does not acquire
|
||||
* the allocator lock. The caller is responsible for supplying
|
||||
* a cleared `tiny_fl` free-list array. For single-threaded applications,
|
||||
* this may be a global array.
|
||||
*/
|
||||
#define GC_MALLOC_WORDS_KIND(result, n, tiny_fl, k, init) \
|
||||
do { \
|
||||
size_t lg = GC_PTRS_TO_WHOLE_GRANULES(n); \
|
||||
\
|
||||
GC_FAST_MALLOC_GRANS(result, lg, tiny_fl, 0 /* `num_direct` */, k, \
|
||||
GC_malloc_kind(GC_RAW_BYTES_FROM_INDEX(lg), k), \
|
||||
init); \
|
||||
} while (0)
|
||||
|
||||
#define GC_MALLOC_WORDS(result, n, tiny_fl) \
|
||||
GC_MALLOC_WORDS_KIND(result, n, tiny_fl, GC_I_NORMAL, \
|
||||
(void)(*(void **)(result) = 0 /* `NULL` */))
|
||||
|
||||
#define GC_MALLOC_ATOMIC_WORDS(result, n, tiny_fl) \
|
||||
GC_MALLOC_WORDS_KIND(result, n, tiny_fl, GC_I_PTRFREE, (void)0)
|
||||
|
||||
/** Allocate a two-pointer initialized object. */
|
||||
#define GC_CONS(result, first, second, tiny_fl) \
|
||||
do { \
|
||||
void *l = (void *)(first); \
|
||||
void *r = (void *)(second); \
|
||||
GC_MALLOC_WORDS_KIND(result, 2, tiny_fl, GC_I_NORMAL, (void)0); \
|
||||
if ((result) != 0 /* `NULL` */) { \
|
||||
*(void **)(result) = l; \
|
||||
GC_ptr_store_and_dirty((void **)(result) + 1, r); \
|
||||
GC_reachable_here(l); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Print address of each object in the free list for the given `kind`
|
||||
* and size `lg` (in granules). The caller should hold the allocator
|
||||
* lock at least in the reader mode. Defined only if the library has
|
||||
* been compiled without `NO_DEBUGGING` macro defined.
|
||||
*/
|
||||
GC_API void GC_CALL GC_print_free_list(int /* `kind` */, size_t /* `lg` */);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* !GC_INLINE_H */
|
||||
+516
@@ -0,0 +1,516 @@
|
||||
/*
|
||||
* Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
|
||||
* Copyright (c) 2001 by Hewlett-Packard Company. All rights reserved.
|
||||
* Copyright (c) 2009-2025 Ivan Maidanski
|
||||
*
|
||||
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
||||
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
||||
*
|
||||
* Permission is hereby granted to use or copy this program
|
||||
* for any purpose, provided the above notices are retained on all copies.
|
||||
* Permission to modify the code and to distribute modified code is granted,
|
||||
* provided the above notices are retained, and a notice that the code was
|
||||
* modified is included with the above copyright notice.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This contains interfaces to the garbage collector marker that are likely
|
||||
* to be useful to clients that provide detailed heap layout information
|
||||
* to the collector. This interface should not be used by normal C or C++
|
||||
* clients. It will be useful to runtimes for other languages.
|
||||
*
|
||||
* This is an experts-only interface! There are many ways to break the
|
||||
* collector in subtle ways by using this functionality.
|
||||
*/
|
||||
#ifndef GC_MARK_H
|
||||
#define GC_MARK_H
|
||||
|
||||
#ifndef GC_H
|
||||
# include "gc.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GC_PROC_BYTES 100
|
||||
|
||||
#if defined(GC_BUILD) || defined(NOT_GCBUILD)
|
||||
struct GC_ms_entry;
|
||||
struct GC_hblk_s;
|
||||
#else
|
||||
struct GC_ms_entry {
|
||||
void *opaque;
|
||||
};
|
||||
struct GC_hblk_s {
|
||||
void *opaque;
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A client-supplied mark procedure. Returns new mark stack pointer.
|
||||
* Primary effect should be to push new entries on the mark stack.
|
||||
* Mark stack pointer values are passed and returned explicitly.
|
||||
* Global variables describing mark stack are not necessarily valid.
|
||||
* (This usually saves a few cycles by keeping things in registers.)
|
||||
* Assumed to scan about `GC_PROC_BYTES` on average. If it needs to do
|
||||
* much more work than that, it should do it in smaller pieces by
|
||||
* pushing itself back on the mark stack. Note that it should always
|
||||
* do some work (defined as "marking some objects") before pushing more
|
||||
* than one entry on the mark stack. This is required to ensure
|
||||
* termination in the event of mark stack overflows. This procedure is
|
||||
* always called with at least one empty entry on the mark stack.
|
||||
* Currently we require that mark procedures look for pointers in
|
||||
* a subset of the places the conservative marker would. It must be safe
|
||||
* to invoke the normal mark procedure instead.
|
||||
*
|
||||
* *Warning*: Such a mark procedure may be invoked on an unused object
|
||||
* residing on a free list. Such objects are cleared, except for a
|
||||
* free-list link field (which is located at the beginning of each
|
||||
* object). Thus mark procedures may not count on the presence of a
|
||||
* type descriptor, and must handle this case correctly somehow. Also,
|
||||
* a mark procedure should be prepared to be executed concurrently from
|
||||
* the marker threads (the latter ones are created only if the client
|
||||
* has called `GC_start_mark_threads()` or started a user thread
|
||||
* previously). For the compatibility reason, `addr` is a pointer to
|
||||
* `GC_word`, but it should be treated as a pointer to `void` pointer.
|
||||
*/
|
||||
typedef struct GC_ms_entry *(GC_CALLBACK *GC_mark_proc)(
|
||||
GC_word * /* `addr` */, struct GC_ms_entry * /* `mark_stack_top` */,
|
||||
struct GC_ms_entry * /* `mark_stack_limit` */, GC_word /* `env` */);
|
||||
|
||||
#define GC_LOG_MAX_MARK_PROCS 6
|
||||
#define GC_MAX_MARK_PROCS (1 << GC_LOG_MAX_MARK_PROCS)
|
||||
|
||||
/*
|
||||
* In a few cases it is necessary to assign statically known indices to
|
||||
* certain mark procedures. Thus we reserve a few for well known clients.
|
||||
* (This is necessary if mark descriptors are compiler generated.)
|
||||
*/
|
||||
#define GC_RESERVED_MARK_PROCS 8
|
||||
#define GC_GCJ_RESERVED_MARK_PROC_INDEX 0
|
||||
|
||||
/*
|
||||
* Object descriptors on mark stack or in objects. Low-order two bits are
|
||||
* tags distinguishing among the following 4 possibilities for the rest
|
||||
* (high-order) bits.
|
||||
*/
|
||||
#define GC_DS_TAG_BITS 2
|
||||
#define GC_DS_TAGS ((1U << GC_DS_TAG_BITS) - 1)
|
||||
|
||||
/**
|
||||
* The entire descriptor is a length in bytes that must be a multiple of 4.
|
||||
*/
|
||||
#define GC_DS_LENGTH 0
|
||||
|
||||
/**
|
||||
* The high-order bits are describing pointer fields. The most
|
||||
* significant bit is set if the first "pointer-sized" word is a pointer.
|
||||
* (This unconventional ordering sometimes makes the marker slightly faster.)
|
||||
* Zeros indicate definite non-pointers; ones indicate possible pointers.
|
||||
* *Note*: only usable if pointers are aligned on the size of a pointer (thus,
|
||||
* extra care should be taken by client on cris and m68k architectures).
|
||||
*/
|
||||
#define GC_DS_BITMAP 1
|
||||
|
||||
/**
|
||||
* The objects referenced by this object can be pushed on the mark stack by
|
||||
* invoking `PROC(descr)`. `ENV(descr)` is passed as the last argument.
|
||||
*/
|
||||
#define GC_DS_PROC 2
|
||||
|
||||
/**
|
||||
* The real descriptor is at the byte displacement from the beginning
|
||||
* of the object given by `descr & ~GC_DS_TAGS`. If the descriptor is
|
||||
* negative, the real descriptor is at
|
||||
* `*<object_start> - (descr & ~GC_DS_TAGS) - GC_INDIR_PER_OBJ_BIAS`.
|
||||
* The latter alternative can be used if each object contains a type
|
||||
* descriptor at the beginning of the object. Note that in the
|
||||
* multi-threaded environments per-object descriptors must be located
|
||||
* in either the first two or last two "pointer-sized" words of the
|
||||
* object, since only those are guaranteed to be cleared while the
|
||||
* allocator lock is held.
|
||||
*/
|
||||
#define GC_DS_PER_OBJECT 3
|
||||
|
||||
#define GC_INDIR_PER_OBJ_BIAS 0x10
|
||||
|
||||
#define GC_MAKE_PROC(proc_index, env) \
|
||||
((((((GC_word)(env)) << GC_LOG_MAX_MARK_PROCS) | (unsigned)(proc_index)) \
|
||||
<< GC_DS_TAG_BITS) \
|
||||
| (GC_word)GC_DS_PROC)
|
||||
|
||||
/**
|
||||
* Bounds on the heap. Guaranteed to be valid. Likely to include future
|
||||
* heap expansion. Hence the bounded range usually includes not-yet-mapped
|
||||
* memory, or might overlap with other data roots. The address of any heap
|
||||
* object is larger than `GC_least_plausible_heap_addr` and less than
|
||||
* `GC_greatest_plausible_heap_addr`.
|
||||
*/
|
||||
GC_API void *GC_least_plausible_heap_addr;
|
||||
GC_API void *GC_greatest_plausible_heap_addr;
|
||||
|
||||
/**
|
||||
* Specify the pointer address mask. Works only if the collector is
|
||||
* built with `DYNAMIC_POINTER_MASK` macro defined. These primitives
|
||||
* are normally needed only to support systems that use high-order
|
||||
* pointer tags. The setter is expected to be called, if needed,
|
||||
* before the collector initialization or, at least, before the first
|
||||
* object is allocated. Both the setter and the getter are unsynchronized.
|
||||
*/
|
||||
GC_API void GC_CALL GC_set_pointer_mask(GC_word);
|
||||
GC_API GC_word GC_CALL GC_get_pointer_mask(void);
|
||||
|
||||
/**
|
||||
* Similar to `GC_set_pointer_mask`/`GC_get_pointer_mask` but for the
|
||||
* pointer address shift. The value should be less than the size of
|
||||
* `GC_word`, in bits. Applied after the mask.
|
||||
*/
|
||||
GC_API void GC_CALL GC_set_pointer_shift(unsigned);
|
||||
GC_API unsigned GC_CALL GC_get_pointer_shift(void);
|
||||
|
||||
/**
|
||||
* Handle nested references in a custom mark procedure.
|
||||
* Check if `obj` is a valid object. If so, ensure that it is marked.
|
||||
* If it was not previously marked, push its contents onto the mark
|
||||
* stack for future scanning. The object will then be scanned using
|
||||
* its mark descriptor. Returns the new mark stack pointer.
|
||||
* Handles mark stack overflows correctly. Since this marks first, it
|
||||
* makes progress even if there are mark stack overflows.
|
||||
* `src` is the address of the pointer to `obj`, which is used only
|
||||
* for back pointer-based heap debugging.
|
||||
* It is strongly recommended that most objects be handled without mark
|
||||
* procedures, e.g. with bitmap descriptors, and that mark procedures
|
||||
* be reserved for the exceptional cases. That will ensure that
|
||||
* performance of this call is not extremely performance critical.
|
||||
* (Otherwise we would need to inline `GC_mark_and_push` completely,
|
||||
* which would tie the client code to a fixed collector version.)
|
||||
* Note that mark procedures should explicitly call `FIXUP_POINTER()`
|
||||
* if required.
|
||||
*/
|
||||
GC_API struct GC_ms_entry *GC_CALL GC_mark_and_push(
|
||||
void * /* `obj` */, struct GC_ms_entry * /* `mark_stack_top` */,
|
||||
struct GC_ms_entry * /* `mark_stack_limit` */, void ** /* `src` */);
|
||||
|
||||
#define GC_MARK_AND_PUSH(obj, msp, lim, src) \
|
||||
(GC_ADDR_LT((char *)GC_least_plausible_heap_addr, (char *)(obj)) \
|
||||
&& GC_ADDR_LT((char *)(obj), \
|
||||
(char *)GC_greatest_plausible_heap_addr) \
|
||||
? GC_mark_and_push(obj, msp, lim, src) \
|
||||
: (msp))
|
||||
|
||||
GC_API void GC_CALL GC_push_proc(GC_word /* `descr` */, void * /* `obj` */);
|
||||
|
||||
GC_API struct GC_ms_entry *GC_CALL
|
||||
GC_custom_push_proc(GC_word /* `descr` */, void * /* `obj` */,
|
||||
struct GC_ms_entry * /* `mark_stack_top` */,
|
||||
struct GC_ms_entry * /* `mark_stack_limit` */);
|
||||
|
||||
GC_API struct GC_ms_entry *GC_CALL
|
||||
GC_custom_push_range(void * /* `bottom` */, void * /* `top` */,
|
||||
struct GC_ms_entry * /* `mark_stack_top` */,
|
||||
struct GC_ms_entry * /* `mark_stack_limit` */);
|
||||
|
||||
/**
|
||||
* The size of the header added to objects allocated through the `GC_debug_`
|
||||
* routines. Defined as a function so that client mark procedures do not
|
||||
* need to be recompiled for the collector library version changes.
|
||||
*/
|
||||
GC_API GC_ATTR_CONST size_t GC_CALL GC_get_debug_header_size(void);
|
||||
#define GC_USR_PTR_FROM_BASE(p) \
|
||||
((void *)((char *)(p) + GC_get_debug_header_size()))
|
||||
|
||||
/*
|
||||
* The same as `GC_get_debug_header_size()` but defined as a variable.
|
||||
* Exists only for the backward compatibility. Some compilers do not
|
||||
* accept `const` together with `deprecated` or `dllimport` attributes,
|
||||
* so the symbol is exported as a non-constant one.
|
||||
*/
|
||||
GC_API GC_ATTR_DEPRECATED
|
||||
#ifdef GC_BUILD
|
||||
const
|
||||
#endif
|
||||
size_t GC_debug_header_size;
|
||||
|
||||
/**
|
||||
* Return the heap block size. Each heap block is devoted to a single size
|
||||
* and kind of object.
|
||||
*/
|
||||
GC_API GC_ATTR_CONST size_t GC_CALL GC_get_hblk_size(void);
|
||||
|
||||
typedef void(GC_CALLBACK *GC_walk_hblk_fn)(struct GC_hblk_s *,
|
||||
void * /* `client_data` */);
|
||||
|
||||
/**
|
||||
* Apply `fn` to each allocated heap block. It is the responsibility
|
||||
* of the caller to avoid data race during the function execution
|
||||
* (e.g. by acquiring the allocator lock at least in the reader mode).
|
||||
*/
|
||||
GC_API void GC_CALL GC_apply_to_all_blocks(GC_walk_hblk_fn,
|
||||
void * /* `client_data` */)
|
||||
GC_ATTR_NONNULL(1);
|
||||
|
||||
/* Same as `GC_walk_hblk_fn` but with index of the free list. */
|
||||
typedef void(GC_CALLBACK *GC_walk_free_blk_fn)(struct GC_hblk_s *,
|
||||
int /* `index` */,
|
||||
void * /* `client_data` */);
|
||||
|
||||
/**
|
||||
* Apply `fn` to each completely empty heap block. It is the responsibility
|
||||
* of the caller to avoid data race during the function execution (e.g. by
|
||||
* acquiring the allocator lock at least in the reader mode).
|
||||
*/
|
||||
GC_API void GC_CALL GC_iterate_free_hblks(GC_walk_free_blk_fn,
|
||||
void * /* `client_data` */)
|
||||
GC_ATTR_NONNULL(1);
|
||||
|
||||
/**
|
||||
* If there are likely to be false references to a block starting at
|
||||
* `h` of the indicated length (`len`), then return the next plausible
|
||||
* starting location for `h` that might avoid these false references.
|
||||
* (In other words: Is the block starting at `h` of size `len` bytes
|
||||
* black-listed? If so, then return the address of the next plausible
|
||||
* `r` such that (`r`,`len`) might not be black-listed. Note that
|
||||
* pointer `r` may not actually be in the heap, we guarantee only that
|
||||
* every smaller value of `r` after `h` is also black-listed.)
|
||||
* Otherwise `NULL` is returned. Assumes the allocator lock is held at
|
||||
* least in the reader mode, but no assertion about it by design.
|
||||
*/
|
||||
GC_API struct GC_hblk_s *GC_CALL
|
||||
GC_is_black_listed(struct GC_hblk_s * /* `h` */, size_t /* `len` */);
|
||||
|
||||
/**
|
||||
* Return the number of set mark bits for the heap block where object `p`
|
||||
* is located. Defined only if the library has been compiled without
|
||||
* `NO_DEBUGGING` macro defined.
|
||||
*/
|
||||
GC_API unsigned GC_CALL GC_count_set_marks_in_hblk(const void * /* `p` */);
|
||||
|
||||
/*
|
||||
* And some routines to support creation of new "kinds", e.g. with custom
|
||||
* mark procedures, by language runtimes. The `_inner` variants assume
|
||||
* the caller holds the allocator lock.
|
||||
*/
|
||||
|
||||
/** Return a new free-list array. */
|
||||
GC_API void **GC_CALL GC_new_free_list(void);
|
||||
GC_API void **GC_CALL GC_new_free_list_inner(void);
|
||||
|
||||
/**
|
||||
* Return a new kind, as specified. The last two parameters must be zero
|
||||
* or one.
|
||||
*/
|
||||
GC_API unsigned GC_CALL GC_new_kind(void ** /* `free_list` */,
|
||||
GC_word /* `mark_descriptor_template` */,
|
||||
int /* `add_size_to_descriptor` */,
|
||||
int /* `clear_new_objects` */)
|
||||
GC_ATTR_NONNULL(1);
|
||||
GC_API unsigned GC_CALL GC_new_kind_inner(
|
||||
void ** /* `free_list` */, GC_word /* `mark_descriptor_template` */,
|
||||
int /* `add_size_to_descriptor` */, int /* `clear_new_objects` */)
|
||||
GC_ATTR_NONNULL(1);
|
||||
|
||||
/**
|
||||
* Return a new mark procedure identifier, suitable for use as the first
|
||||
* argument in `GC_MAKE_PROC()`.
|
||||
*/
|
||||
GC_API unsigned GC_CALL GC_new_proc(GC_mark_proc);
|
||||
GC_API unsigned GC_CALL GC_new_proc_inner(GC_mark_proc);
|
||||
|
||||
/**
|
||||
* Similar to `GC_init_gcj_malloc()` described in `gc_gcj.h` file but with
|
||||
* the proper types of the arguments and an additional runtime checking.
|
||||
* `GC_GCJ_MARK_DESCR_OFFSET` should be passed to `descr_offset` argument.
|
||||
* Defined only if the library has been compiled with `GC_GCJ_SUPPORT`
|
||||
* macro defined.
|
||||
*/
|
||||
GC_API void GC_CALL GC_init_gcj_malloc_mp(unsigned /* `mp_index` */,
|
||||
GC_mark_proc /* `mp` */,
|
||||
size_t /* `descr_offset` */);
|
||||
|
||||
/**
|
||||
* Allocate an object of a given `kind`. By default, there are only
|
||||
* a few kinds: composite (pointerful), atomic, uncollectible, etc.
|
||||
* We claim it is possible for clever client code that understands the
|
||||
* collector internals to add more, e.g. to communicate object layout
|
||||
* information to the collector. Note that in the multi-threaded
|
||||
* contexts, this is usually unsafe for kinds that have the descriptor
|
||||
* in the object itself, since there is otherwise a window in which
|
||||
* the descriptor is not correct. Even in the single-threaded case,
|
||||
* we need to be sure that cleared objects on a free list do not cause
|
||||
* a GC crash if they are accidentally traced.
|
||||
*/
|
||||
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
|
||||
GC_generic_malloc(size_t /* `lb` */, int /* `kind` */);
|
||||
|
||||
/**
|
||||
* Same as `GC_generic_malloc()`, but pointers to past the first heap block
|
||||
* of the resulting object are ignored. We avoid holding the allocator lock
|
||||
* while we clear the memory.
|
||||
*/
|
||||
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
|
||||
GC_generic_malloc_ignore_off_page(size_t /* `lb` */, int /* `kind` */);
|
||||
|
||||
/**
|
||||
* A generalized variant of `GC_malloc_uncollectable()` and
|
||||
* `GC_malloc_atomic_uncollectable()`.
|
||||
*/
|
||||
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
|
||||
GC_generic_malloc_uncollectable(size_t /* `lb` */, int /* `kind` */);
|
||||
|
||||
/**
|
||||
* Same as `GC_generic_malloc()`, but primary for allocating an object
|
||||
* of the same kind as an existing one (`kind` obtained by
|
||||
* `GC_get_kind_and_size()`). Not suitable for `gcj` and typed-`malloc`
|
||||
* kinds.
|
||||
*/
|
||||
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
|
||||
GC_generic_or_special_malloc(size_t /* `size` */, int /* `kind` */);
|
||||
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
|
||||
GC_debug_generic_or_special_malloc(size_t /* `size` */, int /* `kind` */,
|
||||
GC_EXTRA_PARAMS);
|
||||
|
||||
#ifdef GC_DEBUG
|
||||
# define GC_GENERIC_OR_SPECIAL_MALLOC(sz, k) \
|
||||
GC_debug_generic_or_special_malloc(sz, k, GC_EXTRAS)
|
||||
#else
|
||||
# define GC_GENERIC_OR_SPECIAL_MALLOC(sz, k) \
|
||||
GC_generic_or_special_malloc(sz, k)
|
||||
#endif /* !GC_DEBUG */
|
||||
|
||||
/**
|
||||
* Similar to `GC_size` but returns object kind. The size is returned too
|
||||
* if `psize` is not `NULL`. The object pointer should be non-`NULL`.
|
||||
*/
|
||||
GC_API int GC_CALL GC_get_kind_and_size(const void *, size_t * /* `psize` */)
|
||||
GC_ATTR_NONNULL(1);
|
||||
|
||||
/**
|
||||
* A procedure which produces a human-readable description of the
|
||||
* "type" of object `p` into the buffer `out_buf` of length
|
||||
* `GC_TYPE_DESCR_LEN`. This is used by the debug support when
|
||||
* printing objects. These functions should be as robust as possible,
|
||||
* though we do avoid invoking them on objects on the global free list.
|
||||
*/
|
||||
typedef void(GC_CALLBACK *GC_describe_type_fn)(void * /* `p` */,
|
||||
char * /* `out_buf` */);
|
||||
#define GC_TYPE_DESCR_LEN 40
|
||||
|
||||
/**
|
||||
* Register a `describe_type` function to be used when printing objects
|
||||
* of a particular `kind`.
|
||||
*/
|
||||
GC_API void GC_CALL GC_register_describe_type_fn(int /* `kind` */,
|
||||
GC_describe_type_fn);
|
||||
|
||||
/**
|
||||
* Clear some of the inaccessible part of the stack. Returns its argument,
|
||||
* so it can be used in a tail call position, hence clearing another frame.
|
||||
* The argument may be `NULL`.
|
||||
*/
|
||||
GC_API void *GC_CALL GC_clear_stack(void *);
|
||||
|
||||
/**
|
||||
* Set/get the client notifier on collections. The client-supplied procedure
|
||||
* is called at the start of every full collection (called with the allocator
|
||||
* lock held). May be 0. This is a really tricky interface to use correctly.
|
||||
* Unless you really understand the collector internals, the callback should
|
||||
* not, directly or indirectly, make any `GC_` or potentially blocking calls.
|
||||
* In particular, it is not safe to allocate memory using the collector from
|
||||
* within the callback procedure. Both the setter and the getter acquire the
|
||||
* allocator lock (in the reader mode in case of the getter).
|
||||
*/
|
||||
typedef void(GC_CALLBACK *GC_start_callback_proc)(void);
|
||||
GC_API void GC_CALL GC_set_start_callback(GC_start_callback_proc);
|
||||
GC_API GC_start_callback_proc GC_CALL GC_get_start_callback(void);
|
||||
|
||||
/**
|
||||
* Slow/general mark bit manipulation. The caller should hold the
|
||||
* allocator lock. The argument should be the real address of an object
|
||||
* (i.e. the address of the debug header if there is one).
|
||||
*/
|
||||
GC_API void GC_CALL GC_clear_mark_bit(const void *) GC_ATTR_NONNULL(1);
|
||||
GC_API void GC_CALL GC_set_mark_bit(const void *) GC_ATTR_NONNULL(1);
|
||||
|
||||
/**
|
||||
* Get the mark bit. Returns 1 (true) or 0. The caller should hold the
|
||||
* allocator lock at least in the reader mode. The argument should be
|
||||
* the real address of an object (i.e. the address of the debug header
|
||||
* if there is one).
|
||||
*/
|
||||
GC_API int GC_CALL GC_is_marked(const void *) GC_ATTR_NONNULL(1);
|
||||
|
||||
/**
|
||||
* Push everything in the given range onto the mark stack. `bottom` is
|
||||
* the first location to be scanned; `top` is one past the last location
|
||||
* to be scanned. Should only be used if there is no possibility of mark
|
||||
* stack overflow.
|
||||
*/
|
||||
GC_API void GC_CALL GC_push_all(void * /* `bottom` */, void * /* `top` */);
|
||||
|
||||
/**
|
||||
* Similar to `GC_push_all` but treats all interior pointers as valid and
|
||||
* scans the entire region immediately (not just schedules it for scanning),
|
||||
* in case the contents change.
|
||||
*/
|
||||
GC_API void GC_CALL GC_push_all_eager(void * /* `bottom` */,
|
||||
void * /* `top` */);
|
||||
|
||||
/**
|
||||
* Similar to `GC_push_all` but processes either all or only dirty pages
|
||||
* depending on `all` argument.
|
||||
*/
|
||||
GC_API void GC_CALL GC_push_conditional(void * /* `bottom` */,
|
||||
void * /* `top` */,
|
||||
int /* `bool` `all` */);
|
||||
|
||||
GC_API void GC_CALL GC_push_finalizer_structures(void);
|
||||
|
||||
/**
|
||||
* Set/get the client push-other-roots procedure. A client-supplied
|
||||
* procedure should also call the original one. Note that both the setter
|
||||
* and the getter require some external synchronization to avoid data race.
|
||||
*/
|
||||
typedef void(GC_CALLBACK *GC_push_other_roots_proc)(void);
|
||||
GC_API void GC_CALL GC_set_push_other_roots(GC_push_other_roots_proc);
|
||||
GC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void);
|
||||
|
||||
/**
|
||||
* Walk the GC heap visiting all reachable objects. Assume the caller
|
||||
* holds the allocator lock at least in the reader mode. Object base
|
||||
* pointer, object size and client custom data are passed to the callback
|
||||
* (holding the allocator lock in the same mode as the caller does).
|
||||
*/
|
||||
typedef void(GC_CALLBACK *GC_reachable_object_proc)(
|
||||
void * /* `obj` */, size_t /* `bytes` */, void * /* `client_data` */);
|
||||
GC_API void GC_CALL GC_enumerate_reachable_objects_inner(
|
||||
GC_reachable_object_proc, void * /* `client_data` */) GC_ATTR_NONNULL(1);
|
||||
|
||||
/**
|
||||
* Is the given address in one of the temporary static root sections?
|
||||
* Acquires the allocator lock in the reader mode. For the debugging
|
||||
* purpose only.
|
||||
*/
|
||||
GC_API int GC_CALL GC_is_tmp_root(void *);
|
||||
|
||||
GC_API void GC_CALL GC_print_trace(GC_word /* `gc_no` */);
|
||||
GC_API void GC_CALL GC_print_trace_inner(GC_word /* `gc_no` */);
|
||||
|
||||
/**
|
||||
* Set the client for when mark stack is empty. A client can use this
|
||||
* callback to process (un)marked objects and push additional work onto
|
||||
* the stack. Useful for implementing ephemerons. Both the setter and
|
||||
* the getter acquire the allocator lock (in the reader mode in case of
|
||||
* the getter).
|
||||
*/
|
||||
typedef struct GC_ms_entry *(GC_CALLBACK *GC_on_mark_stack_empty_proc)(
|
||||
struct GC_ms_entry * /* `mark_stack_top` */,
|
||||
struct GC_ms_entry * /* `mark_stack_limit` */);
|
||||
GC_API void GC_CALL GC_set_on_mark_stack_empty(GC_on_mark_stack_empty_proc);
|
||||
GC_API GC_on_mark_stack_empty_proc GC_CALL GC_get_on_mark_stack_empty(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* GC_MARK_H */
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) 1994 by Xerox Corporation. All rights reserved.
|
||||
* Copyright (c) 1996 by Silicon Graphics. All rights reserved.
|
||||
* Copyright (c) 1998 by Fergus Henderson. All rights reserved.
|
||||
* Copyright (c) 2000-2010 by Hewlett-Packard Development Company.
|
||||
* All rights reserved.
|
||||
*
|
||||
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
||||
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
||||
*
|
||||
* Permission is hereby granted to use or copy this program
|
||||
* for any purpose, provided the above notices are retained on all copies.
|
||||
* Permission to modify the code and to distribute modified code is granted,
|
||||
* provided the above notices are retained, and a notice that the code was
|
||||
* modified is included with the above copyright notice.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The collector `pthreads` support normally needs to intercept a number
|
||||
* of thread calls. We arrange to do that here, if appropriate.
|
||||
*/
|
||||
|
||||
#ifndef GC_PTHREAD_REDIRECTS_H
|
||||
#define GC_PTHREAD_REDIRECTS_H
|
||||
|
||||
/*
|
||||
* Included from `gc.h` file only. Included only if `GC_PTHREADS` macro
|
||||
* is defined.
|
||||
*/
|
||||
#if defined(GC_H) && defined(GC_PTHREADS)
|
||||
|
||||
/*
|
||||
* We need to intercept calls to many of the threads' primitives, so
|
||||
* that we can locate thread stacks and stop the world.
|
||||
*
|
||||
* Note also that the collector cannot always see thread-specific data.
|
||||
* Such data should generally consist of pointers to uncollectible
|
||||
* objects (allocated with `GC_malloc_uncollectable`, not the system
|
||||
* `malloc`), which are deallocated using the destructor facility in
|
||||
* `pthread_key_create()`. Alternatively, keep a redundant pointer
|
||||
* to thread-specific data on the thread stack.
|
||||
*/
|
||||
|
||||
# ifndef GC_PTHREAD_REDIRECTS_ONLY
|
||||
|
||||
# include <pthread.h>
|
||||
# ifndef GC_NO_DLOPEN
|
||||
# include <dlfcn.h>
|
||||
# endif
|
||||
# ifndef GC_NO_PTHREAD_SIGMASK
|
||||
/* This is needed anyway for proper redirection. */
|
||||
# include <signal.h>
|
||||
# endif
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
# ifndef GC_SUSPEND_THREAD_ID
|
||||
# define GC_SUSPEND_THREAD_ID pthread_t
|
||||
# endif
|
||||
|
||||
# ifndef GC_NO_DLOPEN
|
||||
GC_API void *GC_dlopen(const char * /* `path` */, int /* `mode` */);
|
||||
# endif
|
||||
|
||||
# ifndef GC_NO_PTHREAD_SIGMASK
|
||||
# if defined(GC_PTHREAD_SIGMASK_NEEDED) || defined(__COSMOPOLITAN__) \
|
||||
|| defined(GC_HAVE_PTHREAD_SIGMASK) || defined(_BSD_SOURCE) \
|
||||
|| defined(_GNU_SOURCE) || defined(_NETBSD_SOURCE) \
|
||||
|| (_POSIX_C_SOURCE >= 199506L) || (_XOPEN_SOURCE >= 500) \
|
||||
|| (__POSIX_VISIBLE >= 199506) /*< xBSD internal macro */
|
||||
|
||||
GC_API int GC_pthread_sigmask(int /* `how` */, const sigset_t *,
|
||||
sigset_t * /* `oset` */);
|
||||
# else
|
||||
# define GC_NO_PTHREAD_SIGMASK
|
||||
# endif
|
||||
# endif /* !GC_NO_PTHREAD_SIGMASK */
|
||||
|
||||
# ifndef GC_PTHREAD_CREATE_CONST
|
||||
/* This is used for `pthread_create()` only. */
|
||||
# define GC_PTHREAD_CREATE_CONST const
|
||||
# endif
|
||||
|
||||
GC_API int GC_pthread_create(pthread_t *,
|
||||
GC_PTHREAD_CREATE_CONST pthread_attr_t *,
|
||||
void *(*)(void *), void * /* `arg` */);
|
||||
GC_API int GC_pthread_join(pthread_t, void ** /* `retval` */);
|
||||
GC_API int GC_pthread_detach(pthread_t);
|
||||
|
||||
# ifndef GC_NO_PTHREAD_CANCEL
|
||||
GC_API int GC_pthread_cancel(pthread_t);
|
||||
# endif
|
||||
|
||||
# if defined(GC_HAVE_PTHREAD_EXIT) && !defined(GC_PTHREAD_EXIT_DECLARED)
|
||||
# define GC_PTHREAD_EXIT_DECLARED
|
||||
GC_API void GC_pthread_exit(void *) GC_PTHREAD_EXIT_ATTRIBUTE;
|
||||
# endif
|
||||
|
||||
# ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
# endif
|
||||
|
||||
# endif /* !GC_PTHREAD_REDIRECTS_ONLY */
|
||||
|
||||
# if !defined(GC_NO_THREAD_REDIRECTS) && !defined(GC_USE_LD_WRAP)
|
||||
/*
|
||||
* Unless the compiler supports `#pragma extern_prefix`, the Tru64 UNIX
|
||||
* platform `pthread.h` file redefines some POSIX thread functions to use
|
||||
* mangled names. Anyway, it is safe to `#undef` them before redefining.
|
||||
*/
|
||||
# undef pthread_create
|
||||
# undef pthread_join
|
||||
# undef pthread_detach
|
||||
# define pthread_create GC_pthread_create
|
||||
# define pthread_join GC_pthread_join
|
||||
# define pthread_detach GC_pthread_detach
|
||||
|
||||
# ifndef GC_NO_PTHREAD_SIGMASK
|
||||
# undef pthread_sigmask
|
||||
# define pthread_sigmask GC_pthread_sigmask
|
||||
# endif
|
||||
# ifndef GC_NO_DLOPEN
|
||||
# undef dlopen
|
||||
# define dlopen GC_dlopen
|
||||
# endif
|
||||
# ifndef GC_NO_PTHREAD_CANCEL
|
||||
# undef pthread_cancel
|
||||
# define pthread_cancel GC_pthread_cancel
|
||||
# endif
|
||||
# ifdef GC_HAVE_PTHREAD_EXIT
|
||||
# undef pthread_exit
|
||||
# define pthread_exit GC_pthread_exit
|
||||
# endif
|
||||
# endif /* !GC_NO_THREAD_REDIRECTS */
|
||||
|
||||
#endif /* GC_PTHREADS */
|
||||
|
||||
#endif /* GC_PTHREAD_REDIRECTS_H */
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2005 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
||||
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
||||
*
|
||||
* Permission is hereby granted to use or copy this program
|
||||
* for any purpose, provided the above notices are retained on all copies.
|
||||
* Permission to modify the code and to distribute modified code is granted,
|
||||
* provided the above notices are retained, and a notice that the code was
|
||||
* modified is included with the above copyright notice.
|
||||
*/
|
||||
|
||||
#ifndef GC_TINY_FL_H
|
||||
#define GC_TINY_FL_H
|
||||
|
||||
/*
|
||||
* Constants and data structures for "tiny" free lists.
|
||||
* These are used for thread-local allocation and inlined allocators.
|
||||
* Each global free list also essentially starts with one of these.
|
||||
* However, global free lists are known to the collector.
|
||||
* "Tiny" free lists are basically private to the client.
|
||||
* Their contents are viewed as "in use" and marked accordingly by the
|
||||
* core of the collector. Note that inlined code might know about the
|
||||
* layout of these and the constants involved. Thus any change here
|
||||
* may invalidate clients, and such changes should be avoided.
|
||||
* Hence we keep this as simple as possible.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We always set `GC_GRANULE_BYTES` to twice the length of a pointer.
|
||||
* This means that all allocation requests are rounded up to the next
|
||||
* multiple of 16 on 64-bit architectures or 8 on 32-bit architectures.
|
||||
* This appears to be a reasonable compromise between fragmentation
|
||||
* overhead and space usage for mark bits (usually mark bytes).
|
||||
* On many 64-bit architectures some memory references require 16-byte
|
||||
* alignment, making this necessary anyway. For a few 32-bit
|
||||
* architectures (e.g. i686), we may also need 16-byte alignment for
|
||||
* certain memory references. But currently that does not seem to be
|
||||
* the default for all conventional `malloc` implementations, so we
|
||||
* ignore that problem.
|
||||
* It would always be safe, and often useful, to be able to allocate
|
||||
* very small objects with smaller alignment. But that would cost us
|
||||
* mark bit space, so we no longer do so.
|
||||
* `GC_GRANULE_BYTES` should not be overridden in any instances of the
|
||||
* collector library that may be shared between applications, since it
|
||||
* affects the ABI (application binary interface) to the library.
|
||||
*/
|
||||
#if defined(CPPCHECK) && GC_GRANULE_BYTES == 1
|
||||
# undef GC_GRANULE_BYTES
|
||||
#endif
|
||||
#ifdef GC_GRANULE_BYTES
|
||||
# define GC_GRANULE_PTRS (GC_GRANULE_BYTES / GC_SIZEOF_PTR)
|
||||
#else
|
||||
# define GC_GRANULE_PTRS 2 /*< in pointers */
|
||||
# define GC_GRANULE_BYTES (GC_GRANULE_PTRS * GC_SIZEOF_PTR)
|
||||
#endif /* !GC_GRANULE_BYTES */
|
||||
|
||||
/** Convert size in pointers to that in granules. */
|
||||
#define GC_PTRS_TO_GRANULES(n) ((n) / GC_GRANULE_PTRS)
|
||||
|
||||
/**
|
||||
* Convert size in pointers to that in granules, but rounding up the
|
||||
* result.
|
||||
*/
|
||||
#define GC_PTRS_TO_WHOLE_GRANULES(n) \
|
||||
GC_PTRS_TO_GRANULES((n) + GC_GRANULE_PTRS - 1)
|
||||
|
||||
/*
|
||||
* A "tiny" free-list header contains `GC_TINY_FREELISTS` pointers to
|
||||
* singly-linked lists of objects of different sizes, the `i`-th one
|
||||
* containing objects of `i` granules in size. Note that there is
|
||||
* a list of size zero objects.
|
||||
*/
|
||||
#ifndef GC_TINY_FREELISTS
|
||||
# if GC_GRANULE_BYTES >= 16
|
||||
# define GC_TINY_FREELISTS 25
|
||||
# else
|
||||
# define GC_TINY_FREELISTS 33 /*< up to and including 256 bytes */
|
||||
# endif
|
||||
#endif /* !GC_TINY_FREELISTS */
|
||||
|
||||
/*
|
||||
* The `i`-th free list corresponds to size `i * GC_GRANULE_BYTES`.
|
||||
* Internally to the collector, the index `i` can be computed with
|
||||
* `ALLOC_REQUEST_GRANS()`. The latter also depends on the values
|
||||
* returned by `GC_get_dont_add_byte_at_end()` and
|
||||
* `GC_get_all_interior_pointers()`.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Convert a free-list index to the actual size of objects on that list,
|
||||
* including extra space we added. Not an inverse of the above.
|
||||
*/
|
||||
#define GC_RAW_BYTES_FROM_INDEX(i) (GC_GRANULE_BYTES * (i))
|
||||
|
||||
/* Deprecated. Use `GC_GRANULE_PTRS` instead. */
|
||||
#undef GC_GRANULE_WORDS
|
||||
#define GC_GRANULE_WORDS GC_GRANULE_PTRS
|
||||
|
||||
/* Deprecated. Use `GC_PTRS_TO_GRANULES()` instead. */
|
||||
#define GC_WORDS_TO_GRANULES(n) GC_PTRS_TO_GRANULES(n)
|
||||
|
||||
/* Deprecated. */
|
||||
#define GC_WORDS_TO_WHOLE_GRANULES(n) GC_PTRS_TO_WHOLE_GRANULES(n)
|
||||
|
||||
#endif /* GC_TINY_FL_H */
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
|
||||
* Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
|
||||
* Copyright 1996 Silicon Graphics. All rights reserved.
|
||||
*
|
||||
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
||||
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
||||
*
|
||||
* Permission is hereby granted to use or copy this program
|
||||
* for any purpose, provided the above notices are retained on all copies.
|
||||
* Permission to modify the code and to distribute modified code is granted,
|
||||
* provided the above notices are retained, and a notice that the code was
|
||||
* modified is included with the above copyright notice.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Some simple primitives for allocation with explicit type information.
|
||||
* Facilities for dynamic type inference may be added later.
|
||||
* Should be used only for extremely performance critical applications,
|
||||
* or if conservative collector leakage is otherwise a problem (unlikely).
|
||||
* Note that this is implemented completely separately from the rest
|
||||
* of the collector, and is not linked in unless referenced.
|
||||
* This does not currently support `GC_DEBUG` in any interesting way.
|
||||
*
|
||||
* Note for cris and m68k architectures (and for bcc and wcc compilers):
|
||||
* this API expects all pointers in the type (`T`) are aligned by the size
|
||||
* of a pointer (which might differ from `ALIGNMENT`).
|
||||
*/
|
||||
|
||||
#ifndef GC_TYPED_H
|
||||
#define GC_TYPED_H
|
||||
|
||||
#ifndef GC_H
|
||||
# include "gc.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** The size of `GC_word` (not a pointer) type in bits. */
|
||||
#define GC_WORDSZ (8 * sizeof(GC_word))
|
||||
|
||||
/** The size of a type `t` in pointers. The value is rounded down. */
|
||||
#define GC_SIZEOF_IN_PTRS(t) (sizeof(t) / sizeof(void *))
|
||||
|
||||
/** The offset of a field in pointers. */
|
||||
#define GC_OFFSETOF_IN_PTRS(t, f) (offsetof(t, f) / sizeof(void *))
|
||||
|
||||
/**
|
||||
* The bitmap type. The least significant bit of the first `GC_word` is one
|
||||
* if the first "pointer-sized" word in the object may be a pointer.
|
||||
*/
|
||||
typedef GC_word *GC_bitmap;
|
||||
|
||||
/**
|
||||
* The number of elements (of `GC_word` type) of a bitmap array to
|
||||
* create for a given type `t`. The bitmap is intended to be passed to
|
||||
* `GC_make_descriptor()`.
|
||||
*/
|
||||
#define GC_BITMAP_SIZE(t) ((GC_SIZEOF_IN_PTRS(t) + GC_WORDSZ - 1) / GC_WORDSZ)
|
||||
|
||||
/**
|
||||
* The setter and getter of the bitmap. The `bm` argument should be of
|
||||
* `GC_bitmap` type; `i` argument should be of some `unsigned` type and
|
||||
* should not have side effects.
|
||||
*/
|
||||
#define GC_set_bit(bm, i) \
|
||||
((bm)[(i) / GC_WORDSZ] |= (GC_word)1 << ((i) % GC_WORDSZ))
|
||||
#define GC_get_bit(bm, i) (((bm)[(i) / GC_WORDSZ] >> ((i) % GC_WORDSZ)) & 1)
|
||||
|
||||
typedef GC_word GC_descr;
|
||||
|
||||
/**
|
||||
* Return a type descriptor for the object whose layout is described
|
||||
* by the first argument. The least significant bit of the first
|
||||
* `GC_word` is one if the first "pointer-sized" word in the object may
|
||||
* be a pointer. The second argument (`number_of_bits_in_bitmap`)
|
||||
* specifies the number of meaningful bits in the bitmap.
|
||||
* The actual object may be larger (but not smaller); any additional
|
||||
* "pointer-sized" words in the object are assumed not to contain
|
||||
* pointers. Returns a conservative approximation in the (unlikely)
|
||||
* case of insufficient memory to build the descriptor. Calls to
|
||||
* `GC_make_descriptor()` may consume some amount of a finite resource.
|
||||
* This is intended to be called once per a type, not once per an
|
||||
* allocation.
|
||||
*
|
||||
* It is possible to generate a descriptor for a client type `T` with
|
||||
* aligned pointer fields `f1`, `f2`, ... as follows:
|
||||
* ```
|
||||
* GC_descr t_descr;
|
||||
* {
|
||||
* GC_word bm[GC_BITMAP_SIZE(T)] = { 0 };
|
||||
* GC_set_bit(bm, GC_OFFSETOF_IN_PTRS(T, f1));
|
||||
* GC_set_bit(bm, GC_OFFSETOF_IN_PTRS(T, f2));
|
||||
* ...
|
||||
* t_descr = GC_make_descriptor(bm, GC_SIZEOF_IN_PTRS(T));
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
GC_API GC_descr GC_CALL
|
||||
GC_make_descriptor(const GC_word * /* `GC_bitmap` `bm` */,
|
||||
size_t /* `number_of_bits_in_bitmap` */);
|
||||
|
||||
/**
|
||||
* Allocate an object whose layout is described by `d`. The size
|
||||
* (`size_in_bytes`) may *not* be less than the number of meaningful
|
||||
* bits in the bitmap of `d` multiplied by the size of a pointer.
|
||||
* The returned object is cleared. The returned object may *not* be
|
||||
* passed to `GC_realloc()`.
|
||||
*/
|
||||
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
|
||||
GC_malloc_explicitly_typed(size_t /* `size_in_bytes` */,
|
||||
GC_descr /* `d` */);
|
||||
|
||||
/** The ignore-off-page variant of `GC_malloc_explicitly_typed()`. */
|
||||
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
|
||||
GC_malloc_explicitly_typed_ignore_off_page(size_t /* `size_in_bytes` */,
|
||||
GC_descr /* `d` */);
|
||||
|
||||
/**
|
||||
* Allocate an array of `nelements` elements, each of the given size
|
||||
* (`element_size_in_bytes`), and with the given descriptor (`d`).
|
||||
* The element size must be a multiple of the byte alignment required
|
||||
* for pointers. (E.g. on a 32-bit machine with 16-bit aligned
|
||||
* pointers, `element_size_in_bytes` must be a multiple of 2.)
|
||||
* The element size may *not* be less than the number of meaningful
|
||||
* bits in the bitmap of `d` multiplied by the size of a pointer.
|
||||
* The returned object is cleared.
|
||||
*/
|
||||
GC_API GC_ATTR_MALLOC GC_ATTR_CALLOC_SIZE(1, 2) void *GC_CALL
|
||||
GC_calloc_explicitly_typed(size_t /* `nelements` */,
|
||||
size_t /* `element_size_in_bytes` */,
|
||||
GC_descr /* d */);
|
||||
|
||||
#define GC_CALLOC_TYPED_DESCR_PTRS 1
|
||||
#define GC_CALLOC_TYPED_DESCR_WORDS 8 /*< includes space for pointers */
|
||||
|
||||
#ifdef GC_BUILD
|
||||
struct GC_calloc_typed_descr_s;
|
||||
# define GC_calloc_typed_descr_s GC_calloc_typed_descr_opaque_s
|
||||
#endif
|
||||
|
||||
struct GC_calloc_typed_descr_s {
|
||||
GC_uintptr_t opaque_p[GC_CALLOC_TYPED_DESCR_PTRS];
|
||||
GC_word opaque[GC_CALLOC_TYPED_DESCR_WORDS - GC_CALLOC_TYPED_DESCR_PTRS];
|
||||
};
|
||||
#undef GC_calloc_typed_descr_s
|
||||
|
||||
/**
|
||||
* This is same as `GC_calloc_explicitly_typed` but more optimal in
|
||||
* terms of the performance and memory usage if the client needs to
|
||||
* allocate multiple typed object arrays with the same layout and
|
||||
* number of elements. The client should call it to be prepared for
|
||||
* the subsequent allocations by `GC_calloc_do_explicitly_typed()`, one
|
||||
* or many. The result of the preparation is stored to `*pctd`, even
|
||||
* in case of a failure. The prepared structure could be just dropped
|
||||
* when no longer needed. Returns 0 on failure, 1 on success; the
|
||||
* result could be ignored (as it is also stored to `*pctd` and checked
|
||||
* later by `GC_calloc_do_explicitly_typed()`).
|
||||
*/
|
||||
GC_API int GC_CALL GC_calloc_prepare_explicitly_typed(
|
||||
struct GC_calloc_typed_descr_s * /* `pctd` */, size_t /* `sizeof_ctd` */,
|
||||
size_t /* `nelements` */, size_t /* `element_size_in_bytes` */, GC_descr);
|
||||
|
||||
/** The actual object allocation for the prepared description. */
|
||||
GC_API GC_ATTR_MALLOC void *GC_CALL GC_calloc_do_explicitly_typed(
|
||||
const struct GC_calloc_typed_descr_s * /* `pctd` */,
|
||||
size_t /* `sizeof_ctd` */);
|
||||
|
||||
#ifdef GC_DEBUG
|
||||
# define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) ((void)(d), GC_MALLOC(bytes))
|
||||
# define GC_MALLOC_EXPLICITLY_TYPED_IGNORE_OFF_PAGE(bytes, d) \
|
||||
GC_MALLOC_EXPLICITLY_TYPED(bytes, d)
|
||||
# define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) \
|
||||
((void)(d), GC_MALLOC((n) * (bytes)))
|
||||
#else
|
||||
# define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) \
|
||||
GC_malloc_explicitly_typed(bytes, d)
|
||||
# define GC_MALLOC_EXPLICITLY_TYPED_IGNORE_OFF_PAGE(bytes, d) \
|
||||
GC_malloc_explicitly_typed_ignore_off_page(bytes, d)
|
||||
# define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) \
|
||||
GC_calloc_explicitly_typed(n, bytes, d)
|
||||
#endif
|
||||
|
||||
/* Deprecated. Use `GC_SIZEOF_IN_PTRS()` instead. */
|
||||
#define GC_WORD_LEN(t) GC_SIZEOF_IN_PTRS(t)
|
||||
|
||||
/* Deprecated. Use `GC_OFFSETOF_IN_PTRS()` instead. */
|
||||
#define GC_WORD_OFFSET(t, f) GC_OFFSETOF_IN_PTRS(t, f)
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* GC_TYPED_H */
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 1994 by Xerox Corporation. All rights reserved.
|
||||
* Copyright (c) 1996 by Silicon Graphics. All rights reserved.
|
||||
* Copyright (c) 1998 by Fergus Henderson. All rights reserved.
|
||||
* Copyright (c) 2000-2009 by Hewlett-Packard Development Company.
|
||||
* All rights reserved.
|
||||
*
|
||||
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
||||
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
||||
*
|
||||
* Permission is hereby granted to use or copy this program
|
||||
* for any purpose, provided the above notices are retained on all copies.
|
||||
* Permission to modify the code and to distribute modified code is granted,
|
||||
* provided the above notices are retained, and a notice that the code was
|
||||
* modified is included with the above copyright notice.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This should never be included directly; it is included only from
|
||||
* `gc.h` file.
|
||||
*/
|
||||
#if defined(GC_H)
|
||||
|
||||
/*
|
||||
* The policy regarding version numbers: development code has odd
|
||||
* `minor` number (and `micro` part is 0); when development is finished
|
||||
* and a release is prepared, `minor` number is incremented (keeping
|
||||
* `micro` number still zero), whenever a defect is fixed a new release
|
||||
* is prepared incrementing `micro` part to odd value (the most stable
|
||||
* release has the biggest `micro` number).
|
||||
*/
|
||||
|
||||
/*
|
||||
* The version here should match that in files `CMakeLists.txt`,
|
||||
* `build.zig.zon` and `configure.ac`. Eventually this one may become
|
||||
* unnecessary. For now we need it to keep the old-style build process
|
||||
* working.
|
||||
*/
|
||||
# define GC_TMP_VERSION_MAJOR 8
|
||||
# define GC_TMP_VERSION_MINOR 3
|
||||
# define GC_TMP_VERSION_MICRO 0 /*< 8.3.0 */
|
||||
|
||||
# ifdef GC_VERSION_MAJOR
|
||||
# if GC_TMP_VERSION_MAJOR != GC_VERSION_MAJOR \
|
||||
|| GC_TMP_VERSION_MINOR != GC_VERSION_MINOR \
|
||||
|| GC_TMP_VERSION_MICRO != GC_VERSION_MICRO
|
||||
# error Inconsistent version info. Check README.md, include/gc_version.h and configure.ac.
|
||||
# endif
|
||||
# else
|
||||
# define GC_VERSION_MAJOR GC_TMP_VERSION_MAJOR
|
||||
# define GC_VERSION_MINOR GC_TMP_VERSION_MINOR
|
||||
# define GC_VERSION_MICRO GC_TMP_VERSION_MICRO
|
||||
# endif /* !GC_VERSION_MAJOR */
|
||||
|
||||
#endif
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 1994 by Xerox Corporation. All rights reserved.
|
||||
* Copyright (c) 1996 by Silicon Graphics. All rights reserved.
|
||||
* Copyright (c) 1998 by Fergus Henderson. All rights reserved.
|
||||
* Copyright (c) 2000-2009 by Hewlett-Packard Development Company.
|
||||
* All rights reserved.
|
||||
*
|
||||
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
||||
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
||||
*
|
||||
* Permission is hereby granted to use or copy this program
|
||||
* for any purpose, provided the above notices are retained on all copies.
|
||||
* Permission to modify the code and to distribute modified code is granted,
|
||||
* provided the above notices are retained, and a notice that the code was
|
||||
* modified is included with the above copyright notice.
|
||||
*/
|
||||
|
||||
#ifndef GC_JAVAXFC_H
|
||||
#define GC_JAVAXFC_H
|
||||
|
||||
#ifndef GC_H
|
||||
# include "gc.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Invoke all remaining finalizers that have not yet been run. (Since the
|
||||
* notifier is not called, this should be called from a separate thread.)
|
||||
* This function is needed for strict compliance with the Java standard,
|
||||
* which can make the runtime guarantee that all finalizers are run.
|
||||
* This is problematic for several reasons:
|
||||
* 1. It means that finalizers, and all methods called by them, must be
|
||||
* prepared to deal with objects that have been finalized in spite of
|
||||
* the fact that they are still referenced by statically allocated
|
||||
* pointer variables (i.e. finalizers run at this point must be
|
||||
* prepared to deal with a mostly broken world);
|
||||
* 2. The Java standard implies we have to keep running finalizers until
|
||||
* there are no more left, thus it may mean that we get stuck in
|
||||
* an infinite loop running finalizers that create new finalizable
|
||||
* objects, though that is probably unlikely.
|
||||
* Thus this is not recommended for general use.
|
||||
* Acquires the allocator lock (to enqueue all finalizers).
|
||||
*/
|
||||
GC_API void GC_CALL GC_finalize_all(void);
|
||||
|
||||
#ifdef GC_THREADS
|
||||
/**
|
||||
* External thread suspension support. No thread suspension count
|
||||
* (so a thread which has been suspended numerous times will be resumed
|
||||
* with the very first call to `GC_resume_thread()`). Acquires the
|
||||
* allocator lock. Thread should be registered in the collector.
|
||||
* Unimplemented on some platforms. Not recommended for general use.
|
||||
*/
|
||||
# ifndef GC_SUSPEND_THREAD_ID
|
||||
# define GC_SUSPEND_THREAD_ID void *
|
||||
# endif
|
||||
GC_API void GC_CALL GC_suspend_thread(GC_SUSPEND_THREAD_ID);
|
||||
GC_API void GC_CALL GC_resume_thread(GC_SUSPEND_THREAD_ID);
|
||||
|
||||
/**
|
||||
* Is the given thread suspended externally? The result is either
|
||||
* 1 (true) or 0. Acquires the allocator lock in the reader mode.
|
||||
* Note: returns 0 (false) if the thread is not registered in the collector.
|
||||
* Unimplemented on some platforms (same as `GC_suspend_thread()`).
|
||||
*/
|
||||
GC_API int GC_CALL GC_is_thread_suspended(GC_SUSPEND_THREAD_ID);
|
||||
#endif /* GC_THREADS */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* GC_JAVAXFC_H */
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2011 by Hewlett-Packard Development Company.
|
||||
* All rights reserved.
|
||||
*
|
||||
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
||||
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
||||
*
|
||||
* Permission is hereby granted to use or copy this program
|
||||
* for any purpose, provided the above notices are retained on all copies.
|
||||
* Permission to modify the code and to distribute modified code is granted,
|
||||
* provided the above notices are retained, and a notice that the code was
|
||||
* modified is included with the above copyright notice.
|
||||
*/
|
||||
|
||||
#ifndef GC_LEAK_DETECTOR_H
|
||||
#define GC_LEAK_DETECTOR_H
|
||||
|
||||
/*
|
||||
* Include this header file (e.g., via gcc `--include` option) to turn
|
||||
* the collector into a leak detector.
|
||||
*/
|
||||
|
||||
#ifndef GC_DEBUG
|
||||
# define GC_DEBUG
|
||||
#endif
|
||||
#include "gc.h"
|
||||
|
||||
#ifndef GC_DONT_INCLUDE_STDLIB
|
||||
/*
|
||||
* We ensure the platform `stdlib.h` and `string.h` files are included
|
||||
* before redirecting `malloc` and the accompanying functions.
|
||||
*/
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
#endif
|
||||
|
||||
#undef malloc
|
||||
#define malloc(n) GC_MALLOC(n)
|
||||
#undef calloc
|
||||
#define calloc(m, n) GC_MALLOC((m) * (n))
|
||||
#undef free
|
||||
#define free(p) GC_FREE(p)
|
||||
#undef realloc
|
||||
#define realloc(p, n) GC_REALLOC(p, n)
|
||||
#undef reallocarray
|
||||
#define reallocarray(p, m, n) GC_REALLOC(p, (m) * (n))
|
||||
|
||||
#undef strdup
|
||||
#define strdup(s) GC_STRDUP(s)
|
||||
#undef strndup
|
||||
#define strndup(s, n) GC_STRNDUP(s, n)
|
||||
|
||||
#ifdef GC_REQUIRE_WCSDUP
|
||||
/*
|
||||
* The collector should be built with `GC_REQUIRE_WCSDUP` macro defined
|
||||
* as well to redirect `wcsdup`.
|
||||
*/
|
||||
# include <wchar.h>
|
||||
# undef wcsdup
|
||||
# define wcsdup(s) GC_WCSDUP(s)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following routines for the aligned objects allocation
|
||||
* (`aligned_alloc`, `valloc`, etc.) do not have their debugging
|
||||
* counterparts. Note that `free()` called for such objects may output
|
||||
* a warning that the pointer has no debugging info.
|
||||
*/
|
||||
|
||||
#undef aligned_alloc
|
||||
#define aligned_alloc(a, n) GC_memalign(a, n) /*< identical to `memalign` */
|
||||
#undef memalign
|
||||
#define memalign(a, n) GC_memalign(a, n)
|
||||
#undef posix_memalign
|
||||
#define posix_memalign(p, a, n) GC_posix_memalign(p, a, n)
|
||||
|
||||
/* These are defined in the C23 standard. */
|
||||
#undef free_sized
|
||||
#define free_sized(p, n) (free(p), (void)(n))
|
||||
#undef free_aligned_sized
|
||||
#define free_aligned_sized(p, a, n) \
|
||||
(GC_free(p) /* non-debug */, (void)(a), (void)(n))
|
||||
|
||||
#undef cfree /*< obsolete */
|
||||
#if defined(sun) || defined(__sun)
|
||||
# define cfree(p, m, n) ((void)(m), (void)(n), free(p))
|
||||
#else
|
||||
# define cfree(p) free(p)
|
||||
#endif
|
||||
|
||||
#undef _aligned_malloc
|
||||
#define _aligned_malloc(n, a) GC_memalign(a, n) /*< reverse args order */
|
||||
#undef _aligned_free
|
||||
#define _aligned_free(p) GC_free(p) /*< non-debug */
|
||||
|
||||
#ifndef GC_NO_VALLOC
|
||||
# undef valloc
|
||||
# define valloc(n) GC_valloc(n)
|
||||
# undef pvalloc
|
||||
# define pvalloc(n) GC_pvalloc(n) /*< obsolete */
|
||||
#endif
|
||||
|
||||
#undef malloc_usable_size /*< available in `glibc` */
|
||||
#define malloc_usable_size(p) GC_size(p)
|
||||
#undef malloc_size /*< available in Darwin */
|
||||
#define malloc_size(p) GC_size(p)
|
||||
#undef _msize /*< available in Windows CRT */
|
||||
#define _msize(p) GC_size(p)
|
||||
|
||||
#ifndef CHECK_LEAKS
|
||||
/**
|
||||
* Note 1: `CHECK_LEAKS` does not have `GC_` prefix (preserved for
|
||||
* backward compatibility).
|
||||
* Note 2: `GC_gcollect()` is also called automatically in the
|
||||
* find-leak mode at program exit.
|
||||
*/
|
||||
# define CHECK_LEAKS() GC_gcollect()
|
||||
#endif
|
||||
|
||||
#endif /* GC_LEAK_DETECTOR_H */
|
||||
Reference in new issue
Block a user