Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
fsm.h
Go to the documentation of this file.
1 #ifndef _FSM_H_
2 #define _FSM_H_
3 
4 #include <linux/kernel.h>
5 #include <linux/types.h>
6 #include <linux/timer.h>
7 #include <linux/time.h>
8 #include <linux/slab.h>
9 #include <linux/sched.h>
10 #include <linux/string.h>
11 #include <linux/atomic.h>
12 
16 #define FSM_DEBUG 0
17 
22 #define FSM_TIMER_DEBUG 0
23 
29 #define FSM_DEBUG_HISTORY 0
30 #define FSM_HISTORY_SIZE 40
31 
32 struct fsm_instance_t;
33 
37 typedef void (*fsm_function_t)(struct fsm_instance_t *, int, void *);
38 
42 typedef struct {
44  int nr_events;
45  int nr_states;
46  const char **event_names;
47  const char **state_names;
48 } fsm;
49 
50 #if FSM_DEBUG_HISTORY
51 
54 typedef struct {
55  int state;
56  int event;
57 } fsm_history;
58 #endif
59 
63 typedef struct fsm_instance_t {
64  fsm *f;
66  char name[16];
67  void *userdata;
68  int userint;
70 #if FSM_DEBUG_HISTORY
71  int history_index;
72  int history_size;
73  fsm_history history[FSM_HISTORY_SIZE];
74 #endif
75 } fsm_instance;
76 
80 typedef struct {
83  fsm_function_t function;
84 } fsm_node;
85 
89 typedef struct {
91  struct timer_list tl;
93  void *event_arg;
94 } fsm_timer;
95 
108 extern fsm_instance *
109 init_fsm(char *name, const char **state_names,
110  const char **event_names,
111  int nr_states, int nr_events, const fsm_node *tmpl,
112  int tmpl_len, gfp_t order);
113 
119 extern void kfree_fsm(fsm_instance *fi);
120 
121 #if FSM_DEBUG_HISTORY
122 extern void
123 fsm_print_history(fsm_instance *fi);
124 
125 extern void
126 fsm_record_history(fsm_instance *fi, int state, int event);
127 #endif
128 
142 static inline int
143 fsm_event(fsm_instance *fi, int event, void *arg)
144 {
146  int state = atomic_read(&fi->state);
147 
148  if ((state >= fi->f->nr_states) ||
149  (event >= fi->f->nr_events) ) {
150  printk(KERN_ERR "fsm(%s): Invalid state st(%ld/%ld) ev(%d/%ld)\n",
151  fi->name, (long)state,(long)fi->f->nr_states, event,
152  (long)fi->f->nr_events);
153 #if FSM_DEBUG_HISTORY
154  fsm_print_history(fi);
155 #endif
156  return 1;
157  }
158  r = fi->f->jumpmatrix[fi->f->nr_states * event + state];
159  if (r) {
160 #if FSM_DEBUG
161  printk(KERN_DEBUG "fsm(%s): state %s event %s\n",
162  fi->name, fi->f->state_names[state],
163  fi->f->event_names[event]);
164 #endif
165 #if FSM_DEBUG_HISTORY
166  fsm_record_history(fi, state, event);
167 #endif
168  r(fi, event, arg);
169  return 0;
170  } else {
171 #if FSM_DEBUG || FSM_DEBUG_HISTORY
172  printk(KERN_DEBUG "fsm(%s): no function for event %s in state %s\n",
173  fi->name, fi->f->event_names[event],
174  fi->f->state_names[state]);
175 #endif
176 #if FSM_DEBUG_HISTORY
177  fsm_print_history(fi);
178 #endif
179  return !0;
180  }
181 }
182 
190 static inline void
191 fsm_newstate(fsm_instance *fi, int newstate)
192 {
193  atomic_set(&fi->state,newstate);
194 #if FSM_DEBUG_HISTORY
195  fsm_record_history(fi, newstate, -1);
196 #endif
197 #if FSM_DEBUG
198  printk(KERN_DEBUG "fsm(%s): New state %s\n", fi->name,
199  fi->f->state_names[newstate]);
200 #endif
201  wake_up(&fi->wait_q);
202 }
203 
211 static inline int
212 fsm_getstate(fsm_instance *fi)
213 {
214  return atomic_read(&fi->state);
215 }
216 
224 extern const char *fsm_getstate_str(fsm_instance *fi);
225 
233 extern void fsm_settimer(fsm_instance *fi, fsm_timer *);
234 
240 extern void fsm_deltimer(fsm_timer *timer);
241 
253 extern int fsm_addtimer(fsm_timer *timer, int millisec, int event, void *arg);
254 
263 extern void fsm_modtimer(fsm_timer *timer, int millisec, int event, void *arg);
264 
265 #endif /* _FSM_H_ */