/* Returns true if it is worth calling GC_invoke_finalizers. (Useful if */
/* finalizers can only be called from some kind of "safe state" and */
/* getting into that safe state is expensive.) */
+GC_ATTR_NO_SANITIZE_THREAD
GC_API int GC_CALL GC_should_invoke_finalizers(void)
- GC_ATTR_NO_SANITIZE_THREAD
{
return GC_fnlz_roots.finalize_now != NULL;
}
/* Ensure that either registers are pushed, or callee-save registers */
/* are somewhere on the stack, and then call fn(arg, ctxt). */
/* ctxt is either a pointer to a ucontext_t we generated, or NULL. */
+GC_ATTR_NO_SANITIZE_ADDR
GC_INNER void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *),
volatile ptr_t arg)
- GC_ATTR_NO_SANITIZE_ADDR
{
volatile int dummy;
void * volatile context = 0;
/* acquiring the allocation lock provided the obtained value is used */
/* according to the pattern given in alloc.c file (see the comment */
/* about GC_allocobj usage and, e.g., GC_malloc_kind_global code). */
+GC_ATTR_NO_SANITIZE_THREAD
static void fill_size_map(size_t low_limit, size_t byte_sz, size_t granule_sz)
- GC_ATTR_NO_SANITIZE_THREAD
{
for (; low_limit <= byte_sz; low_limit++)
GC_size_map[low_limit] = granule_sz;
# endif
}
-/* Single argument version, robust against whole program analysis. */
volatile word GC_noop_sink;
-GC_API void GC_CALL GC_noop1(word x) GC_ATTR_NO_SANITIZE_THREAD
+
+/* Single argument version, robust against whole program analysis. */
+GC_ATTR_NO_SANITIZE_THREAD
+GC_API void GC_CALL GC_noop1(word x)
{
GC_noop_sink = x;
}
* encoding, we optionally maintain a cache for the block address to
* header mapping, we prefetch when an object is "grayed", etc.
*/
+GC_ATTR_NO_SANITIZE_ADDR GC_ATTR_NO_SANITIZE_MEMORY GC_ATTR_NO_SANITIZE_THREAD
GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack,
mse *mark_stack_limit)
- GC_ATTR_NO_SANITIZE_ADDR GC_ATTR_NO_SANITIZE_MEMORY
- GC_ATTR_NO_SANITIZE_THREAD
{
signed_word credit = HBLKSIZE; /* Remaining credit for marking work */
ptr_t current_p; /* Pointer to current candidate ptr. */
* and scans the entire region immediately, in case the contents
* change.
*/
+GC_ATTR_NO_SANITIZE_ADDR GC_ATTR_NO_SANITIZE_MEMORY GC_ATTR_NO_SANITIZE_THREAD
GC_API void GC_CALL GC_push_all_eager(char *bottom, char *top)
- GC_ATTR_NO_SANITIZE_ADDR GC_ATTR_NO_SANITIZE_MEMORY
- GC_ATTR_NO_SANITIZE_THREAD
{
word * b = (word *)(((word) bottom + ALIGNMENT-1) & ~(ALIGNMENT-1));
word * t = (word *)(((word) top) & ~(ALIGNMENT-1));
#if defined(WRAP_MARK_SOME) && defined(PARALLEL_MARK)
/* Similar to GC_push_conditional but scans the whole region immediately. */
+ GC_ATTR_NO_SANITIZE_ADDR GC_ATTR_NO_SANITIZE_MEMORY
+ GC_ATTR_NO_SANITIZE_THREAD
GC_INNER void GC_push_conditional_eager(ptr_t bottom, ptr_t top,
GC_bool all)
- GC_ATTR_NO_SANITIZE_ADDR GC_ATTR_NO_SANITIZE_MEMORY
- GC_ATTR_NO_SANITIZE_THREAD
{
word * b = (word *)(((word) bottom + ALIGNMENT-1) & ~(ALIGNMENT-1));
word * t = (word *)(((word) top) & ~(ALIGNMENT-1));
#ifdef THREADS
/* Used to occasionally clear a bigger chunk. */
/* TODO: Should be more random than it is ... */
- static unsigned next_random_no(void) GC_ATTR_NO_SANITIZE_THREAD
+ GC_ATTR_NO_SANITIZE_THREAD
+ static unsigned next_random_no(void)
{
static unsigned random_no = 0;
return ++random_no % 13;
/* correctly. */
#ifdef AO_HAVE_test_and_set_acquire
GC_INNER volatile AO_TS_t GC_fault_handler_lock = AO_TS_INITIALIZER;
+
+ GC_ATTR_NO_SANITIZE_THREAD
static void async_set_pht_entry_from_index(volatile page_hash_table db,
size_t index)
- GC_ATTR_NO_SANITIZE_THREAD
{
while (AO_test_and_set_acquire(&GC_fault_handler_lock) == AO_TS_SET) {
/* empty */
/* race between this function and GC_install_header, GC_remove_header */
/* should not be harmful because the added or removed header should */
/* be already unprotected. */
- static GC_bool is_header_found_async(void *addr) GC_ATTR_NO_SANITIZE_THREAD
+ GC_ATTR_NO_SANITIZE_THREAD
+ static GC_bool is_header_found_async(void *addr)
{
# ifdef HASH_TL
hdr *result;
errno = old_errno;
}
+GC_ATTR_NO_SANITIZE_THREAD
static void update_last_stop_count(GC_thread me, AO_t my_stop_count)
- GC_ATTR_NO_SANITIZE_THREAD
{
me -> stop_info.last_stop_count = my_stop_count;
}
/* suspend_self_inner. The first one seems to be a false positive */
/* as the handler is invoked after RAISE_SIGNAL, and the 2nd one is */
/* safe to be ignored as the flag is checked in a loop. */
- static void set_suspended_ext_flag(GC_thread t) GC_ATTR_NO_SANITIZE_THREAD
+ GC_ATTR_NO_SANITIZE_THREAD
+ static void set_suspended_ext_flag(GC_thread t)
{
t -> flags |= SUSPENDED_EXT;
}
/* Same as for GC_suspend_thread(), TSan reports data races between */
/* this function and GC_suspend_handler_inner, suspend_self_inner; */
/* it is safe to ignore them both. */
- GC_API void GC_CALL GC_resume_thread(GC_SUSPEND_THREAD_ID thread)
- GC_ATTR_NO_SANITIZE_THREAD
- {
+ GC_ATTR_NO_SANITIZE_THREAD
+ GC_API void GC_CALL GC_resume_thread(GC_SUSPEND_THREAD_ID thread) {
GC_thread t;
DCL_LOCK_STATE;
&& (defined(USE_SPIN_LOCK) || !defined(NO_PTHREAD_TRYLOCK))
/* GC_collecting is a hint, a potential data race between */
/* GC_lock() and ENTER/EXIT_GC() is OK to ignore. */
- static GC_bool is_collecting(void) GC_ATTR_NO_SANITIZE_THREAD
+ GC_ATTR_NO_SANITIZE_THREAD
+ static GC_bool is_collecting(void)
{
return GC_collecting;
}
/* and updates spin_max and last_spins could be ignored because these */
/* variables are hints only. (Atomic getters and setters are avoided */
/* here for performance reasons.) */
+ GC_ATTR_NO_SANITIZE_THREAD
static void set_last_spins_and_high_spin_max(unsigned new_last_spins)
- GC_ATTR_NO_SANITIZE_THREAD
{
last_spins = new_last_spins;
spin_max = high_spin_max;
}
- static void reset_spin_max(void) GC_ATTR_NO_SANITIZE_THREAD
+ GC_ATTR_NO_SANITIZE_THREAD
+ static void reset_spin_max(void)
{
spin_max = low_spin_max;
}