PERFORCE change 229368 for review
Jonathan Anderson
jonathan at FreeBSD.org
Tue Jun 4 15:48:20 UTC 2013
http://p4web.freebsd.org/@@229368?ac=10
Change 229368 by jonathan at jonathan-on-joe on 2013/06/04 15:47:30
Incorporate latest libtesla parts into /lib/libtesla.
Affected files ...
.. //depot/projects/ctsrd/tesla/src/lib/libtesla/libtesla.h#6 edit
.. //depot/projects/ctsrd/tesla/src/lib/libtesla/tesla.h#6 edit
.. //depot/projects/ctsrd/tesla/src/lib/libtesla/tesla_class.c#2 edit
.. //depot/projects/ctsrd/tesla/src/lib/libtesla/tesla_debug.c#2 edit
.. //depot/projects/ctsrd/tesla/src/lib/libtesla/tesla_dtrace.c#3 edit
.. //depot/projects/ctsrd/tesla/src/lib/libtesla/tesla_internal.h#7 edit
.. //depot/projects/ctsrd/tesla/src/lib/libtesla/tesla_notification.c#5 edit
.. //depot/projects/ctsrd/tesla/src/lib/libtesla/tesla_update.c#2 edit
Differences ...
==== //depot/projects/ctsrd/tesla/src/lib/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
@@ -180,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);
@@ -236,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/lib/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;
@@ -144,7 +159,7 @@
/**
* Declare that a struct's behaviour is described by an automaton.
*
- * @param struct_name name of the struct that uses the 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
@@ -198,5 +213,6 @@
#endif /* __TESLA_ANALYSER__ */
+/** @} */
+
#endif /* TESLA_H */
-
==== //depot/projects/ctsrd/tesla/src/lib/libtesla/tesla_class.c#2 (text+ko) ====
@@ -53,12 +53,6 @@
tclass->tc_limit = instances;
-#ifdef _KERNEL
- tclass->tc_action = TESLA_ACTION_PRINTF;
-#else
- tclass->tc_action = TESLA_ACTION_FAILSTOP;
-#endif
-
tclass->tc_scope = context;
tclass->tc_limit = instances;
tclass->tc_free = instances;
==== //depot/projects/ctsrd/tesla/src/lib/libtesla/tesla_debug.c#2 (text+ko) ====
@@ -1,4 +1,4 @@
-/** @file debug.c Debugging helpers for TESLA state. */
+/** @file tesla_debug.c Debugging helpers for TESLA state. */
/*-
* Copyright (c) 2012-2013 Jonathan Anderson
* All rights reserved.
@@ -194,14 +194,6 @@
default: print("UNKNOWN (0x%x)\n", c->tc_scope);
}
print(" limit: %d\n", c->tc_limit);
- print(" fail action: ");
- switch (c->tc_action) {
- case TESLA_ACTION_FAILSTOP: print("fail-stop\n"); break;
- case TESLA_ACTION_DTRACE: print("DTrace probe\n"); break;
- case TESLA_ACTION_PRINTF: print("printf()\n"); break;
- default: print("UNKNOWN (0x%x)\n", c->tc_action);
- }
-
print(" %d/%d instances\n", c->tc_limit - c->tc_free, c->tc_limit);
for (uint32_t i = 0; i < c->tc_limit; i++) {
const struct tesla_instance *inst = c->tc_instances + i;
==== //depot/projects/ctsrd/tesla/src/lib/libtesla/tesla_dtrace.c#3 (text+ko) ====
@@ -37,70 +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_transition *transp)
+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_transition *transp)
+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/lib/libtesla/tesla_internal.h#7 (text+ko) ====
@@ -33,6 +33,11 @@
#ifndef TESLA_INTERNAL_H
#define TESLA_INTERNAL_H
+/**
+ * @addtogroup libtesla
+ * @{
+ */
+
#include "config.h"
#ifdef _KERNEL
@@ -61,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)
/**
@@ -129,7 +134,7 @@
const struct tesla_key*, const struct tesla_transitions*,
const struct tesla_transition** trigger);
-/** Copy new entries from @ref source into @ref dest. */
+/** Copy new entries from @a source into @a dest. */
int32_t tesla_key_union(struct tesla_key *dest, const struct tesla_key *source);
@@ -161,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)
@@ -188,7 +193,6 @@
const char *tc_description;/* Description of the assertion. */
uint32_t tc_scope; /* Per-thread or global. */
uint32_t tc_limit; /* Simultaneous automata limit. */
- uint32_t tc_action; /* What to do on failure. */
struct tesla_instance *tc_instances; /* Instances of this class. */
uint32_t tc_free; /* Unused instances. */
@@ -233,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.
@@ -268,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*);
@@ -276,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_transition*);
+#ifdef _KERNEL
+extern struct tesla_event_handlers dtrace_handlers;
+#endif
-/** An exisiting @ref tesla_instance has been cloned because of an event. */
-void tesla_notify_clone(struct tesla_class *,
- struct tesla_instance *old_instance, struct tesla_instance *new_instance,
- const struct tesla_transition*);
-
-/** 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_transition *);
-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 *);
-
/*
* 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)) \
@@ -341,6 +314,7 @@
/** Are we in (verbose) debug mode? */
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__)
@@ -358,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);
@@ -388,4 +362,6 @@
char* sprint_transitions(char *buffer, const char *end,
const struct tesla_transitions *);
+/** @} */
+
#endif /* TESLA_INTERNAL_H */
==== //depot/projects/ctsrd/tesla/src/lib/libtesla/tesla_notification.c#5 (text+ko) ====
@@ -34,97 +34,166 @@
#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->tc_action) {
- case TESLA_ACTION_DTRACE:
- /* XXXRW: more fine-grained DTrace probes? */
- tesla_state_transition_dtrace(tcp, tip, NULL);
- 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? */
- DEBUG(libtesla.instance.new, "new %td: %tx\n",
- tip - tcp->tc_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,
+print_clone(struct tesla_class *tcp,
struct tesla_instance *old_instance, struct tesla_instance *new_instance,
const struct tesla_transition *transp)
{
- switch (tcp->tc_action) {
- case TESLA_ACTION_DTRACE:
- /* XXXRW: more fine-grained DTrace probes? */
- tesla_state_transition_dtrace(tcp, new_instance, transp);
- 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)
+{
+
+ assert(tcp != NULL);
+ assert(tkp != NULL);
- default: {
- DEBUG(libtesla.instance.clone, "clone %td:%tx -> %td:%tx\n",
- old_instance - tcp->tc_instances, transp->from,
- new_instance - tcp->tc_instances, transp->to);
+ print_failure_header(tcp);
- if (transp->flags & TESLA_TRANS_CLEANUP)
- tesla_notify_pass(tcp, new_instance);
+ 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_transition *transp)
+print_no_instance(struct tesla_class *tcp, const struct tesla_key *tkp,
+ const struct tesla_transitions *transp)
{
- switch (tcp->tc_action) {
- case TESLA_ACTION_DTRACE:
- tesla_state_transition_dtrace(tcp, tip, transp);
- return;
+ char buffer[ERROR_BUFFER_LENGTH];
+ const char *end = buffer + sizeof(buffer);
+
+ no_instance_message(buffer, end, tcp, tkp, transp);
+ error("%s", buffer);
+}
- default: {
- DEBUG(libtesla.state.transition, "update %td: %tx->%tx\n",
- tip - tcp->tc_instances, transp->from, transp->to);
+void
+panic_no_instance(struct tesla_class *tcp, const struct tesla_key *tkp,
+ const struct tesla_transitions *transp)
+{
- if (transp->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->tc_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"
@@ -134,76 +203,39 @@
next = sprint_transitions(next, end, transp);
assert(next > buffer);
+}
- switch (tcp->tc_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->tc_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);
- assert(next > buffer);
-
- switch (tcp->tc_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);
}
void
-tesla_notify_pass(struct tesla_class *tcp, struct tesla_instance *tip)
+print_accept(struct tesla_class *tcp, struct tesla_instance *tip)
{
- switch (tcp->tc_action) {
- case TESLA_ACTION_DTRACE:
- tesla_assert_pass_dtrace(tcp, tip);
- return;
-
- default:
- DEBUG(libtesla.instance.success,
- "pass '%s': %td\n", tcp->tc_name,
- tip - tcp->tc_instances);
- break;
- }
+ DEBUG(libtesla.instance.success,
+ "pass '%s': %td\n", tcp->tc_name,
+ tip - tcp->tc_instances);
}
@@ -218,4 +250,3 @@
error("In automaton '%s':\n%s\n", tcp->tc_name, tcp->tc_description);
}
-
==== //depot/projects/ctsrd/tesla/src/lib/libtesla/tesla_update.c#2 (text+ko) ====
@@ -54,6 +54,9 @@
const char *name, const char *description,
const struct tesla_transitions *trans)
{
+
+ assert(ev_handlers != NULL);
+
if (tesla_debugging(DEBUG_NAME)) {
/* We should never see with multiple <<init>> transitions. */
int init_count = 0;
@@ -111,16 +114,20 @@
switch (action) {
case FAIL:
- tesla_notify_assert_fail(class, inst, trans);
+ ev_handlers->teh_bad_transition(class, inst, trans);
break;
case IGNORE:
break;
case UPDATE:
- tesla_notify_transition(class, inst, trigger);
+ ev_handlers->teh_transition(class, inst, trigger);
inst->ti_state = trigger->to;
matched_something = true;
+
+ if (trigger->flags & TESLA_TRANS_CLEANUP)
+ ev_handlers->teh_accept(class, inst);
+
break;
case FORK: {
@@ -148,7 +155,10 @@
clone->ti_state = c->transition->to;
- tesla_notify_clone(class, c->old, clone, c->transition);
+ ev_handlers->teh_clone(class, c->old, clone, c->transition);
+
+ if (c->transition->flags & TESLA_TRANS_CLEANUP)
+ ev_handlers->teh_accept(class, clone);
}
@@ -161,7 +171,7 @@
assert(tesla_instance_active(inst));
matched_something = true;
- tesla_notify_new_instance(class, inst);
+ ev_handlers->teh_init(class, inst);
}
}
@@ -173,7 +183,7 @@
PRINT("\n====\n\n");
if (!matched_something)
- tesla_notify_match_fail(class, pattern, trans);
+ ev_handlers->teh_fail_no_instance(class, pattern, trans);
tesla_class_put(class);
More information about the p4-projects
mailing list