aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2017-11-18 23:07:12 +0100
committerNeels Hofmeyr <neels@hofmeyr.de>2017-11-18 23:07:12 +0100
commitf230123b2b39cf265cf1b42d2ec63c25dbfed5a4 (patch)
treeb8376b3c04de605f8008106549409e4c879fcbce
parent9488d4d54054538ea1d2d805f236dd21a668bbd3 (diff)
add fsm timer_cb2 with T argneels/timer_cb2
-rw-r--r--include/osmocom/core/fsm.h6
-rw-r--r--src/fsm.c14
2 files changed, 17 insertions, 3 deletions
diff --git a/include/osmocom/core/fsm.h b/include/osmocom/core/fsm.h
index 2fbb250..7987922 100644
--- a/include/osmocom/core/fsm.h
+++ b/include/osmocom/core/fsm.h
@@ -72,12 +72,18 @@ struct osmo_fsm {
/*! clean-up function, called during termination */
void (*cleanup)(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause);
/*! timer call-back for states with time-out.
+ * Note that fi->T has already been reset to 0 before calling.
+ * See also timer_cb2(). You should never use both timer_cb and timer_cb2().
* \returns 1 to request termination, 0 to keep running. */
int (*timer_cb)(struct osmo_fsm_inst *fi);
/*! logging sub-system for this FSM */
int log_subsys;
/*! human-readable names of events */
const struct value_string *event_names;
+ /*! timer call-back for states with time-out.
+ * Like timer_cb(), but also gets passed the expired T timer.
+ * \returns 1 to request termination, 0 to keep running. */
+ int (*timer_cb2)(struct osmo_fsm_inst *fi, uint32_t T);
};
/*! a single instanceof an osmocom finite state machine */
diff --git a/src/fsm.c b/src/fsm.c
index 827e8b3..8a2c425 100644
--- a/src/fsm.c
+++ b/src/fsm.c
@@ -178,21 +178,29 @@ static void fsm_tmr_cb(void *data)
struct osmo_fsm_inst *fi = data;
struct osmo_fsm *fsm = fi->fsm;
uint32_t T = fi->T;
+ /* Must not access fi after calling the timer cb, since that may have effected an fi termination
+ * and deallocation, e.g. from dispatching events and/or complex choices made. So set T=0 now,
+ * before calling the timer_cb. */
+ fi->T = 0;
- LOGPFSM(fi, "Timeout of T%u\n", fi->T);
+ LOGPFSM(fi, "Timeout of T%u\n", T);
if (fsm->timer_cb) {
int rc = fsm->timer_cb(fi);
if (rc != 1) {
- fi->T = 0;
return;
}
LOGPFSM(fi, "timer_cb requested termination\n");
+ } else if (fsm->timer_cb2) {
+ int rc = fsm->timer_cb2(fi, T);
+ if (rc != 1) {
+ return;
+ }
+ LOGPFSM(fi, "timer_cb2 requested termination\n");
} else
LOGPFSM(fi, "No timer_cb, automatic termination\n");
/* if timer_cb returns 1 or there is no timer_cb */
- fi->T = 0;
osmo_fsm_inst_term(fi, OSMO_FSM_TERM_TIMEOUT, &T);
}