void lttng_event_notifier_notification_send(struct lttng_event_notifier *event_notifier,
struct lttng_probe_ctx *lttng_probe_ctx,
- const char *stack_data);
+ const char *stack_data,
+ struct lttng_kernel_notifier_ctx *notif_ctx);
#endif /* _LTTNG_EVENT_NOTIFIER_NOTIFICATION_H */
int has_enablers_without_bytecode;
};
+struct lttng_kernel_notifier_ctx {
+ int eval_capture;
+};
+
// FIXME: Really similar to lttng_event above. Could those be merged ?
struct lttng_event_notifier {
enum lttng_event_type evtype; /* First field. */
size_t num_captures;
struct list_head capture_bytecode_runtime_head;
int has_enablers_without_bytecode;
+ int eval_capture; /* Should evaluate capture */
void (*send_notification)(struct lttng_event_notifier *event_notifier,
struct lttng_probe_ctx *lttng_probe_ctx,
- const char *interpreter_stack_data);
+ const char *interpreter_stack_data,
+ struct lttng_kernel_notifier_ctx *notif_ctx);
struct lttng_event_notifier_group *group; /* Weak ref */
};
struct probe_local_vars __tp_locvar; \
struct probe_local_vars *tp_locvar __attribute__((unused)) = \
&__tp_locvar; \
+ struct lttng_kernel_notifier_ctx __notif_ctx; \
+ bool __interpreter_stack_prepared = false; \
\
if (unlikely(!READ_ONCE(__event_notifier->enabled))) \
return; \
\
__event_prepare_interpreter_stack__##_name(__stackvar.__interpreter_stack_data, \
tp_locvar, _args); \
+ __interpreter_stack_prepared = true; \
lttng_list_for_each_entry_rcu(bc_runtime, &__event_notifier->filter_bytecode_runtime_head, node) { \
if (unlikely(bc_runtime->interpreter_funcs.filter(bc_runtime, &__lttng_probe_ctx, \
__stackvar.__interpreter_stack_data) & LTTNG_INTERPRETER_RECORD_FLAG)) \
goto __post; \
} \
\
- if (unlikely(!list_empty(&__event_notifier->capture_bytecode_runtime_head))) \
+ __notif_ctx.eval_capture = LTTNG_READ_ONCE(__event_notifier->eval_capture); \
+ if (unlikely(!__interpreter_stack_prepared && __notif_ctx.eval_capture)) \
__event_prepare_interpreter_stack__##_name( \
__stackvar.__interpreter_stack_data, \
tp_locvar, _args); \
\
__event_notifier->send_notification(__event_notifier, \
&__lttng_probe_ctx, \
- __stackvar.__interpreter_stack_data); \
+ __stackvar.__interpreter_stack_data, \
+ &__notif_ctx); \
\
__post: \
_code_post \
struct probe_local_vars __tp_locvar; \
struct probe_local_vars *tp_locvar __attribute__((unused)) = \
&__tp_locvar; \
+ struct lttng_kernel_notifier_ctx __notif_ctx; \
+ bool __interpreter_stack_prepared = false; \
\
if (unlikely(!READ_ONCE(__event_notifier->enabled))) \
return; \
\
__event_prepare_interpreter_stack__##_name(__stackvar.__interpreter_stack_data, \
tp_locvar); \
+ __interpreter_stack_prepared = true; \
lttng_list_for_each_entry_rcu(bc_runtime, &__event_notifier->filter_bytecode_runtime_head, node) { \
if (unlikely(bc_runtime->interpreter_funcs.filter(bc_runtime, &__lttng_probe_ctx, \
__stackvar.__interpreter_stack_data) & LTTNG_INTERPRETER_RECORD_FLAG)) \
goto __post; \
} \
\
- if (unlikely(!list_empty(&__event_notifier->capture_bytecode_runtime_head))) \
+ __notif_ctx.eval_capture = LTTNG_READ_ONCE(__event_notifier->eval_capture); \
+ if (unlikely(!__interpreter_stack_prepared && __notif_ctx.eval_capture)) \
__event_prepare_interpreter_stack__##_name( \
__stackvar.__interpreter_stack_data, \
tp_locvar); \
\
__event_notifier->send_notification(__event_notifier, \
&__lttng_probe_ctx, \
- __stackvar.__interpreter_stack_data); \
+ __stackvar.__interpreter_stack_data, \
+ &__notif_ctx); \
__post: \
_code_post \
return; \
void lttng_event_notifier_notification_send(struct lttng_event_notifier *event_notifier,
struct lttng_probe_ctx *lttng_probe_ctx,
- const char *stack_data)
+ const char *stack_data,
+ struct lttng_kernel_notifier_ctx *notif_ctx)
{
struct lttng_event_notifier_notification notif = { 0 };
int ret;
goto end;
}
- if (unlikely(!list_empty(&event_notifier->capture_bytecode_runtime_head))) {
+ if (unlikely(notif_ctx->eval_capture)) {
struct lttng_bytecode_runtime *capture_bc_runtime;
/*
* `output` parameter to the capture buffer. If the interpreter
* fails, append an empty capture to the buffer.
*/
- list_for_each_entry(capture_bc_runtime,
+ list_for_each_entry_rcu(capture_bc_runtime,
&event_notifier->capture_bytecode_runtime_head, node) {
struct lttng_interpreter_output output;
list_for_each_entry(runtime,
&event_notifier->capture_bytecode_runtime_head, node)
lttng_bytecode_capture_sync_state(runtime);
+
+ WRITE_ONCE(event_notifier->eval_capture, !!event_notifier->num_captures);
}
}
{
struct lttng_event_notifier *event_notifier =
container_of(p, struct lttng_event_notifier, u.kprobe.kp);
+ struct lttng_kernel_notifier_ctx notif_ctx;
if (unlikely(!READ_ONCE(event_notifier->enabled)))
return 0;
- event_notifier->send_notification(event_notifier, NULL, NULL);
+ notif_ctx.eval_capture = LTTNG_READ_ONCE(event_notifier->eval_capture);
+ event_notifier->send_notification(event_notifier, NULL, NULL, ¬if_ctx);
return 0;
}
struct lttng_uprobe_handler *uprobe_handler =
container_of(uc, struct lttng_uprobe_handler, up_consumer);
struct lttng_event_notifier *event_notifier = uprobe_handler->u.event_notifier;
+ struct lttng_kernel_notifier_ctx notif_ctx;
if (unlikely(!READ_ONCE(event_notifier->enabled)))
return 0;
- event_notifier->send_notification(event_notifier, NULL, NULL);
+ notif_ctx.eval_capture = LTTNG_READ_ONCE(event_notifier->eval_capture);
+ event_notifier->send_notification(event_notifier, NULL, NULL, ¬if_ctx);
return 0;
}