fe5e64decf70367dc6fc4cff63701bb2d10162aa
[babeltrace.git] / include / babeltrace / ctf-ir / event-internal.h
1 #ifndef BABELTRACE_CTF_IR_EVENT_INTERNAL_H
2 #define BABELTRACE_CTF_IR_EVENT_INTERNAL_H
3
4 /*
5 * Babeltrace - CTF IR: Event internal
6 *
7 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
8 *
9 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * SOFTWARE.
28 */
29
30 #include <babeltrace/assert-pre-internal.h>
31 #include <babeltrace/babeltrace-internal.h>
32 #include <babeltrace/values.h>
33 #include <babeltrace/ctf-ir/stream-class.h>
34 #include <babeltrace/ctf-ir/stream.h>
35 #include <babeltrace/ctf-ir/packet.h>
36 #include <babeltrace/ctf-ir/packet-internal.h>
37 #include <babeltrace/ctf-ir/fields.h>
38 #include <babeltrace/ctf-ir/fields-internal.h>
39 #include <babeltrace/ctf-ir/event-class-internal.h>
40 #include <babeltrace/ctf-ir/clock-value-internal.h>
41 #include <babeltrace/ctf-ir/field-wrapper-internal.h>
42 #include <babeltrace/ctf-ir/validation-internal.h>
43 #include <babeltrace/object-internal.h>
44 #include <babeltrace/assert-internal.h>
45 #include <glib.h>
46
47 struct bt_stream_pos;
48
49 struct bt_event_common {
50 struct bt_object base;
51 struct bt_event_class_common *class;
52 struct bt_field_wrapper *header_field;
53 struct bt_field_common *stream_event_context_field;
54 struct bt_field_common *context_field;
55 struct bt_field_common *payload_field;
56 int frozen;
57 };
58
59 struct bt_event {
60 struct bt_event_common common;
61
62 /* Maps clock classes to bt_clock_value. */
63 GHashTable *clock_values;
64 struct bt_packet *packet;
65 };
66
67 BT_HIDDEN
68 int _bt_event_common_validate(struct bt_event_common *event);
69
70 BT_HIDDEN
71 void _bt_event_common_set_is_frozen(struct bt_event_common *event,
72 bool is_frozen);
73
74 BT_HIDDEN
75 void _bt_event_set_is_frozen(struct bt_event *event, bool is_frozen);
76
77 #ifdef BT_DEV_MODE
78 # define bt_event_common_validate _bt_event_common_validate
79 # define bt_event_common_set_is_frozen _bt_event_common_set_is_frozen
80 # define bt_event_set_is_frozen _bt_event_set_is_frozen
81 #else
82 # define bt_event_common_validate(_event) 0
83 # define bt_event_common_set_is_frozen(_event, _is_frozen)
84 # define bt_event_set_is_frozen(_event, _is_frozen)
85 #endif
86
87 #define BT_ASSERT_PRE_EVENT_COMMON_HOT(_event, _name) \
88 BT_ASSERT_PRE_HOT((_event), (_name), ": +%!+_e", (_event))
89
90 static inline
91 struct bt_event_class_common *bt_event_common_borrow_class(
92 struct bt_event_common *event)
93 {
94 BT_ASSERT(event);
95 return event->class;
96 }
97
98 typedef void *(*create_field_func)(void *);
99 typedef void (*release_field_func)(void *);
100 typedef void *(*create_header_field_func)(void *, void *);
101 typedef void (*release_header_field_func)(void *, void *);
102
103 BT_HIDDEN
104 int bt_event_common_initialize(struct bt_event_common *event,
105 struct bt_event_class_common *event_class,
106 struct bt_clock_class *init_expected_clock_class,
107 bool is_shared_with_parent, bt_object_release_func release_func,
108 bt_validation_flag_copy_field_type_func field_type_copy_func,
109 bool must_be_in_trace,
110 int (*map_clock_classes_func)(struct bt_stream_class_common *stream_class,
111 struct bt_field_type_common *packet_context_field_type,
112 struct bt_field_type_common *event_header_field_type),
113 create_field_func create_field_func,
114 release_field_func release_field_func,
115 create_header_field_func create_header_field_func,
116 release_header_field_func release_header_field_func);
117
118 static inline
119 struct bt_field_common *bt_event_common_borrow_payload(
120 struct bt_event_common *event)
121 {
122 struct bt_field_common *payload = NULL;
123
124 BT_ASSERT_PRE_NON_NULL(event, "Event");
125
126 if (!event->payload_field) {
127 BT_LOGV("Event has no current payload field: addr=%p, "
128 "event-class-name=\"%s\", event-class-id=%" PRId64,
129 event, bt_event_class_common_get_name(event->class),
130 bt_event_class_common_get_id(event->class));
131 goto end;
132 }
133
134 payload = event->payload_field;
135
136 end:
137 return payload;
138 }
139
140 static inline
141 struct bt_field_common *bt_event_common_borrow_header(
142 struct bt_event_common *event)
143 {
144 struct bt_field_common *header = NULL;
145
146 BT_ASSERT_PRE_NON_NULL(event, "Event");
147
148 if (!event->header_field) {
149 BT_LOGV("Event has no current header field: addr=%p, "
150 "event-class-name=\"%s\", event-class-id=%" PRId64,
151 event, bt_event_class_common_get_name(event->class),
152 bt_event_class_common_get_id(event->class));
153 goto end;
154 }
155
156 header = event->header_field->field;
157
158 end:
159 return header;
160 }
161
162 static inline
163 struct bt_field_common *bt_event_common_borrow_context(
164 struct bt_event_common *event)
165 {
166 struct bt_field_common *context = NULL;
167
168 BT_ASSERT_PRE_NON_NULL(event, "Event");
169
170 if (!event->context_field) {
171 BT_LOGV("Event has no current context field: addr=%p, "
172 "event-class-name=\"%s\", event-class-id=%" PRId64,
173 event, bt_event_class_common_get_name(event->class),
174 bt_event_class_common_get_id(event->class));
175 goto end;
176 }
177
178 context = event->context_field;
179
180 end:
181 return context;
182 }
183
184 static inline
185 struct bt_field_common *bt_event_common_borrow_stream_event_context(
186 struct bt_event_common *event)
187 {
188 struct bt_field_common *stream_event_context = NULL;
189
190 BT_ASSERT_PRE_NON_NULL(event, "Event");
191
192 if (!event->stream_event_context_field) {
193 BT_LOGV("Event has no current stream event context field: addr=%p, "
194 "event-class-name=\"%s\", event-class-id=%" PRId64,
195 event, bt_event_class_common_get_name(event->class),
196 bt_event_class_common_get_id(event->class));
197 goto end;
198 }
199
200 stream_event_context = event->stream_event_context_field;
201
202 end:
203 return stream_event_context;
204 }
205
206 static inline
207 void bt_event_common_finalize(struct bt_object *obj,
208 void (*field_release_func)(void *),
209 void (*header_field_release_func)(void *, struct bt_event_common *))
210 {
211 struct bt_event_common *event = (void *) obj;
212
213 BT_LOGD("Destroying event: addr=%p, "
214 "event-class-name=\"%s\", event-class-id=%" PRId64,
215 event,
216 event->class ? bt_event_class_common_get_name(event->class) : NULL,
217 event->class ? bt_event_class_common_get_id(event->class) : INT64_C(-1));
218
219 if (event->header_field) {
220 BT_LOGD_STR("Releasing event's header field.");
221 header_field_release_func(event->header_field, event);
222 }
223
224 if (event->stream_event_context_field) {
225 BT_LOGD_STR("Releasing event's stream event context field.");
226 field_release_func(event->stream_event_context_field);
227 }
228
229 if (event->context_field) {
230 BT_LOGD_STR("Releasing event's context field.");
231 field_release_func(event->context_field);
232 }
233
234 if (event->payload_field) {
235 BT_LOGD_STR("Releasing event's payload field.");
236 field_release_func(event->payload_field);
237 }
238
239 /*
240 * Leave this after calling header_field_release_func() because
241 * this function receives the event object and could need its
242 * class to perform some cleanup.
243 */
244 if (!event->base.parent) {
245 /*
246 * Event was keeping a reference to its class since it shared no
247 * common ancestor with it to guarantee they would both have the
248 * same lifetime.
249 */
250 bt_put(event->class);
251 }
252 }
253
254 BT_UNUSED
255 static inline
256 void _bt_event_reset_dev_mode(struct bt_event *event)
257 {
258 GHashTableIter iter;
259 gpointer key, value;
260
261 BT_ASSERT(event);
262
263 if (event->common.header_field) {
264 bt_field_common_set_is_frozen_recursive(
265 event->common.header_field->field, false);
266 bt_field_common_reset_recursive(
267 event->common.header_field->field);
268 }
269
270 if (event->common.stream_event_context_field) {
271 bt_field_common_set_is_frozen_recursive(
272 event->common.stream_event_context_field, false);
273 bt_field_common_reset_recursive(
274 event->common.stream_event_context_field);
275 }
276
277 if (event->common.context_field) {
278 bt_field_common_set_is_frozen_recursive(
279 event->common.context_field, false);
280 bt_field_common_reset_recursive(event->common.context_field);
281 }
282
283 if (event->common.payload_field) {
284 bt_field_common_set_is_frozen_recursive(
285 event->common.payload_field, false);
286 bt_field_common_reset_recursive(event->common.payload_field);
287 }
288
289 g_hash_table_iter_init(&iter, event->clock_values);
290 while (g_hash_table_iter_next(&iter, &key, &value)) {
291 struct bt_clock_value *clock_value = value;
292
293 BT_ASSERT(clock_value);
294 bt_clock_value_reset(clock_value);
295 bt_clock_value_set_is_frozen(clock_value, false);
296 }
297 }
298
299 #ifdef BT_DEV_MODE
300 # define bt_event_reset_dev_mode _bt_event_reset_dev_mode
301 #else
302 # define bt_event_reset_dev_mode(_x)
303 #endif
304
305 BT_HIDDEN
306 void bt_event_destroy(struct bt_event *event);
307
308 static inline
309 void bt_event_reset(struct bt_event *event)
310 {
311 BT_ASSERT(event);
312 bt_event_set_is_frozen(event, false);
313 bt_event_reset_dev_mode(event);
314 bt_object_put_no_null_check(&event->packet->base);
315 event->packet = NULL;
316 }
317
318 static inline
319 void bt_event_recycle(struct bt_event *event)
320 {
321 struct bt_event_class *event_class;
322
323 BT_ASSERT(event);
324 BT_LIB_LOGD("Recycling event: %!+e", event);
325
326 /*
327 * Those are the important ordered steps:
328 *
329 * 1. Reset the event object (put any permanent reference it
330 * has, unfreeze it and its fields in developer mode, etc.),
331 * but do NOT put its class's reference. This event class
332 * contains the pool to which we're about to recycle this
333 * event object, so we must guarantee its existence thanks
334 * to this existing reference.
335 *
336 * 2. Move the event class reference to our `event_class`
337 * variable so that we can set the event's class member
338 * to NULL before recycling it. We CANNOT do this after
339 * we put the event class reference because this bt_put()
340 * could destroy the event class, also destroying its
341 * event pool, thus also destroying our event object (this
342 * would result in an invalid write access).
343 *
344 * 3. Recycle the event object.
345 *
346 * 4. Put our event class reference.
347 */
348 bt_event_reset(event);
349 event_class = BT_FROM_COMMON(event->common.class);
350 BT_ASSERT(event_class);
351 event->common.class = NULL;
352 bt_object_pool_recycle_object(&event_class->event_pool, event);
353 bt_object_put_no_null_check(&event_class->common.base);
354 }
355
356 static inline
357 void bt_event_set_packet(struct bt_event *event, struct bt_packet *packet)
358 {
359 BT_ASSERT_PRE_NON_NULL(event, "Event");
360 BT_ASSERT_PRE_NON_NULL(packet, "Packet");
361 BT_ASSERT_PRE_EVENT_COMMON_HOT(BT_TO_COMMON(event), "Event");
362 BT_ASSERT(!event->packet);
363 event->packet = packet;
364 bt_object_get_no_null_check_no_parent_check(&event->packet->base);
365 BT_LOGV("Set event's packet: event-addr=%p, "
366 "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
367 "packet-addr=%p",
368 event, bt_event_class_common_get_name(event->common.class),
369 bt_event_class_common_get_id(event->common.class), packet);
370 }
371
372 static inline
373 struct bt_event *bt_event_create(struct bt_event_class *event_class,
374 struct bt_packet *packet)
375 {
376 struct bt_event *event = NULL;
377
378 BT_ASSERT(event_class);
379 event = bt_object_pool_create_object(&event_class->event_pool);
380 if (unlikely(!event)) {
381 BT_LIB_LOGE("Cannot allocate one event from event class's event pool: "
382 "%![event-class-]+E", event_class);
383 goto end;
384 }
385
386 if (unlikely(!event->common.class)) {
387 event->common.class = BT_TO_COMMON(event_class);
388 bt_object_get_no_null_check(&event_class->common.base);
389 }
390
391 BT_ASSERT(packet);
392 bt_event_set_packet(event, packet);
393 goto end;
394
395 end:
396 return event;
397 }
398
399 BT_HIDDEN
400 struct bt_event *bt_event_new(struct bt_event_class *event_class);
401
402 #endif /* BABELTRACE_CTF_IR_EVENT_INTERNAL_H */
This page took 0.037989 seconds and 4 git commands to generate.