aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2016-06-18 10:36:25 +0200
committerHarald Welte <laforge@gnumonks.org>2016-06-27 15:17:53 +0200
commitf627c0f0afb280d30aa00da395560db963aba462 (patch)
tree8410f33485c959e2408335a00d571d4384697697
parentd826f1771cdada9009db599a9cf3882192bf0454 (diff)
fsm: Introduce default time-out handling
If a FSM doesn't specify any timer_cb, simply terminate the FSM by default on time-out. This is a reasonable default for most cases, and avoids copy+pasting a one-line timer_cb function in every FSM. Also, even if there is a timer_cb, let it have a return value to decide if the core should terminate after return from timer_cb or not. Change-Id: I0461a9593bfb729c82b7d1d1cf9f30b1079d0212
-rw-r--r--include/osmocom/core/fsm.h4
-rw-r--r--src/fsm.c21
2 files changed, 16 insertions, 9 deletions
diff --git a/include/osmocom/core/fsm.h b/include/osmocom/core/fsm.h
index 401ee04..ce0db15 100644
--- a/include/osmocom/core/fsm.h
+++ b/include/osmocom/core/fsm.h
@@ -26,6 +26,8 @@ enum osmo_fsm_term_cause {
OSMO_FSM_TERM_REGULAR,
/*! \brief erroneous termination of process */
OSMO_FSM_TERM_ERROR,
+ /*! \brief termination due to time-out */
+ OSMO_FSM_TERM_TIMEOUT,
};
/*! \brief description of a rule in the FSM */
@@ -63,7 +65,7 @@ struct osmo_fsm {
/*! \breif clean-up function, called during termination */
void (*cleanup)(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause);
/*! \brief timer call-back for states with time-out */
- void (*timer_cb)(struct osmo_fsm_inst *fi);
+ int (*timer_cb)(struct osmo_fsm_inst *fi);
/*! \brief logging sub-system for this FSM */
int log_subsys;
/*! \brief human-readable names of events */
diff --git a/src/fsm.c b/src/fsm.c
index ede769d..8fedae2 100644
--- a/src/fsm.c
+++ b/src/fsm.c
@@ -136,10 +136,20 @@ static void fsm_tmr_cb(void *data)
{
struct osmo_fsm_inst *fi = data;
struct osmo_fsm *fsm = fi->fsm;
+ uint32_t T = fi->T;
LOGPFSM(fi, "Timeout of T%u\n", fi->T);
- fsm->timer_cb(fi);
+ if (fsm->timer_cb) {
+ int rc = fsm->timer_cb(fi);
+ if (rc != 1)
+ return;
+ LOGPFSM(fi, "timer_cb requested termination\n");
+ } else
+ LOGPFSM(fi, "No timer_cb, automatic termination\n");
+
+ /* if timer_cb returns 1 or there is no timer_cb */
+ osmo_fsm_inst_term(fi, OSMO_FSM_TERM_TIMEOUT, &T);
}
/*! \brief allocate a new instance of a specified FSM
@@ -317,13 +327,8 @@ int osmo_fsm_inst_state_chg(struct osmo_fsm_inst *fi, uint32_t new_state,
st->onenter(fi, old_state);
if (timeout_secs) {
- if (!fsm->timer_cb)
- LOGP(fsm->log_subsys, LOGL_ERROR, "cannot start "
- "timer for FSM without timer call-back\n");
- else {
- fi->T = T;
- osmo_timer_schedule(&fi->timer, timeout_secs, 0);
- }
+ fi->T = T;
+ osmo_timer_schedule(&fi->timer, timeout_secs, 0);
}
return 0;