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 <gbmhunter@gmail.com>
This commit is contained in:
Geoffrey Hunter 2025-01-09 21:19:27 +13:00 committed by Benjamin Cabé
parent 1e75491cdb
commit fa795f4912

View file

@ -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