*/
static void
reclaim_chunks_cb(struct rcu_head *arg) {
- qp_rcuctx_t *rcuctx = isc_urcu_container(arg, qp_rcuctx_t, rcu_head);
+ qp_rcuctx_t *rcuctx = caa_container_of(arg, qp_rcuctx_t, rcu_head);
REQUIRE(QPRCU_VALID(rcuctx));
dns_qpmulti_t *multi = rcuctx->multi;
REQUIRE(QPMULTI_VALID(multi));
}
}
- isc_urcu_cleanup(rcuctx, rcu_head, reclaim_chunks_cb);
+ call_rcu(&rcuctx->rcu_head, reclaim_chunks_cb);
LOG_STATS("qp will reclaim %u chunks", count);
}
static void
qpmulti_destroy_cb(struct rcu_head *arg) {
- qp_rcuctx_t *rcuctx = isc_urcu_container(arg, qp_rcuctx_t, rcu_head);
+ qp_rcuctx_t *rcuctx = caa_container_of(arg, qp_rcuctx_t, rcu_head);
REQUIRE(QPRCU_VALID(rcuctx));
/* only nonzero for reclaim_chunks_cb() */
REQUIRE(rcuctx->count == 0);
.multi = multi,
};
isc_mem_attach(qp->mctx, &rcuctx->mctx);
- isc_urcu_cleanup(rcuctx, rcu_head, qpmulti_destroy_cb);
+ call_rcu(&rcuctx->rcu_head, qpmulti_destroy_cb);
}
/***********************************************************************
dns__rbtdb_freeglue(glue);
glue = old_glue;
} else if (glue != NULL) {
- __tsan_release(glue);
cds_wfs_push(&rbtversion->glue_stack,
&header->wfs_node);
}
* zone.
*/
if (glue != (void *)-1) {
- __tsan_acquire(glue);
addglue_to_message(glue, msg);
}
static void
free_gluelist_rcu(struct rcu_head *rcu_head) {
- dns_glue_t *glue = isc_urcu_container(rcu_head, dns_glue_t, rcu_head);
+ dns_glue_t *glue = caa_container_of(rcu_head, dns_glue_t, rcu_head);
dns__rbtdb_freeglue(glue);
}
caa_container_of(node, dns_slabheader_t, wfs_node);
dns_glue_t *glue = rcu_xchg_pointer(&header->glue_list, NULL);
- isc_urcu_cleanup(glue, rcu_head, free_gluelist_rcu);
+ call_rcu(&glue->rcu_head, free_gluelist_rcu);
}
rcu_read_unlock();
}
* The function returns 'false' in case the queue was empty - in such
* case we need to trigger the async callback.
*/
- __tsan_release(job);
if (!cds_wfcq_enqueue(&loop->async_jobs.head, &loop->async_jobs.tail,
&job->wfcq_node))
{
*/
struct cds_wfcq_node *node, *next;
__cds_wfcq_for_each_blocking_safe(&jobs.head, &jobs.tail, node, next) {
- isc_job_t *job = isc_urcu_container(node, isc_job_t, wfcq_node);
+ isc_job_t *job = caa_container_of(node, isc_job_t, wfcq_node);
job->cb(job->cbarg);
#pragma GCC diagnostic pop
-/*
- * Help thread sanitizer to understand `call_rcu()`:
- *
- * The `rcu_head` argument to `call_rcu()` is expected to be embedded
- * in a structure defined by the caller, which is named `_rcuctx` in
- * these macros. The callback function uses `caa_container_of()` to
- * recover the `rcuctx` pointer from the `_rcu_head` pointer that is
- * passed to the callback.
- *
- * We explain the ordering dependency to tsan by releasing `_rcuctx`
- * pointer before `call_rcu()` and acquiring it in the callback
- * funtion. We pass the outer `_rcuctx` pointer to the `__tsan_`
- * barriers, because it should match a pointer that is known by tsan
- * to have been returned by `malloc()`.
- */
-
-#define isc_urcu_cleanup(ptr, member, func) \
- { \
- __tsan_release(ptr); \
- call_rcu(&(ptr)->member, func); \
- }
-
-#define isc_urcu_container(ptr, type, member) \
- ({ \
- type *_ptr = caa_container_of(ptr, type, member); \
- __tsan_acquire(_ptr); \
- _ptr; \
- })
-
#if defined(RCU_QSBR)
/*
#endif /* if __has_feature(thread_sanitizer) */
#if __SANITIZE_THREAD__
-/*
- * We should rather be including <sanitizer/tsan_interface.h>, but GCC 10
- * header is broken, so we just make the declarations by hand.
- */
-void
-__tsan_acquire(void *addr);
-void
-__tsan_release(void *addr);
#define ISC_NO_SANITIZE_THREAD __attribute__((no_sanitize("thread")))
#else /* if __SANITIZE_THREAD__ */
#define ISC_NO_SANITIZE_THREAD
-#define __tsan_acquire(addr)
-#define __tsan_release(addr)
#endif /* if __SANITIZE_THREAD__ */
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR >= 6)
return;
}
- isc_job_t *job = isc_urcu_container(node, isc_job_t, wfcq_node);
+ isc_job_t *job = caa_container_of(node, isc_job_t, wfcq_node);
job->cb(job->cbarg);
}
* The cds_wfcq_enqueue() is non-blocking (no internal
* mutex involved), so it offers a slight advantage.
*/
- __tsan_release(job);
cds_wfcq_enqueue("a->jobs.head, "a->jobs.tail,
&job->wfcq_node);
}
.func = func,
.arg = arg,
};
- __tsan_release(wrap);
return (wrap);
}
CMM_ACCESS_ONCE(jemalloc_enforce_init) = malloc(1);
free(jemalloc_enforce_init);
- /* Reassure Thread Sanitizer that it is safe to free the wrapper */
- __tsan_acquire(wrap);
free(wrap);
ret = func(arg);