From fa795f491252b4accc7a2336d8f27054da575cc5 Mon Sep 17 00:00:00 2001 From: Geoffrey Hunter Date: Thu, 9 Jan 2025 21:19:27 +1300 Subject: [PATCH] lib: smf: Fix handled bug causing events to not propagate. When using the SMF for a project discovered that events would sometimes not propagate to parent states correctly. Could not create a minimum reproducable test case for this, but it was found that these changes fixed the bug. This commit creates a new function to reset internal state, which is called on entry to smf_set_initial() and smf_set_state(). Closes #81300. Signed-off-by: Geoffrey Hunter --- lib/smf/smf.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/lib/smf/smf.c b/lib/smf/smf.c index 2c050526a56..e511db240ec 100644 --- a/lib/smf/smf.c +++ b/lib/smf/smf.c @@ -148,8 +148,6 @@ static bool smf_execute_ancestor_run_actions(struct smf_ctx *ctx) /* The child state either transitioned or handled it. Either way, stop propagating. */ if (internal->new_state || internal->handled) { - internal->new_state = false; - internal->handled = false; return false; } @@ -173,9 +171,6 @@ static bool smf_execute_ancestor_run_actions(struct smf_ctx *ctx) } } - internal->new_state = false; - internal->handled = false; - /* All done executing the run actions */ return false; @@ -209,10 +204,24 @@ static bool smf_execute_all_exit_actions(struct smf_ctx *const ctx, const struct } #endif /* CONFIG_SMF_ANCESTOR_SUPPORT */ -void smf_set_initial(struct smf_ctx *ctx, const struct smf_state *init_state) +/** + * @brief Reset the internal state of the state machine back to default values. + * Should be called on entry to smf_set_initial() and smf_set_state(). + * + * @param ctx State machine context. + */ +static void smf_clear_internal_state(struct smf_ctx *ctx) { struct internal_ctx *const internal = (void *)&ctx->internal; + internal->is_exit = false; + internal->terminate = false; + internal->handled = false; + internal->new_state = false; +} + +void smf_set_initial(struct smf_ctx *ctx, const struct smf_state *init_state) +{ #ifdef CONFIG_SMF_INITIAL_TRANSITION /* * The final target will be the deepest leaf state that @@ -223,15 +232,14 @@ void smf_set_initial(struct smf_ctx *ctx, const struct smf_state *init_state) } #endif - internal->is_exit = false; - internal->terminate = false; - internal->handled = false; - internal->new_state = false; + smf_clear_internal_state(ctx); ctx->current = init_state; ctx->previous = NULL; ctx->terminate_val = 0; #ifdef CONFIG_SMF_ANCESTOR_SUPPORT + struct internal_ctx *const internal = (void *)&ctx->internal; + ctx->executing = init_state; const struct smf_state *topmost = get_last_of(init_state); @@ -389,6 +397,11 @@ int32_t smf_run_state(struct smf_ctx *const ctx) return ctx->terminate_val; } + /* Executing a states run function could cause a transition, so clear the + * internal state to ensure that the transition is handled correctly. + */ + smf_clear_internal_state(ctx); + #ifdef CONFIG_SMF_ANCESTOR_SUPPORT ctx->executing = ctx->current; #endif