fsm.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:5k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /**
  2.  * $Id: fsm.c,v 1.3 2001/06/18 16:49:19 felfert Exp $
  3.  *
  4.  * A generic FSM based on fsm used in isdn4linux
  5.  *
  6.  */
  7. #include "fsm.h"
  8. #include <linux/version.h>
  9. #include <linux/config.h>
  10. #include <linux/module.h>
  11. fsm_instance *
  12. init_fsm(char *name, const char **state_names, const char **event_names, int nr_states,
  13. int nr_events, const fsm_node *tmpl, int tmpl_len, int order)
  14. {
  15. int i;
  16. fsm_instance *this;
  17. fsm_function_t *m;
  18. fsm *f;
  19. this = (fsm_instance *)kmalloc(sizeof(fsm_instance), order);
  20. if (this == NULL) {
  21. printk(KERN_WARNING
  22. "fsm(%s): init_fsm: Couldn't alloc instancen", name);
  23. return NULL;
  24. }
  25. memset(this, 0, sizeof(fsm_instance));
  26. strncpy(this->name, name, sizeof(this->name));
  27. f = (fsm *)kmalloc(sizeof(fsm), order);
  28. if (f == NULL) {
  29. printk(KERN_WARNING
  30. "fsm(%s): init_fsm: Couldn't alloc fsmn", name);
  31. kfree_fsm(this);
  32. return NULL;
  33. }
  34. memset(f, 0, sizeof(fsm));
  35. f->nr_events = nr_events;
  36. f->nr_states = nr_states;
  37. f->event_names = event_names;
  38. f->state_names = state_names;
  39. this->f = f;
  40. m = (fsm_function_t *)kmalloc(
  41. sizeof(fsm_function_t) * nr_states * nr_events, order);
  42. if (m == NULL) {
  43. printk(KERN_WARNING
  44. "fsm(%s): init_fsm: Couldn't alloc jumptablen", name);
  45. kfree_fsm(this);
  46. return NULL;
  47. }
  48. memset(m, 0, sizeof(fsm_function_t) * f->nr_states * f->nr_events);
  49. f->jumpmatrix = m;
  50. for (i = 0; i < tmpl_len; i++) {
  51. if ((tmpl[i].cond_state >= nr_states) ||
  52.     (tmpl[i].cond_event >= nr_events)   ) {
  53. printk(KERN_ERR
  54. "fsm(%s): init_fsm: Bad template l=%d st(%ld/%ld) ev(%ld/%ld)n",
  55. name, i, (long)tmpl[i].cond_state, (long)f->nr_states,
  56. (long)tmpl[i].cond_event, (long)f->nr_events);
  57. kfree_fsm(this);
  58. return NULL;
  59. } else
  60. m[nr_states * tmpl[i].cond_event + tmpl[i].cond_state] =
  61. tmpl[i].function;
  62. }
  63. return this;
  64. }
  65. void
  66. kfree_fsm(fsm_instance *this)
  67. {
  68. if (this) {
  69. if (this->f) {
  70. if (this->f->jumpmatrix)
  71. kfree(this->f->jumpmatrix);
  72. kfree(this->f);
  73. }
  74. kfree(this);
  75. } else
  76. printk(KERN_WARNING
  77. "fsm: kfree_fsm called with NULL argumentn");
  78. }
  79. #if FSM_DEBUG_HISTORY
  80. void
  81. fsm_print_history(fsm_instance *fi)
  82. {
  83. int idx = 0;
  84. int i;
  85. if (fi->history_size >= FSM_HISTORY_SIZE)
  86. idx = fi->history_index;
  87. printk(KERN_DEBUG "fsm(%s): History:n", fi->name);
  88. for (i = 0; i < fi->history_size; i++) {
  89. int e = fi->history[idx].event;
  90. int s = fi->history[idx++].state;
  91. idx %= FSM_HISTORY_SIZE;
  92. if (e == -1)
  93. printk(KERN_DEBUG "  S=%sn",
  94.        fi->f->state_names[s]);
  95. else
  96. printk(KERN_DEBUG "  S=%s E=%sn",
  97.        fi->f->state_names[s],
  98.        fi->f->event_names[e]);
  99. }
  100. fi->history_size = fi->history_index = 0;
  101. }
  102. void
  103. fsm_record_history(fsm_instance *fi, int state, int event)
  104. {
  105. fi->history[fi->history_index].state = state;
  106. fi->history[fi->history_index++].event = event;
  107. fi->history_index %= FSM_HISTORY_SIZE;
  108. if (fi->history_size < FSM_HISTORY_SIZE)
  109. fi->history_size++;
  110. }
  111. #endif
  112. const char *
  113. fsm_getstate_str(fsm_instance *fi)
  114. {
  115. int st = atomic_read(&fi->state);
  116. if (st >= fi->f->nr_states)
  117. return "Invalid";
  118. return fi->f->state_names[st];
  119. }
  120. static void
  121. fsm_expire_timer(fsm_timer *this)
  122. {
  123. #if FSM_TIMER_DEBUG
  124. printk(KERN_DEBUG "fsm(%s): Timer %p expiredn",
  125.        this->fi->name, this);
  126. #endif
  127. fsm_event(this->fi, this->expire_event, this->event_arg);
  128. }
  129. void
  130. fsm_settimer(fsm_instance *fi, fsm_timer *this)
  131. {
  132. this->fi = fi;
  133. this->tl.function = (void *)fsm_expire_timer;
  134. this->tl.data = (long)this;
  135. #if FSM_TIMER_DEBUG
  136. printk(KERN_DEBUG "fsm(%s): Create timer %pn", fi->name,
  137.        this);
  138. #endif
  139. init_timer(&this->tl);
  140. }
  141. void
  142. fsm_deltimer(fsm_timer *this)
  143. {
  144. #if FSM_TIMER_DEBUG
  145. printk(KERN_DEBUG "fsm(%s): Delete timer %pn", this->fi->name,
  146. this);
  147. #endif
  148. del_timer(&this->tl);
  149. }
  150. int
  151. fsm_addtimer(fsm_timer *this, int millisec, int event, void *arg)
  152. {
  153. #if FSM_TIMER_DEBUG
  154. printk(KERN_DEBUG "fsm(%s): Add timer %p %dmsn",
  155.        this->fi->name, this, millisec);
  156. #endif
  157. #if LINUX_VERSION_CODE >= 0x020300
  158. if (this->tl.list.next || this->tl.list.prev) {
  159. printk(KERN_WARNING "fsm(%s): timer already active!n",
  160. this->fi->name);
  161. return -1;
  162. }
  163. #else
  164. if (this->tl.next || this->tl.prev) {
  165. printk(KERN_WARNING "fsm(%s): timer already active!n",
  166. this->fi->name);
  167. return -1;
  168. }
  169. #endif
  170. init_timer(&this->tl);
  171. this->tl.function = (void *)fsm_expire_timer;
  172. this->tl.data = (long)this;
  173. this->expire_event = event;
  174. this->event_arg = arg;
  175. this->tl.expires = jiffies + (millisec * HZ) / 1000;
  176. add_timer(&this->tl);
  177. return 0;
  178. }
  179. void
  180. fsm_modtimer(fsm_timer *this, int millisec, int event, void *arg)
  181. {
  182. #if FSM_TIMER_DEBUG
  183. printk(KERN_DEBUG "fsm(%s): Restart timer %p %dmsn",
  184. this->fi->name, this, millisec);
  185. #endif
  186. #if LINUX_VERSION_CODE >= 0x020300
  187. if (this->tl.list.next || this->tl.list.prev)
  188. del_timer(&this->tl);
  189. #else
  190. if (this->tl.next || this->tl.prev)
  191. del_timer(&this->tl);
  192. #endif
  193. init_timer(&this->tl);
  194. this->tl.function = (void *)fsm_expire_timer;
  195. this->tl.data = (long)this;
  196. this->expire_event = event;
  197. this->event_arg = arg;
  198. this->tl.expires = jiffies + (millisec * HZ) / 1000;
  199. add_timer(&this->tl);
  200. }
  201. EXPORT_SYMBOL(init_fsm);
  202. EXPORT_SYMBOL(kfree_fsm);
  203. EXPORT_SYMBOL(fsm_settimer);
  204. EXPORT_SYMBOL(fsm_deltimer);
  205. EXPORT_SYMBOL(fsm_addtimer);
  206. EXPORT_SYMBOL(fsm_modtimer);
  207. EXPORT_SYMBOL(fsm_getstate_str);
  208. #if FSM_DEBUG_HISTORY
  209. EXPORT_SYMBOL(fsm_print_history);
  210. EXPORT_SYMBOL(fsm_record_history);
  211. #endif