Introduce the notifier list that fires whenever runstate_set() changes the runstate. Any components can register to observe the old and new runstate values before the switch completes.
For instance, an upcoming change will use this hook to refresh the fw_cfg 'bootorder' and 'bios-geometry' entries when the instance leaves RUN_STATE_PRELAUNCH for RUN_STATE_RUNING. Signed-off-by: Dongli Zhang <[email protected]> --- include/system/runstate.h | 8 ++++++++ system/runstate.c | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/include/system/runstate.h b/include/system/runstate.h index 929379adae..de812ec320 100644 --- a/include/system/runstate.h +++ b/include/system/runstate.h @@ -11,6 +11,14 @@ bool runstate_is_running(void); bool runstate_needs_reset(void); void runstate_replay_enable(void); +typedef struct VMRunStateTransition { + RunState old_state; + RunState new_state; +} VMRunStateTransition; + +void qemu_add_runstate_transition_notifier(Notifier *notifier); +void qemu_remove_runstate_transition_notifier(Notifier *notifier); + typedef void VMChangeStateHandler(void *opaque, bool running, RunState state); typedef int VMChangeStateHandlerWithRet(void *opaque, bool running, RunState state); diff --git a/system/runstate.c b/system/runstate.c index eca722b43c..01b76463d7 100644 --- a/system/runstate.c +++ b/system/runstate.c @@ -65,6 +65,8 @@ static NotifierList exit_notifiers = NOTIFIER_LIST_INITIALIZER(exit_notifiers); +static NotifierList runstate_transition_notifiers = + NOTIFIER_LIST_INITIALIZER(runstate_transition_notifiers); static RunState current_run_state = RUN_STATE_PRELAUNCH; @@ -226,6 +228,17 @@ static void runstate_init(void) qemu_mutex_init(&vmstop_lock); } +static void runstate_transition_notify(RunState old_state, + RunState new_state) +{ + VMRunStateTransition transition = { + .old_state = old_state, + .new_state = new_state, + }; + + notifier_list_notify(&runstate_transition_notifiers, &transition); +} + /* This function will abort() on invalid state transitions */ void runstate_set(RunState new_state) { @@ -245,6 +258,8 @@ void runstate_set(RunState new_state) abort(); } + runstate_transition_notify(current_run_state, new_state); + current_run_state = new_state; } @@ -403,6 +418,16 @@ int vm_state_notify(bool running, RunState state) return ret; } +void qemu_add_runstate_transition_notifier(Notifier *notifier) +{ + notifier_list_add(&runstate_transition_notifiers, notifier); +} + +void qemu_remove_runstate_transition_notifier(Notifier *notifier) +{ + notifier_remove(notifier); +} + static ShutdownCause reset_requested; static ShutdownCause shutdown_requested; static int shutdown_exit_code = EXIT_SUCCESS; -- 2.39.3
