• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/uqmi/uqmid/osmocom/fsm.h

  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