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