#include "common/ust-fd.h"
#include "common/dynamic-type.h"
#include "common/ust-context-provider.h"
-#include "lttng-ust-uuid.h"
-#include "tracepoint-internal.h"
+#include "common/tracepoint.h"
#include "common/strutils.h"
#include "lttng-bytecode.h"
-#include "lttng-tracer.h"
+#include "common/tracer.h"
#include "lttng-tracer-core.h"
#include "lttng-ust-statedump.h"
#include "context-internal.h"
#include "lib/lttng-ust/events.h"
-#include "wait.h"
#include "common/ringbuffer/shm.h"
#include "common/ringbuffer/frontend_types.h"
#include "common/ringbuffer/frontend.h"
strcat(name, desc->event_name);
}
+static
+void lttng_event_enabler_unsync(struct lttng_event_enabler *event_enabler)
+{
+ cds_list_move(&event_enabler->node,
+ &event_enabler->chan->parent->session->priv->unsync_enablers_head);
+}
+
+static
+void lttng_session_unsync_enablers(struct lttng_ust_session *session)
+{
+ cds_list_splice(&session->priv->sync_enablers_head,
+ &session->priv->unsync_enablers_head);
+ CDS_INIT_LIST_HEAD(&session->priv->sync_enablers_head);
+}
+
+static
+void lttng_event_notifier_enabler_unsync(struct lttng_event_notifier_enabler *event_notifier_enabler)
+{
+ cds_list_move(&event_notifier_enabler->node,
+ &event_notifier_enabler->group->unsync_enablers_head);
+}
+
+static
+void lttng_event_notifier_group_unsync_enablers(struct lttng_event_notifier_group *event_notifier_group)
+{
+ cds_list_splice(&event_notifier_group->sync_enablers_head,
+ &event_notifier_group->unsync_enablers_head);
+ CDS_INIT_LIST_HEAD(&event_notifier_group->sync_enablers_head);
+}
+
/*
* Called with ust lock held.
*/
int req_loglevel)
{
if (!has_loglevel)
- loglevel = TRACE_DEFAULT;
+ loglevel = LTTNG_UST_TRACEPOINT_LOGLEVEL_DEFAULT;
switch (req_type) {
case LTTNG_UST_ABI_LOGLEVEL_RANGE:
if (loglevel <= req_loglevel
- || (req_loglevel == -1 && loglevel <= TRACE_DEBUG))
+ || (req_loglevel == -1 && loglevel <= LTTNG_UST_TRACEPOINT_LOGLEVEL_DEBUG))
return 1;
else
return 0;
case LTTNG_UST_ABI_LOGLEVEL_SINGLE:
if (loglevel == req_loglevel
- || (req_loglevel == -1 && loglevel <= TRACE_DEBUG))
+ || (req_loglevel == -1 && loglevel <= LTTNG_UST_TRACEPOINT_LOGLEVEL_DEBUG))
return 1;
else
return 0;
case LTTNG_UST_ABI_LOGLEVEL_ALL:
default:
- if (loglevel <= TRACE_DEBUG)
+ if (loglevel <= LTTNG_UST_TRACEPOINT_LOGLEVEL_DEBUG)
return 1;
else
return 0;
CDS_INIT_LIST_HEAD(&session->priv->chan_head);
CDS_INIT_LIST_HEAD(&session->priv->events_head);
CDS_INIT_LIST_HEAD(&session->priv->enums_head);
- CDS_INIT_LIST_HEAD(&session->priv->enablers_head);
+ CDS_INIT_LIST_HEAD(&session->priv->unsync_enablers_head);
+ CDS_INIT_LIST_HEAD(&session->priv->sync_enablers_head);
for (i = 0; i < LTTNG_UST_EVENT_HT_SIZE; i++)
CDS_INIT_HLIST_HEAD(&session->priv->events_ht.table[i]);
for (i = 0; i < LTTNG_UST_ENUM_HT_SIZE; i++)
return NULL;
}
- CDS_INIT_LIST_HEAD(&event_notifier_group->enablers_head);
+ CDS_INIT_LIST_HEAD(&event_notifier_group->sync_enablers_head);
+ CDS_INIT_LIST_HEAD(&event_notifier_group->unsync_enablers_head);
CDS_INIT_LIST_HEAD(&event_notifier_group->event_notifiers_head);
for (i = 0; i < LTTNG_UST_EVENT_NOTIFIER_HT_SIZE; i++)
CDS_INIT_HLIST_HEAD(&event_notifier_group->event_notifiers_ht.table[i]);
static
void _lttng_channel_unmap(struct lttng_ust_channel_buffer *lttng_chan)
{
- struct lttng_ust_lib_ring_buffer_channel *chan;
+ struct lttng_ust_ring_buffer_channel *chan;
struct lttng_ust_shm_handle *handle;
cds_list_del(<tng_chan->priv->node);
{
int ret;
const struct lttng_ust_event_desc *desc;
- char name[LTTNG_UST_ABI_SYM_NAME_LEN];
assert(event->priv->registered == 0);
desc = event->priv->desc;
- lttng_ust_format_event_name(desc, name);
- ret = lttng_ust_tp_probe_register_queue_release(name,
- desc->probe_callback,
- event, desc->signature);
+ ret = lttng_ust_tp_probe_register_queue_release(desc->probe_desc->provider_name,
+ desc->event_name,
+ desc->tp_class->probe_callback,
+ event, desc->tp_class->signature);
WARN_ON_ONCE(ret);
if (!ret)
event->priv->registered = 1;
{
int ret;
const struct lttng_ust_event_desc *desc;
- char name[LTTNG_UST_ABI_SYM_NAME_LEN];
assert(event->priv->registered == 1);
desc = event->priv->desc;
- lttng_ust_format_event_name(desc, name);
- ret = lttng_ust_tp_probe_unregister_queue_release(name,
- desc->probe_callback,
+ ret = lttng_ust_tp_probe_unregister_queue_release(desc->probe_desc->provider_name,
+ desc->event_name,
+ desc->tp_class->probe_callback,
event);
WARN_ON_ONCE(ret);
if (!ret)
lttng_ust_urcu_synchronize_rcu(); /* Wait for in-flight events to complete */
lttng_ust_tp_probe_prune_release_queue();
cds_list_for_each_entry_safe(event_enabler, event_tmpenabler,
- &session->priv->enablers_head, node)
+ &session->priv->unsync_enablers_head, node)
+ lttng_event_enabler_destroy(event_enabler);
+ cds_list_for_each_entry_safe(event_enabler, event_tmpenabler,
+ &session->priv->sync_enablers_head, node)
lttng_event_enabler_destroy(event_enabler);
cds_list_for_each_entry_safe(event_recorder_priv, tmpevent_recorder_priv,
&session->priv->events_head, node)
lttng_ust_urcu_synchronize_rcu();
cds_list_for_each_entry_safe(notifier_enabler, tmpnotifier_enabler,
- &event_notifier_group->enablers_head, node)
+ &event_notifier_group->sync_enablers_head, node)
+ lttng_event_notifier_enabler_destroy(notifier_enabler);
+ cds_list_for_each_entry_safe(notifier_enabler, tmpnotifier_enabler,
+ &event_notifier_group->unsync_enablers_head, node)
lttng_event_notifier_enabler_destroy(notifier_enabler);
cds_list_for_each_entry_safe(event_notifier_priv, tmpevent_notifier_priv,
static
int lttng_create_all_event_enums(size_t nr_fields,
- const struct lttng_ust_event_field **event_fields,
+ const struct lttng_ust_event_field * const *event_fields,
struct lttng_ust_session *session)
{
size_t i;
goto socket_error;
}
- ret = lttng_create_all_event_enums(desc->nr_fields, desc->fields,
+ ret = lttng_create_all_event_enums(desc->tp_class->nr_fields, desc->tp_class->fields,
session);
if (ret < 0) {
DBG("Error (%d) adding enum to session", ret);
event_recorder->parent->priv->desc = desc;
if (desc->loglevel)
- loglevel = *(*event_recorder->parent->priv->desc->loglevel);
+ loglevel = *(*desc->loglevel);
else
- loglevel = TRACE_DEFAULT;
+ loglevel = LTTNG_UST_TRACEPOINT_LOGLEVEL_DEFAULT;
if (desc->model_emf_uri)
uri = *(desc->model_emf_uri);
else
chan->priv->parent.objd,
name,
loglevel,
- desc->signature,
- desc->nr_fields,
- desc->fields,
+ desc->tp_class->signature,
+ desc->tp_class->nr_fields,
+ desc->tp_class->fields,
uri,
&event_recorder->priv->id);
if (ret < 0) {
unsigned int i;
/* Destroy enums of the current event. */
- for (i = 0; i < event_recorder->parent->priv->desc->nr_fields; i++) {
+ for (i = 0; i < event_recorder->parent->priv->desc->tp_class->nr_fields; i++) {
const struct lttng_ust_enum_desc *enum_desc;
const struct lttng_ust_event_field *field;
struct lttng_enum *curr_enum;
- field = event_recorder->parent->priv->desc->fields[i];
+ field = event_recorder->parent->priv->desc->tp_class->fields[i];
switch (field->type->type) {
case lttng_ust_type_enum:
enum_desc = lttng_ust_get_type_enum(field->type)->desc;
struct lttng_ust_session_private *session_priv;
cds_list_for_each_entry(session_priv, &sessions, node) {
+ /*
+ * New probes have appeared, we need to re-sync all
+ * enablers.
+ */
+ lttng_session_unsync_enablers(session_priv->pub);
lttng_session_lazy_sync_event_enablers(session_priv->pub);
}
return 0;
struct lttng_event_notifier_group *event_notifier_group;
cds_list_for_each_entry(event_notifier_group, &event_notifier_groups, node) {
+ /*
+ * New probes have appeared, we need to re-sync all
+ * enablers.
+ */
+ lttng_event_notifier_group_unsync_enablers(event_notifier_group);
lttng_event_notifier_group_sync_enablers(event_notifier_group);
}
return 0;
event_enabler->chan = chan;
/* ctx left NULL */
event_enabler->base.enabled = 0;
- cds_list_add(&event_enabler->node, &event_enabler->chan->parent->session->priv->enablers_head);
+ cds_list_add(&event_enabler->node, &event_enabler->chan->parent->session->priv->unsync_enablers_head);
lttng_session_lazy_sync_event_enablers(event_enabler->chan->parent->session);
return event_enabler;
event_notifier_enabler->group = event_notifier_group;
cds_list_add(&event_notifier_enabler->node,
- &event_notifier_group->enablers_head);
+ &event_notifier_group->unsync_enablers_head);
lttng_event_notifier_group_sync_enablers(event_notifier_group);
int lttng_event_enabler_enable(struct lttng_event_enabler *event_enabler)
{
lttng_event_enabler_as_enabler(event_enabler)->enabled = 1;
+ lttng_event_enabler_unsync(event_enabler);
lttng_session_lazy_sync_event_enablers(event_enabler->chan->parent->session);
return 0;
int lttng_event_enabler_disable(struct lttng_event_enabler *event_enabler)
{
lttng_event_enabler_as_enabler(event_enabler)->enabled = 0;
+ lttng_event_enabler_unsync(event_enabler);
lttng_session_lazy_sync_event_enablers(event_enabler->chan->parent->session);
return 0;
{
_lttng_enabler_attach_filter_bytecode(
lttng_event_enabler_as_enabler(event_enabler), bytecode);
-
+ lttng_event_enabler_unsync(event_enabler);
lttng_session_lazy_sync_event_enablers(event_enabler->chan->parent->session);
return 0;
}
{
_lttng_enabler_attach_exclusion(
lttng_event_enabler_as_enabler(event_enabler), excluder);
-
+ lttng_event_enabler_unsync(event_enabler);
lttng_session_lazy_sync_event_enablers(event_enabler->chan->parent->session);
return 0;
}
struct lttng_event_notifier_enabler *event_notifier_enabler)
{
lttng_event_notifier_enabler_as_enabler(event_notifier_enabler)->enabled = 1;
+ lttng_event_notifier_enabler_unsync(event_notifier_enabler);
lttng_event_notifier_group_sync_enablers(event_notifier_enabler->group);
return 0;
struct lttng_event_notifier_enabler *event_notifier_enabler)
{
lttng_event_notifier_enabler_as_enabler(event_notifier_enabler)->enabled = 0;
+ lttng_event_notifier_enabler_unsync(event_notifier_enabler);
lttng_event_notifier_group_sync_enablers(event_notifier_enabler->group);
return 0;
_lttng_enabler_attach_filter_bytecode(
lttng_event_notifier_enabler_as_enabler(event_notifier_enabler),
bytecode);
-
+ lttng_event_notifier_enabler_unsync(event_notifier_enabler);
lttng_event_notifier_group_sync_enablers(event_notifier_enabler->group);
return 0;
}
/* Take ownership of bytecode */
*bytecode = NULL;
event_notifier_enabler->num_captures++;
-
+ lttng_event_notifier_enabler_unsync(event_notifier_enabler);
lttng_event_notifier_group_sync_enablers(event_notifier_enabler->group);
return 0;
}
_lttng_enabler_attach_exclusion(
lttng_event_notifier_enabler_as_enabler(event_notifier_enabler),
excluder);
-
+ lttng_event_notifier_enabler_unsync(event_notifier_enabler);
lttng_event_notifier_group_sync_enablers(event_notifier_enabler->group);
return 0;
}
{
struct lttng_event_enabler *event_enabler;
struct lttng_ust_event_recorder_private *event_recorder_priv;
+ struct cds_list_head iter_list;
+
+ /*
+ * lttng_event_enabler_ref_event_recorders can cause lazy probes
+ * to add items to the unsync_enablers_head list. Iterate on a
+ * local copy of that list until it is stable (empty).
+ */
+ do {
+ CDS_INIT_LIST_HEAD(&iter_list);
+ cds_list_splice(&session->priv->unsync_enablers_head, &iter_list);
+ CDS_INIT_LIST_HEAD(&session->priv->unsync_enablers_head);
+ cds_list_for_each_entry(event_enabler, &iter_list, node)
+ lttng_event_enabler_ref_event_recorders(event_enabler);
+ cds_list_splice(&iter_list, &session->priv->sync_enablers_head);
+ } while (!cds_list_empty(&session->priv->unsync_enablers_head));
- cds_list_for_each_entry(event_enabler, &session->priv->enablers_head, node)
- lttng_event_enabler_ref_event_recorders(event_enabler);
/*
* For each event, if at least one of its enablers is enabled,
* and its channel and session transient states are enabled, we
lttng_ust_tp_probe_prune_release_queue();
}
-/* Support for event notifier is introduced by probe provider major version 2. */
-static
-bool lttng_ust_probe_supports_event_notifier(const struct lttng_ust_probe_desc *probe_desc)
-{
- return probe_desc->major >= 2;
-}
-
static
void lttng_create_event_notifier_if_missing(
struct lttng_event_notifier_enabler *event_notifier_enabler)
if (found)
continue;
- /* Check that the probe supports event notifiers, else report the error. */
- if (!lttng_ust_probe_supports_event_notifier(probe_desc)) {
- ERR("Probe \"%s\" contains event \"%s:%s\" which matches an enabled event notifier, "
- "but its version (%u.%u) is too old and does not implement event notifiers. "
- "It needs to be recompiled against a newer version of LTTng-UST, otherwise "
- "this event will not generate any notification.",
- probe_desc->provider_name,
- probe_desc->provider_name, desc->event_name,
- probe_desc->major,
- probe_desc->minor);
- continue;
- }
/*
* We need to create a event_notifier for this event probe.
*/
{
struct lttng_event_notifier_enabler *event_notifier_enabler;
struct lttng_ust_event_notifier_private *event_notifier_priv;
+ struct cds_list_head iter_list;
- cds_list_for_each_entry(event_notifier_enabler, &event_notifier_group->enablers_head, node)
- lttng_event_notifier_enabler_ref_event_notifiers(event_notifier_enabler);
+ /*
+ * lttng_event_notifier_enabler_ref_event_notifiers can cause
+ * lazy probes to add items to the unsync_enablers_head list.
+ * Iterate on a local copy of that list until it is stable
+ * (empty).
+ */
+ do {
+ CDS_INIT_LIST_HEAD(&iter_list);
+ cds_list_splice(&event_notifier_group->unsync_enablers_head, &iter_list);
+ CDS_INIT_LIST_HEAD(&event_notifier_group->unsync_enablers_head);
+ cds_list_for_each_entry(event_notifier_enabler, &iter_list, node)
+ lttng_event_notifier_enabler_ref_event_notifiers(event_notifier_enabler);
+ cds_list_splice(&iter_list, &event_notifier_group->sync_enablers_head);
+ } while (!cds_list_empty(&event_notifier_group->unsync_enablers_head));
/*
* For each event_notifier, if at least one of its enablers is enabled,
* context (either app context callbacks, or dummy callbacks).
*/
void lttng_ust_context_set_session_provider(const char *name,
- size_t (*get_size)(void *priv, size_t offset),
- void (*record)(void *priv, struct lttng_ust_lib_ring_buffer_ctx *ctx,
+ size_t (*get_size)(void *priv, struct lttng_ust_probe_ctx *probe_ctx,
+ size_t offset),
+ void (*record)(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_ctx_value *value),
- void *priv)
+ void (*get_value)(void *priv, struct lttng_ust_probe_ctx *probe_ctx,
+ struct lttng_ust_ctx_value *value))
{
struct lttng_ust_session_private *session_priv;
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,
- 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,
- name, get_size, record, get_value, priv);
+ name, get_size, record, get_value);
if (ret)
abort();
}
* context (either app context callbacks, or dummy callbacks).
*/
void lttng_ust_context_set_event_notifier_group_provider(const char *name,
- size_t (*get_size)(void *priv, size_t offset),
- void (*record)(void *priv, struct lttng_ust_lib_ring_buffer_ctx *ctx,
+ size_t (*get_size)(void *priv, struct lttng_ust_probe_ctx *probe_ctx,
+ size_t offset),
+ void (*record)(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_ctx_value *value),
- void *priv)
+ void (*get_value)(void *priv, struct lttng_ust_probe_ctx *probe_ctx,
+ struct lttng_ust_ctx_value *value))
{
struct lttng_event_notifier_group *event_notifier_group;
ret = lttng_ust_context_set_provider_rcu(
&event_notifier_group->ctx,
- name, get_size, record, get_value, priv);
+ name, get_size, record, get_value);
if (ret)
abort();
}