summary refs log tree commit diff stats
path: root/include/qemu/rcu.h
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2013-05-13 17:49:24 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2015-02-02 16:55:10 +0100
commit26387f86c9d6ac3a7a93b76108c502646afb6c25 (patch)
treed3368c961d75f789cfeefc0fb01d33813f1294b8 /include/qemu/rcu.h
parentd62cb4f2fdc0977f9ca9f41d297c3d2c44874171 (diff)
downloadfocaccia-qemu-26387f86c9d6ac3a7a93b76108c502646afb6c25.tar.gz
focaccia-qemu-26387f86c9d6ac3a7a93b76108c502646afb6c25.zip
rcu: add call_rcu
Asynchronous callbacks provided by call_rcu are particularly important
for QEMU, because the BQL makes it hard to use synchronize_rcu.

In addition, the current RCU implementation is not particularly friendly
to multiple concurrent synchronize_rcu callers, making call_rcu even
more important.

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'include/qemu/rcu.h')
-rw-r--r--include/qemu/rcu.h22
1 files changed, 22 insertions, 0 deletions
diff --git a/include/qemu/rcu.h b/include/qemu/rcu.h
index da043f2462..068a279a79 100644
--- a/include/qemu/rcu.h
+++ b/include/qemu/rcu.h
@@ -118,6 +118,28 @@ extern void synchronize_rcu(void);
 extern void rcu_register_thread(void);
 extern void rcu_unregister_thread(void);
 
+struct rcu_head;
+typedef void RCUCBFunc(struct rcu_head *head);
+
+struct rcu_head {
+    struct rcu_head *next;
+    RCUCBFunc *func;
+};
+
+extern void call_rcu1(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(({                                                         \
+         char __attribute__((unused))                                    \
+            offset_must_be_zero[-offsetof(typeof(*(head)), field)],      \
+            func_type_invalid = (func) - (void (*)(typeof(head)))(func); \
+         &(head)->field;                                                 \
+      }),                                                                \
+      (RCUCBFunc *)(func))
+
 #ifdef __cplusplus
 }
 #endif