[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 1/3] rcu: use call_rcu semantics from liburcu
From: |
Emilio G. Cota |
Subject: |
[Qemu-devel] [PATCH 1/3] rcu: use call_rcu semantics from liburcu |
Date: |
Tue, 3 Feb 2015 17:08:17 -0500 |
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 <address@hidden>
---
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