X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=blobdiff_plain;f=include%2Fbabeltrace%2Fctf-ir%2Fevent-internal.h;h=39efd2f8de166d3dad1b5137eb50d1e40895db39;hp=43a77a23069ef92a115e2f954303cb33b3de2911;hb=44c440bc5fe8219cc17d1b786d91fd83c4c9860a;hpb=2dd764c1b4c758c8843e4e06e56012661b656166 diff --git a/include/babeltrace/ctf-ir/event-internal.h b/include/babeltrace/ctf-ir/event-internal.h index 43a77a23..39efd2f8 100644 --- a/include/babeltrace/ctf-ir/event-internal.h +++ b/include/babeltrace/ctf-ir/event-internal.h @@ -27,241 +27,193 @@ * SOFTWARE. */ +/* Protection: this file uses BT_LIB_LOG*() macros directly */ +#ifndef BABELTRACE_LIB_LOGGING_INTERNAL_H +# error Please define include before including this file. +#endif + #include #include #include +#include #include #include +#include #include +#include #include #include #include #include -#include #include #include #include -struct bt_stream_pos; - -struct bt_event_common { - struct bt_object base; - struct bt_event_class_common *class; - struct bt_field_wrapper *header_field; - struct bt_field_common *stream_event_context_field; - struct bt_field_common *context_field; - struct bt_field_common *payload_field; - int frozen; -}; +#define BT_ASSERT_PRE_EVENT_HOT(_event) \ + BT_ASSERT_PRE_HOT((_event), "Event", ": %!+e", (_event)) struct bt_event { - struct bt_event_common common; - - /* Maps clock classes to bt_clock_value. */ - GHashTable *clock_values; + struct bt_object base; + struct bt_event_class *class; struct bt_packet *packet; + struct bt_field_wrapper *header_field; + struct bt_field *common_context_field; + struct bt_field *specific_context_field; + struct bt_field *payload_field; + struct bt_clock_value *default_cv; + bool frozen; }; BT_HIDDEN -int _bt_event_common_validate(struct bt_event_common *event); +void bt_event_destroy(struct bt_event *event); BT_HIDDEN -void _bt_event_common_freeze(struct bt_event_common *event); +struct bt_event *bt_event_new(struct bt_event_class *event_class); BT_HIDDEN -void _bt_event_freeze(struct bt_event *event); +void _bt_event_set_is_frozen(struct bt_event *event, bool is_frozen); #ifdef BT_DEV_MODE -# define bt_event_common_validate _bt_event_common_validate -# define bt_event_common_freeze _bt_event_common_freeze -# define bt_event_freeze _bt_event_freeze +# define bt_event_set_is_frozen _bt_event_set_is_frozen #else -# define bt_event_common_validate(_event) 0 -# define bt_event_common_freeze(_event) -# define bt_event_freeze(_event) +# define bt_event_set_is_frozen(_event, _is_frozen) #endif -#define BT_ASSERT_PRE_EVENT_COMMON_HOT(_event, _name) \ - BT_ASSERT_PRE_HOT((_event), (_name), ": +%!+_e", (_event)) - +BT_UNUSED static inline -struct bt_event_class_common *bt_event_common_borrow_class( - struct bt_event_common *event) +void _bt_event_reset_dev_mode(struct bt_event *event) { BT_ASSERT(event); - return event->class; -} - -typedef void *(*create_field_func)(void *); -typedef void (*release_field_func)(void *); -typedef void *(*create_header_field_func)(void *, void *); -typedef void (*release_header_field_func)(void *, void *); - -BT_HIDDEN -int bt_event_common_initialize(struct bt_event_common *event, - struct bt_event_class_common *event_class, - struct bt_clock_class *init_expected_clock_class, - bt_object_release_func release_func, - bt_validation_flag_copy_field_type_func field_type_copy_func, - bool must_be_in_trace, - int (*map_clock_classes_func)(struct bt_stream_class_common *stream_class, - struct bt_field_type_common *packet_context_field_type, - struct bt_field_type_common *event_header_field_type), - create_field_func create_field_func, - release_field_func release_field_func, - create_header_field_func create_header_field_func, - release_header_field_func release_header_field_func); -static inline -struct bt_field_common *bt_event_common_borrow_payload( - struct bt_event_common *event) -{ - struct bt_field_common *payload = NULL; - - BT_ASSERT_PRE_NON_NULL(event, "Event"); + if (event->header_field) { + bt_field_set_is_frozen( + event->header_field->field, false); + bt_field_reset( + event->header_field->field); + } - if (!event->payload_field) { - BT_LOGV("Event has no current payload field: addr=%p, " - "event-class-name=\"%s\", event-class-id=%" PRId64, - event, bt_event_class_common_get_name(event->class), - bt_event_class_common_get_id(event->class)); - goto end; + if (event->common_context_field) { + bt_field_set_is_frozen( + event->common_context_field, false); + bt_field_reset( + event->common_context_field); } - payload = event->payload_field; + if (event->specific_context_field) { + bt_field_set_is_frozen( + event->specific_context_field, false); + bt_field_reset(event->specific_context_field); + } -end: - return payload; + if (event->payload_field) { + bt_field_set_is_frozen( + event->payload_field, false); + bt_field_reset(event->payload_field); + } } +#ifdef BT_DEV_MODE +# define bt_event_reset_dev_mode _bt_event_reset_dev_mode +#else +# define bt_event_reset_dev_mode(_x) +#endif + static inline -struct bt_field_common *bt_event_common_borrow_header( - struct bt_event_common *event) +void bt_event_reset(struct bt_event *event) { - struct bt_field_common *header = NULL; - - BT_ASSERT_PRE_NON_NULL(event, "Event"); + BT_ASSERT(event); + BT_LIB_LOGD("Resetting event: %!+e", event); + bt_event_set_is_frozen(event, false); - if (!event->header_field) { - BT_LOGV("Event has no current header field: addr=%p, " - "event-class-name=\"%s\", event-class-id=%" PRId64, - event, bt_event_class_common_get_name(event->class), - bt_event_class_common_get_id(event->class)); - goto end; + if (event->default_cv) { + bt_clock_value_reset(event->default_cv); } - header = event->header_field->field; - -end: - return header; + bt_object_put_no_null_check(&event->packet->base); + event->packet = NULL; } static inline -struct bt_field_common *bt_event_common_borrow_context( - struct bt_event_common *event) +void bt_event_recycle(struct bt_event *event) { - struct bt_field_common *context = NULL; - - BT_ASSERT_PRE_NON_NULL(event, "Event"); + struct bt_event_class *event_class; - if (!event->context_field) { - BT_LOGV("Event has no current context field: addr=%p, " - "event-class-name=\"%s\", event-class-id=%" PRId64, - event, bt_event_class_common_get_name(event->class), - bt_event_class_common_get_id(event->class)); - goto end; - } - - context = event->context_field; + BT_ASSERT(event); + BT_LIB_LOGD("Recycling event: %!+e", event); -end: - return context; + /* + * Those are the important ordered steps: + * + * 1. Reset the event object (put any permanent reference it + * has, unfreeze it and its fields in developer mode, etc.), + * but do NOT put its class's reference. This event class + * contains the pool to which we're about to recycle this + * event object, so we must guarantee its existence thanks + * to this existing reference. + * + * 2. Move the event class reference to our `event_class` + * variable so that we can set the event's class member + * to NULL before recycling it. We CANNOT do this after + * we put the event class reference because this bt_put() + * could destroy the event class, also destroying its + * event pool, thus also destroying our event object (this + * would result in an invalid write access). + * + * 3. Recycle the event object. + * + * 4. Put our event class reference. + */ + bt_event_reset(event); + event_class = event->class; + BT_ASSERT(event_class); + event->class = NULL; + bt_object_pool_recycle_object(&event_class->event_pool, event); + bt_object_put_no_null_check(&event_class->base); } static inline -struct bt_field_common *bt_event_common_borrow_stream_event_context( - struct bt_event_common *event) +void bt_event_set_packet(struct bt_event *event, struct bt_packet *packet) { - struct bt_field_common *stream_event_context = NULL; - BT_ASSERT_PRE_NON_NULL(event, "Event"); - - if (!event->stream_event_context_field) { - BT_LOGV("Event has no current stream event context field: addr=%p, " - "event-class-name=\"%s\", event-class-id=%" PRId64, - event, bt_event_class_common_get_name(event->class), - bt_event_class_common_get_id(event->class)); - goto end; - } - - stream_event_context = event->stream_event_context_field; - -end: - return stream_event_context; + BT_ASSERT_PRE_NON_NULL(packet, "Packet"); + BT_ASSERT_PRE_EVENT_HOT(event); + BT_ASSERT_PRE(bt_event_class_borrow_stream_class( + event->class) == packet->stream->class, + "Packet's stream class and event's stream class differ: " + "%![event-]+e, %![packet-]+a", event, packet); + + BT_ASSERT(!event->packet); + event->packet = packet; + bt_object_get_no_null_check_no_parent_check(&event->packet->base); + BT_LIB_LOGV("Set event's packet: %![event-]+e, %![packet-]+a", + event, packet); } static inline -void bt_event_common_finalize(struct bt_object *obj, - void (*field_release_func)(void *), - void (*header_field_release_func)(void *, struct bt_event_common *)) +struct bt_event *bt_event_create(struct bt_event_class *event_class, + struct bt_packet *packet) { - struct bt_event_common *event = (void *) obj; + struct bt_event *event = NULL; - BT_LOGD("Destroying event: addr=%p, " - "event-class-name=\"%s\", event-class-id=%" PRId64, - event, - event->class ? bt_event_class_common_get_name(event->class) : NULL, - event->class ? bt_event_class_common_get_id(event->class) : INT64_C(-1)); - - if (event->header_field) { - BT_LOGD_STR("Releasing event's header field."); - header_field_release_func(event->header_field, event); + BT_ASSERT(event_class); + event = bt_object_pool_create_object(&event_class->event_pool); + if (unlikely(!event)) { + BT_LIB_LOGE("Cannot allocate one event from event class's event pool: " + "%![ec-]+E", event_class); + goto end; } - if (event->stream_event_context_field) { - BT_LOGD_STR("Releasing event's stream event context field."); - field_release_func(event->stream_event_context_field); + if (likely(!event->class)) { + event->class = event_class; + bt_object_get_no_null_check(&event_class->base); } - if (event->context_field) { - BT_LOGD_STR("Releasing event's context field."); - field_release_func(event->context_field); - } + BT_ASSERT(packet); + bt_event_set_packet(event, packet); + goto end; - if (event->payload_field) { - BT_LOGD_STR("Releasing event's payload field."); - field_release_func(event->payload_field); - } - - /* - * Leave this after calling header_field_release_func() because - * this function receives the event object and could need its - * class to perform some cleanup. - */ - if (!event->base.parent) { - /* - * Event was keeping a reference to its class since it shared no - * common ancestor with it to guarantee they would both have the - * same lifetime. - */ - bt_put(event->class); - } +end: + return event; } -BT_HIDDEN -struct bt_event *bt_event_new(struct bt_event_class *event_class); - -BT_HIDDEN -struct bt_event *bt_event_create(struct bt_event_class *event_class, - struct bt_packet *packet); - -BT_HIDDEN -void bt_event_recycle(struct bt_event *event); - -BT_HIDDEN -void bt_event_destroy(struct bt_event *event); - -BT_HIDDEN -int bt_event_set_packet(struct bt_event *event, struct bt_packet *packet); - #endif /* BABELTRACE_CTF_IR_EVENT_INTERNAL_H */