summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorschodet2008-06-13 12:56:59 +0000
committerschodet2008-06-13 12:56:59 +0000
commitbd78f94ed22354d407ac406cf83c89a4f616e73e (patch)
treef0619feb14431ecf9ea6626f7ef08927ddc1888f
parentb9eb3c949e0b95a8cf6d135e2189a7c05b55825f (diff)
* cp2/fsm:
- implemented bare events support. git-svn-id: svn+ssh://pessac/svn/cesar/trunk@2322 017c9cb6-072f-447c-8318-d5b54f68fe89
-rw-r--r--cesar/cp2/fsm/inc/context.h9
-rw-r--r--cesar/cp2/fsm/inc/events.h11
-rw-r--r--cesar/cp2/fsm/src/events.c35
-rw-r--r--cesar/cp2/fsm/src/fsm.c88
4 files changed, 137 insertions, 6 deletions
diff --git a/cesar/cp2/fsm/inc/context.h b/cesar/cp2/fsm/inc/context.h
index 0d7617bc12..da914c538d 100644
--- a/cesar/cp2/fsm/inc/context.h
+++ b/cesar/cp2/fsm/inc/context.h
@@ -13,18 +13,21 @@
* \ingroup cp2_fsm
*/
+#include "lib/slab.h"
+
/** FSM context. */
struct cp_fsm_t
{
/** Current state. */
cp_fsm_state_t state;
- /** Currently handled event, reset to CP_FSM_EVENT_TYPE_NB when no event
- * is handled. */
- cp_fsm_event_type_t handled_event;
+ /** Currently handled event, reset to NULL when no event is handled. */
+ cp_fsm_event_t *handled_event;
/** Head of pending event list. */
cp_fsm_event_t *head;
/** Tail of pending event list. */
cp_fsm_event_t *tail;
+ /** Slab cache for bare events. */
+ slab_cache_t event_bare_cache;
};
typedef struct cp_fsm_t cp_fsm_t;
diff --git a/cesar/cp2/fsm/inc/events.h b/cesar/cp2/fsm/inc/events.h
index 98e28e5d96..179fc5cf99 100644
--- a/cesar/cp2/fsm/inc/events.h
+++ b/cesar/cp2/fsm/inc/events.h
@@ -26,11 +26,13 @@
* \param transition transition function to call
*/
typedef void (*cp_fsm_event_handler_t) (cp_t *ctx, cp_fsm_event_t *event,
- void *transition);
+ cp_fsm_transition_t transition);
/** Event base structure. */
struct cp_fsm_event_t
{
+ /** Next event in queue. */
+ cp_fsm_event_t *next;
/** Event type. */
cp_fsm_event_type_t type;
/** Handle transition callback. */
@@ -73,6 +75,13 @@ cp_fsm_event_beacon_new (cp_t *ctx, cp_fsm_event_type_t type,
cp_beacon_desc_t *beacon, cp_net_t *net,
cp_sta_t *sta);
+/**
+ * Initialise event part of FSM context.
+ * \param ctx control plane context
+ */
+void
+cp_fsm_event_init (cp_t *ctx);
+
END_DECLS
#endif /* cp2_fsm_inc_events_h */
diff --git a/cesar/cp2/fsm/src/events.c b/cesar/cp2/fsm/src/events.c
index e84d7a5e1b..46985a3aed 100644
--- a/cesar/cp2/fsm/src/events.c
+++ b/cesar/cp2/fsm/src/events.c
@@ -12,12 +12,36 @@
*/
#include "common/std.h"
+#include "cp2/inc/context.h"
+
#include "fsm.h"
+#include "inc/tables.h"
+
+typedef void (*cp_fsm_event_bare_transition_t) (cp_t *ctx);
+
+void
+cp_fsm_event_bare_handler (cp_t *ctx, cp_fsm_event_t *event,
+ cp_fsm_transition_t transition)
+{
+ dbg_assert (ctx);
+ dbg_assert_ptr (event);
+ dbg_assert (transition);
+ cp_fsm_event_bare_transition_t t = transition;
+ /* Call transition. */
+ t (ctx);
+}
cp_fsm_event_t *
cp_fsm_event_bare_new (cp_t *ctx, cp_fsm_event_type_t type)
{
- return NULL;
+ dbg_assert (ctx);
+ dbg_assert (type < CP_FSM_EVENT_TYPE_NB);
+ cp_fsm_event_t *e;
+ e = slab_alloc (&ctx->fsm.event_bare_cache);
+ e->next = NULL;
+ e->type = type;
+ e->handler = cp_fsm_event_bare_handler;
+ return e;
}
cp_fsm_event_t *
@@ -33,3 +57,12 @@ cp_fsm_event_beacon_new (cp_t *ctx, cp_fsm_event_type_t type,
{
return NULL;
}
+
+void
+cp_fsm_event_init (cp_t *ctx)
+{
+ dbg_assert (ctx);
+ slab_cache_init (&ctx->fsm.event_bare_cache, "event_bare",
+ sizeof (cp_fsm_event_t), NULL);
+}
+
diff --git a/cesar/cp2/fsm/src/fsm.c b/cesar/cp2/fsm/src/fsm.c
index 04ee3e5bf9..6e0efe4585 100644
--- a/cesar/cp2/fsm/src/fsm.c
+++ b/cesar/cp2/fsm/src/fsm.c
@@ -12,32 +12,118 @@
*/
#include "common/std.h"
+#include "cp2/inc/context.h"
+
#include "fsm.h"
#include "inc/tables.h"
-#include "inc/context.h"
void
cp_fsm_init (cp_t *ctx)
{
+ dbg_assert (ctx);
+ ctx->fsm.state = 0;
+ ctx->fsm.handled_event = NULL;
+ ctx->fsm.head = NULL;
+ ctx->fsm.tail = NULL;
+ cp_fsm_event_init (ctx);
}
void
cp_fsm_uninit (cp_t *ctx)
{
+ dbg_assert (ctx);
+ dbg_assert (!ctx->fsm.handled_event);
+ cp_fsm_event_t *p, *pnext;
+ for (p = ctx->fsm.head; p; p = pnext)
+ {
+ pnext = p->next;
+ slab_release (p);
+ }
}
void
cp_fsm_process (cp_t *ctx)
{
+ dbg_assert (ctx);
+ dbg_assert (ctx->fsm.state < CP_FSM_STATE_NB);
+ dbg_assert (!ctx->fsm.handled_event);
+ if (ctx->fsm.head)
+ {
+ /* Extract event from queue. */
+ cp_fsm_event_t *e = ctx->fsm.head;
+ ctx->fsm.head = e->next;
+ if (!e->next)
+ dbg_invalid_ptr (ctx->fsm.tail);
+ dbg_assert (e->type < CP_FSM_EVENT_TYPE_NB);
+ dbg_assert (e->handler);
+ /* Handle event. */
+ ctx->fsm.handled_event = e;
+ cp_fsm_transition_t t =
+ cp_fsm_transition_table[ctx->fsm.state][e->type];
+ if (t)
+ {
+ e->handler (ctx, e, t);
+ /* If state has not been set, this means that there is one and
+ * only one branch for this transition. Check this and change
+ * state. */
+ if (ctx->fsm.handled_event)
+ {
+ cp_fsm_state_t to =
+ cp_fsm_only_branch_table[ctx->fsm.state][e->type];
+ dbg_assert_print (to != CP_FSM_STATE_NB,
+ "no branch selected");
+ dbg_assert (to < CP_FSM_STATE_NB);
+ if (to != CP_FSM_STATE_NB) /* Be clement for errors. */
+ ctx->fsm.state = to;
+ ctx->fsm.handled_event = NULL;
+ }
+ }
+ /* Release event. */
+ slab_release (e);
+ }
}
void
cp_fsm_post (cp_t *ctx, cp_fsm_event_t *event)
{
+ dbg_assert (ctx);
+ dbg_assert (ctx->fsm.state < CP_FSM_STATE_NB);
+ dbg_assert_ptr (event);
+ dbg_assert (event->next == NULL);
+ dbg_assert (event->type < CP_FSM_EVENT_TYPE_NB);
+ dbg_assert (event->handler);
+ /* Add event to event queue, do not add reference as it is transfered to
+ * us. */
+ if (ctx->fsm.head)
+ {
+ dbg_assert_ptr (ctx->fsm.tail);
+ ctx->fsm.tail->next = event;
+ }
+ else
+ ctx->fsm.head = event;
+ ctx->fsm.tail = event;
}
void
cp_fsm_branch (cp_t *ctx, cp_fsm_branch_t branch)
{
+ dbg_assert (ctx);
+ dbg_assert (ctx->fsm.state < CP_FSM_STATE_NB);
+ dbg_assert_print (ctx->fsm.handled_event,
+ "not in transition or duplicated branch");
+ /* Check there is actually several branches. */
+ dbg_assert_print (cp_fsm_only_branch_table[ctx->fsm.state]
+ [ctx->fsm.handled_event->type] == CP_FSM_STATE_NB,
+ "no branch");
+ /* Check this correspond to the current transition. */
+ cp_fsm_state_t state = ((uint) branch >> 16) & 0xff;
+ cp_fsm_event_type_t event_type = ((uint) branch >> 8) & 0xff;
+ dbg_assert_print (state == ctx->fsm.state
+ && event_type == ctx->fsm.handled_event->type,
+ "bad branch");
+ /* Select this branch. */
+ cp_fsm_state_t to = ((uint) branch) & 0xff;
+ ctx->fsm.state = to;
+ ctx->fsm.handled_event = NULL;
}