PERFORCE change 229369 for review

Jonathan Anderson jonathan at FreeBSD.org
Tue Jun 4 15:53:26 UTC 2013


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

Change 229369 by jonathan at jonathan-on-joe on 2013/06/04 15:52:24

	Integrate latest libtesla changes into sys/libtesla.

Affected files ...

.. //depot/projects/ctsrd/tesla/src/sys/libtesla/Makefile#4 integrate
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/config.h#1 branch
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/debug.c#6 delete
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/key.c#4 delete
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/libtesla.h#6 integrate
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/state-global.c#3 delete
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/state-perthread.c#9 delete
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/state.c#8 delete
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/store.c#7 delete
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/tesla.h#6 integrate
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/tesla_class.c#1 branch
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/tesla_class_global.c#1 branch
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/tesla_class_perthread.c#1 branch
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/tesla_debug.c#1 branch
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/tesla_dtrace.c#4 integrate
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/tesla_internal.h#11 integrate
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/tesla_key.c#1 branch
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/tesla_notification.c#4 integrate
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/tesla_store.c#1 branch
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/tesla_strnlen.h#1 branch
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/tesla_update.c#1 branch
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/tesla_util.c#1 branch
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/update.c#8 delete
.. //depot/projects/ctsrd/tesla/src/sys/libtesla/util.c#3 delete

Differences ...

==== //depot/projects/ctsrd/tesla/src/sys/libtesla/Makefile#4 (text+ko) ====

@@ -7,8 +7,8 @@
 CFLAGS+=	-I${.CURDIR}
 
 INCS=		tesla.h libtesla.h
-SRCS=		debug.c key.c tesla_dtrace.c tesla_notification.c state.c \
-		state-global.c state-perthread.c store.c update.c util.c
+SRCS=		tesla_class.c tesla_class_global.c tesla_class_perthread.c \
+		tesla_debug.c tesla_dtrace.c tesla_key.c tesla_notification.c \
+		tesla_store.c tesla_update.c tesla_util.c
 
 .include <bsd.lib.mk>
-

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

@@ -34,6 +34,12 @@
 #ifndef _TESLA_STATE
 #define	_TESLA_STATE
 
+/**
+ * Support library for TESLA instrumentation.
+ * @addtogroup libtesla
+ * @{
+ */
+
 #ifdef _KERNEL
 #include <sys/types.h>
 #else
@@ -60,16 +66,18 @@
 	uint32_t	from;
 
 	/** The mask of the state we're moving from. */
-	uint32_t	mask;
+	uint32_t	from_mask;
 
 	/** The state we are moving to. */
 	uint32_t	to;
 
+	/** A mask of the keys that the 'to' state should have set. */
+	uint32_t	to_mask;
+
 	/** Things we may need to do on this transition. */
 	int		flags;
 };
 
-#define	TESLA_TRANS_FORK	0x01	/* Always fork on this transition. */
 #define	TESLA_TRANS_INIT	0x02	/* May need to initialise the class. */
 #define	TESLA_TRANS_CLEANUP	0x04	/* Clean up the class now. */
 
@@ -178,7 +186,7 @@
 /**
  * Check to see if a key matches a pattern.
  *
- * @returns  1 if @ref #k matches @ref pattern, 0 otherwise
+ * @returns  1 if @a k matches @a pattern, 0 otherwise
  */
 int32_t	tesla_key_matches(
 	    const struct tesla_key *pattern, const struct tesla_key *k);
@@ -213,7 +221,7 @@
  *
  * @returns     1 if active, 0 if inactive
  */
-int32_t	tesla_instance_active(struct tesla_instance *i);
+int32_t	tesla_instance_active(const struct tesla_instance *i);
 
 
 /** Clone an existing instance into a new instance. */
@@ -234,4 +242,48 @@
 void	tesla_instance_destroy(struct tesla_class *tsp,
 	    struct tesla_instance *tip);
 
+
+/*
+ * Event notification:
+ */
+/** A new @ref tesla_instance has been created. */
+typedef void	(*tesla_ev_new_instance)(struct tesla_class *,
+	    struct tesla_instance *);
+
+/** A @ref tesla_instance has taken a transition. */
+typedef void	(*tesla_ev_transition)(struct tesla_class *,
+	    struct tesla_instance *, const struct tesla_transition*);
+
+/** An exisiting @ref tesla_instance has been cloned because of an event. */
+typedef void	(*tesla_ev_clone)(struct tesla_class *,
+	    struct tesla_instance *orig, struct tesla_instance *copy,
+	    const struct tesla_transition*);
+
+/** 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 *);
+
+/** 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 *);
+
+/** A @ref tesla_instance has accepted a sequence of events. */
+typedef void	(*tesla_ev_accept)(struct tesla_class *,
+	    struct tesla_instance *);
+
+/** A vector of event handlers. */
+struct tesla_event_handlers {
+	tesla_ev_new_instance	teh_init;
+	tesla_ev_transition	teh_transition;
+	tesla_ev_clone		teh_clone;
+	tesla_ev_no_instance	teh_fail_no_instance;
+	tesla_ev_bad_transition	teh_bad_transition;
+	tesla_ev_accept		teh_accept;
+};
+
+/** Register a set of event handlers. */
+int	tesla_set_event_handlers(struct tesla_event_handlers *);
+
+/** @} */
+
 #endif /* _TESLA_STATE */

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

@@ -28,10 +28,25 @@
  * SUCH DAMAGE.
  */
 
+/**
+ * @mainpage TESLA API documentation
+ *
+ * This is the API documentation for TESLA's programmer interface
+ * (@ref ConsumerAPI), runtime support library (@ref libtesla) and
+ * analysis/instrumentation implementation.
+ */
+
 #ifndef	TESLA_H
 #define	TESLA_H
 
-/** Basic TESLA types (magic for the compiler to munge). */
+/**
+ * API for programmers who want to use TESLA in their code.
+ *
+ * @addtogroup ConsumerAPI
+ * @{
+ */
+
+/** The basic TESLA type is a pointer to a TESLA Basic TESLA types (magic for the compiler to munge). */
 typedef	struct __tesla_event {}		__tesla_event;
 typedef	struct __tesla_locality {}	__tesla_locality;
 
@@ -84,7 +99,27 @@
 /** Function events inside this predicate refer to the caller context. */
 struct __tesla_event* __tesla_caller(__tesla_event*, ...);
 
+/**
+ * Events named in this predicate should only occur exactly as described.
+ *
+ * This is the default behaviour for explicit automata representations.
+ */
+struct __tesla_event* __tesla_strict(__tesla_event*, ...);
 
+/**
+ * Events named in this predicate must occur as described <i>if</i> the
+ * execution trace includes a NOW event; otherwise, any number of non-NOW
+ * events can occur in any order.
+ *
+ * For instance, if the assertion names the VOP_WRITE() event, we don't want
+ * to preclude the use of VOP_WRITE() in code paths that don't include this
+ * assertion's NOW event.
+ *
+ * This is the default behaviour for inline assertions.
+ */
+struct __tesla_event* __tesla_conditional(__tesla_event*, ...);
+
+
 /** Nothing to see here, move along... */
 struct __tesla_event* __tesla_ignore;
 
@@ -108,14 +143,35 @@
  */
 
 struct __tesla_automaton_description;
+struct __tesla_automaton_usage;
 
 /** In an explicit automata description, return this to say "we're done". */
 struct __tesla_automaton_description*	__tesla_automaton_done();
 
+inline struct __tesla_automaton_usage*
+__tesla_struct_uses_automaton(const char *automaton,
+	__tesla_locality *loc, ...)
+{
+	return 0;
+}
+
+
+/**
+ * Declare that a struct's behaviour is described by an automaton.
+ *
+ * @param	subject		name of the struct that uses the automaton
+ * @param	automaton	reference to the automaton description
+ * @param	loc		a TESLA locality (global, per-thread...)
+ * @param	start		event that kicks off the automaton
+ * @param	end		event that winds up the automaton
+ */
+#define	__tesla_struct_usage(subject, automaton, loc, start, end) \
+	struct __tesla_automaton_usage*					\
+	__tesla_struct_automaton_usage_##struct_name##_##automaton(subject) { \
+		return __tesla_struct_uses_automaton(			\
+			#automaton, loc, start, end);	\
+	}
 
-/** Declare an automaton that describes behaviour of this struct. */
-#define	__tesla_struct_automaton(fn_name) \
-	void *__tesla_automaton_struct_uses_##fn_name;
 
 /**
  * Define an automaton to describe a struct's behaviour.
@@ -138,21 +194,25 @@
 #define	__tesla_global		((struct __tesla_locality*) 0)
 #define	__tesla_perthread	((struct __tesla_locality*) 0)
 
-#define __tesla_sequence(...)	1
+#define __tesla_sequence(...)		1
 
-#define	__tesla_struct_automaton(fn_name)
+#define	__tesla_struct_automaton(...)
 #define	__tesla_automaton(name, ...)
 
-#define	__tesla_call(...)	0
-#define	__tesla_return(...)	0
+#define	__tesla_call(...)		0
+#define	__tesla_return(...)		0
+
+#define	__tesla_callee(...)		0
+#define	__tesla_caller(...)		0
 
-#define	__tesla_callee(...)	0
-#define	__tesla_caller(...)	0
+#define	__tesla_optional(...)		0
+#define	__tesla_any(...)		0
 
-#define	__tesla_optional(...)	0
-#define	__tesla_any(...)	0
+#define	__tesla_strict(...)		0
+#define	__tesla_conditional(...)	0
 
 #endif	/* __TESLA_ANALYSER__ */
 
+/** @} */
+
 #endif	/* TESLA_H */
-

==== //depot/projects/ctsrd/tesla/src/sys/libtesla/tesla_dtrace.c#4 (text+ko) ====

@@ -37,72 +37,77 @@
 #include <sys/sdt.h>
 
 SDT_PROVIDER_DEFINE(tesla);
-SDT_PROBE_DEFINE2(tesla, kernel, , state_transition, state-transition,
+
+SDT_PROBE_DEFINE2(tesla, kernel, notify, new_instance, new-instance,
+    "struct tesla_class *", "struct tesla_instance *");
+SDT_PROBE_DEFINE3(tesla, kernel, notify, transition, transition,
+    "struct tesla_class *", "struct tesla_instance *",
+    "struct tesla_transition *");
+SDT_PROBE_DEFINE4(tesla, kernel, notify, clone, clone,
+    "struct tesla_class *", "struct tesla_instance *",
+    "struct tesla_instance *", "struct tesla_transition *");
+SDT_PROBE_DEFINE3(tesla, kernel, notify, no_instance, no-instance-match,
+    "struct tesla_class *", "struct tesla_key *",
+    "struct tesla_transitions *");
+SDT_PROBE_DEFINE3(tesla, kernel, notify, bad_transition, bad-transition,
+    "struct tesla_class *", "struct tesla_instance *",
+    "struct tesla_transitions *");
+SDT_PROBE_DEFINE2(tesla, kernel, notify, accept, accept,
     "struct tesla_class *", "struct tesla_instance *");
-SDT_PROBE_DEFINE2(tesla, kernel, assert, fail, fail, "struct tesla_class *",
-    "struct tesla_instance *");
-SDT_PROBE_DEFINE2(tesla, kernel, assert, pass, pass, "struct tesla_class *",
-    "struct tesla_instance *");
 
-void
-tesla_state_transition_dtrace(struct tesla_class *tcp,
-    struct tesla_instance *tip,
-    __unused const struct tesla_transitions *transp,
-    __unused uint32_t transition_index)
+static void
+new_instance(struct tesla_class *tcp, struct tesla_instance *tip)
 {
 
-	SDT_PROBE(tesla, kernel, , state_transition, tcp, tip, 0, 0, 0);
+	SDT_PROBE(tesla, kernel, assert, new_instance, tcp, tip, 0, 0, 0);
 }
 
-void
-tesla_assert_fail_dtrace(struct tesla_class *tcp, struct tesla_instance *tip,
-    __unused const struct tesla_transitions *transp)
+static void
+transition(struct tesla_class *tcp, struct tesla_instance *tip,
+    const struct tesla_transition *ttp)
 {
 
-	if (tip)
-	    SDT_PROBE(tesla, kernel, assert, fail, tcp, tip, 0, 0, 0);
-
-	/* XXXRW:
-	 * 'tip' could be NULL if we failed to match any automaton instances
-	 * to go with a supplied key; perhaps a separate probe?
-	 */
+	SDT_PROBE(tesla, kernel, notify, transition, tcp, tip, ttp, 0, 0);
 }
 
-void
-tesla_assert_pass_dtrace(struct tesla_class *tcp, struct tesla_instance *tip)
+static void
+clone(struct tesla_class *tcp, struct tesla_instance *origp,
+    struct tesla_instance *copyp, const struct tesla_transition *ttp)
 {
 
-	SDT_PROBE(tesla, kernel, assert, pass, tcp, tip, 0, 0, 0);
+	SDT_PROBE(tesla, kernel, notify, clone, tcp, origp, copyp, ttp, 0);
 }
 
-#else /* !_KERNEL */
-
-void
-tesla_state_transition_dtrace(__unused struct tesla_class *tcp,
-    __unused struct tesla_instance *tip,
-    __unused const struct tesla_transitions *transp,
-    __unused uint32_t transition_index)
+static void
+no_instance(struct tesla_class *tcp, const struct tesla_key *tkp,
+    const struct tesla_transitions *)
 {
 
-	assert(0 && "DTrace not implemented in userspace");
+	SDT_PROBE(tesla, kernel, notify, no_instance, tcp, tkp, ttp, 0, 0);
 }
 
-void
-tesla_assert_fail_dtrace(__unused struct tesla_class *tcp,
-    __unused struct tesla_instance *tip,
-    __unused const struct tesla_transitions *transp)
+static void
+bad_transition(struct tesla_class *tcp, struct tesla_instance *tip,
+    const struct tesla_transitions *ttp)
 {
 
-	assert(0 && "DTrace not implemented in userspace");
+	SDT_PROBE(tesla, kernel, notify, bad_transition, tcp, tip, ttp, 0, 0);
 }
 
-void
-tesla_assert_pass_dtrace(__unused struct tesla_class *tcp,
-    __unused struct tesla_instance *tip)
+static void
+accept(struct tesla_class *tcp, struct tesla_instance *tip)
 {
 
-	assert(0 && "DTrace not implemented in userspace");
+	SDT_PROBE(tesla, kernel, notify, accept, tcp, tip, 0, 0, 0);
 }
 
+struct tesla_event_handlers dtrace_handler = {
+	.teh_init			= new_instance,
+	.teh_transition			= transition,
+	.teh_clone			= clone,
+	.teh_fail_no_instance		= no_instance,
+	.teh_fail_bad_transition	= bad_transition,
+	.teh_accept			= accept
+};
+
 #endif /* _KERNEL */
-

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

@@ -33,6 +33,13 @@
 #ifndef TESLA_INTERNAL_H
 #define	TESLA_INTERNAL_H
 
+/**
+ * @addtogroup libtesla
+ * @{
+ */
+
+#include "config.h"
+
 #ifdef _KERNEL
 #include "opt_kdb.h"
 #include <sys/param.h>
@@ -59,7 +66,7 @@
 #include <libtesla.h>
 #endif
 
-//! Is @ref x a subset of @ref y?
+/** Is @a x a subset of @a y? */
 #define	SUBSET(x,y) ((x & y) == x)
 
 /**
@@ -70,7 +77,7 @@
 /**
  * Clean up a @ref tesla_class.
  */
-void	tesla_class_free(struct tesla_class*);
+void	tesla_class_destroy(struct tesla_class*);
 
 /**
  * Create a new @ref tesla_instance.
@@ -102,7 +109,32 @@
 int32_t	tesla_match(struct tesla_class *tclass, const struct tesla_key *key,
 	    struct tesla_instance **array, uint32_t *size);
 
-/** Copy new entries from @ref source into @ref dest. */
+/** Actions that can be taken by @ref tesla_update_state. */
+enum tesla_action_t {
+	/** The instance's state should be updated. */
+	UPDATE,
+
+	/** The instance should be copied to a new instance. */
+	FORK,
+
+	/** The instance is irrelevant to the given transitions. */
+	IGNORE,
+
+	/** The instance matches, but there are no valid transitions for it. */
+	FAIL
+};
+
+/**
+ * What is the correct action to perform on a given @ref tesla_instance to
+ * satisfy a set of @ref tesla_transitions?
+ *
+ * @param[out]   trigger    the @ref tesla_transition that triggered the action
+ */
+enum tesla_action_t	tesla_action(const struct tesla_instance*,
+	    const struct tesla_key*, const struct tesla_transitions*,
+	    const struct tesla_transition** trigger);
+
+/** Copy new entries from @a source into @a dest. */
 int32_t	tesla_key_union(struct tesla_key *dest, const struct tesla_key *source);
 
 
@@ -134,10 +166,10 @@
 
 #else	/* !_KERNEL */
 
-/** @ref errx() is the userspace equivalent of panic(). */
+/** @a errx() is the userspace equivalent of panic(). */
 #define tesla_panic(...) errx(1, __VA_ARGS__)
 
-/** POSIX @ref assert() doesn't let us provide an error message. */
+/** POSIX @a assert() doesn't let us provide an error message. */
 #define tesla_assert(condition, ...) assert(condition)
 
 #define tesla_malloc(len) calloc(1, len)
@@ -153,44 +185,29 @@
 
 
 /*
- * Instance table definition, used for both global and per-thread scopes.  A
- * more refined data structure might eventually be used here.
- */
-struct tesla_table {
-	uint32_t		tt_length;
-	uint32_t		tt_free;
-	struct tesla_instance	tt_instances[];
-};
-
-/*
  * Assertion state definition is internal to libtesla so we can change it as
  * we need to.
  */
 struct tesla_class {
-	const char	*ts_name;	/* Name of the assertion. */
-	const char	*ts_description;/* Description of the assertion. */
-	uint32_t	 ts_scope;	/* Per-thread or global. */
-	uint32_t	 ts_limit;	/* Simultaneous automata limit. */
-	uint32_t	 ts_action;	/* What to do on failure. */
+	const char	*tc_name;	/* Name of the assertion. */
+	const char	*tc_description;/* Description of the assertion. */
+	uint32_t	 tc_scope;	/* Per-thread or global. */
+	uint32_t	 tc_limit;	/* Simultaneous automata limit. */
+
+	struct tesla_instance	*tc_instances;	/* Instances of this class. */
+	uint32_t		tc_free;	/* Unused instances. */
 
-	/*
-	 * State fields if global.  Table must be last field as it uses a
-	 * zero-length array.
-	 */
 #ifdef _KERNEL
-	struct mtx		ts_lock;	/* Synchronise ts_table. */
+	struct mtx		tc_lock;	/* Synchronise tc_table. */
 #else
-	pthread_mutex_t		 ts_lock;	/* Synchronise ts_table. */
+	pthread_mutex_t		 tc_lock;	/* Synchronise tc_table. */
 #endif
-
-	struct tesla_table	*ts_table;	/* Table of instances. */
 };
 
 typedef struct tesla_class		tesla_class;
 typedef struct tesla_instance		tesla_instance;
 typedef struct tesla_key		tesla_key;
 typedef struct tesla_store		tesla_store;
-typedef struct tesla_table		tesla_table;
 typedef struct tesla_transition		tesla_transition;
 typedef struct tesla_transitions	tesla_transitions;
 
@@ -220,12 +237,6 @@
 int	tesla_class_init(struct tesla_class*, uint32_t context,
 		uint32_t instances);
 
-#if 0
-//! We have failed to find an instance that matches a @ref tesla_key.
-void	tesla_match_fail(struct tesla_class*, const struct tesla_key*,
-		const struct tesla_transitions*);
-#endif
-
 /*
  * XXXRW: temporarily, maximum number of classes and instances are hard-coded
  * constants.  In the future, this should somehow be more dynamic.
@@ -255,7 +266,7 @@
 void	tesla_class_global_release(struct tesla_class*);
 void	tesla_class_global_destroy(struct tesla_class*);
 
-int32_t	tesla_class_perthread_postinit(struct tesla_class*c);
+int32_t	tesla_class_perthread_postinit(struct tesla_class*);
 void	tesla_class_perthread_acquire(struct tesla_class*);
 void	tesla_class_perthread_release(struct tesla_class*);
 void	tesla_class_perthread_destroy(struct tesla_class*);
@@ -263,44 +274,19 @@
 /*
  * Event notification:
  */
-/** A new @ref tesla_instance has been created. */
-void	tesla_notify_new_instance(struct tesla_class *,
-    struct tesla_instance *);
+extern struct tesla_event_handlers	*ev_handlers;
+extern struct tesla_event_handlers	failstop_handlers;
+extern struct tesla_event_handlers	printf_handlers;
 
-/** A @ref tesla_instance has taken an expected transition. */
-void	tesla_notify_transition(struct tesla_class *, struct tesla_instance *,
-    const struct tesla_transitions *, uint32_t index);
-
-/** An exisiting @ref tesla_instance has been cloned because of an event. */
-void	tesla_notify_clone(struct tesla_class *, struct tesla_instance *,
-    const struct tesla_transitions *, uint32_t index);
-
-/** A @ref tesla_instance was unable to take any of a set of transitions. */
-void	tesla_notify_assert_fail(struct tesla_class *, struct tesla_instance *,
-    const struct tesla_transitions *);
-
-/** No @ref tesla_class instance was found to match a @ref tesla_key. */
-void	tesla_notify_match_fail(struct tesla_class *, const struct tesla_key *,
-    const struct tesla_transitions *);
-
-/** A @ref tesla_instance has "passed" (worked through the automaton). */
-void	tesla_notify_pass(struct tesla_class *, struct tesla_instance *);
-
-/*
- * DTrace notifications of various events.
- */
-void	tesla_state_transition_dtrace(struct tesla_class *,
-	    struct tesla_instance *, const struct tesla_transitions *,
-	    uint32_t transition_index);
-void	tesla_assert_fail_dtrace(struct tesla_class *,
-	    struct tesla_instance *, const struct tesla_transitions *);
-void	tesla_assert_pass_dtrace(struct tesla_class *,
-	    struct tesla_instance *);
+#ifdef _KERNEL
+extern struct tesla_event_handlers	dtrace_handlers;
+#endif
 
 /*
  * Debug helpers.
  */
 
+/** Do a @a sprintf() into a buffer, checking bounds appropriately. */
 #define	SAFE_SPRINTF(current, end, ...) do {				\
 	int written = snprintf(current, end - current, __VA_ARGS__);	\
 	if ((written > 0) && (current + written < end))			\
@@ -321,24 +307,24 @@
 
 #ifdef _KERNEL
 #include <sys/systm.h>
-#define DEBUG_PRINT(...) print(__VA_ARGS__)
 #else
 #include <stdio.h>
-#define DEBUG_PRINT(...) print(__VA_ARGS__)
 #endif
-#define VERBOSE_PRINT(...) if (verbose_debug()) DEBUG_PRINT(__VA_ARGS__)
 
 /** Are we in (verbose) debug mode? */
-int32_t	verbose_debug(void);
+int32_t	tesla_debugging(const char*);
+
+/** Emit debugging information with a debug name (e.g., libtesla.event). */
+#define DEBUG(dclass, ...) \
+	if (tesla_debugging(#dclass)) printf(__VA_ARGS__)
 
 #else // NDEBUG
 
 // When not in debug mode, some values might not get checked.
 #define __debug __unused
-#define DEBUG_PRINT(...)
-#define VERBOSE_PRINT(...)
 
-int32_t	verbose_debug(void) { return 0; }
+#define DEBUG(...)
+int32_t	tesla_debugging(const char*) { return 0; }
 
 #endif
 
@@ -346,10 +332,10 @@
  * Assert that a @ref tesla_instance is an instance of a @ref tesla_class.
  *
  * This could be expensive (a linear walk over all @ref tesla_instance in
- * @ref #tclass), so it should only be called from debug code.
+ * @a tclass), so it should only be called from debug code.
  *
  * @param   i          the instance to test
- * @param   tclass     the expected class of @ref #i
+ * @param   tclass     the expected class of @a i
  */
 void	assert_instanceof(struct tesla_instance *i, struct tesla_class *tclass);
 
@@ -357,16 +343,25 @@
 char*	key_string(char *buffer, const char *end, const struct tesla_key *);
 
 /** Print a @ref tesla_key to stderr. */
-void	print_key(const struct tesla_key *key);
+void	print_key(const char *debug_name, const struct tesla_key *key);
 
 /** Print a @ref tesla_class to stderr. */
 void	print_class(const struct tesla_class*);
 
+/** Print a human-readable version of a @ref tesla_transition. */
+void	print_transition(const char *debug, const struct tesla_transition *);
+
+/** Print a human-readable version of a @ref tesla_transition into a buffer. */
+char*	sprint_transition(char *buffer, const char *end,
+    const struct tesla_transition *);
+
 /** Print a human-readable version of @ref tesla_transitions. */
-void	print_transitions(const struct tesla_transitions *);
+void	print_transitions(const char *debug, const struct tesla_transitions *);
 
 /** Print a human-readable version of @ref tesla_transitions into a buffer. */
 char*	sprint_transitions(char *buffer, const char *end,
     const struct tesla_transitions *);
 
+/** @} */
+
 #endif /* TESLA_INTERNAL_H */

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

@@ -34,185 +34,208 @@
 
 #define	ERROR_BUFFER_LENGTH	1024
 
+int
+tesla_set_event_handlers(struct tesla_event_handlers *tehp)
+{
+
+	if (!tehp || !tehp->teh_init || !tehp->teh_transition
+	    || !tehp->teh_clone || !tehp->teh_fail_no_instance
+	    || !tehp->teh_bad_transition
+	    || !tehp->teh_accept)
+		return (TESLA_ERROR_EINVAL);
+
+	ev_handlers = tehp;
+	return (TESLA_SUCCESS);
+}
+
+/*
+ * printf()-based event handlers:
+ */
+static void	print_new_instance(struct tesla_class *,
+	    struct tesla_instance *);
+
+static void	print_transition_taken(struct tesla_class *,
+	    struct tesla_instance *, const struct tesla_transition*);
+
+static void	print_clone(struct tesla_class *,
+	    struct tesla_instance *orig, struct tesla_instance *copy,
+	    const struct tesla_transition*);
+
+static void	print_no_instance(struct tesla_class *,
+	    const struct tesla_key *, const struct tesla_transitions *);
+
+static void	print_bad_transition(struct tesla_class *,
+	    struct tesla_instance *, const struct tesla_transitions *);
+
+static void	print_accept(struct tesla_class *, struct tesla_instance *);
+
+struct tesla_event_handlers printf_handlers = {
+	.teh_init		= print_new_instance,
+	.teh_transition		= print_transition_taken,
+	.teh_clone		= print_clone,
+	.teh_fail_no_instance	= print_no_instance,
+	.teh_bad_transition	= print_bad_transition,
+	.teh_accept		= print_accept
+};
+
+
+/*
+ * Wrappers that panic on failure:
+ */
+static void	panic_no_instance(struct tesla_class *,
+	    const struct tesla_key *, const struct tesla_transitions *);
+
+static void	panic_bad_transition(struct tesla_class *,
+	    struct tesla_instance *, const struct tesla_transitions *);
+
+struct tesla_event_handlers failstop_handlers = {
+	.teh_init		= print_new_instance,
+	.teh_transition		= print_transition_taken,
+	.teh_clone		= print_clone,
+	.teh_fail_no_instance	= panic_no_instance,
+	.teh_bad_transition	= panic_bad_transition,
+	.teh_accept		= print_accept
+};
+
+
+/** Default to print-with-failstop in userspace, DTrace in the kernel. */
+struct tesla_event_handlers	*ev_handlers =
+#ifdef _KERNEL
+	&dtrace_handlers
+#else
+	&failstop_handlers
+#endif
+	;
+
 static void	print_failure_header(const struct tesla_class *);
 
+
 void
-tesla_notify_new_instance(struct tesla_class *tcp,
-    struct tesla_instance *tip)
+print_new_instance(struct tesla_class *tcp, struct tesla_instance *tip)
 {
 
-	switch (tcp->ts_action) {
-	case TESLA_ACTION_DTRACE:
-		/* XXXRW: more fine-grained DTrace probes? */
-		tesla_state_transition_dtrace(tcp, tip, NULL, -1);
-		return;
+	DEBUG(libtesla.instance.new, "new    %td: %tx\n",
+		tip - tcp->tc_instances, tip->ti_state);
+}
 
-	default:
-		/* for the PRINTF action, should this be a non-verbose print? */
-		VERBOSE_PRINT("new    %td: %tx\n",
-		              tip - tcp->ts_table->tt_instances,
-		              tip->ti_state);
+void
+print_transition_taken(struct tesla_class *tcp,
+    struct tesla_instance *tip, const struct tesla_transition *transp)
+{
 
-		/*
-		 * XXXJA: convince self that we can never "pass" an assertion
-		 *        with an event that creates a new instance
-		 */
-
-		break;
-	}
+	DEBUG(libtesla.state.transition, "update %td: %tx->%tx\n",
+		tip - tcp->tc_instances, transp->from, transp->to);
 }
 
 void
-tesla_notify_clone(struct tesla_class *tcp, struct tesla_instance *tip,
-    const struct tesla_transitions *transp, uint32_t index)
+print_clone(struct tesla_class *tcp,
+    struct tesla_instance *old_instance, struct tesla_instance *new_instance,
+    const struct tesla_transition *transp)
 {
 
-	switch (tcp->ts_action) {
-	case TESLA_ACTION_DTRACE:
-		/* XXXRW: more fine-grained DTrace probes? */
-		tesla_state_transition_dtrace(tcp, tip, transp, index);
-		return;
+	DEBUG(libtesla.instance.clone, "clone  %td:%tx -> %td:%tx\n",
+		old_instance - tcp->tc_instances, transp->from,
+		new_instance - tcp->tc_instances, transp->to);
+}
+
+static void
+no_instance_message(char *buffer, const char *end,
+    struct tesla_class *tcp, const struct tesla_key *tkp,
+    const struct tesla_transitions *transp)
+{
 
-	default: {
-		/* for the PRINTF action, should this be a non-verbose print? */
-		assert(index >= 0);
-		assert(index < transp->length);
-		const struct tesla_transition *t = transp->transitions + index;
+	assert(tcp != NULL);
+	assert(tkp != NULL);
 
-		VERBOSE_PRINT("clone  %td:%tx -> %tx\n",
-		              tip - tcp->ts_table->tt_instances,
-		              tip->ti_state, t->to);
+	print_failure_header(tcp);
 
-		if (t->flags & TESLA_TRANS_CLEANUP)
-			tesla_notify_pass(tcp, tip);
+	char *next = buffer;
 
-		break;
-	}
-	}
+	SAFE_SPRINTF(next, end, "No instance matched key '");
+	next = key_string(next, end, tkp);
+	SAFE_SPRINTF(next, end, "' for transition(s) ");
+	next = sprint_transitions(next, end, transp);
+	assert(next > buffer);
 }
 
 void
-tesla_notify_transition(struct tesla_class *tcp,
-    struct tesla_instance *tip, const struct tesla_transitions *transp,
-    uint32_t index)
+print_no_instance(struct tesla_class *tcp, const struct tesla_key *tkp,
+    const struct tesla_transitions *transp)
 {
 
-	switch (tcp->ts_action) {
-	case TESLA_ACTION_DTRACE:
-		tesla_state_transition_dtrace(tcp, tip, transp, index);
-		return;
+	char buffer[ERROR_BUFFER_LENGTH];
+	const char *end = buffer + sizeof(buffer);
 
-	default: {
-		/* for the PRINTF action, should this be a non-verbose print? */
-		assert(index >= 0);
-		assert(index < transp->length);
-		const struct tesla_transition *t = transp->transitions + index;
+	no_instance_message(buffer, end, tcp, tkp, transp);
+	error("%s", buffer);
+}
 
-		VERBOSE_PRINT("update %td: %tx->%tx\n",
-		              tip - tcp->ts_table->tt_instances,
-		              t->from, t->to);
+void
+panic_no_instance(struct tesla_class *tcp, const struct tesla_key *tkp,
+    const struct tesla_transitions *transp)
+{
 
-		if (t->flags & TESLA_TRANS_CLEANUP)
-			tesla_notify_pass(tcp, tip);
+	char buffer[ERROR_BUFFER_LENGTH];
+	const char *end = buffer + sizeof(buffer);
 
-		break;
-	}
-	}
+	no_instance_message(buffer, end, tcp, tkp, transp);
+	tesla_panic("%s", buffer);
 }
 
-void
-tesla_notify_assert_fail(struct tesla_class *tcp, struct tesla_instance *tip,
+static void
+bad_transition_message(char *buffer, const char *end,
+    struct tesla_class *tcp, struct tesla_instance *tip,
     const struct tesla_transitions *transp)
 {
+
 	assert(tcp != NULL);
 	assert(tip != NULL);
 
-	if (tcp->ts_action == TESLA_ACTION_DTRACE) {
-		tesla_assert_fail_dtrace(tcp, tip, transp);
-		return;
-	}
-
 	print_failure_header(tcp);
 
-	char buffer[ERROR_BUFFER_LENGTH];
 	char *next = buffer;
-	const char *end = buffer + sizeof(buffer);
 
 	SAFE_SPRINTF(next, end,
 		"Instance %td is in state %d\n"
 		"but required to take a transition in ",
-		(tip - tcp->ts_table->tt_instances), tip->ti_state);
+		(tip - tcp->tc_instances), tip->ti_state);
 	assert(next > buffer);
 
 	next = sprint_transitions(next, end, transp);
+	assert(next > buffer);
+}
 
-	switch (tcp->ts_action) {
-	case TESLA_ACTION_DTRACE:
-		assert(0 && "handled above");
-		return;
+void
+print_bad_transition(struct tesla_class *tcp, struct tesla_instance *tip,
+    const struct tesla_transitions *transp)
+{
 
-	case TESLA_ACTION_FAILSTOP:
-		tesla_panic("%s", buffer);
-		break;
+	char buffer[ERROR_BUFFER_LENGTH];
+	const char *end = buffer + sizeof(buffer);
 
-	case TESLA_ACTION_PRINTF:
-		error("%s", buffer);
-		break;
-	}
+	bad_transition_message(buffer, end, tcp, tip, transp);
+	error("%s", buffer);
 }
 
 void
-tesla_notify_match_fail(struct tesla_class *tcp, const struct tesla_key *tkp,
+panic_bad_transition(struct tesla_class *tcp, struct tesla_instance *tip,
     const struct tesla_transitions *transp)
 {
-	assert(tcp != NULL);
-	assert(tkp != NULL);
-
-	if (tcp->ts_action == TESLA_ACTION_DTRACE) {
-		tesla_assert_fail_dtrace(tcp, NULL, NULL);
-		return;
-	}
 
-	print_failure_header(tcp);
-
 	char buffer[ERROR_BUFFER_LENGTH];
-	char *next = buffer;
 	const char *end = buffer + sizeof(buffer);
 
-	SAFE_SPRINTF(next, end, "No instance matched key '");
-	next = key_string(next, end, tkp);
-	SAFE_SPRINTF(next, end, "' for transition(s) ");
-	next = sprint_transitions(next, end, transp);
-
-	switch (tcp->ts_action) {
-	case TESLA_ACTION_DTRACE:
-		assert(0 && "handled above");
-		break;
-
-	case TESLA_ACTION_FAILSTOP:
-		tesla_panic("%s", buffer);
-		break;
-
-	case TESLA_ACTION_PRINTF:
-		error("%s", buffer);
-		break;
-	}
+	bad_transition_message(buffer, end, tcp, tip, transp);
+	tesla_panic("%s", buffer);
 }
 

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list