Computer Laboratory

tesla_internal.h
Go to the documentation of this file.
1 /*-
2  * Copyright (c) 2011, 2013 Robert N. M. Watson
3  * All rights reserved.
4  *
5  * This software was developed by SRI International and the University of
6  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
7  * ("CTSRD"), as part of the DARPA CRASH research programme.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $Id$
31  */
32 
33 #ifndef TESLA_INTERNAL_H
34 #define TESLA_INTERNAL_H
35 
41 #ifdef HAVE_CONFIG_H
42 #include "config.h"
43 #endif
44 
45 #ifdef _KERNEL
46 #include "opt_kdb.h"
47 #include "opt_kdtrace.h"
48 #include <sys/param.h>
49 #include <sys/eventhandler.h>
50 #include <sys/kdb.h>
51 #include <sys/kernel.h>
52 #include <sys/lock.h>
53 #include <sys/mutex.h>
54 #include <sys/malloc.h>
55 #include <sys/proc.h>
56 #include <sys/sx.h>
57 #include <sys/systm.h>
58 
59 #include <machine/_inttypes.h>
60 #else
61 #include <assert.h>
62 #include <err.h>
63 #include <pthread.h>
64 #include <stdlib.h>
65 #include <string.h>
66 #endif
67 
68 #include <libtesla.h>
69 
71 #define SUBSET(x,y) ((x & y) == x)
72 
76 void tesla_die(int32_t errno, const char *event) __attribute__((noreturn));
77 
81 int32_t tesla_store_reset(struct tesla_store *store);
82 
86 void tesla_store_free(struct tesla_store*);
87 
88 
92 void tesla_class_reset(struct tesla_class*);
93 
97 void tesla_class_destroy(struct tesla_class*);
98 
99 
105 int32_t tesla_instance_new(struct tesla_class *tclass,
106  const struct tesla_key *name, uint32_t state,
107  struct tesla_instance **out);
108 
116 int32_t tesla_instance_active(const struct tesla_instance *i);
117 
118 
120 int32_t tesla_instance_clone(struct tesla_class *tclass,
121  const struct tesla_instance *orig, struct tesla_instance **copy);
122 
124 void tesla_instance_clear(struct tesla_instance *tip);
125 
126 
139 int32_t tesla_match(struct tesla_class *tclass, const struct tesla_key *key,
140  struct tesla_instance **array, uint32_t *size);
141 
147 int32_t tesla_key_matches(
148  const struct tesla_key *pattern, const struct tesla_key *k);
149 
150 
155 
158 
161 
164 
167 };
168 
175 enum tesla_action_t tesla_action(const struct tesla_instance*,
176  const struct tesla_key*, const struct tesla_transitions*,
177  const struct tesla_transition** trigger);
178 
180 int32_t tesla_key_union(struct tesla_key *dest, const struct tesla_key *source);
181 
182 
183 #ifndef __unused
184 #if __has_attribute(unused)
185 #define __unused __attribute__((unused))
186 #else
187 #define __unused
188 #endif
189 #endif
190 
191 // Kernel vs userspace implementation details.
192 #ifdef _KERNEL
193 
195 #define tesla_panic(...) panic(__VA_ARGS__)
196 
198 #define tesla_assert(...) KASSERT(__VA_ARGS__)
199 
201 #define assert(cond) KASSERT((cond), ("Assertion failed: '%s'", #cond))
202 
203 #define tesla_malloc(len) malloc(len, M_TESLA, M_WAITOK | M_ZERO)
204 #define tesla_free(x) free(x, M_TESLA)
205 
206 #define tesla_lock(l) mtx_lock(l)
207 #define tesla_unlock(l) mtx_unlock(l)
208 
209 #else /* !_KERNEL */
210 
212 #define tesla_panic(...) errx(1, __VA_ARGS__)
213 
215 #define tesla_assert(condition, ...) assert(condition)
216 
217 #define tesla_malloc(len) calloc(1, len)
218 #define tesla_free(x) free(x)
219 
220 #define tesla_lock(l) \
221  do { __debug int err = pthread_mutex_lock(l); assert(err == 0); } while(0)
222 
223 #define tesla_unlock(l) \
224  do { __debug int err = pthread_mutex_unlock(l); assert(err == 0); } while(0)
225 
226 #endif
227 
228 
229 /*
230  * Assertion state definition is internal to libtesla so we can change it as
231  * we need to.
232  */
233 struct tesla_class {
234  const char *tc_name; /* Name of the assertion. */
235  const char *tc_description;/* Automaton representation. */
236  enum tesla_context tc_context; /* Global, thread... */
237  uint32_t tc_limit; /* Maximum instances. */
238 
239  struct tesla_instance *tc_instances; /* Instances of this class. */
240  uint32_t tc_free; /* Unused instances. */
241 
242 #ifdef _KERNEL
243  struct mtx tc_lock; /* Synchronise tc_table. */
244 #else
245  pthread_mutex_t tc_lock; /* Synchronise tc_table. */
246 #endif
247 };
248 
249 typedef struct tesla_class tesla_class;
251 typedef struct tesla_key tesla_key;
252 typedef struct tesla_store tesla_store;
255 
256 
263 struct tesla_store {
264  uint32_t length;
266 };
267 
272 int tesla_store_init(tesla_store*, enum tesla_context context,
273  uint32_t classes, uint32_t instances);
274 
279 int tesla_class_init(struct tesla_class*, enum tesla_context context,
280  uint32_t instances);
281 
282 /*
283  * XXXRW: temporarily, maximum number of classes and instances are hard-coded
284  * constants. In the future, this should somehow be more dynamic.
285  */
286 #define TESLA_MAX_CLASSES 128
287 #define TESLA_MAX_INSTANCES 128
288 
289 #if defined(_KERNEL) && defined(MALLOC_DECLARE)
290 /*
291  * Memory type for TESLA allocations in the kernel.
292  */
293 MALLOC_DECLARE(M_TESLA);
294 #endif
295 
296 /*
297  * Context-specific automata management:
298  */
303 
308 
309 /*
310  * Event notification:
311  */
312 #if defined(_KERNEL) && defined(KDTRACE_HOOKS)
313 extern const struct tesla_event_handlers dtrace_handlers;
314 #endif
315 
316 void ev_new_instance(struct tesla_class *, struct tesla_instance *);
317 void ev_transition(struct tesla_class *, struct tesla_instance *,
318  const struct tesla_transition*);
319 void ev_clone(struct tesla_class *, struct tesla_instance *orig,
320  struct tesla_instance *copy, const struct tesla_transition *);
321 void ev_no_instance(struct tesla_class *, const struct tesla_key *,
322  const struct tesla_transitions *);
323 void ev_bad_transition(struct tesla_class *, struct tesla_instance *,
324  const struct tesla_transitions *);
325 void ev_err(struct tesla_class *tcp, int errno, const char *message);
326 void ev_accept(struct tesla_class *, struct tesla_instance *);
327 void ev_ignored(const struct tesla_class *, const struct tesla_key *,
328  const struct tesla_transitions *);
329 
330 /*
331  * Debug helpers.
332  */
333 
335 #define SAFE_SPRINTF(current, end, ...) do { \
336  int written = snprintf(current, end - current, __VA_ARGS__); \
337  if ((written > 0) && (current + written < end)) \
338  current += written; \
339 } while (0)
340 
341 #define print(...) printf(__VA_ARGS__)
342 
343 #ifdef _KERNEL
344 #define error(...) printf(__VA_ARGS__)
345 #else
346 #define error(...) fprintf(stderr, __VA_ARGS__)
347 #endif
348 
349 #ifndef NDEBUG
350 
351 #define __debug
352 
353 #ifdef _KERNEL
354 #include <sys/systm.h>
355 #else
356 #include <stdio.h>
357 #endif
358 
360 int32_t tesla_debugging(const char*);
361 
363 #define DEBUG(dclass, ...) \
364  if (tesla_debugging(#dclass)) printf(__VA_ARGS__)
365 
366 #else // NDEBUG
367 
368 // When not in debug mode, some values might not get checked.
369 #define __debug __unused
370 
371 #define DEBUG(...)
372 int32_t tesla_debugging(const char*) { return 0; }
373 
374 #endif
375 
385 void assert_instanceof(struct tesla_instance *i, struct tesla_class *tclass);
386 
388 char* key_string(char *buffer, const char *end, const struct tesla_key *);
389 
391 void print_key(const char *debug_name, const struct tesla_key *key);
392 
394 void print_class(const struct tesla_class*);
395 
397 void print_transition(const char *debug, const struct tesla_transition *);
398 
400 char* sprint_transition(char *buffer, const char *end,
401  const struct tesla_transition *);
402 
404 void print_transitions(const char *debug, const struct tesla_transitions *);
405 
407 char* sprint_transitions(char *buffer, const char *end,
408  const struct tesla_transitions *);
409 
412 #endif /* TESLA_INTERNAL_H */