diff options
author | Paolo Bonzini | 2013-05-13 17:49:24 +0200 |
---|---|---|
committer | Paolo Bonzini | 2015-02-02 16:55:10 +0100 |
commit | 26387f86c9d6ac3a7a93b76108c502646afb6c25 (patch) | |
tree | d3368c961d75f789cfeefc0fb01d33813f1294b8 /include | |
parent | rcu: allow nesting of rcu_read_lock/rcu_read_unlock (diff) | |
download | qemu-26387f86c9d6ac3a7a93b76108c502646afb6c25.tar.gz qemu-26387f86c9d6ac3a7a93b76108c502646afb6c25.tar.xz 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')
-rw-r--r-- | include/qemu/rcu.h | 22 |
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 |