diff options
-rw-r--r-- | include/osmocom/core/fsm.h | 13 | ||||
-rw-r--r-- | src/fsm.c | 62 |
2 files changed, 55 insertions, 20 deletions
diff --git a/include/osmocom/core/fsm.h b/include/osmocom/core/fsm.h index 8f65533b..a2c20b78 100644 --- a/include/osmocom/core/fsm.h +++ b/include/osmocom/core/fsm.h @@ -187,4 +187,17 @@ void _osmo_fsm_inst_term(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause, void *data, const char *file, int line); +/*! \brief Terminate all child FSM instances of an FSM instance. + * + * This is a macro that calls _osmo_fsm_inst_term_children() with the given + * parameters as well as the caller's source file and line number for logging + * purposes. See there for documentation. + */ +#define osmo_fsm_inst_term_children(fi, cause, data) \ + _osmo_fsm_inst_term_children(fi, cause, data, __BASE_FILE__, __LINE__) +void _osmo_fsm_inst_term_children(struct osmo_fsm_inst *fi, + enum osmo_fsm_term_cause cause, + void *data, + const char *file, int line); + /*! @} */ @@ -421,13 +421,53 @@ void _osmo_fsm_inst_term(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause, void *data, const char *file, int line) { - struct osmo_fsm_inst *first_child, *last_seen_first_child; struct osmo_fsm_inst *parent = fi->proc.parent; uint32_t parent_term_event = fi->proc.parent_term_event; LOGPFSMSRC(fi, file, line, "Terminating (cause = %s)\n", osmo_fsm_term_cause_name(cause)); + _osmo_fsm_inst_term_children(fi, OSMO_FSM_TERM_PARENT, NULL, + file, line); + + /* delete ourselves from the parent */ + if (parent) + LOGPFSMSRC(fi, file, line, "Removing from parent %s\n", + osmo_fsm_inst_name(parent)); + llist_del(&fi->proc.child); + + /* call destructor / clean-up function */ + if (fi->fsm->cleanup) + fi->fsm->cleanup(fi, cause); + + LOGPFSMSRC(fi, file, line, "Freeing instance\n"); + osmo_fsm_inst_free(fi); + + /* indicate our termination to the parent */ + if (parent && cause != OSMO_FSM_TERM_PARENT) + _osmo_fsm_inst_dispatch(parent, parent_term_event, data, + file, line); +} + +/*! \brief Terminate all child FSM instances of an FSM instance. + * + * Iterate over all children and send them a termination event, with the given + * cause. Pass OSMO_FSM_TERM_PARENT to avoid dispatching events from the + * terminated child FSMs. + * + * \param[in] fi FSM instance that should be cleared of child FSMs + * \param[in] cause Cause / reason for termination (OSMO_FSM_TERM_PARENT) + * \param[in] data Opaque event data to be passed with the parent term events + * \param[in] file Calling source file (from osmo_fsm_inst_term_children macro) + * \param[in] line Calling source line (from osmo_fsm_inst_term_children macro) + */ +void _osmo_fsm_inst_term_children(struct osmo_fsm_inst *fi, + enum osmo_fsm_term_cause cause, + void *data, + const char *file, int line) +{ + struct osmo_fsm_inst *first_child, *last_seen_first_child; + /* iterate over all children, starting from the beginning every time: * terminating an FSM may emit events that cause other FSMs to also * terminate and remove themselves from this list. */ @@ -447,27 +487,9 @@ void _osmo_fsm_inst_term(struct osmo_fsm_inst *fi, last_seen_first_child = first_child; /* terminate child */ - _osmo_fsm_inst_term(first_child, OSMO_FSM_TERM_PARENT, NULL, + _osmo_fsm_inst_term(first_child, cause, data, file, line); } - - /* delete ourselves from the parent */ - if (parent) - LOGPFSMSRC(fi, file, line, "Removing from parent %s\n", - osmo_fsm_inst_name(parent)); - llist_del(&fi->proc.child); - - /* call destructor / clean-up function */ - if (fi->fsm->cleanup) - fi->fsm->cleanup(fi, cause); - - LOGPFSMSRC(fi, file, line, "Freeing instance\n"); - osmo_fsm_inst_free(fi); - - /* indicate our termination to the parent */ - if (parent && cause != OSMO_FSM_TERM_PARENT) - _osmo_fsm_inst_dispatch(parent, parent_term_event, data, - file, line); } const struct value_string osmo_fsm_term_cause_names[] = { |