From: Mathieu Desnoyers Date: Fri, 19 Mar 2021 04:03:17 +0000 (-0400) Subject: Refactoring and fix: bytecode ABI X-Git-Tag: v2.13.0-rc1~240 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=a2e4d05e924d4cb02b47430c2d0f39e6a6a89720;p=lttng-ust.git Refactoring and fix: bytecode ABI Introduce an "event filter" callback to be called by the instrumentation probe, and move the bytecode list into private data structures. This will allow much more freedom in choosing how bytecodes are combined both in terms of logic (OR vs AND) and implementation (jits). Currently, we keep callbacks internally as well for each bytecode evaluation, but nothing prevents to change how this works in the future to improve performance now that this is all private. For filters, we add the following fields to struct lttng_ust_event_common: int eval_filter; /* Need to evaluate filters */ int (*run_filter)(struct lttng_ust_event_common *event, const char *stack_data, void *filter_ctx); "eval_filter" is a state indicating whether the filter should be evaluated at all. It combines internal knowledge of whether the filter bytecode list is empty, and whether there are enablers without filter bytecode attached to the event. For captures, a new struct lttng_ust_notification_ctx is introduced, which is to be used as additional "context" to the notification_send() callback. This allows passing the "eval_capture" state from the probe to the notification callback, and fixes a bug where a sequence of: - create notification enabler, - enable notification enabler, - add capture to enabler, where a tracepoint runs concurrently with add capture happens to do a first capture list_empty check which skips the stack preparation, whereas the second capture list_empty check within the notification callback finds a capture entry, and thus attempts to use an uninitialized stack. The notification callback is also modified to use an RCU-aware list traversal. For captures, the following field is added to struct lttng_ust_event_notifier: int eval_capture; /* Need to evaluate capture */ which is to be read once by the probe and its state saved and used thorough the entire probe execution. Signed-off-by: Mathieu Desnoyers Change-Id: Iae70c5e7924f14b38e14676368cf2516951218ee --- diff --git a/include/lttng/ust-events.h b/include/lttng/ust-events.h index 58a0baf4..e8e4bf2c 100644 --- a/include/lttng/ust-events.h +++ b/include/lttng/ust-events.h @@ -296,60 +296,6 @@ struct lttng_ust_probe_desc { /* Data structures used by the tracer. */ -/* - * Bytecode interpreter return value. - */ -enum lttng_ust_bytecode_interpreter_ret { - LTTNG_UST_BYTECODE_INTERPRETER_ERROR = -1, - LTTNG_UST_BYTECODE_INTERPRETER_OK = 0, -}; - -struct lttng_interpreter_output; -struct lttng_ust_bytecode_runtime_private; - -enum lttng_ust_bytecode_filter_result { - LTTNG_UST_BYTECODE_FILTER_ACCEPT = 0, - LTTNG_UST_BYTECODE_FILTER_REJECT = 1, -}; - -/* - * IMPORTANT: this structure is part of the ABI between the probe and - * UST. Fields need to be only added at the end, never reordered, never - * removed. - * - * The field @struct_size should be used to determine the size of the - * structure. It should be queried before using additional fields added - * at the end of the structure. - */ -struct lttng_ust_bytecode_filter_ctx { - uint32_t struct_size; /* Size of this structure. */ - - enum lttng_ust_bytecode_filter_result result; - - /* End of base ABI. Fields below should be used after checking struct_size. */ -}; - -/* - * IMPORTANT: this structure is part of the ABI between the probe and - * UST. Fields need to be only added at the end, never reordered, never - * removed. - * - * The field @struct_size should be used to determine the size of the - * structure. It should be queried before using additional fields added - * at the end of the structure. - */ -struct lttng_ust_bytecode_runtime { - uint32_t struct_size; /* Size of this structure. */ - - struct lttng_ust_bytecode_runtime_private *priv; - int (*interpreter_func)(struct lttng_ust_bytecode_runtime *bytecode_runtime, - const char *interpreter_stack_data, - void *ctx); - struct cds_list_head node; /* list of bytecode runtime in event */ - - /* End of base ABI. Fields below should be used after checking struct_size. */ -}; - /* * lttng_event structure is referred to by the tracing fast path. It * must be kept small. @@ -367,6 +313,14 @@ enum lttng_ust_event_type { LTTNG_UST_EVENT_TYPE_NOTIFIER = 1, }; +/* + * Result of the run_filter() callback. + */ +enum lttng_ust_event_filter_result { + LTTNG_UST_EVENT_FILTER_ACCEPT = 0, + LTTNG_UST_EVENT_FILTER_REJECT = 1, +}; + /* * IMPORTANT: this structure is part of the ABI between the probe and * UST. Fields need to be only added at the end, never reordered, never @@ -391,9 +345,10 @@ struct lttng_ust_event_common { void *child; /* Pointer to child, for inheritance by aggregation. */ int enabled; - int has_enablers_without_bytecode; - /* list of struct lttng_ust_bytecode_runtime, sorted by seqnum */ - struct cds_list_head filter_bytecode_runtime_head; + int eval_filter; /* Need to evaluate filters */ + int (*run_filter)(struct lttng_ust_event_common *event, + const char *stack_data, + void *filter_ctx); /* End of base ABI. Fields below should be used after checking struct_size. */ }; @@ -426,6 +381,22 @@ struct lttng_ust_event_recorder { /* End of base ABI. Fields below should be used after checking struct_size. */ }; +/* + * IMPORTANT: this structure is part of the ABI between the probe and + * UST. Fields need to be only added at the end, never reordered, never + * removed. + * + * The field @struct_size should be used to determine the size of the + * structure. It should be queried before using additional fields added + * at the end of the structure. + */ +struct lttng_ust_notification_ctx { + uint32_t struct_size; /* Size of this structure. */ + int eval_capture; /* Capture evaluation available. */ + + /* End of base ABI. Fields below should be used after checking struct_size. */ +}; + struct lttng_ust_event_notifier_private; /* @@ -448,9 +419,10 @@ struct lttng_ust_event_notifier { struct lttng_ust_event_common *parent; /* Inheritance by aggregation. */ struct lttng_ust_event_notifier_private *priv; /* Private event notifier interface */ + int eval_capture; /* Need to evaluate capture */ void (*notification_send)(struct lttng_ust_event_notifier *event_notifier, - const char *stack_data); - struct cds_list_head capture_bytecode_runtime_head; + const char *stack_data, + struct lttng_ust_notification_ctx *notif_ctx); /* End of base ABI. Fields below should be used after checking struct_size. */ }; diff --git a/include/lttng/ust-tracepoint-event.h b/include/lttng/ust-tracepoint-event.h index 4fc1ea91..fc327a68 100644 --- a/include/lttng/ust-tracepoint-event.h +++ b/include/lttng/ust-tracepoint-event.h @@ -796,6 +796,7 @@ void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)) \ char __interpreter_stack_data[2 * sizeof(unsigned long) * __num_fields]; \ } __stackvar; \ int __ret; \ + bool __interpreter_stack_prepared = false; \ \ if (0) \ (void) __dynamic_len_idx; /* don't warn if unused */ \ @@ -821,24 +822,12 @@ void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)) \ return; \ if (caa_unlikely(!TP_RCU_LINK_TEST())) \ return; \ - if (caa_unlikely(!cds_list_empty(&__event->filter_bytecode_runtime_head))) { \ - struct lttng_ust_bytecode_runtime *__filter_bc_runtime; \ - int __filter_record = __event->has_enablers_without_bytecode; \ - struct lttng_ust_bytecode_filter_ctx filter_ctx; \ - \ - filter_ctx.struct_size = sizeof(struct lttng_ust_bytecode_filter_ctx); \ + if (caa_unlikely(CMM_ACCESS_ONCE(__event->eval_filter))) { \ __event_prepare_interpreter_stack__##_provider##___##_name(__stackvar.__interpreter_stack_data, \ _TP_ARGS_DATA_VAR(_args)); \ - tp_list_for_each_entry_rcu(__filter_bc_runtime, &__event->filter_bytecode_runtime_head, node) { \ - if (caa_likely(__filter_bc_runtime->interpreter_func(__filter_bc_runtime, \ - __stackvar.__interpreter_stack_data, &filter_ctx) == LTTNG_UST_BYTECODE_INTERPRETER_OK)) { \ - if (caa_unlikely(filter_ctx.result == LTTNG_UST_BYTECODE_FILTER_ACCEPT)) { \ - __filter_record = 1; \ - break; \ - } \ - } \ - } \ - if (caa_likely(!__filter_record)) \ + __interpreter_stack_prepared = true; \ + if (caa_likely(__event->run_filter(__event, \ + __stackvar.__interpreter_stack_data, NULL) != LTTNG_UST_EVENT_FILTER_ACCEPT)) \ return; \ } \ switch (__event->type) { \ @@ -869,13 +858,18 @@ void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)) \ case LTTNG_UST_EVENT_TYPE_NOTIFIER: \ { \ struct lttng_ust_event_notifier *__event_notifier = (struct lttng_ust_event_notifier *) __event->child; \ + struct lttng_ust_notification_ctx __notif_ctx; \ + \ + __notif_ctx.struct_size = sizeof(struct lttng_ust_notification_ctx); \ + __notif_ctx.eval_capture = CMM_ACCESS_ONCE(__event_notifier->eval_capture); \ \ - if (caa_unlikely(!cds_list_empty(&__event_notifier->capture_bytecode_runtime_head))) \ + if (caa_unlikely(!__interpreter_stack_prepared && __notif_ctx.eval_capture)) \ __event_prepare_interpreter_stack__##_provider##___##_name(__stackvar.__interpreter_stack_data, \ _TP_ARGS_DATA_VAR(_args)); \ \ __event_notifier->notification_send(__event_notifier, \ - __stackvar.__interpreter_stack_data); \ + __stackvar.__interpreter_stack_data, \ + &__notif_ctx); \ break; \ } \ } \ diff --git a/liblttng-ust/event-notifier-notification.c b/liblttng-ust/event-notifier-notification.c index b4c666aa..40ad731e 100644 --- a/liblttng-ust/event-notifier-notification.c +++ b/liblttng-ust/event-notifier-notification.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "ust-events-internal.h" #include "../libmsgpack/msgpack.h" @@ -357,7 +358,8 @@ void notification_send(struct lttng_event_notifier_notification *notif, void lttng_event_notifier_notification_send( struct lttng_ust_event_notifier *event_notifier, - const char *stack_data) + const char *stack_data, + struct lttng_ust_notification_ctx *notif_ctx) { /* * This function is called from the probe, we must do dynamic @@ -367,7 +369,7 @@ void lttng_event_notifier_notification_send( notification_init(¬if, event_notifier); - if (caa_unlikely(!cds_list_empty(&event_notifier->capture_bytecode_runtime_head))) { + if (caa_unlikely(notif_ctx->eval_capture)) { struct lttng_ust_bytecode_runtime *capture_bc_runtime; /* @@ -376,8 +378,8 @@ void lttng_event_notifier_notification_send( * `output` parameter to the capture buffer. If the interpreter * fails, append an empty capture to the buffer. */ - cds_list_for_each_entry(capture_bc_runtime, - &event_notifier->capture_bytecode_runtime_head, node) { + cds_list_for_each_entry_rcu(capture_bc_runtime, + &event_notifier->priv->capture_bytecode_runtime_head, node) { struct lttng_interpreter_output output; if (capture_bc_runtime->interpreter_func(capture_bc_runtime, diff --git a/liblttng-ust/lttng-bytecode-interpreter.c b/liblttng-ust/lttng-bytecode-interpreter.c index c329415b..a384d61f 100644 --- a/liblttng-ust/lttng-bytecode-interpreter.c +++ b/liblttng-ust/lttng-bytecode-interpreter.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include "ust-events-internal.h" @@ -711,7 +712,7 @@ int lttng_bytecode_interpret(struct lttng_ust_bytecode_runtime *ust_bytecode, void *caller_ctx) { struct bytecode_runtime *bytecode = caa_container_of(ust_bytecode, struct bytecode_runtime, p); - struct lttng_ust_ctx *ctx = lttng_ust_rcu_dereference(*ust_bytecode->priv->pctx); + struct lttng_ust_ctx *ctx = lttng_ust_rcu_dereference(*ust_bytecode->pctx); void *pc, *next_pc, *start_pc; int ret = -EINVAL, retval = 0; struct estack _stack; @@ -879,7 +880,7 @@ int lttng_bytecode_interpret(struct lttng_ust_bytecode_runtime *ust_bytecode, case REG_DOUBLE: case REG_STRING: case REG_PTR: - if (ust_bytecode->priv->type != LTTNG_UST_BYTECODE_TYPE_CAPTURE) { + if (ust_bytecode->type != LTTNG_UST_BYTECODE_TYPE_CAPTURE) { ret = -EINVAL; goto end; } @@ -2480,7 +2481,7 @@ end: return LTTNG_UST_BYTECODE_INTERPRETER_ERROR; /* Prepare output. */ - switch (ust_bytecode->priv->type) { + switch (ust_bytecode->type) { case LTTNG_UST_BYTECODE_TYPE_FILTER: { struct lttng_ust_bytecode_filter_ctx *filter_ctx = @@ -2505,6 +2506,33 @@ end: return LTTNG_UST_BYTECODE_INTERPRETER_OK; } +/* + * Return LTTNG_UST_EVENT_FILTER_ACCEPT or LTTNG_UST_EVENT_FILTER_REJECT. + */ +int lttng_ust_interpret_event_filter(struct lttng_ust_event_common *event, + const char *interpreter_stack_data, + void *event_filter_ctx) +{ + struct lttng_ust_bytecode_runtime *filter_bc_runtime; + struct cds_list_head *filter_bytecode_runtime_head = &event->priv->filter_bytecode_runtime_head; + struct lttng_ust_bytecode_filter_ctx bytecode_filter_ctx; + bool filter_record = false; + + cds_list_for_each_entry_rcu(filter_bc_runtime, filter_bytecode_runtime_head, node) { + if (caa_likely(filter_bc_runtime->interpreter_func(filter_bc_runtime, + interpreter_stack_data, &bytecode_filter_ctx) == LTTNG_UST_BYTECODE_INTERPRETER_OK)) { + if (caa_unlikely(bytecode_filter_ctx.result == LTTNG_UST_BYTECODE_FILTER_ACCEPT)) { + filter_record = true; + break; + } + } + } + if (filter_record) + return LTTNG_UST_EVENT_FILTER_ACCEPT; + else + return LTTNG_UST_EVENT_FILTER_REJECT; +} + #undef START_OP #undef OP #undef PO diff --git a/liblttng-ust/lttng-bytecode-specialize.c b/liblttng-ust/lttng-bytecode-specialize.c index 28b0ea72..065c0eb2 100644 --- a/liblttng-ust/lttng-bytecode-specialize.c +++ b/liblttng-ust/lttng-bytecode-specialize.c @@ -374,7 +374,7 @@ static int specialize_context_lookup_name(struct lttng_ust_ctx *ctx, const char *name; offset = ((struct get_symbol *) insn->data)->offset; - name = bytecode->p.priv->bc->bc.data + bytecode->p.priv->bc->bc.reloc_offset + offset; + name = bytecode->p.bc->bc.data + bytecode->p.bc->bc.reloc_offset + offset; return lttng_get_context_index(ctx, name); } @@ -503,7 +503,7 @@ static int specialize_app_context_lookup(struct lttng_ust_ctx **pctx, ssize_t data_offset; offset = ((struct get_symbol *) insn->data)->offset; - orig_name = runtime->p.priv->bc->bc.data + runtime->p.priv->bc->bc.reloc_offset + offset; + orig_name = runtime->p.bc->bc.data + runtime->p.bc->bc.reloc_offset + offset; name = zmalloc(strlen(orig_name) + strlen("$app.") + 1); if (!name) { ret = -ENOMEM; @@ -564,7 +564,7 @@ static int specialize_payload_lookup(struct lttng_ust_event_desc *event_desc, nr_fields = event_desc->nr_fields; offset = ((struct get_symbol *) insn->data)->offset; - name = runtime->p.priv->bc->bc.data + runtime->p.priv->bc->bc.reloc_offset + offset; + name = runtime->p.bc->bc.data + runtime->p.bc->bc.reloc_offset + offset; for (i = 0; i < nr_fields; i++) { field = event_desc->fields[i]; if (field->nofilter) { @@ -631,7 +631,7 @@ int lttng_bytecode_specialize(struct lttng_ust_event_desc *event_desc, int ret = -EINVAL; struct vstack _stack; struct vstack *stack = &_stack; - struct lttng_ust_ctx **pctx = bytecode->p.priv->pctx; + struct lttng_ust_ctx **pctx = bytecode->p.pctx; vstack_init(stack); diff --git a/liblttng-ust/lttng-bytecode-validator.c b/liblttng-ust/lttng-bytecode-validator.c index ea86c5e7..68b9e008 100644 --- a/liblttng-ust/lttng-bytecode-validator.c +++ b/liblttng-ust/lttng-bytecode-validator.c @@ -256,11 +256,11 @@ int validate_get_symbol(struct bytecode_runtime *bytecode, const char *str, *str_limit; size_t len_limit; - if (sym->offset >= bytecode->p.priv->bc->bc.len - bytecode->p.priv->bc->bc.reloc_offset) + if (sym->offset >= bytecode->p.bc->bc.len - bytecode->p.bc->bc.reloc_offset) return -EINVAL; - str = bytecode->p.priv->bc->bc.data + bytecode->p.priv->bc->bc.reloc_offset + sym->offset; - str_limit = bytecode->p.priv->bc->bc.data + bytecode->p.priv->bc->bc.len; + str = bytecode->p.bc->bc.data + bytecode->p.bc->bc.reloc_offset + sym->offset; + str_limit = bytecode->p.bc->bc.data + bytecode->p.bc->bc.len; len_limit = str_limit - str; if (strnlen(str, len_limit) == len_limit) return -EINVAL; diff --git a/liblttng-ust/lttng-bytecode.c b/liblttng-ust/lttng-bytecode.c index 6ce5e54a..3fe50c36 100644 --- a/liblttng-ust/lttng-bytecode.c +++ b/liblttng-ust/lttng-bytecode.c @@ -276,7 +276,7 @@ int apply_context_reloc(struct bytecode_runtime *runtime, struct load_op *op; struct lttng_ust_ctx_field *ctx_field; int idx; - struct lttng_ust_ctx **pctx = runtime->p.priv->pctx; + struct lttng_ust_ctx **pctx = runtime->p.pctx; dbg_printf("Apply context reloc: %u %s\n", reloc_offset, context_name); @@ -385,7 +385,7 @@ int bytecode_is_linked(struct lttng_ust_bytecode_node *bytecode, struct lttng_ust_bytecode_runtime *bc_runtime; cds_list_for_each_entry(bc_runtime, bytecode_runtime_head, node) { - if (bc_runtime->priv->bc == bytecode) + if (bc_runtime->bc == bytecode) return 1; } return 0; @@ -404,7 +404,6 @@ int link_bytecode(struct lttng_ust_event_desc *event_desc, { int ret, offset, next_offset; struct bytecode_runtime *runtime = NULL; - struct lttng_ust_bytecode_runtime_private *runtime_priv = NULL; size_t runtime_alloc_len; if (!bytecode) @@ -422,19 +421,9 @@ int link_bytecode(struct lttng_ust_event_desc *event_desc, ret = -ENOMEM; goto alloc_error; } - runtime_priv = zmalloc(sizeof(struct lttng_ust_bytecode_runtime_private)); - if (!runtime_priv) { - free(runtime); - runtime = NULL; - ret = -ENOMEM; - goto alloc_error; - } - runtime->p.priv = runtime_priv; - runtime->p.struct_size = sizeof(struct lttng_ust_bytecode_runtime); - runtime_priv->pub = runtime; - runtime_priv->type = bytecode->type; - runtime_priv->bc = bytecode; - runtime_priv->pctx = ctx; + runtime->p.type = bytecode->type; + runtime->p.bc = bytecode; + runtime->p.pctx = ctx; runtime->len = bytecode->bc.reloc_offset; /* copy original bytecode */ memcpy(runtime->code, bytecode->bc.data, runtime->len); @@ -468,14 +457,14 @@ int link_bytecode(struct lttng_ust_event_desc *event_desc, } runtime->p.interpreter_func = lttng_bytecode_interpret; - runtime->p.priv->link_failed = 0; + runtime->p.link_failed = 0; cds_list_add_rcu(&runtime->p.node, insert_loc); dbg_printf("Linking successful.\n"); return 0; link_error: runtime->p.interpreter_func = lttng_bytecode_interpret_error; - runtime_priv->link_failed = 1; + runtime->p.link_failed = 1; cds_list_add_rcu(&runtime->p.node, insert_loc); alloc_error: dbg_printf("Linking failed.\n"); @@ -484,9 +473,9 @@ alloc_error: void lttng_bytecode_sync_state(struct lttng_ust_bytecode_runtime *runtime) { - struct lttng_ust_bytecode_node *bc = runtime->priv->bc; + struct lttng_ust_bytecode_node *bc = runtime->bc; - if (!bc->enabler->enabled || runtime->priv->link_failed) + if (!bc->enabler->enabled || runtime->link_failed) runtime->interpreter_func = lttng_bytecode_interpret_error; else runtime->interpreter_func = lttng_bytecode_interpret; @@ -520,7 +509,7 @@ void lttng_enabler_link_bytecode(struct lttng_ust_event_desc *event_desc, * linked with the instance. */ cds_list_for_each_entry(runtime, instance_bytecode_head, node) { - if (runtime->priv->bc == enabler_bc) { + if (runtime->bc == enabler_bc) { found = 1; break; } @@ -540,7 +529,7 @@ void lttng_enabler_link_bytecode(struct lttng_ust_event_desc *event_desc, */ cds_list_for_each_entry_reverse(runtime, instance_bytecode_head, node) { - if (runtime->priv->bc->bc.seqnum <= enabler_bc->bc.seqnum) { + if (runtime->bc->bc.seqnum <= enabler_bc->bc.seqnum) { /* insert here */ insert_loc = &runtime->node; goto add_within; @@ -576,12 +565,11 @@ void free_filter_runtime(struct cds_list_head *bytecode_runtime_head) cds_list_for_each_entry_safe(runtime, tmp, bytecode_runtime_head, p.node) { free(runtime->data); - free(runtime->p.priv); free(runtime); } } void lttng_free_event_filter_runtime(struct lttng_ust_event_common *event) { - free_filter_runtime(&event->filter_bytecode_runtime_head); + free_filter_runtime(&event->priv->filter_bytecode_runtime_head); } diff --git a/liblttng-ust/lttng-bytecode.h b/liblttng-ust/lttng-bytecode.h index 220e8d03..846d11a4 100644 --- a/liblttng-ust/lttng-bytecode.h +++ b/liblttng-ust/lttng-bytecode.h @@ -23,6 +23,7 @@ #include #include #include "bytecode.h" +#include "ust-events-internal.h" /* Interpreter stack length, in number of entries */ #define INTERPRETER_STACK_LEN 10 /* includes 2 dummy */ diff --git a/liblttng-ust/lttng-events.c b/liblttng-ust/lttng-events.c index 9dc69ba9..9c65dc45 100644 --- a/liblttng-ust/lttng-events.c +++ b/liblttng-ust/lttng-events.c @@ -750,9 +750,10 @@ int lttng_event_recorder_create(struct lttng_ust_event_desc *desc, event_recorder->chan = chan; /* Event will be enabled by enabler sync. */ + event_recorder->parent->run_filter = lttng_ust_interpret_event_filter; event_recorder->parent->enabled = 0; event_recorder->parent->priv->registered = 0; - CDS_INIT_LIST_HEAD(&event_recorder->parent->filter_bytecode_runtime_head); + CDS_INIT_LIST_HEAD(&event_recorder->parent->priv->filter_bytecode_runtime_head); CDS_INIT_LIST_HEAD(&event_recorder->parent->priv->enablers_ref_head); event_recorder->parent->priv->desc = desc; @@ -847,11 +848,12 @@ int lttng_event_notifier_create(struct lttng_ust_event_desc *desc, event_notifier_priv->error_counter_index = error_counter_index; /* Event notifier will be enabled by enabler sync. */ + event_notifier->parent->run_filter = lttng_ust_interpret_event_filter; event_notifier->parent->enabled = 0; event_notifier_priv->parent.registered = 0; - CDS_INIT_LIST_HEAD(&event_notifier->parent->filter_bytecode_runtime_head); - CDS_INIT_LIST_HEAD(&event_notifier->capture_bytecode_runtime_head); + CDS_INIT_LIST_HEAD(&event_notifier->parent->priv->filter_bytecode_runtime_head); + CDS_INIT_LIST_HEAD(&event_notifier->priv->capture_bytecode_runtime_head); CDS_INIT_LIST_HEAD(&event_notifier_priv->parent.enablers_ref_head); event_notifier_priv->parent.desc = desc; event_notifier->notification_send = lttng_event_notifier_notification_send; @@ -1238,7 +1240,7 @@ int lttng_event_enabler_ref_event_recorders(struct lttng_event_enabler *event_en */ lttng_enabler_link_bytecode(event_recorder_priv->parent.desc, &session->priv->ctx, - &event_recorder_priv->pub->parent->filter_bytecode_runtime_head, + &event_recorder_priv->parent.filter_bytecode_runtime_head, <tng_event_enabler_as_enabler(event_enabler)->filter_bytecode_head); /* TODO: merge event context. */ @@ -1654,7 +1656,8 @@ void lttng_session_sync_event_enablers(struct lttng_ust_session *session) cds_list_for_each_entry(event_recorder_priv, &session->priv->events_head, node) { struct lttng_enabler_ref *enabler_ref; struct lttng_ust_bytecode_runtime *runtime; - int enabled = 0, has_enablers_without_bytecode = 0; + int enabled = 0, has_enablers_without_filter_bytecode = 0; + int nr_filters = 0; /* Enable events */ cds_list_for_each_entry(enabler_ref, @@ -1689,18 +1692,21 @@ void lttng_session_sync_event_enablers(struct lttng_ust_session *session) &event_recorder_priv->parent.enablers_ref_head, node) { if (enabler_ref->ref->enabled && cds_list_empty(&enabler_ref->ref->filter_bytecode_head)) { - has_enablers_without_bytecode = 1; + has_enablers_without_filter_bytecode = 1; break; } } - event_recorder_priv->pub->parent->has_enablers_without_bytecode = - has_enablers_without_bytecode; + event_recorder_priv->parent.has_enablers_without_filter_bytecode = + has_enablers_without_filter_bytecode; /* Enable filters */ cds_list_for_each_entry(runtime, - &event_recorder_priv->pub->parent->filter_bytecode_runtime_head, node) { + &event_recorder_priv->parent.filter_bytecode_runtime_head, node) { lttng_bytecode_sync_state(runtime); + nr_filters++; } + CMM_STORE_SHARED(event_recorder_priv->parent.pub->eval_filter, + !(has_enablers_without_filter_bytecode || !nr_filters)); } lttng_ust_tp_probe_prune_release_queue(); } @@ -1840,14 +1846,14 @@ int lttng_event_notifier_enabler_ref_event_notifiers( */ lttng_enabler_link_bytecode(event_notifier_priv->parent.desc, &event_notifier_group->ctx, - &event_notifier_priv->pub->parent->filter_bytecode_runtime_head, + &event_notifier_priv->parent.filter_bytecode_runtime_head, <tng_event_notifier_enabler_as_enabler(event_notifier_enabler)->filter_bytecode_head); /* * Link capture bytecodes if not linked yet. */ lttng_enabler_link_bytecode(event_notifier_priv->parent.desc, - &event_notifier_group->ctx, &event_notifier_priv->pub->capture_bytecode_runtime_head, + &event_notifier_group->ctx, &event_notifier_priv->capture_bytecode_runtime_head, &event_notifier_enabler->capture_bytecode_head); event_notifier_priv->num_captures = event_notifier_enabler->num_captures; @@ -1872,7 +1878,8 @@ void lttng_event_notifier_group_sync_enablers(struct lttng_event_notifier_group cds_list_for_each_entry(event_notifier_priv, &event_notifier_group->event_notifiers_head, node) { struct lttng_enabler_ref *enabler_ref; struct lttng_ust_bytecode_runtime *runtime; - int enabled = 0, has_enablers_without_bytecode = 0; + int enabled = 0, has_enablers_without_filter_bytecode = 0; + int nr_filters = 0, nr_captures = 0; /* Enable event_notifiers */ cds_list_for_each_entry(enabler_ref, @@ -1901,24 +1908,30 @@ void lttng_event_notifier_group_sync_enablers(struct lttng_event_notifier_group &event_notifier_priv->parent.enablers_ref_head, node) { if (enabler_ref->ref->enabled && cds_list_empty(&enabler_ref->ref->filter_bytecode_head)) { - has_enablers_without_bytecode = 1; + has_enablers_without_filter_bytecode = 1; break; } } - event_notifier_priv->pub->parent->has_enablers_without_bytecode = - has_enablers_without_bytecode; + event_notifier_priv->parent.has_enablers_without_filter_bytecode = + has_enablers_without_filter_bytecode; /* Enable filters */ cds_list_for_each_entry(runtime, - &event_notifier_priv->pub->parent->filter_bytecode_runtime_head, node) { + &event_notifier_priv->parent.filter_bytecode_runtime_head, node) { lttng_bytecode_sync_state(runtime); + nr_filters++; } + CMM_STORE_SHARED(event_notifier_priv->parent.pub->eval_filter, + !(has_enablers_without_filter_bytecode || !nr_filters)); /* Enable captures. */ cds_list_for_each_entry(runtime, - &event_notifier_priv->pub->capture_bytecode_runtime_head, node) { + &event_notifier_priv->capture_bytecode_runtime_head, node) { lttng_bytecode_sync_state(runtime); + nr_captures++; } + CMM_STORE_SHARED(event_notifier_priv->pub->eval_capture, + !!nr_captures); } lttng_ust_tp_probe_prune_release_queue(); } diff --git a/liblttng-ust/lttng-tracer-core.h b/liblttng-ust/lttng-tracer-core.h index 80b49f7f..54983cba 100644 --- a/liblttng-ust/lttng-tracer-core.h +++ b/liblttng-ust/lttng-tracer-core.h @@ -31,6 +31,7 @@ struct lttng_ust_lib_ring_buffer_ctx; struct lttng_ust_ctx_value; struct lttng_ust_event_recorder; struct lttng_ust_event_notifier; +struct lttng_ust_notification_ctx; __attribute__((visibility("hidden"))) int ust_lock(void) __attribute__ ((warn_unused_result)); @@ -100,7 +101,8 @@ void lttng_ust_dummy_get_value(struct lttng_ust_ctx_field *field, __attribute__((visibility("hidden"))) void lttng_event_notifier_notification_send( struct lttng_ust_event_notifier *event_notifier, - const char *stack_data); + const char *stack_data, + struct lttng_ust_notification_ctx *notif_ctx); __attribute__((visibility("hidden"))) struct lttng_counter_transport *lttng_counter_transport_find(const char *name); diff --git a/liblttng-ust/ust-events-internal.h b/liblttng-ust/ust-events-internal.h index 4e73e3e3..65023b3f 100644 --- a/liblttng-ust/ust-events-internal.h +++ b/liblttng-ust/ust-events-internal.h @@ -111,6 +111,26 @@ struct lttng_ust_bytecode_node { } bc; }; +/* + * Bytecode interpreter return value. + */ +enum lttng_ust_bytecode_interpreter_ret { + LTTNG_UST_BYTECODE_INTERPRETER_ERROR = -1, + LTTNG_UST_BYTECODE_INTERPRETER_OK = 0, +}; + +struct lttng_interpreter_output; +struct lttng_ust_bytecode_runtime_private; + +enum lttng_ust_bytecode_filter_result { + LTTNG_UST_BYTECODE_FILTER_ACCEPT = 0, + LTTNG_UST_BYTECODE_FILTER_REJECT = 1, +}; + +struct lttng_ust_bytecode_filter_ctx { + enum lttng_ust_bytecode_filter_result result; +}; + struct lttng_ust_excluder_node { struct cds_list_head node; struct lttng_enabler *enabler; @@ -250,6 +270,10 @@ struct lttng_ust_event_common_private { struct cds_list_head enablers_ref_head; int registered; /* has reg'd tracepoint probe */ uint64_t user_token; + + int has_enablers_without_filter_bytecode; + /* list of struct lttng_ust_bytecode_runtime, sorted by seqnum */ + struct cds_list_head filter_bytecode_runtime_head; }; struct lttng_ust_event_recorder_private { @@ -270,14 +294,18 @@ struct lttng_ust_event_notifier_private { uint64_t error_counter_index; struct cds_list_head node; /* Event notifier list */ struct cds_hlist_node hlist; /* Hash table of event notifiers */ -}; + struct cds_list_head capture_bytecode_runtime_head; -struct lttng_ust_bytecode_runtime_private { - struct bytecode_runtime *pub; /* Public bytecode runtime interface */ +}; +struct lttng_ust_bytecode_runtime { enum lttng_ust_bytecode_type type; struct lttng_ust_bytecode_node *bc; int link_failed; + int (*interpreter_func)(struct lttng_ust_bytecode_runtime *bytecode_runtime, + const char *interpreter_stack_data, + void *ctx); + struct cds_list_head node; /* list of bytecode runtime in event */ /* * Pointer to a URCU-protected pointer owned by an `struct * lttng_session`or `struct lttng_event_notifier_group`. @@ -864,4 +892,9 @@ struct lttng_ust_channel_buffer *lttng_ust_alloc_channel_buffer(void); __attribute__((visibility("hidden"))) void lttng_ust_free_channel_common(struct lttng_ust_channel_common *chan); +__attribute__((visibility("hidden"))) +int lttng_ust_interpret_event_filter(struct lttng_ust_event_common *event, + const char *interpreter_stack_data, + void *filter_ctx); + #endif /* _LTTNG_UST_EVENTS_INTERNAL_H */