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; |
| 117 | } proc; |
| 118 | }; |
| 119 | |
| 120 | void osmo_fsm_log_addr(bool log_addr); |
| 121 | |
Neels Hofmeyr | 6a13e7f | 2016-12-14 17:37:34 +0100 | [diff] [blame] | 122 | #define LOGPFSML(fi, level, fmt, args...) \ |
Harald Welte | 3385e4b | 2018-06-02 14:39:08 +0200 | [diff] [blame] | 123 | LOGP((fi)->fsm->log_subsys, OSMO_MAX(level, (fi)->log_level), \ |
| 124 | "%s{%s}: " fmt, \ |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 125 | osmo_fsm_inst_name(fi), \ |
| 126 | osmo_fsm_state_name((fi)->fsm, (fi)->state), ## args) |
| 127 | |
Neels Hofmeyr | 6a13e7f | 2016-12-14 17:37:34 +0100 | [diff] [blame] | 128 | #define LOGPFSM(fi, fmt, args...) \ |
| 129 | LOGPFSML(fi, (fi)->log_level, fmt, ## args) |
| 130 | |
Neels Hofmeyr | eeacf90 | 2016-12-23 01:00:13 +0100 | [diff] [blame] | 131 | #define LOGPFSMLSRC(fi, level, caller_file, caller_line, fmt, args...) \ |
| 132 | LOGPSRC((fi)->fsm->log_subsys, level, \ |
| 133 | caller_file, caller_line, \ |
| 134 | "%s{%s}: " fmt, \ |
| 135 | osmo_fsm_inst_name(fi), \ |
| 136 | osmo_fsm_state_name((fi)->fsm, (fi)->state), \ |
| 137 | ## args) |
| 138 | |
| 139 | #define LOGPFSMSRC(fi, caller_file, caller_line, fmt, args...) \ |
| 140 | LOGPFSMLSRC(fi, (fi)->log_level, \ |
| 141 | caller_file, caller_line, \ |
| 142 | fmt, ## args) |
| 143 | |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 144 | int osmo_fsm_register(struct osmo_fsm *fsm); |
Max | 8b25a3f | 2016-11-01 11:02:17 +0100 | [diff] [blame] | 145 | void osmo_fsm_unregister(struct osmo_fsm *fsm); |
Harald Welte | 8808bb4 | 2017-01-07 11:11:03 +0100 | [diff] [blame] | 146 | struct osmo_fsm *osmo_fsm_find_by_name(const char *name); |
Harald Welte | 4585e67 | 2017-04-16 17:23:56 +0200 | [diff] [blame] | 147 | struct osmo_fsm_inst *osmo_fsm_inst_find_by_name(const struct osmo_fsm *fsm, |
| 148 | const char *name); |
| 149 | struct osmo_fsm_inst *osmo_fsm_inst_find_by_id(const struct osmo_fsm *fsm, |
| 150 | const char *id); |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 151 | struct osmo_fsm_inst *osmo_fsm_inst_alloc(struct osmo_fsm *fsm, void *ctx, void *priv, |
| 152 | int log_level, const char *id); |
| 153 | struct osmo_fsm_inst *osmo_fsm_inst_alloc_child(struct osmo_fsm *fsm, |
| 154 | struct osmo_fsm_inst *parent, |
| 155 | uint32_t parent_term_event); |
Philipp Maier | 2a06a49 | 2018-01-16 18:45:56 +0100 | [diff] [blame] | 156 | void osmo_fsm_inst_unlink_parent(struct osmo_fsm_inst *fi, void *ctx); |
| 157 | void osmo_fsm_inst_change_parent(struct osmo_fsm_inst *fi, |
| 158 | struct osmo_fsm_inst *new_parent, |
| 159 | uint32_t new_parent_term_event); |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 160 | void osmo_fsm_inst_free(struct osmo_fsm_inst *fi); |
| 161 | |
Daniel Willmann | b0c43a6 | 2018-02-08 18:00:37 +0100 | [diff] [blame] | 162 | 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] | 163 | int osmo_fsm_inst_update_id_f(struct osmo_fsm_inst *fi, const char *fmt, ...); |
Daniel Willmann | b0c43a6 | 2018-02-08 18:00:37 +0100 | [diff] [blame] | 164 | |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 165 | const char *osmo_fsm_event_name(struct osmo_fsm *fsm, uint32_t event); |
| 166 | const char *osmo_fsm_inst_name(struct osmo_fsm_inst *fi); |
| 167 | const char *osmo_fsm_state_name(struct osmo_fsm *fsm, uint32_t state); |
| 168 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 169 | /*! return the name of the state the FSM instance is currently in. */ |
Neels Hofmeyr | fca04bb | 2017-02-28 03:38:38 +0100 | [diff] [blame] | 170 | static inline const char *osmo_fsm_inst_state_name(struct osmo_fsm_inst *fi) |
| 171 | { return osmo_fsm_state_name(fi->fsm, fi->state); } |
| 172 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 173 | /*! perform a state change of the given FSM instance |
Neels Hofmeyr | 725698a | 2016-12-14 17:24:54 +0100 | [diff] [blame] | 174 | * |
| 175 | * This is a macro that calls _osmo_fsm_inst_state_chg() with the given |
| 176 | * parameters as well as the caller's source file and line number for logging |
| 177 | * purposes. See there for documentation. |
| 178 | */ |
| 179 | #define osmo_fsm_inst_state_chg(fi, new_state, timeout_secs, T) \ |
| 180 | _osmo_fsm_inst_state_chg(fi, new_state, timeout_secs, T, \ |
| 181 | __BASE_FILE__, __LINE__) |
| 182 | int _osmo_fsm_inst_state_chg(struct osmo_fsm_inst *fi, uint32_t new_state, |
| 183 | unsigned long timeout_secs, int T, |
| 184 | const char *file, int line); |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 185 | |
Neels Hofmeyr | 407df02 | 2018-05-25 18:20:06 +0200 | [diff] [blame] | 186 | /*! perform a state change while keeping the current timer running. |
| 187 | * |
| 188 | * This is useful to keep a timeout across several states (without having to round the |
| 189 | * remaining time to seconds). |
| 190 | * |
| 191 | * This is a macro that calls _osmo_fsm_inst_state_chg_keep_timer() with the given |
| 192 | * parameters as well as the caller's source file and line number for logging |
| 193 | * purposes. See there for documentation. |
| 194 | */ |
| 195 | #define osmo_fsm_inst_state_chg_keep_timer(fi, new_state) \ |
| 196 | _osmo_fsm_inst_state_chg_keep_timer(fi, new_state, \ |
| 197 | __BASE_FILE__, __LINE__) |
| 198 | int _osmo_fsm_inst_state_chg_keep_timer(struct osmo_fsm_inst *fi, uint32_t new_state, |
| 199 | const char *file, int line); |
| 200 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 201 | /*! dispatch an event to an osmocom finite state machine instance |
Neels Hofmeyr | 725698a | 2016-12-14 17:24:54 +0100 | [diff] [blame] | 202 | * |
| 203 | * This is a macro that calls _osmo_fsm_inst_dispatch() with the given |
| 204 | * parameters as well as the caller's source file and line number for logging |
| 205 | * purposes. See there for documentation. |
| 206 | */ |
| 207 | #define osmo_fsm_inst_dispatch(fi, event, data) \ |
| 208 | _osmo_fsm_inst_dispatch(fi, event, data, __BASE_FILE__, __LINE__) |
| 209 | int _osmo_fsm_inst_dispatch(struct osmo_fsm_inst *fi, uint32_t event, void *data, |
| 210 | const char *file, int line); |
| 211 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 212 | /*! Terminate FSM instance with given cause |
Neels Hofmeyr | 725698a | 2016-12-14 17:24:54 +0100 | [diff] [blame] | 213 | * |
| 214 | * This is a macro that calls _osmo_fsm_inst_term() with the given parameters |
| 215 | * as well as the caller's source file and line number for logging purposes. |
| 216 | * See there for documentation. |
| 217 | */ |
| 218 | #define osmo_fsm_inst_term(fi, cause, data) \ |
| 219 | _osmo_fsm_inst_term(fi, cause, data, __BASE_FILE__, __LINE__) |
| 220 | void _osmo_fsm_inst_term(struct osmo_fsm_inst *fi, |
| 221 | enum osmo_fsm_term_cause cause, void *data, |
| 222 | const char *file, int line); |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 223 | |
Neels Hofmeyr | 87e4550 | 2017-06-20 00:17:59 +0200 | [diff] [blame] | 224 | /*! Terminate all child FSM instances of an FSM instance. |
Neels Hofmeyr | c014f60 | 2016-12-23 04:26:39 +0100 | [diff] [blame] | 225 | * |
| 226 | * This is a macro that calls _osmo_fsm_inst_term_children() with the given |
| 227 | * parameters as well as the caller's source file and line number for logging |
| 228 | * purposes. See there for documentation. |
| 229 | */ |
| 230 | #define osmo_fsm_inst_term_children(fi, cause, data) \ |
| 231 | _osmo_fsm_inst_term_children(fi, cause, data, __BASE_FILE__, __LINE__) |
| 232 | void _osmo_fsm_inst_term_children(struct osmo_fsm_inst *fi, |
| 233 | enum osmo_fsm_term_cause cause, |
| 234 | void *data, |
| 235 | const char *file, int line); |
| 236 | |
Harald Welte | 136e737 | 2016-05-29 10:53:17 +0900 | [diff] [blame] | 237 | /*! @} */ |