Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/s390/net/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 4 kB image not shown  

Quelle  fsm.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * A generic FSM based on fsm used in isdn4linux
 *
 */


#include "fsm.h"
#include <linux/export.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/timer.h>

MODULE_AUTHOR("(C) 2000 IBM Corp. by Fritz Elfert ");
MODULE_DESCRIPTION("Finite state machine helper functions");
MODULE_LICENSE("GPL");

fsm_instance *
init_fsm(char *name, const char **state_names, const char **event_names, int nr_states,
  int nr_events, const fsm_node *tmpl, int tmpl_len, gfp_t order)
{
 int i;
 fsm_instance *this;
 fsm_function_t *m;
 fsm *f;

 this = kzalloc(sizeof(fsm_instance), order);
 if (this == NULL) {
  printk(KERN_WARNING
   "fsm(%s): init_fsm: Couldn't alloc instance\n", name);
  return NULL;
 }
 strscpy(this->name, name, sizeof(this->name));
 init_waitqueue_head(&this->wait_q);

 f = kzalloc(sizeof(fsm), order);
 if (f == NULL) {
  printk(KERN_WARNING
   "fsm(%s): init_fsm: Couldn't alloc fsm\n", name);
  kfree_fsm(this);
  return NULL;
 }
 f->nr_events = nr_events;
 f->nr_states = nr_states;
 f->event_names = event_names;
 f->state_names = state_names;
 this->f = f;

 m = kcalloc(nr_states*nr_events, sizeof(fsm_function_t), order);
 if (m == NULL) {
  printk(KERN_WARNING
   "fsm(%s): init_fsm: Couldn't alloc jumptable\n", name);
  kfree_fsm(this);
  return NULL;
 }
 f->jumpmatrix = m;

 for (i = 0; i < tmpl_len; i++) {
  if ((tmpl[i].cond_state >= nr_states) ||
      (tmpl[i].cond_event >= nr_events)   ) {
   printk(KERN_ERR
    "fsm(%s): init_fsm: Bad template l=%d st(%ld/%ld) ev(%ld/%ld)\n",
    name, i, (long)tmpl[i].cond_state, (long)f->nr_states,
    (long)tmpl[i].cond_event, (long)f->nr_events);
   kfree_fsm(this);
   return NULL;
  } else
   m[nr_states * tmpl[i].cond_event + tmpl[i].cond_state] =
    tmpl[i].function;
 }
 return this;
}

void
kfree_fsm(fsm_instance *this)
{
 if (this) {
  if (this->f) {
   kfree(this->f->jumpmatrix);
   kfree(this->f);
  }
  kfree(this);
 } else
  printk(KERN_WARNING
   "fsm: kfree_fsm called with NULL argument\n");
}

#if FSM_DEBUG_HISTORY
void
fsm_print_history(fsm_instance *fi)
{
 int idx = 0;
 int i;

 if (fi->history_size >= FSM_HISTORY_SIZE)
  idx = fi->history_index;

 printk(KERN_DEBUG "fsm(%s): History:\n", fi->name);
 for (i = 0; i < fi->history_size; i++) {
  int e = fi->history[idx].event;
  int s = fi->history[idx++].state;
  idx %= FSM_HISTORY_SIZE;
  if (e == -1)
   printk(KERN_DEBUG " S=%s\n",
          fi->f->state_names[s]);
  else
   printk(KERN_DEBUG " S=%s E=%s\n",
          fi->f->state_names[s],
          fi->f->event_names[e]);
 }
 fi->history_size = fi->history_index = 0;
}

void
fsm_record_history(fsm_instance *fi, int state, int event)
{
 fi->history[fi->history_index].state = state;
 fi->history[fi->history_index++].event = event;
 fi->history_index %= FSM_HISTORY_SIZE;
 if (fi->history_size < FSM_HISTORY_SIZE)
  fi->history_size++;
}
#endif

const char *
fsm_getstate_str(fsm_instance *fi)
{
 int st = atomic_read(&fi->state);
 if (st >= fi->f->nr_states)
  return "Invalid";
 return fi->f->state_names[st];
}

static void
fsm_expire_timer(struct timer_list *t)
{
 fsm_timer *this = timer_container_of(this, t, tl);
#if FSM_TIMER_DEBUG
 printk(KERN_DEBUG "fsm(%s): Timer %p expired\n",
        this->fi->name, this);
#endif
 fsm_event(this->fi, this->expire_event, this->event_arg);
}

void
fsm_settimer(fsm_instance *fi, fsm_timer *this)
{
 this->fi = fi;
#if FSM_TIMER_DEBUG
 printk(KERN_DEBUG "fsm(%s): Create timer %p\n", fi->name,
        this);
#endif
 timer_setup(&this->tl, fsm_expire_timer, 0);
}

void
fsm_deltimer(fsm_timer *this)
{
#if FSM_TIMER_DEBUG
 printk(KERN_DEBUG "fsm(%s): Delete timer %p\n", this->fi->name,
  this);
#endif
 timer_delete(&this->tl);
}

int
fsm_addtimer(fsm_timer *thisint millisec, int event, void *arg)
{

#if FSM_TIMER_DEBUG
 printk(KERN_DEBUG "fsm(%s): Add timer %p %dms\n",
        this->fi->name, this, millisec);
#endif

 timer_setup(&this->tl, fsm_expire_timer, 0);
 this->expire_event = event;
 this->event_arg = arg;
 this->tl.expires = jiffies + (millisec * HZ) / 1000;
 add_timer(&this->tl);
 return 0;
}

/* FIXME: this function is never used, why */
void
fsm_modtimer(fsm_timer *thisint millisec, int event, void *arg)
{

#if FSM_TIMER_DEBUG
 printk(KERN_DEBUG "fsm(%s): Restart timer %p %dms\n",
  this->fi->name, this, millisec);
#endif

 timer_delete(&this->tl);
 timer_setup(&this->tl, fsm_expire_timer, 0);
 this->expire_event = event;
 this->event_arg = arg;
 this->tl.expires = jiffies + (millisec * HZ) / 1000;
 add_timer(&this->tl);
}

EXPORT_SYMBOL(init_fsm);
EXPORT_SYMBOL(kfree_fsm);
EXPORT_SYMBOL(fsm_settimer);
EXPORT_SYMBOL(fsm_deltimer);
EXPORT_SYMBOL(fsm_addtimer);
EXPORT_SYMBOL(fsm_modtimer);
EXPORT_SYMBOL(fsm_getstate_str);

#if FSM_DEBUG_HISTORY
EXPORT_SYMBOL(fsm_print_history);
EXPORT_SYMBOL(fsm_record_history);
#endif

Messung V0.5
C=95 H=90 G=92

¤ Dauer der Verarbeitung: 0.3 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.