The recently added call_rcu does not match liburcu's call_rcu's semantics; instead, call_rcu1 does. Fix it by doing the following:
- Rename QEMU's call_rcu to call_rcu_first_elem - Rename QEMU's call_rcu1 to call_rcu The end goal is to be able to switch at compile-time between liburcu and QEMU's RCU implementation. Signed-off-by: Emilio G. Cota <c...@braap.org> --- docs/rcu.txt | 21 ++++++++++----------- include/qemu/rcu.h | 6 +++--- memory.c | 4 ++-- util/rcu.c | 2 +- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/docs/rcu.txt b/docs/rcu.txt index 61752b9..575f563 100644 --- a/docs/rcu.txt +++ b/docs/rcu.txt @@ -85,8 +85,8 @@ The core RCU API is small: synchronize_rcu. If this is not possible (for example, because the updater is protected by the BQL), you can use call_rcu. - void call_rcu1(struct rcu_head * head, - void (*func)(struct rcu_head *head)); + void call_rcu(struct rcu_head * head, + void (*func)(struct rcu_head *head)); This function invokes func(head) after all pre-existing RCU read-side critical sections on all threads have completed. This @@ -106,7 +106,7 @@ The core RCU API is small: so that the reclaimer function can fetch the struct foo address and free it: - call_rcu1(&foo.rcu, foo_reclaim); + call_rcu(&foo.rcu, foo_reclaim); void foo_reclaim(struct rcu_head *rp) { @@ -117,15 +117,15 @@ The core RCU API is small: For the common case where the rcu_head member is the first of the struct, you can use the following macro. - void call_rcu(T *p, - void (*func)(T *p), - field-name); + void call_rcu_first_elem(T *p, + void (*func)(T *p), + field-name); - call_rcu1 is typically used through this macro, in the common case + call_rcu is typically used through this macro, in the common case where the "struct rcu_head" is the first field in the struct. In the above case, one could have written simply: - call_rcu(foo_reclaim, g_free, rcu); + call_rcu_first_elem(foo_reclaim, g_free, rcu); typeof(*p) atomic_rcu_read(p); @@ -196,10 +196,9 @@ DIFFERENCES WITH LINUX - atomic_rcu_read and atomic_rcu_set replace rcu_dereference and rcu_assign_pointer. They take a _pointer_ to the variable being accessed. -- call_rcu is a macro that has an extra argument (the name of the first - field in the struct, which must be a struct rcu_head), and expects the +- call_rcu_first_elem is a macro that has an extra argument (the name of the + first field in the struct, which must be a struct rcu_head), and expects the type of the callback's argument to be the type of the first argument. - call_rcu1 is the same as Linux's call_rcu. RCU PATTERNS diff --git a/include/qemu/rcu.h b/include/qemu/rcu.h index 068a279..492d943 100644 --- a/include/qemu/rcu.h +++ b/include/qemu/rcu.h @@ -126,13 +126,13 @@ struct rcu_head { RCUCBFunc *func; }; -extern void call_rcu1(struct rcu_head *head, RCUCBFunc *func); +extern void call_rcu(struct rcu_head *head, RCUCBFunc *func); /* The operands of the minus operator must have the same type, * which must be the one that we specify in the cast. */ -#define call_rcu(head, func, field) \ - call_rcu1(({ \ +#define call_rcu_first_elem(head, func, field) \ + call_rcu(({ \ char __attribute__((unused)) \ offset_must_be_zero[-offsetof(typeof(*(head)), field)], \ func_type_invalid = (func) - (void (*)(typeof(head)))(func); \ diff --git a/memory.c b/memory.c index 9b91243..dc5e4e9 100644 --- a/memory.c +++ b/memory.c @@ -755,7 +755,7 @@ static void address_space_update_topology(AddressSpace *as) /* Writes are protected by the BQL. */ atomic_rcu_set(&as->current_map, new_view); - call_rcu(old_view, flatview_unref, rcu); + call_rcu_first_elem(old_view, flatview_unref, rcu); /* Note that all the old MemoryRegions are still alive up to this * point. This relieves most MemoryListeners from the need to @@ -1983,7 +1983,7 @@ void address_space_destroy(AddressSpace *as) * entries that the guest should never use. Wait for the old * values to expire before freeing the data. */ - call_rcu(as, do_address_space_destroy, rcu); + call_rcu_first_elem(as, do_address_space_destroy, rcu); } bool io_mem_read(MemoryRegion *mr, hwaddr addr, uint64_t *pval, unsigned size) diff --git a/util/rcu.c b/util/rcu.c index c9c3e6e..309a6e4 100644 --- a/util/rcu.c +++ b/util/rcu.c @@ -253,7 +253,7 @@ static void *call_rcu_thread(void *opaque) abort(); } -void call_rcu1(struct rcu_head *node, void (*func)(struct rcu_head *node)) +void call_rcu(struct rcu_head *node, void (*func)(struct rcu_head *node)) { node->func = func; enqueue(node); -- 1.8.3