diff options
| author | Neels Hofmeyr <nhofmeyr@sysmocom.de> | 2016-12-23 04:26:39 +0100 | 
|---|---|---|
| committer | Harald Welte <laforge@gnumonks.org> | 2016-12-24 17:11:52 +0000 | 
| commit | c014f606d055bb0ab09b6b9128078cb7a4e06c4c (patch) | |
| tree | 1aef887fc7337f4c7fa431b15ff845a6cb3a9eca | |
| parent | eeacf906dd961002dba7e53ec9144d08a2b2d0ee (diff) | |
fsm: factor out osmo_fsm_inst_term_children() from osmo_fsm_inst_term()
osmo_fsm_inst_term() has code for safe child removal, publish that part as
osmo_fsm_inst_term_children(); also use from osmo_fsm_inst_term().
As with osmo_fsm_inst_term(), add osmo_fsm_inst_term_children() macro to pass
the caller's source file and line to new _osmo_fsm_inst_term_children().
Rationale: in openbsc's VLR, I want to discard child FSMs when certain events
are handled. I could keep a pointer to each one, or simply iterate all
children, making the code a lot simpler in some places.
(Unfortunately, the patch may be displayed subobtimally. This really only moves
the children-loop to a new function, replaces it with a call to
_osmo_fsm_inst_term_children(fi, OSMO_FSM_TERM_PARENT, NULL, file, line) and
drops two local iterator variables. No other code changes are made, even though
the diff may show large removal + addition chunks)
Change-Id: I8dac1206259cbd251660f793ad023aaa1dc705a2
| -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[] = {  | 
