PERFORCE change 422201 for review

Jonathan Anderson jonathan at FreeBSD.org
Thu Aug 22 14:29:55 UTC 2013


http://p4web.freebsd.org/@@422201?ac=10

Change 422201 by jonathan at jonathan-on-joe on 2013/08/22 14:29:03

	Pull in latest TESLA parts (commit db6ceb) from GitHub.
	
	This includes a very large change to how libtesla works; you will need to update TESLA tools to use this!

Affected files ...

.. //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/include/libtesla.h#12 edit
.. //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/include/tesla-macros.h#11 edit
.. //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/include/tesla.h#10 edit
.. //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/libtesla/tesla_class.c#8 edit
.. //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/libtesla/tesla_debug.c#6 edit
.. //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/libtesla/tesla_internal.h#12 edit
.. //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/libtesla/tesla_notification.c#16 edit
.. //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/libtesla/tesla_store.c#8 edit
.. //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/libtesla/tesla_update.c#12 edit

Differences ...

==== //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/include/libtesla.h#12 (text+ko) ====

@@ -31,8 +31,12 @@
  * $Id$
  */
 
-#ifndef _TESLA_STATE
-#define	_TESLA_STATE
+#ifndef	_LIBTESLA_H
+#define	_LIBTESLA_H
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
 
 /**
  * Support library for TESLA instrumentation.
@@ -66,7 +70,54 @@
 const char	*tesla_strerror(int32_t error);
 
 
+
 /**
+ * An internal description of a TESLA automaton, which may be instantiated
+ * a number of times with different names and current states.
+ */
+struct tesla_class;
+
+struct tesla_transitions;
+
+/**
+ * A static description of a TESLA automaton.
+ */
+struct tesla_automaton {
+	/** A unique name, hopefully human-readable. */
+	const char			*ta_name;
+
+	/**
+	 * The number of symbols in the input alphabet (events that can
+	 * be observed).
+	 *
+	 * Input alphabet symbols are integers in the range [0,alphabet_size].
+	 */
+	const int32_t			 ta_alphabet_size;
+
+	/**
+	 * Transitions that will be taken in response to events.
+	 *
+	 * The transitions that can be taken in response to event 42 will
+	 * be found in transitions[42].
+	 */
+	const struct tesla_transitions	*ta_transitions;
+
+	/** Original source description of the automaton. */
+	const char			*ta_description;
+
+	/** Human-readable descriptions of input symbols (for debugging). */
+	const char*			*ta_symbol_names;
+};
+
+
+/**
+ * Register a @ref tesla_automaton (which must survive for the lifetime of
+ * libtesla), receiving a registered @ref tesla_class back.
+ */
+int	tesla_register(const struct tesla_automaton*, struct tesla_class**);
+
+
+/**
  * A storage container for one or more @ref tesla_class objects.
  *
  * There may be one @ref tesla_store for each thread (for storing thread-local
@@ -105,32 +156,21 @@
 
 
 /**
- * A description of a TESLA automaton, which may be instantiated a number of
- * times with different names and current states.
- */
-struct tesla_class;
-
-/**
  * Retrieve (or create) a @ref tesla_class from a @ref tesla_store.
  *
  * Once the caller is done with the @ref tesla_class, @ref tesla_class_put
  * must be called.
  *
  * @param[in]   store    where the @ref tesla_class is expected to be stored
- * @param[in]   id       a client-generated handle (a small integer, used as
- *                       an index into an array)
+ * @param[in]   description   information about the automaton
  * @param[out]  tclass   the retrieved (or generated) @ref tesla_class;
  *                       only set if function returns TESLA_SUCCESS
- * @param[in]   name     a user-readable name (e.g. an automata filename)
- * @param[in]   description   a user-readable description (for error messages)
  *
  * @returns a TESLA error code (TESLA_SUCCESS, TESLA_ERROR_EINVAL, etc.)
  */
 int32_t	tesla_class_get(struct tesla_store *store,
-	                uint32_t id,
-	                struct tesla_class **tclass,
-	                const char *name,
-	                const char *description);
+	                const struct tesla_automaton *description,
+	                struct tesla_class **tclass);
 
 /** Release resources (e.g., locks) associated with a @ref tesla_class. */
 void	tesla_class_put(struct tesla_class*);
@@ -168,9 +208,6 @@
 
 	/** Possible transitions: exactly one must be taken. */
 	struct tesla_transition	*transitions;
-
-	/** A human-readable description for debugging purposes. */
-	const char		*description;
 };
 
 #define	TESLA_KEY_SIZE		4
@@ -196,10 +233,15 @@
 
 /**
  * Update all automata instances that match a given key to a new state.
+ *
+ * @param  context      where the automaton is stored
+ * @param  automaton    static description of the automaton
+ * @param  symbol       identifier of the input symbol (event) to be consumed
+ * @param  pattern      the name extracted from the event
  */
-void	tesla_update_state(enum tesla_context context, uint32_t class_id,
-	const struct tesla_key *key, const char *name, const char *description,
-	const struct tesla_transitions*);
+void	tesla_update_state(enum tesla_context context,
+	const struct tesla_automaton *automaton,
+	uint32_t symbol, const struct tesla_key *pattern);
 
 
 /** A single instance of an automaton: a name (@ref ti_key) and a state. */
@@ -227,14 +269,15 @@
 
 /** No @ref tesla_class instance was found to match a @ref tesla_key. */
 typedef void	(*tesla_ev_no_instance)(struct tesla_class *,
-	    const struct tesla_key *, const struct tesla_transitions *);
+	    int32_t symbol, const struct tesla_key *);
 
 /** A @ref tesla_instance is not in the right state to take a transition. */
 typedef void	(*tesla_ev_bad_transition)(struct tesla_class *,
-	    struct tesla_instance *, const struct tesla_transitions *);
+	    struct tesla_instance *, int32_t symbol);
 
 /** Generic error handler. */
-typedef void	(*tesla_ev_error)(struct tesla_class *, int32_t, const char *);
+typedef void	(*tesla_ev_error)(const struct tesla_automaton *,
+	    int32_t symbol, int32_t errno, const char *message);
 
 /** A @ref tesla_instance has accepted a sequence of events. */
 typedef void	(*tesla_ev_accept)(struct tesla_class *,
@@ -242,7 +285,7 @@
 
 /** An event is being ignored. */
 typedef void	(*tesla_ev_ignored)(const struct tesla_class *,
-	    const struct tesla_key *, const struct tesla_transitions *);
+	    int32_t symbol, const struct tesla_key *);
 
 /** A vector of event handlers. */
 struct tesla_event_handlers {
@@ -288,4 +331,6 @@
 
 /** @} */
 
+__END_DECLS
+
 #endif /* _TESLA_STATE */

==== //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/include/tesla-macros.h#11 (text+ko) ====

@@ -32,6 +32,10 @@
 #ifndef	TESLA_MACROS_H
 #define	TESLA_MACROS_H
 
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
 /**
  * @addtogroup ConsumerAPI
  * @{
@@ -46,8 +50,8 @@
 /** An assertion made within the execution of a particular function. */
 #define	TESLA_WITHIN(function, expression)				\
 	TESLA_PERTHREAD(						\
-		callee(called(function)),				\
-		callee(returned(function)),				\
+		callee(call(function)),					\
+		callee(returnfrom(function)),				\
 		expression						\
 	)
 
@@ -70,8 +74,8 @@
 /** A strictly-ordered sequence of events. */
 #define	TSEQUENCE(...)		__tesla_sequence(TIGNORE, __VA_ARGS__)
 
-#define	called(...)		__tesla_call(((void)__VA_ARGS__, TIGNORE))
-#define	returned(...)		__tesla_return(__VA_ARGS__)
+#define	call(...)		__tesla_call(((void) __VA_ARGS__, TIGNORE))
+#define	returnfrom(...)		__tesla_return(((void) (__VA_ARGS__), TIGNORE))
 
 #define	callee(...)		__tesla_callee(TIGNORE, __VA_ARGS__)
 #define	caller(...)		__tesla_caller(TIGNORE, __VA_ARGS__)
@@ -104,4 +108,6 @@
 
 /** @} */
 
+__END_DECLS
+
 #endif	/* !TESLA_MACROS_H */

==== //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/include/tesla.h#10 (text+ko) ====

@@ -39,6 +39,10 @@
 #ifndef	TESLA_H
 #define	TESLA_H
 
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
 /**
  * API for programmers who want to use TESLA in their code.
  *
@@ -166,6 +170,10 @@
 /** In an explicit automata description, return this to say "we're done". */
 struct __tesla_automaton_description*	__tesla_automaton_done();
 
+#ifndef __unused
+#define __unused
+#endif
+
 inline struct __tesla_automaton_usage*
 __tesla_struct_uses_automaton(__unused const char *automaton,
 	__unused __tesla_locality *loc, ...)
@@ -234,4 +242,6 @@
 
 /** @} */
 
+__END_DECLS
+
 #endif	/* TESLA_H */

==== //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/libtesla/tesla_class.c#8 (text+ko) ====

@@ -151,7 +151,7 @@
 		return (TESLA_SUCCESS);
 	}
 
-	tesla_assert(*out != NULL, ("no free instances but tc_free was > 0"));
+	tesla_assert(0 && ("no free instances but tc_free was > 0"));
 	return (TESLA_ERROR_ENOMEM);
 }
 
@@ -189,7 +189,8 @@
 tesla_class_reset(struct tesla_class *c)
 {
 
-	DEBUG(libtesla.class.reset, "tesla_class_reset %s\n", c->tc_name);
+	DEBUG(libtesla.class.reset, "tesla_class_reset %s\n",
+	      c->tc_automaton->ta_name);
 
 	bzero(c->tc_instances, sizeof(c->tc_instances[0]) * c->tc_limit);
 	c->tc_free = c->tc_limit;

==== //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/libtesla/tesla_debug.c#6 (text+ko) ====

@@ -217,7 +217,7 @@
 
 	print("----\n");
 	print("struct tesla_class @ 0x%tx {\n", (intptr_t) c);
-	print("  name:         '%s',\n", c->tc_name);
+	print("  name:         '%s',\n", c->tc_automaton->ta_name);
 	print("  description:  '[...]',\n");   // TL;DR
 	print("  scope:        ");
 	switch (c->tc_context) {

==== //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/libtesla/tesla_internal.h#12 (text+ko) ====

@@ -33,6 +33,10 @@
 #ifndef TESLA_INTERNAL_H
 #define	TESLA_INTERNAL_H
 
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
 /**
  * @addtogroup libtesla
  * @{
@@ -181,6 +185,17 @@
 	    const struct tesla_key*, const struct tesla_transitions*,
 	    const struct tesla_transition** trigger);
 
+static __inline uint32_t
+fnv_hash32(uint32_t x)
+{
+	return x * ((uint32_t) 0x01000193UL);
+}
+
+static __inline uint64_t
+fnv_hash64(uint32_t x)
+{
+	return x * ((uint64_t) 0x100000001b3ULL);
+}
 
 #ifndef __unused
 #if __has_attribute(unused)
@@ -230,13 +245,15 @@
  * we need to.
  */
 struct tesla_class {
-	const char		*tc_name;	/* Name of the assertion. */
-	const char		*tc_description;/* Automaton representation. */
+	/**
+	 * Static automaton description.
+	 */
+	const struct tesla_automaton *tc_automaton;
 	enum tesla_context	 tc_context;	/* Global, thread... */
+
 	uint32_t		 tc_limit;	/* Maximum instances. */
-
+	uint32_t		 tc_free;	/* Unused instances. */
 	struct tesla_instance	*tc_instances;	/* Instances of this class. */
-	uint32_t		tc_free;	/* Unused instances. */
 
 #ifdef _KERNEL
 	struct mtx		tc_lock;	/* Synchronise tc_table. */
@@ -260,8 +277,11 @@
  * or in a thread-local context.
  */
 struct tesla_store {
-	uint32_t		length;
-	struct tesla_class	*classes;
+	/** Number of slots to hold TESLA classes. */
+	uint32_t		 ts_length;
+
+	/** Actual slots that classes might be stored in. */
+	struct tesla_class	*ts_classes;
 };
 
 /**
@@ -314,17 +334,18 @@
 
 void	ev_new_instance(struct tesla_class *, struct tesla_instance *);
 void	ev_transition(struct tesla_class *, struct tesla_instance *,
-	    const struct tesla_transition*);
+	    const struct tesla_transition *);
 void	ev_clone(struct tesla_class *, struct tesla_instance *orig,
 	    struct tesla_instance *copy, const struct tesla_transition *);
-void	ev_no_instance(struct tesla_class *, const struct tesla_key *,
-	    const struct tesla_transitions *);
+void	ev_no_instance(struct tesla_class *, int32_t symbol,
+	    const struct tesla_key *);
 void	ev_bad_transition(struct tesla_class *, struct tesla_instance *,
-	    const struct tesla_transitions *);
-void	ev_err(struct tesla_class *tcp, int errno, const char *message);
+	    int32_t symbol);
+void	ev_err(const struct tesla_automaton *, int symbol, int errno,
+	    const char *);
 void	ev_accept(struct tesla_class *, struct tesla_instance *);
-void	ev_ignored(const struct tesla_class *, const struct tesla_key *,
-	    const struct tesla_transitions *);
+void	ev_ignored(const struct tesla_class *, int32_t symbol,
+	    const struct tesla_key *);
 
 /*
  * Debug helpers.
@@ -414,5 +435,6 @@
 
 /** @} */
 
+__END_DECLS
 
 #endif /* TESLA_INTERNAL_H */

==== //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/libtesla/tesla_notification.c#16 (text+ko) ====

@@ -143,26 +143,27 @@
 }
 
 void
-ev_no_instance(struct tesla_class *tcp, const struct tesla_key *tkp,
-	const struct tesla_transitions *ttp)
+ev_no_instance(struct tesla_class *tcp, int32_t symbol,
+	const struct tesla_key *tkp)
 {
 
-	FOREACH_ERROR_HANDLER(teh_fail_no_instance, tcp, tkp, ttp);
+	FOREACH_ERROR_HANDLER(teh_fail_no_instance, tcp, symbol, tkp);
 }
 
 void
 ev_bad_transition(struct tesla_class *tcp, struct tesla_instance *tip,
-	const struct tesla_transitions *ttp)
+	int32_t symbol)
 {
 
-	FOREACH_ERROR_HANDLER(teh_bad_transition, tcp, tip, ttp);
+	FOREACH_ERROR_HANDLER(teh_bad_transition, tcp, tip, symbol);
 }
 
 void
-ev_err(struct tesla_class *tcp, int errno, const char *message)
+ev_err(const struct tesla_automaton *a, int symbol, int errno,
+	const char *message)
 {
 
-	FOREACH_ERROR_HANDLER(teh_err, tcp, errno, message);
+	FOREACH_ERROR_HANDLER(teh_err, a, symbol, errno, message);
 }
 
 void
@@ -173,11 +174,11 @@
 }
 
 void
-ev_ignored(const struct tesla_class *tcp, const struct tesla_key *tkp,
-	const struct tesla_transitions *ttp)
+ev_ignored(const struct tesla_class *tcp, int32_t symbol,
+	const struct tesla_key *tkp)
 {
 
-	FOREACH_ERROR_HANDLER(teh_ignored, tcp, tkp, ttp);
+	FOREACH_ERROR_HANDLER(teh_ignored, tcp, symbol, tkp);
 }
 
 
@@ -193,7 +194,9 @@
 	kdb_backtrace();
 #endif
 
-	error("In automaton '%s':\n%s\n", tcp->tc_name, tcp->tc_description);
+	error("In automaton '%s':\n%s\n",
+	      tcp->tc_automaton->ta_name,
+	      tcp->tc_automaton->ta_description);
 }
 
 static void
@@ -225,13 +228,16 @@
 }
 
 static void
-print_no_instance(struct tesla_class *tcp, const struct tesla_key *tkp,
-    const struct tesla_transitions *transp)
+print_no_instance(struct tesla_class *tcp, int32_t symbol,
+    const struct tesla_key *tkp)
 {
 
 	assert(tcp != NULL);
 	assert(tkp != NULL);
 
+	const tesla_transitions *transp =
+		tcp->tc_automaton->ta_transitions + symbol;
+
 	print_failure_header(tcp);
 
 	char buffer[ERROR_BUFFER_LENGTH];
@@ -249,12 +255,15 @@
 
 static void
 print_bad_transition(struct tesla_class *tcp, struct tesla_instance *tip,
-    const struct tesla_transitions *transp)
+    int32_t symbol)
 {
 
 	assert(tcp != NULL);
 	assert(tip != NULL);
 
+	const tesla_transitions *transp
+		= tcp->tc_automaton->ta_transitions + symbol;
+
 	print_failure_header(tcp);
 
 	char buffer[ERROR_BUFFER_LENGTH];
@@ -274,11 +283,13 @@
 }
 
 static void
-print_error(struct tesla_class *tcp, int errno, const char *message)
+print_error(const struct tesla_automaton *a, int symbol, int errno,
+	const char *message)
 {
 
-	DEBUG(libtesla.event, "%s in '%s': %s\n",
-	      tesla_strerror(errno), tcp->tc_name, message);
+	DEBUG(libtesla.event, "%s in '%s' %s: %s\n",
+		message, a->ta_name, a->ta_symbol_names[symbol],
+		tesla_strerror(errno));
 }
 
 static void
@@ -286,23 +297,18 @@
 {
 
 	DEBUG(libtesla.instance.success,
-		"pass '%s': %td\n", tcp->tc_name,
+		"pass '%s': %td\n", tcp->tc_automaton->ta_name,
 		tip - tcp->tc_instances);
 }
 
 static void
-print_ignored(const struct tesla_class *tcp, const struct tesla_key *tkp,
-    const struct tesla_transitions *transp)
+print_ignored(const struct tesla_class *tcp, int32_t symbol,
+    __unused const struct tesla_key *tkp)
 {
-	char buffer[ERROR_BUFFER_LENGTH];
-	char *next = buffer;
-	const char *end = buffer + sizeof(buffer);
+	const struct tesla_automaton *a = tcp->tc_automaton;
 
-	next = key_string(next, end, tkp);
-	SAFE_SPRINTF(next, end, " : ");
-	sprint_transitions(next, end, transp);
-
-	DEBUG(libtesla.event, "ignore '%s':%s", tcp->tc_name, buffer);
+	DEBUG(libtesla.event, "ignore '%s': %s", a->ta_name,
+		a->ta_symbol_names[symbol]);
 }
 
 static const struct tesla_event_handlers printf_handlers = {
@@ -331,29 +337,33 @@
  * Wrappers that panic on failure:
  */
 static void
-panic_no_instance(struct tesla_class *tcp,
-	__unused const struct tesla_key *tkp,
-	__unused const struct tesla_transitions *ttp)
+panic_no_instance(struct tesla_class *tcp, int32_t symbol,
+	__unused const struct tesla_key *tkp)
 {
+	const char *event_name = tcp->tc_automaton->ta_symbol_names[symbol];
 
-	tesla_panic("TESLA: failure in '%s': no such instance", tcp->tc_name);
+	tesla_panic("TESLA: failure in '%s' %s: no such instance",
+	            tcp->tc_automaton->ta_name, event_name);
 }
 
 static void
 panic_bad_transition(struct tesla_class *tcp,
-	__unused struct tesla_instance *tip,
-	__unused const struct tesla_transitions *ttp)
+	__unused struct tesla_instance *tip, int32_t symbol)
 {
+	const char *event_name = tcp->tc_automaton->ta_symbol_names[symbol];
 
-	tesla_panic("TESLA: failure in '%s': bad transition", tcp->tc_name);
+	tesla_panic("TESLA: failure in '%s' %s: bad transition",
+	            tcp->tc_automaton->ta_name, event_name);
 }
 
 static void
-panic_errno(struct tesla_class *tcp, int errno, const char *message)
+panic_error(const struct tesla_automaton *a, int symbol, int errno,
+	const char *message)
 {
 
-	tesla_panic("TESLA: %s in '%s': %s",
-	            tesla_strerror(errno), tcp->tc_name, message);
+	tesla_panic("TESLA: %s in '%s' %s: %s", message,
+		a->ta_name, a->ta_symbol_names[symbol],
+		tesla_strerror(errno));
 }
 
 static const struct tesla_event_handlers failstop_handlers = {
@@ -362,7 +372,7 @@
 	.teh_clone		= 0,
 	.teh_fail_no_instance	= panic_no_instance,
 	.teh_bad_transition	= panic_bad_transition,
-	.teh_err		= panic_errno,
+	.teh_err		= panic_error,
 	.teh_accept		= 0,
 	.teh_ignored		= 0,
 };

==== //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/libtesla/tesla_store.c#8 (text+ko) ====

@@ -43,7 +43,7 @@
 void		tesla_pthread_destructor(void*);
 #endif
 
-static struct tesla_store global_store = { .length = 0 };
+static struct tesla_store global_store = { .ts_length = 0 };
 
 static void	tesla_class_acquire(tesla_class*);
 
@@ -107,13 +107,13 @@
 		return (TESLA_ERROR_EINVAL);
 	}
 
-	if (store->length == 0) {
+	if (store->ts_length == 0) {
 		int32_t error =
 			tesla_store_init(store, context, classes, instances);
 
 		if (error != TESLA_SUCCESS) return (error);
 
-		assert(store->classes != NULL);
+		assert(store->ts_classes != NULL);
 	}
 
 	*storep = store;
@@ -128,19 +128,21 @@
 	assert(classes > 0);
 	assert(instances > 0);
 
-	store->length = classes;
-	store->classes = tesla_malloc(classes * sizeof(tesla_class));
-	if (store->classes == NULL)
+	store->ts_length = classes;
+	store->ts_classes = tesla_malloc(classes * sizeof(tesla_class));
+	if (store->ts_classes == NULL)
 		return (TESLA_ERROR_ENOMEM);
 
 	int error = TESLA_SUCCESS;
 	for (uint32_t i = 0; i < classes; i++) {
-		error = tesla_class_init(store->classes + i, context, instances);
+		error = tesla_class_init(store->ts_classes + i,
+		                         context, instances);
+
 		assert(error == TESLA_SUCCESS);
 		if (error != TESLA_SUCCESS)
 			break;
 
-		assert(store->classes[i].tc_context >= 0);
+		assert(store->ts_classes[i].tc_context >= 0);
 	}
 
 	return (error);
@@ -152,8 +154,8 @@
 {
 	DEBUG(libtesla.store.free, "tesla_store_free %tx\n", store);
 
-	for (uint32_t i = 0; i < store->length; i++)
-		tesla_class_destroy(store->classes + i);
+	for (uint32_t i = 0; i < store->ts_length; i++)
+		tesla_class_destroy(store->ts_classes + i);
 
 	tesla_free(store);
 }
@@ -164,30 +166,54 @@
 {
 	DEBUG(libtesla.store.reset, "tesla_store_reset %tx\n", store);
 
-	for (uint32_t i = 0; i < store->length; i++)
-		tesla_class_reset(store->classes + i);
+	for (uint32_t i = 0; i < store->ts_length; i++)
+		tesla_class_reset(store->ts_classes + i);
 }
 
 
 int32_t
-tesla_class_get(tesla_store *store, uint32_t id, tesla_class **tclassp,
-                const char *name, const char *description)
+tesla_class_get(struct tesla_store *store,
+                const struct tesla_automaton *description,
+                struct tesla_class **tclassp)
 {
 	assert(store != NULL);
+	assert(description != NULL);
 	assert(tclassp != NULL);
 
-	if (id >= store->length)
-		return (TESLA_ERROR_EINVAL);
+	uint32_t desc_hash = fnv_hash32((uint32_t) description);
+	const uint32_t len = store->ts_length;
+
+	// Find the class: start at the bucket indicated by the hash but
+	// walk around the array if there is a collision.
+	tesla_class *tclass = NULL;
+	for (uint32_t i = 0; i < len; i++) {
+		tesla_class *t = store->ts_classes + ((desc_hash + i) % len);
+		assert(t != NULL);
+
+		// If the bucket is empty, the class doesn't exist in the
+		// hash table; take ownership of this bucket.
+		if (t->tc_automaton == NULL) {
+			t->tc_automaton = description;
+			tclass = t;
+			break;
+		}
+
+		// There is something there; is it the class we're looking for?
+		if (t->tc_automaton == description) {
+			tclass = t;
+			break;
+		}
+
+		// Otherwise, there is a collision... keep walking around
+		// the hash table, looking for the desired class.
+	}
+
+	if (tclass == NULL)
+		return (TESLA_ERROR_ENOENT);
 
-	tesla_class *tclass = &store->classes[id];
-	assert(tclass != NULL);
 	assert(tclass->tc_instances != NULL);
 	assert(tclass->tc_context >= 0);
 
-	if (tclass->tc_name == NULL) tclass->tc_name = name;
-	if (tclass->tc_description == NULL)
-		tclass->tc_description = description;
-
 	tesla_class_acquire(tclass);
 
 	*tclassp = tclass;

==== //depot/projects/ctsrd/tesla/src/sys/contrib/tesla/libtesla/tesla_update.c#12 (text+ko) ====

@@ -42,11 +42,12 @@
 #define PRINT(...) DEBUG(libtesla.state.update, __VA_ARGS__)
 
 void
-tesla_update_state(enum tesla_context tesla_context, uint32_t class_id,
-	const struct tesla_key *pattern,
-	const char *name, const char *description,
-	const struct tesla_transitions *trans)
+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;
 
 	if (tesla_debugging(DEBUG_NAME)) {
 		/* We should never see with multiple <<init>> transitions. */
@@ -63,7 +64,7 @@
 	            (tesla_context == TESLA_CONTEXT_GLOBAL
 		     ? "global"
 		     : "per-thread"));
-	PRINT("  class:        %d ('%s')\n", class_id, name);
+	PRINT("  class:        '%s'\n", autom->ta_name);
 
 	PRINT("  transitions:  ");
 	print_transitions(DEBUG_NAME, trans);
@@ -80,7 +81,7 @@
 	PRINT("store: 0x%tx\n", (intptr_t) store);
 
 	struct tesla_class *class;
-	ret = tesla_class_get(store, class_id, &class, name, description);
+	ret = tesla_class_get(store, autom, &class);
 	assert(ret == TESLA_SUCCESS);
 
 	print_class(class);
@@ -113,7 +114,7 @@
 
 		switch (action) {
 		case FAIL:
-			ev_bad_transition(class, inst, trans);
+			ev_bad_transition(class, inst, symbol);
 			break;
 
 		case IGNORE:
@@ -133,7 +134,7 @@
 		case FORK: {
 			if (cloned >= max_clones) {
 				err = TESLA_ERROR_ENOMEM;
-				ev_err(class, err, "too many clones");
+				ev_err(autom, symbol, err, "too many clones");
 				goto cleanup;
 			}
 
@@ -172,7 +173,7 @@
 		struct tesla_instance *clone;
 		err = tesla_instance_clone(class, c->old, &clone);
 		if (err != TESLA_SUCCESS) {
-			ev_err(class, err, "failed to clone instance");
+			ev_err(autom, symbol, err, "failed to clone instance");
 			goto cleanup;
 		}
 
@@ -180,7 +181,7 @@
 		new_name.tk_mask &= c->transition->to_mask;
 		err = tesla_key_union(&clone->ti_key, &new_name);
 		if (err != TESLA_SUCCESS) {
-			ev_err(class, err, "failed to union keys");
+			ev_err(autom, symbol, err, "failed to union keys");
 			goto cleanup;
 		}
 
@@ -200,7 +201,8 @@
 			struct tesla_instance *inst;
 			err = tesla_instance_new(class, pattern, t->to, &inst);
 			if (err != TESLA_SUCCESS) {
-				ev_err(class, err, "failed to create instance");
+				ev_err(autom, symbol, err,
+					"failed to init instance");
 				goto cleanup;
 			}
 
@@ -215,10 +217,10 @@
 		// 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, pattern, trans);
+			ev_ignored(class, symbol, pattern);
 
 		// Otherwise, we ought to have matched something.
-		else ev_no_instance(class, pattern, trans);
+		else ev_no_instance(class, symbol, pattern);
 	}
 
 	// Does it cause class cleanup?


More information about the p4-projects mailing list