The callbacks require the complete application context field names to
compare against the tables received from the TLS area.
We also need to free memory allocated by for the context event field and
context name in a destroy callback.
Therefore, allocate a data structure for each application context, and
use that data structure as private data. This allows callback to reach
the context name, and a destroy callback to free the allocated memory.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Change-Id: Ia34fe00f5945fb58ef991f9d40dec36ac9ab322c
/* End of base ABI. Fields below should be used after checking struct_size. */
};
/* End of base ABI. Fields below should be used after checking struct_size. */
};
+/*
+ * Application context callback private data
+ *
+ * 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_app_context {
+ uint32_t struct_size;
+
+ struct lttng_ust_event_field *event_field;
+ char *ctx_name;
+
+ /* End of base ABI. Fields below should be used after checking struct_size. */
+};
+
/*
* Returns an opaque pointer on success, which must be passed to
* lttng_ust_context_provider_unregister for unregistration. Returns
/*
* Returns an opaque pointer on success, which must be passed to
* lttng_ust_context_provider_unregister for unregistration. Returns
static size_t get_size_cb(void *priv, struct lttng_ust_probe_ctx *probe_ctx __attribute__((unused)),
size_t offset)
{
static size_t get_size_cb(void *priv, struct lttng_ust_probe_ctx *probe_ctx __attribute__((unused)),
size_t offset)
{
+ const struct lttng_ust_app_context *app_ctx = (const struct lttng_ust_app_context *) priv;
+ const char *ctx_name = app_ctx->ctx_name;
struct lttng_ust_jni_ctx_entry *jctx;
size_t size = 0;
struct lttng_ust_jni_ctx_entry *jctx;
size_t size = 0;
- struct lttng_ust_jni_provider *jni_provider = (struct lttng_ust_jni_provider *) priv;
- const char *ctx_name = jni_provider->name;
enum lttng_ust_jni_type jni_type;
size += lttng_ust_ring_buffer_align(offset, lttng_ust_rb_alignof(char));
enum lttng_ust_jni_type jni_type;
size += lttng_ust_ring_buffer_align(offset, lttng_ust_rb_alignof(char));
struct lttng_ust_ring_buffer_ctx *ctx,
struct lttng_ust_channel_buffer *lttng_chan_buf)
{
struct lttng_ust_ring_buffer_ctx *ctx,
struct lttng_ust_channel_buffer *lttng_chan_buf)
{
+ const struct lttng_ust_app_context *app_ctx = (const struct lttng_ust_app_context *) priv;
+ const char *ctx_name = app_ctx->ctx_name;
struct lttng_ust_jni_ctx_entry *jctx;
struct lttng_ust_jni_ctx_entry *jctx;
- struct lttng_ust_jni_provider *jni_provider = (struct lttng_ust_jni_provider *) priv;
- const char *ctx_name = jni_provider->name;
enum lttng_ust_jni_type jni_type;
char sel_char;
enum lttng_ust_jni_type jni_type;
char sel_char;
static void get_value_cb(void *priv, struct lttng_ust_probe_ctx *probe_ctx __attribute__((unused)),
struct lttng_ust_ctx_value *value)
{
static void get_value_cb(void *priv, struct lttng_ust_probe_ctx *probe_ctx __attribute__((unused)),
struct lttng_ust_ctx_value *value)
{
- struct lttng_ust_jni_provider *jni_provider = (struct lttng_ust_jni_provider *) priv;
+ const struct lttng_ust_app_context *app_ctx = (const struct lttng_ust_app_context *) priv;
+ const char *ctx_name = app_ctx->ctx_name;
struct lttng_ust_jni_ctx_entry *jctx;
struct lttng_ust_jni_ctx_entry *jctx;
- const char *ctx_name = jni_provider->name;
enum lttng_ust_jni_type jni_type;
jctx = lookup_ctx_by_name(ctx_name);
enum lttng_ust_jni_type jni_type;
jctx = lookup_ctx_by_name(ctx_name);
struct lttng_ust_ring_buffer_ctx *ctx,
struct lttng_ust_channel_buffer *chan),
void (*get_value)(void *priv, struct lttng_ust_probe_ctx *probe_ctx,
struct lttng_ust_ring_buffer_ctx *ctx,
struct lttng_ust_channel_buffer *chan),
void (*get_value)(void *priv, struct lttng_ust_probe_ctx *probe_ctx,
- struct lttng_ust_ctx_value *value),
- void *priv)
+ struct lttng_ust_ctx_value *value))
__attribute__((visibility("hidden")));
#endif /* _LTTNG_UST_CONTEXT_PROVIDER_INTERNAL_H */
__attribute__((visibility("hidden")));
#endif /* _LTTNG_UST_CONTEXT_PROVIDER_INTERNAL_H */
struct lttng_ust_ring_buffer_ctx *ctx,
struct lttng_ust_channel_buffer *chan),
void (*get_value)(void *priv, struct lttng_ust_probe_ctx *probe_ctx,
struct lttng_ust_ring_buffer_ctx *ctx,
struct lttng_ust_channel_buffer *chan),
void (*get_value)(void *priv, struct lttng_ust_probe_ctx *probe_ctx,
- struct lttng_ust_ctx_value *value),
- void *priv)
+ struct lttng_ust_ctx_value *value))
__attribute__((visibility("hidden")));
void lttng_ust_context_set_session_provider(const char *name,
__attribute__((visibility("hidden")));
void lttng_ust_context_set_session_provider(const char *name,
struct lttng_ust_ring_buffer_ctx *ctx,
struct lttng_ust_channel_buffer *chan),
void (*get_value)(void *priv, struct lttng_ust_probe_ctx *probe_ctx,
struct lttng_ust_ring_buffer_ctx *ctx,
struct lttng_ust_channel_buffer *chan),
void (*get_value)(void *priv, struct lttng_ust_probe_ctx *probe_ctx,
- struct lttng_ust_ctx_value *value),
- void *priv)
+ struct lttng_ust_ctx_value *value))
__attribute__((visibility("hidden")));
#endif /* _LTTNG_UST_EVENTS_INTERNAL_H */
__attribute__((visibility("hidden")));
#endif /* _LTTNG_UST_EVENTS_INTERNAL_H */
lttng_ust_context_set_session_provider(provider->name,
provider->get_size, provider->record,
lttng_ust_context_set_session_provider(provider->name,
provider->get_size, provider->record,
- provider->get_value, provider->priv);
lttng_ust_context_set_event_notifier_group_provider(provider->name,
provider->get_size, provider->record,
lttng_ust_context_set_event_notifier_group_provider(provider->name,
provider->get_size, provider->record,
- provider->get_value, provider->priv);
end:
ust_unlock();
return reg_provider;
end:
ust_unlock();
return reg_provider;
goto end;
lttng_ust_context_set_session_provider(reg_provider->provider->name,
lttng_ust_dummy_get_size, lttng_ust_dummy_record,
goto end;
lttng_ust_context_set_session_provider(reg_provider->provider->name,
lttng_ust_dummy_get_size, lttng_ust_dummy_record,
- lttng_ust_dummy_get_value, NULL);
+ lttng_ust_dummy_get_value);
lttng_ust_context_set_event_notifier_group_provider(reg_provider->provider->name,
lttng_ust_dummy_get_size, lttng_ust_dummy_record,
lttng_ust_context_set_event_notifier_group_provider(reg_provider->provider->name,
lttng_ust_dummy_get_size, lttng_ust_dummy_record,
- lttng_ust_dummy_get_value, NULL);
+ lttng_ust_dummy_get_value);
cds_hlist_del(®_provider->node);
end:
cds_hlist_del(®_provider->node);
end:
+static
+void app_context_destroy(void *priv)
+{
+ struct lttng_ust_app_context *app_ctx = (struct lttng_ust_app_context *) priv;
+
+ free(app_ctx->ctx_name);
+ free(app_ctx->event_field);
+}
+
+static
+const struct lttng_ust_type_common app_ctx_type = {
+ .type = lttng_ust_type_dynamic,
+};
+
/*
* Called with ust mutex held.
* Add application context to array of context, even if the application
/*
* Called with ust mutex held.
* Add application context to array of context, even if the application
const struct lttng_ust_context_provider *provider;
struct lttng_ust_ctx_field new_field = { 0 };
struct lttng_ust_event_field *event_field = NULL;
const struct lttng_ust_context_provider *provider;
struct lttng_ust_ctx_field new_field = { 0 };
struct lttng_ust_event_field *event_field = NULL;
- struct lttng_ust_type_common *type = NULL;
+ struct lttng_ust_app_context *app_ctx = NULL;
ret = -ENOMEM;
goto error_field_name_alloc;
}
ret = -ENOMEM;
goto error_field_name_alloc;
}
- type = zmalloc(sizeof(struct lttng_ust_type_common));
- if (!type) {
+ app_ctx = zmalloc(sizeof(struct lttng_ust_app_context));
+ if (!app_ctx) {
- goto error_field_type_alloc;
+ goto error_app_ctx_alloc;
+ app_ctx->struct_size = sizeof(struct lttng_ust_app_context);
+ app_ctx->event_field = event_field;
+ app_ctx->ctx_name = ctx_name;
+
event_field->name = ctx_name;
event_field->name = ctx_name;
- type->type = lttng_ust_type_dynamic;
- event_field->type = type;
+ event_field->type = &app_ctx_type;
new_field.event_field = event_field;
/*
* If provider is not found, we add the context anyway, but
new_field.event_field = event_field;
/*
* If provider is not found, we add the context anyway, but
new_field.get_size = provider->get_size;
new_field.record = provider->record;
new_field.get_value = provider->get_value;
new_field.get_size = provider->get_size;
new_field.record = provider->record;
new_field.get_value = provider->get_value;
- new_field.priv = provider->priv;
} else {
new_field.get_size = lttng_ust_dummy_get_size;
new_field.record = lttng_ust_dummy_record;
new_field.get_value = lttng_ust_dummy_get_value;
} else {
new_field.get_size = lttng_ust_dummy_get_size;
new_field.record = lttng_ust_dummy_record;
new_field.get_value = lttng_ust_dummy_get_value;
+ new_field.priv = app_ctx;
+ new_field.destroy = app_context_destroy;
/*
* For application context, add it by expanding
* ctx array.
/*
* For application context, add it by expanding
* ctx array.
- free(type);
-error_field_type_alloc:
+ free(app_ctx);
+error_app_ctx_alloc:
free(ctx_name);
error_field_name_alloc:
free(event_field);
free(ctx_name);
error_field_name_alloc:
free(event_field);
struct lttng_ust_ring_buffer_ctx *ctx,
struct lttng_ust_channel_buffer *chan),
void (*get_value)(void *priv, struct lttng_ust_probe_ctx *probe_ctx,
struct lttng_ust_ring_buffer_ctx *ctx,
struct lttng_ust_channel_buffer *chan),
void (*get_value)(void *priv, struct lttng_ust_probe_ctx *probe_ctx,
- struct lttng_ust_ctx_value *value),
- void *priv)
+ struct lttng_ust_ctx_value *value))
{
int i, ret;
struct lttng_ust_ctx *ctx = *_ctx, *new_ctx;
{
int i, ret;
struct lttng_ust_ctx *ctx = *_ctx, *new_ctx;
new_fields[i].get_size = get_size;
new_fields[i].record = record;
new_fields[i].get_value = get_value;
new_fields[i].get_size = get_size;
new_fields[i].record = record;
new_fields[i].get_value = get_value;
- new_fields[i].priv = priv;
}
new_ctx->fields = new_fields;
lttng_ust_rcu_assign_pointer(*_ctx, new_ctx);
}
new_ctx->fields = new_fields;
lttng_ust_rcu_assign_pointer(*_ctx, new_ctx);
struct lttng_ust_ring_buffer_ctx *ctx,
struct lttng_ust_channel_buffer *chan),
void (*get_value)(void *priv, struct lttng_ust_probe_ctx *probe_ctx,
struct lttng_ust_ring_buffer_ctx *ctx,
struct lttng_ust_channel_buffer *chan),
void (*get_value)(void *priv, struct lttng_ust_probe_ctx *probe_ctx,
- struct lttng_ust_ctx_value *value),
- void *priv)
+ struct lttng_ust_ctx_value *value))
{
struct lttng_ust_session_private *session_priv;
{
struct lttng_ust_session_private *session_priv;
int ret;
ret = lttng_ust_context_set_provider_rcu(&session_priv->ctx,
int ret;
ret = lttng_ust_context_set_provider_rcu(&session_priv->ctx,
- name, get_size, record, get_value, priv);
+ name, get_size, record, get_value);
if (ret)
abort();
cds_list_for_each_entry(chan, &session_priv->chan_head, node) {
ret = lttng_ust_context_set_provider_rcu(&chan->ctx,
if (ret)
abort();
cds_list_for_each_entry(chan, &session_priv->chan_head, node) {
ret = lttng_ust_context_set_provider_rcu(&chan->ctx,
- name, get_size, record, get_value, priv);
+ name, get_size, record, get_value);
if (ret)
abort();
}
cds_list_for_each_entry(event_recorder_priv, &session_priv->events_head, node) {
ret = lttng_ust_context_set_provider_rcu(&event_recorder_priv->ctx,
if (ret)
abort();
}
cds_list_for_each_entry(event_recorder_priv, &session_priv->events_head, node) {
ret = lttng_ust_context_set_provider_rcu(&event_recorder_priv->ctx,
- name, get_size, record, get_value, priv);
+ name, get_size, record, get_value);
struct lttng_ust_ring_buffer_ctx *ctx,
struct lttng_ust_channel_buffer *chan),
void (*get_value)(void *priv, struct lttng_ust_probe_ctx *probe_ctx,
struct lttng_ust_ring_buffer_ctx *ctx,
struct lttng_ust_channel_buffer *chan),
void (*get_value)(void *priv, struct lttng_ust_probe_ctx *probe_ctx,
- struct lttng_ust_ctx_value *value),
- void *priv)
+ struct lttng_ust_ctx_value *value))
{
struct lttng_event_notifier_group *event_notifier_group;
{
struct lttng_event_notifier_group *event_notifier_group;
ret = lttng_ust_context_set_provider_rcu(
&event_notifier_group->ctx,
ret = lttng_ust_context_set_provider_rcu(
&event_notifier_group->ctx,
- name, get_size, record, get_value, priv);
+ name, get_size, record, get_value);