Neels Hofmeyr | 17518fe | 2017-06-20 04:35:06 +0200 | [diff] [blame] | 1 | /*! \file fsm.h |
| 2 | * Finite State Machine |
| 3 | */ |
| 4 | |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 5 | #pragma once |
| 6 | |
| 7 | #include <stdint.h> |
| 8 | #include <stdbool.h> |
| 9 | |
| 10 | #include <osmocom/core/linuxlist.h> |
| 11 | #include <osmocom/core/timer.h> |
| 12 | #include <osmocom/core/utils.h> |
Neels Hofmeyr | 344776d | 2019-11-09 06:41:10 +0100 | [diff] [blame] | 13 | #include <osmocom/core/logging.h> |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 14 | |
| 15 | /*! \defgroup fsm Finite State Machine abstraction |
| 16 | * @{ |
Neels Hofmeyr | 17518fe | 2017-06-20 04:35:06 +0200 | [diff] [blame] | 17 | * \file fsm.h */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 18 | |
| 19 | struct osmo_fsm_inst; |
| 20 | |
| 21 | enum osmo_fsm_term_cause { |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 22 | /*! terminate because parent terminated */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 23 | OSMO_FSM_TERM_PARENT, |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 24 | /*! terminate on explicit user request */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 25 | OSMO_FSM_TERM_REQUEST, |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 26 | /*! regular termination of process */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 27 | OSMO_FSM_TERM_REGULAR, |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 28 | /*! erroneous termination of process */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 29 | OSMO_FSM_TERM_ERROR, |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 30 | /*! termination due to time-out */ |
Harald Welte | f627c0f | 2016-06-18 10:36:25 +0200 | [diff] [blame] | 31 | OSMO_FSM_TERM_TIMEOUT, |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 32 | }; |
| 33 | |
Neels Hofmeyr | 5c5c78a | 2016-12-14 18:35:47 +0100 | [diff] [blame] | 34 | extern const struct value_string osmo_fsm_term_cause_names[]; |
| 35 | static inline const char *osmo_fsm_term_cause_name(enum osmo_fsm_term_cause cause) |
| 36 | { |
| 37 | return get_value_string(osmo_fsm_term_cause_names, cause); |
| 38 | } |
| 39 | |
| 40 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 41 | /*! description of a rule in the FSM */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 42 | struct osmo_fsm_state { |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 43 | /*! bit-mask of permitted input events for this state */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 44 | uint32_t in_event_mask; |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 45 | /*! bit-mask to which other states this state may transiton */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 46 | uint32_t out_state_mask; |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 47 | /*! human-readable name of this state */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 48 | const char *name; |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 49 | /*! function to be called for events arriving in this state */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 50 | void (*action)(struct osmo_fsm_inst *fi, uint32_t event, void *data); |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 51 | /*! function to be called just after entering the state */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 52 | void (*onenter)(struct osmo_fsm_inst *fi, uint32_t prev_state); |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 53 | /*! function to be called just before leaving the state */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 54 | void (*onleave)(struct osmo_fsm_inst *fi, uint32_t next_state); |
| 55 | }; |
| 56 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 57 | /*! a description of an osmocom finite state machine */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 58 | struct osmo_fsm { |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 59 | /*! global list */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 60 | struct llist_head list; |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 61 | /*! list of instances of this FSM */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 62 | struct llist_head instances; |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 63 | /*! human readable name */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 64 | const char *name; |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 65 | /*! table of state transition rules */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 66 | const struct osmo_fsm_state *states; |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 67 | /*! number of entries in \ref states */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 68 | unsigned int num_states; |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 69 | /*! bit-mask of events permitted in all states */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 70 | uint32_t allstate_event_mask; |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 71 | /*! function pointer to be called for allstate events */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 72 | void (*allstate_action)(struct osmo_fsm_inst *fi, uint32_t event, void *data); |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 73 | /*! clean-up function, called during termination */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 74 | void (*cleanup)(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause); |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 75 | /*! timer call-back for states with time-out. |
Neels Hofmeyr | dda5e79 | 2016-12-09 16:10:34 +0100 | [diff] [blame] | 76 | * \returns 1 to request termination, 0 to keep running. */ |
Harald Welte | f627c0f | 2016-06-18 10:36:25 +0200 | [diff] [blame] | 77 | int (*timer_cb)(struct osmo_fsm_inst *fi); |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 78 | /*! logging sub-system for this FSM */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 79 | int log_subsys; |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 80 | /*! human-readable names of events */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 81 | const struct value_string *event_names; |
Philipp Maier | d1f5793 | 2018-02-14 18:20:07 +0100 | [diff] [blame] | 82 | /*! graceful exit function, called at the beginning of termination */ |
| 83 | void (*pre_term)(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause); |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 84 | }; |
| 85 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 86 | /*! a single instanceof an osmocom finite state machine */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 87 | struct osmo_fsm_inst { |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 88 | /*! member in the fsm->instances list */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 89 | struct llist_head list; |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 90 | /*! back-pointer to the FSM of which we are an instance */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 91 | struct osmo_fsm *fsm; |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 92 | /*! human readable identifier */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 93 | const char *id; |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 94 | /*! human readable fully-qualified name */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 95 | const char *name; |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 96 | /*! some private data of this instance */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 97 | void *priv; |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 98 | /*! logging level for this FSM */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 99 | int log_level; |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 100 | /*! current state of the FSM */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 101 | uint32_t state; |
| 102 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 103 | /*! timer number for states with time-out */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 104 | int T; |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 105 | /*! timer back-end for states with time-out */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 106 | struct osmo_timer_list timer; |
| 107 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 108 | /*! support for fsm-based procedures */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 109 | struct { |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 110 | /*! the parent FSM that has created us */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 111 | struct osmo_fsm_inst *parent; |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 112 | /*! the event we should send upon termination */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 113 | uint32_t parent_term_event; |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 114 | /*! a list of children processes */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 115 | struct llist_head children; |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 116 | /*! \ref llist_head linked to parent->proc.children */ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 117 | struct llist_head child; |
Neels Hofmeyr | 3b414a4 | 2019-04-08 00:33:53 +0200 | [diff] [blame] | 118 | /*! Indicator whether osmo_fsm_inst_term() was already invoked on this instance. */ |
| 119 | bool terminating; |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 120 | } proc; |
| 121 | }; |
| 122 | |
| 123 | void osmo_fsm_log_addr(bool log_addr); |
Neels Hofmeyr | 050f2d3 | 2018-05-31 15:30:15 +0200 | [diff] [blame] | 124 | void osmo_fsm_log_timeouts(bool log_timeouts); |
Neels Hofmeyr | 1f9cc01 | 2019-03-24 05:56:21 +0100 | [diff] [blame] | 125 | void osmo_fsm_term_safely(bool term_safely); |
Neels Hofmeyr | 988f6d7 | 2019-10-04 20:37:17 +0200 | [diff] [blame] | 126 | void osmo_fsm_set_dealloc_ctx(void *ctx); |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 127 | |
Neels Hofmeyr | 691ba52 | 2018-12-19 23:34:25 +0100 | [diff] [blame] | 128 | /*! Log using FSM instance's context, on explicit logging subsystem and level. |
| 129 | * \param fi An osmo_fsm_inst. |
| 130 | * \param subsys A logging subsystem, e.g. DLGLOBAL. |
| 131 | * \param level A logging level, e.g. LOGL_INFO. |
| 132 | * \param fmt printf-like format string. |
| 133 | * \param args Format string arguments. |
| 134 | */ |
| 135 | #define LOGPFSMSL(fi, subsys, level, fmt, args...) \ |
| 136 | LOGPFSMSLSRC(fi, subsys, level, __FILE__, __LINE__, fmt, ## args) |
| 137 | |
| 138 | /*! Log using FSM instance's context, on explicit logging subsystem and level, |
| 139 | * and passing explicit source file and line information. |
| 140 | * \param fi An osmo_fsm_inst. |
| 141 | * \param subsys A logging subsystem, e.g. DLGLOBAL. |
| 142 | * \param level A logging level, e.g. LOGL_INFO. |
| 143 | * \param caller_file A string constant containing a source file path, like __FILE__. |
| 144 | * \param caller_line A number constant containing a source file line, like __LINE__. |
| 145 | * \param fmt printf-like format string. |
| 146 | * \param args Format string arguments. |
| 147 | */ |
| 148 | #define LOGPFSMSLSRC(fi, subsys, level, caller_file, caller_line, fmt, args...) \ |
| 149 | LOGPSRC(subsys, level, \ |
| 150 | caller_file, caller_line, \ |
| 151 | "%s{%s}: " fmt, \ |
| 152 | osmo_fsm_inst_name(fi), \ |
| 153 | (fi) ? osmo_fsm_state_name((fi)->fsm, (fi)->state) : "fi=NULL", ## args) |
| 154 | |
| 155 | |
Neels Hofmeyr | b11ff7c | 2018-12-20 00:19:29 +0100 | [diff] [blame] | 156 | /*! Log using FSM instance's context, on explicit logging level. |
| 157 | * \param fi An osmo_fsm_inst. |
| 158 | * \param level A logging level, e.g. LOGL_INFO. |
| 159 | * \param fmt printf-like format string. |
| 160 | * \param args Format string arguments. |
| 161 | */ |
Neels Hofmeyr | 6a13e7f | 2016-12-14 17:37:34 +0100 | [diff] [blame] | 162 | #define LOGPFSML(fi, level, fmt, args...) \ |
Neels Hofmeyr | e5bde90 | 2018-12-20 00:00:11 +0100 | [diff] [blame] | 163 | LOGPFSMLSRC(fi, level, __FILE__, __LINE__, fmt, ## args) |
Neels Hofmeyr | 6a13e7f | 2016-12-14 17:37:34 +0100 | [diff] [blame] | 164 | |
Neels Hofmeyr | b11ff7c | 2018-12-20 00:19:29 +0100 | [diff] [blame] | 165 | /*! Log using FSM instance's context, on explicit logging level, and with explicit source file and line info. |
| 166 | * The log subsystem to log on is obtained from the underlying FSM definition. |
| 167 | * \param fi An osmo_fsm_inst. |
| 168 | * \param level A logging level, e.g. LOGL_INFO. |
| 169 | * \param caller_file A string constant containing a source file path, like __FILE__. |
| 170 | * \param caller_line A number constant containing a source file line, like __LINE__. |
| 171 | * \param fmt printf-like format string. |
| 172 | * \param args Format string arguments. |
| 173 | */ |
Neels Hofmeyr | eeacf90 | 2016-12-23 01:00:13 +0100 | [diff] [blame] | 174 | #define LOGPFSMLSRC(fi, level, caller_file, caller_line, fmt, args...) \ |
Neels Hofmeyr | 691ba52 | 2018-12-19 23:34:25 +0100 | [diff] [blame] | 175 | LOGPFSMSLSRC(fi, (fi) ? (fi)->fsm->log_subsys : DLGLOBAL, level, \ |
| 176 | caller_file, caller_line, fmt, ## args) |
Neels Hofmeyr | eeacf90 | 2016-12-23 01:00:13 +0100 | [diff] [blame] | 177 | |
Neels Hofmeyr | b11ff7c | 2018-12-20 00:19:29 +0100 | [diff] [blame] | 178 | /*! Log using FSM instance's context. |
| 179 | * The log level to log on is obtained from the FSM instance. |
| 180 | * The log subsystem to log on is obtained from the underlying FSM definition. |
| 181 | * \param fi An osmo_fsm_inst. |
| 182 | * \param fmt printf-like format string. |
| 183 | * \param args Format string arguments. |
| 184 | */ |
Neels Hofmeyr | e5bde90 | 2018-12-20 00:00:11 +0100 | [diff] [blame] | 185 | #define LOGPFSM(fi, fmt, args...) \ |
Neels Hofmeyr | b0b39af | 2018-12-20 00:03:59 +0100 | [diff] [blame] | 186 | LOGPFSML(fi, (fi) ? (fi)->log_level : LOGL_ERROR, fmt, ## args) |
Neels Hofmeyr | e5bde90 | 2018-12-20 00:00:11 +0100 | [diff] [blame] | 187 | |
Neels Hofmeyr | b11ff7c | 2018-12-20 00:19:29 +0100 | [diff] [blame] | 188 | /*! Log using FSM instance's context, with explicit source file and line info. |
| 189 | * The log level to log on is obtained from the FSM instance. |
| 190 | * The log subsystem to log on is obtained from the underlying FSM definition. |
| 191 | * \param fi An osmo_fsm_inst. |
| 192 | * \param caller_file A string constant containing a source file path, like __FILE__. |
| 193 | * \param caller_line A number constant containing a source file line, like __LINE__. |
| 194 | * \param fmt printf-like format string. |
| 195 | * \param args Format string arguments. |
| 196 | */ |
Neels Hofmeyr | eeacf90 | 2016-12-23 01:00:13 +0100 | [diff] [blame] | 197 | #define LOGPFSMSRC(fi, caller_file, caller_line, fmt, args...) \ |
Neels Hofmeyr | b0b39af | 2018-12-20 00:03:59 +0100 | [diff] [blame] | 198 | LOGPFSMLSRC(fi, (fi) ? (fi)->log_level : LOGL_ERROR, \ |
Neels Hofmeyr | eeacf90 | 2016-12-23 01:00:13 +0100 | [diff] [blame] | 199 | caller_file, caller_line, \ |
| 200 | fmt, ## args) |
| 201 | |
Neels Hofmeyr | 5734bff | 2019-02-21 02:27:48 +0100 | [diff] [blame] | 202 | #define OSMO_T_FMT "%c%u" |
| 203 | #define OSMO_T_FMT_ARGS(T) ((T) >= 0 ? 'T' : 'X'), ((T) >= 0 ? T : -T) |
| 204 | |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 205 | int osmo_fsm_register(struct osmo_fsm *fsm); |
Max | 8b25a3f | 2016-11-01 11:02:17 +0100 | [diff] [blame] | 206 | void osmo_fsm_unregister(struct osmo_fsm *fsm); |
Harald Welte | 8808bb4 | 2017-01-07 11:11:03 +0100 | [diff] [blame] | 207 | struct osmo_fsm *osmo_fsm_find_by_name(const char *name); |
Harald Welte | 4585e67 | 2017-04-16 17:23:56 +0200 | [diff] [blame] | 208 | struct osmo_fsm_inst *osmo_fsm_inst_find_by_name(const struct osmo_fsm *fsm, |
| 209 | const char *name); |
| 210 | struct osmo_fsm_inst *osmo_fsm_inst_find_by_id(const struct osmo_fsm *fsm, |
| 211 | const char *id); |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 212 | struct osmo_fsm_inst *osmo_fsm_inst_alloc(struct osmo_fsm *fsm, void *ctx, void *priv, |
| 213 | int log_level, const char *id); |
| 214 | struct osmo_fsm_inst *osmo_fsm_inst_alloc_child(struct osmo_fsm *fsm, |
| 215 | struct osmo_fsm_inst *parent, |
| 216 | uint32_t parent_term_event); |
Philipp Maier | 2a06a49 | 2018-01-16 18:45:56 +0100 | [diff] [blame] | 217 | void osmo_fsm_inst_unlink_parent(struct osmo_fsm_inst *fi, void *ctx); |
| 218 | void osmo_fsm_inst_change_parent(struct osmo_fsm_inst *fi, |
| 219 | struct osmo_fsm_inst *new_parent, |
| 220 | uint32_t new_parent_term_event); |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 221 | void osmo_fsm_inst_free(struct osmo_fsm_inst *fi); |
| 222 | |
Daniel Willmann | b0c43a6 | 2018-02-08 18:00:37 +0100 | [diff] [blame] | 223 | int osmo_fsm_inst_update_id(struct osmo_fsm_inst *fi, const char *id); |
Neels Hofmeyr | a64c45a | 2018-03-31 16:34:49 +0200 | [diff] [blame] | 224 | int osmo_fsm_inst_update_id_f(struct osmo_fsm_inst *fi, const char *fmt, ...); |
Neels Hofmeyr | b480b74 | 2019-04-11 06:58:44 +0200 | [diff] [blame] | 225 | int osmo_fsm_inst_update_id_f_sanitize(struct osmo_fsm_inst *fi, char replace_with, const char *fmt, ...); |
Daniel Willmann | b0c43a6 | 2018-02-08 18:00:37 +0100 | [diff] [blame] | 226 | |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 227 | const char *osmo_fsm_event_name(struct osmo_fsm *fsm, uint32_t event); |
| 228 | const char *osmo_fsm_inst_name(struct osmo_fsm_inst *fi); |
| 229 | const char *osmo_fsm_state_name(struct osmo_fsm *fsm, uint32_t state); |
| 230 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 231 | /*! return the name of the state the FSM instance is currently in. */ |
Neels Hofmeyr | fca04bb | 2017-02-28 03:38:38 +0100 | [diff] [blame] | 232 | static inline const char *osmo_fsm_inst_state_name(struct osmo_fsm_inst *fi) |
Neels Hofmeyr | 56632b6 | 2019-01-22 00:22:17 +0100 | [diff] [blame] | 233 | { return fi ? osmo_fsm_state_name(fi->fsm, fi->state) : "NULL"; } |
Neels Hofmeyr | fca04bb | 2017-02-28 03:38:38 +0100 | [diff] [blame] | 234 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 235 | /*! perform a state change of the given FSM instance |
Neels Hofmeyr | 725698a | 2016-12-14 17:24:54 +0100 | [diff] [blame] | 236 | * |
| 237 | * This is a macro that calls _osmo_fsm_inst_state_chg() with the given |
| 238 | * parameters as well as the caller's source file and line number for logging |
| 239 | * purposes. See there for documentation. |
| 240 | */ |
| 241 | #define osmo_fsm_inst_state_chg(fi, new_state, timeout_secs, T) \ |
| 242 | _osmo_fsm_inst_state_chg(fi, new_state, timeout_secs, T, \ |
Neels Hofmeyr | 983dcb9 | 2018-08-20 12:33:22 +0200 | [diff] [blame] | 243 | __FILE__, __LINE__) |
Neels Hofmeyr | 725698a | 2016-12-14 17:24:54 +0100 | [diff] [blame] | 244 | int _osmo_fsm_inst_state_chg(struct osmo_fsm_inst *fi, uint32_t new_state, |
| 245 | unsigned long timeout_secs, int T, |
| 246 | const char *file, int line); |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 247 | |
Harald Welte | 7b74551 | 2019-05-18 21:03:55 +0200 | [diff] [blame] | 248 | #define osmo_fsm_inst_state_chg_ms(fi, new_state, timeout_ms, T) \ |
| 249 | _osmo_fsm_inst_state_chg_ms(fi, new_state, timeout_ms, T, \ |
| 250 | __FILE__, __LINE__) |
| 251 | int _osmo_fsm_inst_state_chg_ms(struct osmo_fsm_inst *fi, uint32_t new_state, |
| 252 | unsigned long timeout_ms, int T, |
| 253 | const char *file, int line); |
| 254 | |
Neels Hofmeyr | 407df02 | 2018-05-25 18:20:06 +0200 | [diff] [blame] | 255 | /*! perform a state change while keeping the current timer running. |
| 256 | * |
| 257 | * This is useful to keep a timeout across several states (without having to round the |
| 258 | * remaining time to seconds). |
| 259 | * |
| 260 | * This is a macro that calls _osmo_fsm_inst_state_chg_keep_timer() with the given |
| 261 | * parameters as well as the caller's source file and line number for logging |
| 262 | * purposes. See there for documentation. |
| 263 | */ |
| 264 | #define osmo_fsm_inst_state_chg_keep_timer(fi, new_state) \ |
| 265 | _osmo_fsm_inst_state_chg_keep_timer(fi, new_state, \ |
Neels Hofmeyr | 983dcb9 | 2018-08-20 12:33:22 +0200 | [diff] [blame] | 266 | __FILE__, __LINE__) |
Neels Hofmeyr | 407df02 | 2018-05-25 18:20:06 +0200 | [diff] [blame] | 267 | int _osmo_fsm_inst_state_chg_keep_timer(struct osmo_fsm_inst *fi, uint32_t new_state, |
| 268 | const char *file, int line); |
| 269 | |
Neels Hofmeyr | d4b79c8 | 2019-03-06 05:43:23 +0100 | [diff] [blame] | 270 | /*! perform a state change while keeping the current timer if running, or starting a timer otherwise. |
| 271 | * |
| 272 | * This is useful to keep a timeout across several states, but to make sure that some timeout is actually running. |
| 273 | * |
| 274 | * This is a macro that calls _osmo_fsm_inst_state_chg_keep_or_start_timer() with the given |
| 275 | * parameters as well as the caller's source file and line number for logging |
| 276 | * purposes. See there for documentation. |
| 277 | */ |
| 278 | #define osmo_fsm_inst_state_chg_keep_or_start_timer(fi, new_state, timeout_secs, T) \ |
| 279 | _osmo_fsm_inst_state_chg_keep_or_start_timer(fi, new_state, timeout_secs, T, \ |
| 280 | __FILE__, __LINE__) |
| 281 | int _osmo_fsm_inst_state_chg_keep_or_start_timer(struct osmo_fsm_inst *fi, uint32_t new_state, |
| 282 | unsigned long timeout_secs, int T, |
| 283 | const char *file, int line); |
| 284 | |
Harald Welte | 7b74551 | 2019-05-18 21:03:55 +0200 | [diff] [blame] | 285 | #define osmo_fsm_inst_state_chg_keep_or_start_timer_ms(fi, new_state, timeout_ms, T) \ |
| 286 | _osmo_fsm_inst_state_chg_keep_or_start_timer_ms(fi, new_state, timeout_ms, T, \ |
| 287 | __FILE__, __LINE__) |
| 288 | int _osmo_fsm_inst_state_chg_keep_or_start_timer_ms(struct osmo_fsm_inst *fi, uint32_t new_state, |
| 289 | unsigned long timeout_ms, int T, |
| 290 | const char *file, int line); |
| 291 | |
| 292 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 293 | /*! dispatch an event to an osmocom finite state machine instance |
Neels Hofmeyr | 725698a | 2016-12-14 17:24:54 +0100 | [diff] [blame] | 294 | * |
| 295 | * This is a macro that calls _osmo_fsm_inst_dispatch() with the given |
| 296 | * parameters as well as the caller's source file and line number for logging |
| 297 | * purposes. See there for documentation. |
| 298 | */ |
| 299 | #define osmo_fsm_inst_dispatch(fi, event, data) \ |
Neels Hofmeyr | 983dcb9 | 2018-08-20 12:33:22 +0200 | [diff] [blame] | 300 | _osmo_fsm_inst_dispatch(fi, event, data, __FILE__, __LINE__) |
Neels Hofmeyr | 725698a | 2016-12-14 17:24:54 +0100 | [diff] [blame] | 301 | int _osmo_fsm_inst_dispatch(struct osmo_fsm_inst *fi, uint32_t event, void *data, |
| 302 | const char *file, int line); |
| 303 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 304 | /*! Terminate FSM instance with given cause |
Neels Hofmeyr | 725698a | 2016-12-14 17:24:54 +0100 | [diff] [blame] | 305 | * |
| 306 | * This is a macro that calls _osmo_fsm_inst_term() with the given parameters |
| 307 | * as well as the caller's source file and line number for logging purposes. |
| 308 | * See there for documentation. |
| 309 | */ |
| 310 | #define osmo_fsm_inst_term(fi, cause, data) \ |
Neels Hofmeyr | 983dcb9 | 2018-08-20 12:33:22 +0200 | [diff] [blame] | 311 | _osmo_fsm_inst_term(fi, cause, data, __FILE__, __LINE__) |
Neels Hofmeyr | 725698a | 2016-12-14 17:24:54 +0100 | [diff] [blame] | 312 | void _osmo_fsm_inst_term(struct osmo_fsm_inst *fi, |
| 313 | enum osmo_fsm_term_cause cause, void *data, |
| 314 | const char *file, int line); |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 315 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 316 | /*! Terminate all child FSM instances of an FSM instance. |
Neels Hofmeyr | c014f60 | 2016-12-23 04:26:39 +0100 | [diff] [blame] | 317 | * |
| 318 | * This is a macro that calls _osmo_fsm_inst_term_children() with the given |
| 319 | * parameters as well as the caller's source file and line number for logging |
| 320 | * purposes. See there for documentation. |
| 321 | */ |
| 322 | #define osmo_fsm_inst_term_children(fi, cause, data) \ |
Neels Hofmeyr | 983dcb9 | 2018-08-20 12:33:22 +0200 | [diff] [blame] | 323 | _osmo_fsm_inst_term_children(fi, cause, data, __FILE__, __LINE__) |
Neels Hofmeyr | c014f60 | 2016-12-23 04:26:39 +0100 | [diff] [blame] | 324 | void _osmo_fsm_inst_term_children(struct osmo_fsm_inst *fi, |
| 325 | enum osmo_fsm_term_cause cause, |
| 326 | void *data, |
| 327 | const char *file, int line); |
| 328 | |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 329 | /*! @} */ |