PERFORCE change 1046466 for review
Jonathan Anderson
jonathan at FreeBSD.org
Fri Oct 11 15:56:02 UTC 2013
http://p4web.freebsd.org/@@1046466?ac=10
Change 1046466 by jonathan at jonathan-on-zenith on 2013/10/11 15:55:05
Merge optimised version of TESLA kernel parts.
Affected files ...
.. //depot/projects/ctsrd/tesla/src/sys/amd64/conf/TESLA_NODEBUG#2 edit
.. //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/include/libtesla.h#14 edit
.. //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/libtesla/tesla_dtrace.c#13 edit
.. //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/libtesla/tesla_internal.h#15 edit
.. //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/libtesla/tesla_notification.c#19 edit
.. //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/libtesla/tesla_store.c#9 edit
.. //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/libtesla/tesla_update.c#14 edit
Differences ...
==== //depot/projects/ctsrd/tesla/src/sys/amd64/conf/TESLA_NODEBUG#2 (text+ko) ====
@@ -1,6 +1,7 @@
include TESLA
ident TESLA_NODEBUG
+options TESLA
nooptions INVARIANTS
nooptions INVARIANT_SUPPORT
nooptions WITNESS
==== //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/include/libtesla.h#14 (text+ko) ====
@@ -76,7 +76,7 @@
* a number of times with different names and current states.
*/
struct tesla_class;
-
+struct tesla_lifetime_event;
struct tesla_transitions;
/**
@@ -94,6 +94,11 @@
*/
const int32_t ta_alphabet_size;
+ /**
+ * The symbol number used to signal cleanup.
+ */
+ const int32_t ta_cleanup_symbol;
+
/**
* Transitions that will be taken in response to events.
*
@@ -107,6 +112,54 @@
/** Human-readable descriptions of input symbols (for debugging). */
const char* *ta_symbol_names;
+
+ /** The automaton's lifetime. */
+ const struct tesla_lifetime *ta_lifetime;
+};
+
+
+/**
+ * A short, unique, deterministic representation of a lifetime entry/exit event,
+ * a pair of which defines an automaton's lifetime.
+ */
+struct tesla_lifetime_event {
+ /**
+ * An opaque representation of the automaton's initialisation event.
+ *
+ * This description should be short and deterministic,
+ * i.e., multiple automata that share the same init event should
+ * have exactly the same ta_init description string.
+ *
+ * This can be written by hand if needed (e.g. for testing),
+ * but in practice we generate it from protocol buffers.
+ */
+ const char *tle_repr;
+
+ /** The length of @ref #tle_repr. */
+ const int32_t tle_length;
+
+ /**
+ * A precomputed hash of @ref #tle_repr.
+ *
+ * libtesla doesn't care what hash algorithm is used; in test code or
+ * statically-compiled clients, incrementing integers works well.
+ *
+ * All clients should be consistent, however; the TESLA instrumenter
+ * uses SuperFastHash.
+ */
+ const int32_t tle_hash;
+};
+
+
+/**
+ * The description of a TESLA lifetime.
+ */
+struct tesla_lifetime {
+ struct tesla_lifetime_event tl_begin;
+ struct tesla_lifetime_event tl_end;
+
+ /** A human-readable string for debugging. */
+ const char *tl_repr;
};
@@ -246,7 +299,20 @@
const struct tesla_automaton *automaton,
uint32_t symbol, const struct tesla_key *pattern);
+/**
+ * We have encountered an entry bound for some automata.
+ *
+ * @param context Where the automaton is stored.
+ * @param l Static description of the lifetime (begin, end events).
+ */
+void tesla_sunrise(enum tesla_context context,
+ const struct tesla_lifetime *l);
+
+/** We have encountered an exit bound for some automata. */
+void tesla_sunset(enum tesla_context context,
+ const struct tesla_lifetime*);
+
/** A single instance of an automaton: a name (@ref ti_key) and a state. */
struct tesla_instance {
struct tesla_key ti_key;
@@ -257,6 +323,14 @@
/*
* Event notification:
*/
+/** An initialisation event has occurred; entering an automaton lifetime. */
+typedef void (*tesla_ev_sunrise)(enum tesla_context,
+ const struct tesla_lifetime *);
+
+/** A cleanup event has occurred; exiting an automaton lifetime. */
+typedef void (*tesla_ev_sunset)(enum tesla_context,
+ const struct tesla_lifetime *);
+
/** A new @ref tesla_instance has been created. */
typedef void (*tesla_ev_new_instance)(struct tesla_class *,
struct tesla_instance *);
@@ -292,6 +366,8 @@
/** A vector of event handlers. */
struct tesla_event_handlers {
+ tesla_ev_sunrise teh_sunrise;
+ tesla_ev_sunset teh_sunset;
tesla_ev_new_instance teh_init;
tesla_ev_transition teh_transition;
tesla_ev_clone teh_clone;
==== //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/libtesla/tesla_dtrace.c#13 (text+ko) ====
@@ -38,6 +38,10 @@
SDT_PROVIDER_DEFINE(tesla);
+SDT_PROBE_DEFINE2(tesla, automata, lifetime, sunrise, sunrise,
+ "enum tesla_context context", "struct tesla_lifetime *");
+SDT_PROBE_DEFINE2(tesla, automata, lifetime, sunset, sunset,
+ "enum tesla_context context", "struct tesla_lifetime *");
SDT_PROBE_DEFINE2(tesla, automata, instance, create, create,
"struct tesla_class *", "struct tesla_instance *");
SDT_PROBE_DEFINE3(tesla, automata, event, transition, state-transition,
@@ -60,6 +64,20 @@
"struct tesla_class *", "int32_t", "struct tesla_key *");
static void
+sunrise(enum tesla_context c, const struct tesla_lifetime *tl)
+{
+
+ SDT_PROBE(tesla, automata, lifetime, sunrise, c, tl, 0, 0, 0);
+}
+
+static void
+sunset(enum tesla_context c, const struct tesla_lifetime *tl)
+{
+
+ SDT_PROBE(tesla, automata, lifetime, sunset, c, tl, 0, 0, 0);
+}
+
+static void
new_instance(struct tesla_class *tcp, struct tesla_instance *tip)
{
@@ -144,6 +162,8 @@
}
const struct tesla_event_handlers dtrace_handlers = {
+ .teh_sunrise = sunrise,
+ .teh_sunset = sunset,
.teh_init = new_instance,
.teh_transition = transition,
.teh_clone = clone,
==== //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/libtesla/tesla_internal.h#15 (text+ko) ====
@@ -65,6 +65,7 @@
#include <assert.h>
#include <err.h>
#include <pthread.h>
+#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#endif
@@ -79,7 +80,28 @@
#define assert(cond) KASSERT((cond), ("Assertion failed: '%s'", #cond))
#endif
+
/**
+ * The current runtime state of a TESLA lifetime.
+ */
+struct tesla_lifetime_state {
+ struct tesla_lifetime_event tls_begin;
+ struct tesla_lifetime_event tls_end;
+
+ /** A place to register a few classes that share this lifetime. */
+ struct tesla_class* tls_classes[4];
+
+ /** A place to register more classes that share this lifetime. */
+ struct tesla_class* *tls_dyn_classes;
+
+ /** The number of values @ref tls_dyn_classes can hold. */
+ uint32_t tls_dyn_capacity;
+
+ /** The number of values currently in @ref tls_dyn_classes. */
+ uint32_t tls_dyn_count;
+};
+
+/**
* Call this if things go catastrophically, unrecoverably wrong.
*/
void tesla_die(int32_t errnum, const char *event) __attribute__((noreturn));
@@ -130,8 +152,46 @@
return ((i->ti_state != 0) || (i->ti_key.tk_mask != 0));
}
+static inline bool
+same_lifetime(const struct tesla_lifetime *x, const struct tesla_lifetime *y)
+{
+ assert(x != NULL);
+ assert(y != NULL);
+
+ return (x->tl_begin.tle_length == y->tl_begin.tle_length)
+ && (x->tl_end.tle_length == y->tl_end.tle_length)
+ && (x->tl_begin.tle_hash == y->tl_begin.tle_hash)
+ && (x->tl_end.tle_hash == y->tl_end.tle_hash)
+ && (strncmp(x->tl_begin.tle_repr, y->tl_begin.tle_repr,
+ x->tl_begin.tle_length) == 0)
+ && (strncmp(x->tl_end.tle_repr, y->tl_end.tle_repr,
+ x->tl_end.tle_length) == 0)
+ ;
+}
+
+/**
+ * Compare the static parts of a @ref tesla_lifetime_state with a
+ * @ref tesla_lifetime.
+ */
+static inline bool
+same_static_lifetime(const struct tesla_lifetime *x,
+ const struct tesla_lifetime_state *y)
+{
+ assert(x != NULL);
+ assert(y != NULL);
+ return (x->tl_begin.tle_length == y->tls_begin.tle_length)
+ && (x->tl_end.tle_length == y->tls_end.tle_length)
+ && (x->tl_begin.tle_hash == y->tls_begin.tle_hash)
+ && (x->tl_end.tle_hash == y->tls_end.tle_hash)
+ && (strncmp(x->tl_begin.tle_repr, y->tls_begin.tle_repr,
+ x->tl_begin.tle_length) == 0)
+ && (strncmp(x->tl_end.tle_repr, y->tls_end.tle_repr,
+ x->tl_end.tle_length) == 0)
+ ;
+}
+
/** Clone an existing instance into a new instance. */
int32_t tesla_instance_clone(struct tesla_class *tclass,
const struct tesla_instance *orig, struct tesla_instance **copy);
@@ -262,10 +322,13 @@
#endif
};
+
typedef struct tesla_automaton tesla_automaton;
typedef struct tesla_class tesla_class;
typedef struct tesla_instance tesla_instance;
typedef struct tesla_key tesla_key;
+typedef struct tesla_lifetime_event tesla_lifetime_event;
+typedef struct tesla_lifetime_state tesla_lifetime_state;
typedef struct tesla_store tesla_store;
typedef struct tesla_transition tesla_transition;
typedef struct tesla_transitions tesla_transitions;
@@ -283,6 +346,19 @@
/** Actual slots that classes might be stored in. */
struct tesla_class *ts_classes;
+
+ /**
+ * Information about live/dead automata classes; may be shared among
+ * automata.
+ *
+ * For instance, the lifetime [enter syscall, exit syscall] is shared
+ * by many automata we've written for the FreeBSD kernel. Each
+ * @ref tesla_store should only record these events once.
+ */
+ struct tesla_lifetime_state *ts_lifetimes;
+
+ /** The number of lifetimes that we currently know about. */
+ uint32_t ts_lifetime_count;
};
/**
@@ -333,6 +409,8 @@
extern const struct tesla_event_handlers dtrace_handlers;
#endif
+void ev_sunrise(enum tesla_context, const struct tesla_lifetime *);
+void ev_sunset(enum tesla_context, const struct tesla_lifetime *);
void ev_new_instance(struct tesla_class *, struct tesla_instance *);
void ev_transition(struct tesla_class *, struct tesla_instance *,
const struct tesla_transition *);
==== //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/libtesla/tesla_notification.c#19 (text+ko) ====
@@ -51,7 +51,8 @@
check_event_handler(const struct tesla_event_handlers *tehp)
{
- if (!tehp || !tehp->teh_init || !tehp->teh_transition
+ if (!tehp || !tehp->teh_sunrise || !tehp->teh_sunset
+ || !tehp->teh_init || !tehp->teh_transition
|| !tehp->teh_clone || !tehp->teh_fail_no_instance
|| !tehp->teh_bad_transition || !tehp->teh_err
|| !tehp->teh_accept || !tehp->teh_ignored)
@@ -118,8 +119,23 @@
if (event_handlers->tem_handlers[i]->x) \
event_handlers->tem_handlers[i]->x(__VA_ARGS__)
+void
+ev_sunrise(enum tesla_context c, const struct tesla_lifetime *tl)
+{
+
+ FOREACH_ERROR_HANDLER(teh_sunrise, c, tl);
+}
+
void
+ev_sunset(enum tesla_context c, const struct tesla_lifetime *tl)
+{
+
+ FOREACH_ERROR_HANDLER(teh_sunset, c, tl);
+}
+
+
+void
ev_new_instance(struct tesla_class *tcp, struct tesla_instance *tip)
{
@@ -201,6 +217,22 @@
}
static void
+print_sunrise(enum tesla_context c, const struct tesla_lifetime *tl)
+{
+
+ DEBUG(libtesla.sunrise, "sunrise %s %s\n",
+ (c == TESLA_CONTEXT_GLOBAL) ? "global" : "per-thread", tl->tl_repr);
+}
+
+static void
+print_sunset(enum tesla_context c, const struct tesla_lifetime *tl)
+{
+
+ DEBUG(libtesla.sunset, "sunset %s %s\n",
+ (c == TESLA_CONTEXT_GLOBAL) ? "global" : "per-thread", tl->tl_repr);
+}
+
+static void
print_new_instance(struct tesla_class *tcp, struct tesla_instance *tip)
{
@@ -318,11 +350,13 @@
{
const struct tesla_automaton *a = tcp->tc_automaton;
- DEBUG(libtesla.event, "ignore '%s': %s", a->ta_name,
+ DEBUG(libtesla.event, "ignore '%s': %s\n", a->ta_name,
a->ta_symbol_names[symbol]);
}
static const struct tesla_event_handlers printf_handlers = {
+ .teh_sunrise = print_sunrise,
+ .teh_sunset = print_sunset,
.teh_init = print_new_instance,
.teh_transition = print_transition_taken,
.teh_clone = print_clone,
@@ -334,6 +368,8 @@
};
static const struct tesla_event_handlers printf_on_failure = {
+ .teh_sunrise = 0,
+ .teh_sunset = 0,
.teh_init = 0,
.teh_transition = 0,
.teh_clone = 0,
==== //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/libtesla/tesla_store.c#9 (text+ko) ====
@@ -145,6 +145,18 @@
assert(store->ts_classes[i].tc_context >= 0);
}
+ /*
+ * For now, allocate as many lifetime storage slots as there are
+ * classes. In practice, many automata will share lifetime information.
+ *
+ * TODO(JA): perhaps allocate fewer of these?
+ */
+ const size_t lifetime_size = classes * sizeof(store->ts_lifetimes[0]);
+ store->ts_lifetimes = tesla_malloc(lifetime_size);
+ bzero(store->ts_lifetimes, lifetime_size);
+
+ store->ts_lifetime_count = 0;
+
return (error);
}
@@ -157,6 +169,7 @@
for (uint32_t i = 0; i < store->ts_length; i++)
tesla_class_destroy(store->ts_classes + i);
+ tesla_free(store->ts_lifetimes);
tesla_free(store);
}
==== //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/libtesla/tesla_update.c#14 (text+ko) ====
@@ -39,24 +39,104 @@
#endif
+static void tesla_update_class_state(struct tesla_class *, struct tesla_store *,
+ uint32_t symbol, const struct tesla_key *);
+
+
+void
+tesla_sunrise(enum tesla_context context, const struct tesla_lifetime *l)
+{
+ __unused int ret;
+ assert(l != NULL);
+
+ struct tesla_store *store;
+ ret = tesla_store_get(context, TESLA_MAX_CLASSES,
+ TESLA_MAX_INSTANCES, &store);
+ assert(ret == TESLA_SUCCESS);
+ assert(store->ts_lifetime_count < store->ts_length);
+
+ tesla_lifetime_state *ls = NULL;
+
+ // TODO: lock global store
+
+ const uint32_t lifetimes = store->ts_lifetime_count;
+ for (uint32_t i = 0; i < lifetimes; i++) {
+ if (same_static_lifetime(l, store->ts_lifetimes + i)) {
+ ls = store->ts_lifetimes + i;
+ break;
+ }
+ }
+
+ if (ls == NULL) {
+ ls = store->ts_lifetimes + lifetimes;
+ store->ts_lifetime_count++;
+
+ ls->tls_begin = l->tl_begin;
+ ls->tls_end = l->tl_end;
+ }
+
+ ev_sunrise(context, l);
+}
+
+
+void
+tesla_sunset(enum tesla_context context, const struct tesla_lifetime *l)
+{
+ __unused int ret;
+ assert(l != NULL);
+
+ ev_sunset(context, l);
+
+ struct tesla_store *store;
+ ret = tesla_store_get(context, TESLA_MAX_CLASSES,
+ TESLA_MAX_INSTANCES, &store);
+ assert(ret == TESLA_SUCCESS);
+ assert(store->ts_lifetime_count < store->ts_length);
+
+ tesla_lifetime_state *ls = NULL;
+
+ const uint32_t lifetimes = store->ts_lifetime_count;
+ for (uint32_t i = 0; i < lifetimes; i++) {
+ if (same_static_lifetime(l, store->ts_lifetimes + i)) {
+ ls = store->ts_lifetimes + i;
+ break;
+ }
+ }
+
+ assert(ls != NULL && "tesla_sunset() without corresponding sunrise");
+
+ tesla_key empty_key;
+ empty_key.tk_mask = 0;
+
+ const size_t static_classes =
+ sizeof(ls->tls_classes) / sizeof(ls->tls_classes[0]);
+
+ for (size_t i = 0; i < static_classes; i++) {
+ tesla_class *class = ls->tls_classes[i];
+ if (class == NULL)
+ break;
+
+ tesla_update_class_state(class, store,
+ class->tc_automaton->ta_cleanup_symbol, &empty_key);
+ }
+
+ const size_t dynamic_classes = ls->tls_dyn_count;
+ for (size_t i = 0; i < dynamic_classes; i++) {
+ tesla_class *class = ls->tls_dyn_classes[i];
+ if (class == NULL)
+ break;
+
+ tesla_update_class_state(class, store,
+ class->tc_automaton->ta_cleanup_symbol, &empty_key);
+ }
+}
+
+
void
tesla_update_state(enum tesla_context tesla_context,
const struct tesla_automaton *autom, uint32_t symbol,
const struct tesla_key *pattern)
{
- const struct tesla_transitions *trans =
- autom->ta_transitions + symbol;
-
-#ifndef NDEBUG
- /* We should never see with multiple <<init>> transitions. */
- int init_count = 0;
- for (uint32_t i = 0; i < trans->length; i++)
- if (trans->transitions[i].flags & TESLA_TRANS_INIT)
- init_count++;
-
- assert(init_count < 2);
-#endif
-
struct tesla_store *store;
int ret = tesla_store_get(tesla_context, TESLA_MAX_CLASSES,
TESLA_MAX_INSTANCES, &store);
@@ -66,11 +146,18 @@
ret = tesla_class_get(store, autom, &class);
assert(ret == TESLA_SUCCESS);
- // Did we match any instances?
- bool matched_something = false;
+ tesla_update_class_state(class, store, symbol, pattern);
+
+ tesla_class_put(class);
+}
+
- // When we're done, do we need to clean up the class?
- bool cleanup_required = false;
+static void
+tesla_update_class_state(struct tesla_class *class, struct tesla_store *store,
+ uint32_t symbol, const struct tesla_key *pattern)
+{
+ int err;
+ const struct tesla_automaton *autom = class->tc_automaton;
// Make space for cloning existing instances.
size_t cloned = 0;
@@ -80,8 +167,131 @@
const tesla_transition *transition;
} clones[max_clones];
+ // Has this class been initialised?
+ bool initialised = false;
+ tesla_lifetime_state *lifetime = NULL;
+ const uint32_t lifetimes = store->ts_lifetime_count;
+ for (uint32_t i = 0; i < lifetimes; i++) {
+ if (!same_static_lifetime(autom->ta_lifetime,
+ store->ts_lifetimes + i))
+ continue;
+
+ initialised = true;
+ lifetime = store->ts_lifetimes + i;
+ break;
+ }
+
+ if (!initialised) {
+ ev_ignored(class, symbol, pattern);
+ return;
+
+ } else if (class->tc_limit == class->tc_free) {
+ // Late initialisation: find the init transition and pretend
+ // it has already been taken.
+ struct tesla_instance *inst = NULL;
+
+ for (uint32_t i = 0; i < autom->ta_alphabet_size; i++) {
+ const tesla_transitions *trans =
+ autom->ta_transitions + i;
+
+ for (uint32_t j = 0; i < trans->length; i++) {
+ const tesla_transition *t =
+ trans->transitions + j;
+
+ if (!(t->flags & TESLA_TRANS_INIT))
+ continue;
+
+ static const tesla_key empty = { .tk_mask = 0 };
+
+ err = tesla_instance_new(class, &empty,
+ t->to, &inst);
+
+ if (err != TESLA_SUCCESS) {
+
+ ev_err(autom, symbol, err,
+ "failed to initialise instance");
+ return;
+ }
+
+ break;
+ }
+ }
+
+ if (inst == NULL) {
+ // The automaton does not have an init transition!
+ err = TESLA_ERROR_EINVAL;
+ ev_err(autom, symbol, err,
+ "automaton has no init transition");
+ return;
+ }
+
+ assert(tesla_instance_active(inst));
+ ev_new_instance(class, inst);
+
+ // Register this class for eventual cleanup.
+ tesla_lifetime_state *ls = lifetime;
+ const size_t static_classes =
+ sizeof(ls->tls_classes) / sizeof(ls->tls_classes[0]);
+
+ size_t i;
+ for (i = 0; i < static_classes; i++) {
+ if (ls->tls_classes[i] != NULL)
+ continue;
+
+ ls->tls_classes[i] = class;
+ break;
+ }
+
+ if (i == static_classes) {
+#ifdef _KERNEL
+ /*
+ * TODO(JA): we should also do the dynamic thing,
+ * but we might have to do it by noting
+ * that we don't have enough space and
+ * leaving the allocation for a later time
+ * when we know it's safe.
+ */
+ ev_err(autom, symbol, TESLA_ERROR_ENOMEM,
+ "out of dynamic registration space in lifetime");
+#else
+ static size_t unit_size =
+ sizeof(ls->tls_dyn_classes[0]);
+
+ tesla_class ***dyn_classes = &ls->tls_dyn_classes;
+
+ if (ls->tls_dyn_capacity == 0) {
+ // Need to create a fresh allocation.
+ size_t count = 8;
+ *dyn_classes = calloc(count, unit_size);
+ ls->tls_dyn_capacity = count;
+ } else {
+ size_t count = 2 * ls->tls_dyn_capacity;
+ *dyn_classes = realloc(*dyn_classes,
+ count * unit_size);
+ ls->tls_dyn_capacity = count;
+ }
+
+ assert(ls->tls_dyn_count < ls->tls_dyn_capacity);
+ ls->tls_dyn_classes[ls->tls_dyn_count++] = class;
+#endif
+ }
+ }
+
+
+ // Did we match any instances?
+ bool matched_something = false;
+
+ // When we're done, do we need to clean up the class?
+ bool cleanup_required = false;
+
+
+ // What transitions can we take?
+ const tesla_transitions *trans = autom->ta_transitions + symbol;
+ assert(trans->length > 0);
+ assert(trans->length < 10000);
+
// Iterate over existing instances, figure out what to do with each.
- int err = TESLA_SUCCESS;
+ err = TESLA_SUCCESS;
int expected = class->tc_limit - class->tc_free;
for (uint32_t i = 0; expected > 0 && (i < class->tc_limit); i++) {
assert(class->tc_instances != NULL);
@@ -98,6 +308,7 @@
break;
case IGNORE:
+ // TODO(JA): this should become unreachable
break;
case UPDATE:
@@ -115,7 +326,7 @@
if (cloned >= max_clones) {
err = TESLA_ERROR_ENOMEM;
ev_err(autom, symbol, err, "too many clones");
- goto cleanup;
+ return;
}
struct clone_info *clone = clones + cloned++;
@@ -154,7 +365,7 @@
err = tesla_instance_clone(class, c->old, &clone);
if (err != TESLA_SUCCESS) {
ev_err(autom, symbol, err, "failed to clone instance");
- goto cleanup;
+ return;
}
tesla_key new_name = *pattern;
@@ -162,7 +373,7 @@
err = tesla_key_union(&clone->ti_key, &new_name);
if (err != TESLA_SUCCESS) {
ev_err(autom, symbol, err, "failed to union keys");
- goto cleanup;
+ return;
}
clone->ti_state = c->transition->to;
@@ -173,42 +384,12 @@
ev_accept(class, clone);
}
-
- // Does this transition cause class instance initialisation?
- for (uint32_t i = 0; i < trans->length; i++) {
- const tesla_transition *t = trans->transitions + i;
- if (t->flags & TESLA_TRANS_INIT) {
- struct tesla_instance *inst;
- err = tesla_instance_new(class, pattern, t->to, &inst);
- if (err != TESLA_SUCCESS) {
- ev_err(autom, symbol, err,
- "failed to init instance");
- goto cleanup;
- }
-
- assert(tesla_instance_active(inst));
+ if (!matched_something)
+ ev_no_instance(class, symbol, pattern);
- matched_something = true;
- ev_new_instance(class, inst);
- }
- }
-
- if (!matched_something) {
- // If the class hasn't received any <<init>> events yet,
- // simply ignore the event: it is out of scope.
- if (class->tc_free == class->tc_limit)
- ev_ignored(class, symbol, pattern);
-
- // Otherwise, we ought to have matched something.
- else ev_no_instance(class, symbol, pattern);
- }
-
// Does it cause class cleanup?
if (cleanup_required)
tesla_class_reset(class);
-
-cleanup:
- tesla_class_put(class);
}
enum tesla_action_t
More information about the p4-projects
mailing list