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