Computer Laboratory

tesla_class.c
Go to the documentation of this file.
1 /*-
2  * Copyright (c) 2011, 2013 Robert N. M. Watson
3  * Copyright (c) 2011 Anil Madhavapeddy
4  * Copyright (c) 2012-2013 Jonathan Anderson
5  * All rights reserved.
6  *
7  * This software was developed by SRI International and the University of
8  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
9  * ("CTSRD"), as part of the DARPA CRASH research programme.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  * notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in the
18  * documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $Id$
33  */
34 
35 #include "tesla_internal.h"
36 
37 #ifdef _KERNEL
38 MALLOC_DEFINE(M_TESLA, "tesla", "TESLA internal state");
39 #else
40 #include <inttypes.h>
41 #include <stdio.h>
42 #endif
43 
44 
45 int
46 tesla_class_init(struct tesla_class *tclass, enum tesla_context context,
47  uint32_t instances)
48 {
49  assert(tclass != NULL);
50  assert(context >= 0);
51  assert(instances > 0);
52  // TODO: write a TESLA assertion about locking here.
53 
54  tclass->tc_limit = instances;
55 
56  tclass->tc_context = context;
57  tclass->tc_limit = instances;
58  tclass->tc_free = instances;
59  tclass->tc_instances =
60  tesla_malloc(instances * sizeof(tclass->tc_instances[0]));
61 
62  switch (context) {
64  return tesla_class_global_postinit(tclass);
65 
67  return tesla_class_perthread_postinit(tclass);
68 
69  default:
70  assert(0 && "unhandled TESLA context");
71  return (TESLA_ERROR_UNKNOWN);
72  }
73 }
74 
75 
76 void
78 {
79  tesla_free(class->tc_instances);
80  switch (class->tc_context) {
83  break;
84 
87  break;
88  }
89 }
90 
91 
92 int
93 tesla_match(struct tesla_class *tclass, const struct tesla_key *pattern,
94  struct tesla_instance **array, uint32_t *size)
95 {
96  assert(tclass != NULL);
97  assert(pattern != NULL);
98  assert(array != NULL);
99  assert(size != NULL);
100 
101  // Assume that any and every instance could match.
102  if (*size < tclass->tc_limit) {
103  *size = tclass->tc_limit;
104  return (TESLA_ERROR_ENOMEM);
105  }
106 
107  // Copy matches into the array.
108  *size = 0;
109  for (uint32_t i = 0; i < tclass->tc_limit; i++) {
110  struct tesla_instance *inst = tclass->tc_instances + i;
111  if (tesla_instance_active(inst)
112  && tesla_key_matches(pattern, &inst->ti_key)) {
113  array[*size] = inst;
114  *size += 1;
115  }
116  }
117 
118  return (TESLA_SUCCESS);
119 }
120 
121 
122 int
124 {
125  assert(i != NULL);
126 
127  return ((i->ti_state != 0) || (i->ti_key.tk_mask != 0));
128 }
129 
130 
131 int32_t
132 tesla_instance_new(struct tesla_class *tclass, const struct tesla_key *name,
133  uint32_t state, struct tesla_instance **out)
134 {
135  assert(tclass != NULL);
136  assert(name != NULL);
137  assert(out != NULL);
138 
139  // A new instance must not look inactive.
140  if ((state == 0) && (name->tk_mask == 0))
141  return (TESLA_ERROR_EINVAL);
142 
143  if (tclass->tc_free == 0)
144  return (TESLA_ERROR_ENOMEM);
145 
146  for (uint32_t i = 0; i < tclass->tc_limit; i++) {
147  struct tesla_instance *inst = tclass->tc_instances + i;
148  if (tesla_instance_active(inst))
149  continue;
150 
151  // Initialise the new instance.
152  inst->ti_key = *name;
153  inst->ti_state = state;
154 
155  tclass->tc_free--;
156  *out = inst;
157 
158  return (TESLA_SUCCESS);
159  }
160 
161  tesla_assert(*out != NULL, ("no free instances but tc_free was > 0"));
162  return (TESLA_ERROR_ENOMEM);
163 }
164 
165 int
167  const struct tesla_instance *orig, struct tesla_instance **copy)
168 {
169  return tesla_instance_new(tclass, &orig->ti_key, orig->ti_state, copy);
170 }
171 
172 void
174 {
175 
176  bzero(tip, sizeof(*tip));
177  assert(!tesla_instance_active(tip));
178 }
179 
180 void
182 {
183  switch (tsp->tc_context) {
185  return tesla_class_global_release(tsp);
186 
188  return tesla_class_perthread_release(tsp);
189 
190  default:
191  assert(0 && "unhandled TESLA context");
192  }
193 }
194 
195 void
197 {
198 
199  DEBUG(libtesla.class.reset, "tesla_class_reset %s\n", c->tc_name);
200 
201  bzero(c->tc_instances, sizeof(c->tc_instances[0]) * c->tc_limit);
202  c->tc_free = c->tc_limit;
203 }