plugins: add [pre|post]fork helpers to linux-user
Special care needs to be taken in ensuring locks are in a consistent state across fork events. Add helpers so the plugin system can ensure that. Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Fixes: https://gitlab.com/qemu-project/qemu/-/issues/358 Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Tested-by: Daniel P. Berrangé <berrange@redhat.com> Message-Id: <20221004115221.2174499-1-alex.bennee@linaro.org>
This commit is contained in:
parent
37e62694e4
commit
f7e15affa8
@ -224,6 +224,23 @@ void qemu_plugin_disable_mem_helpers(CPUState *cpu);
|
|||||||
*/
|
*/
|
||||||
void qemu_plugin_user_exit(void);
|
void qemu_plugin_user_exit(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemu_plugin_user_prefork_lock(): take plugin lock before forking
|
||||||
|
*
|
||||||
|
* This is a user-mode only helper to take the internal plugin lock
|
||||||
|
* before a fork event. This is ensure a consistent lock state
|
||||||
|
*/
|
||||||
|
void qemu_plugin_user_prefork_lock(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemu_plugin_user_postfork(): reset the plugin lock
|
||||||
|
* @is_child: is this thread the child
|
||||||
|
*
|
||||||
|
* This user-mode only helper resets the lock state after a fork so we
|
||||||
|
* can continue using the plugin interface.
|
||||||
|
*/
|
||||||
|
void qemu_plugin_user_postfork(bool is_child);
|
||||||
|
|
||||||
#else /* !CONFIG_PLUGIN */
|
#else /* !CONFIG_PLUGIN */
|
||||||
|
|
||||||
static inline void qemu_plugin_add_opts(void)
|
static inline void qemu_plugin_add_opts(void)
|
||||||
@ -287,6 +304,13 @@ static inline void qemu_plugin_disable_mem_helpers(CPUState *cpu)
|
|||||||
|
|
||||||
static inline void qemu_plugin_user_exit(void)
|
static inline void qemu_plugin_user_exit(void)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
static inline void qemu_plugin_user_prefork_lock(void)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
static inline void qemu_plugin_user_postfork(bool is_child)
|
||||||
|
{ }
|
||||||
|
|
||||||
#endif /* !CONFIG_PLUGIN */
|
#endif /* !CONFIG_PLUGIN */
|
||||||
|
|
||||||
#endif /* QEMU_PLUGIN_H */
|
#endif /* QEMU_PLUGIN_H */
|
||||||
|
@ -142,10 +142,12 @@ void fork_start(void)
|
|||||||
start_exclusive();
|
start_exclusive();
|
||||||
mmap_fork_start();
|
mmap_fork_start();
|
||||||
cpu_list_lock();
|
cpu_list_lock();
|
||||||
|
qemu_plugin_user_prefork_lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void fork_end(int child)
|
void fork_end(int child)
|
||||||
{
|
{
|
||||||
|
qemu_plugin_user_postfork(child);
|
||||||
mmap_fork_end(child);
|
mmap_fork_end(child);
|
||||||
if (child) {
|
if (child) {
|
||||||
CPUState *cpu, *next_cpu;
|
CPUState *cpu, *next_cpu;
|
||||||
|
@ -526,6 +526,26 @@ void qemu_plugin_user_exit(void)
|
|||||||
qemu_plugin_atexit_cb();
|
qemu_plugin_atexit_cb();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helpers for *-user to ensure locks are sane across fork() events.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void qemu_plugin_user_prefork_lock(void)
|
||||||
|
{
|
||||||
|
qemu_rec_mutex_lock(&plugin.lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_plugin_user_postfork(bool is_child)
|
||||||
|
{
|
||||||
|
if (is_child) {
|
||||||
|
/* should we just reset via plugin_init? */
|
||||||
|
qemu_rec_mutex_init(&plugin.lock);
|
||||||
|
} else {
|
||||||
|
qemu_rec_mutex_unlock(&plugin.lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call this function after longjmp'ing to the main loop. It's possible that the
|
* Call this function after longjmp'ing to the main loop. It's possible that the
|
||||||
* last instruction of a TB might have used helpers, and therefore the
|
* last instruction of a TB might have used helpers, and therefore the
|
||||||
|
Loading…
Reference in New Issue
Block a user