diff options
author | Greg Kurz <groug@kaod.org> | 2021-11-09 19:35:22 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2021-11-10 13:20:15 +0100 |
commit | ef149763a8fcce70b85dfda27cc1222ecf765750 (patch) | |
tree | b63ade31a861723451db40bb192d9f060c5f3066 /include/qemu | |
parent | a0b9c5f75c05c12d30328a305377383652e62e63 (diff) | |
download | qemu-ef149763a8fcce70b85dfda27cc1222ecf765750.zip qemu-ef149763a8fcce70b85dfda27cc1222ecf765750.tar.gz qemu-ef149763a8fcce70b85dfda27cc1222ecf765750.tar.bz2 |
rcu: Introduce force_rcu notifier
The drain_rcu_call() function can be blocked as long as an RCU reader
stays in a read-side critical section. This is typically what happens
when a TCG vCPU is executing a busy loop. It can deadlock the QEMU
monitor as reported in https://gitlab.com/qemu-project/qemu/-/issues/650 .
This can be avoided by allowing drain_rcu_call() to enforce an RCU grace
period. Since each reader might need to do specific actions to end a
read-side critical section, do it with notifiers.
Prepare ground for this by adding a notifier list to the RCU reader
struct and use it in wait_for_readers() if drain_rcu_call() is in
progress. An API is added for readers to register their notifiers.
This is largely based on a draft from Paolo Bonzini.
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20211109183523.47726-2-groug@kaod.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'include/qemu')
-rw-r--r-- | include/qemu/rcu.h | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/include/qemu/rcu.h b/include/qemu/rcu.h index 515d327..e69efbd 100644 --- a/include/qemu/rcu.h +++ b/include/qemu/rcu.h @@ -27,6 +27,7 @@ #include "qemu/thread.h" #include "qemu/queue.h" #include "qemu/atomic.h" +#include "qemu/notify.h" #include "qemu/sys_membarrier.h" #ifdef __cplusplus @@ -66,6 +67,13 @@ struct rcu_reader_data { /* Data used for registry, protected by rcu_registry_lock */ QLIST_ENTRY(rcu_reader_data) node; + + /* + * NotifierList used to force an RCU grace period. Accessed under + * rcu_registry_lock. Note that the notifier is called _outside_ + * the thread! + */ + NotifierList force_rcu; }; extern __thread struct rcu_reader_data rcu_reader; @@ -180,6 +188,13 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(RCUReadAuto, rcu_read_auto_unlock) #define RCU_READ_LOCK_GUARD() \ g_autoptr(RCUReadAuto) _rcu_read_auto __attribute__((unused)) = rcu_read_auto_lock() +/* + * Force-RCU notifiers tell readers that they should exit their + * read-side critical section. + */ +void rcu_add_force_rcu_notifier(Notifier *n); +void rcu_remove_force_rcu_notifier(Notifier *n); + #ifdef __cplusplus } #endif |