2 * SPDX-License-Identifier: LGPL-2.1-only
4 * Copyright 2010-2012 (C) Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6 * Holds LTTng probes registry.
12 #include <urcu/list.h>
13 #include <urcu/hlist.h>
14 #include <lttng/ust-events.h>
15 #include <lttng/tracepoint.h>
16 #include "tracepoint-internal.h"
18 #include <ust-helper.h>
21 #include "lttng-tracer-core.h"
24 #include "ust-events-internal.h"
27 * probe list is protected by ust_lock()/ust_unlock().
29 static CDS_LIST_HEAD(_probe_list
);
32 * List of probes registered by not yet processed.
34 static CDS_LIST_HEAD(lazy_probe_init
);
37 * lazy_nesting counter ensures we don't trigger lazy probe registration
38 * fixup while we are performing the fixup. It is protected by the ust
41 static int lazy_nesting
;
44 * Validate that each event within the probe provider refers to the
45 * right probe, and that the resulting name is not too long.
48 bool check_event_provider(struct lttng_ust_probe_desc
*probe_desc
)
52 for (i
= 0; i
< probe_desc
->nr_events
; i
++) {
53 const struct lttng_ust_event_desc
*event_desc
= probe_desc
->event_desc
[i
];
55 if (event_desc
->probe_desc
!= probe_desc
) {
56 ERR("Error registering probe provider '%s'. Event '%s:%s' refers to the wrong provider descriptor.",
57 probe_desc
->provider_name
, probe_desc
->provider_name
, event_desc
->event_name
);
58 return false; /* provider mismatch */
60 if (!lttng_ust_validate_event_name(event_desc
)) {
61 ERR("Error registering probe provider '%s'. Event '%s:%s' name is too long.",
62 probe_desc
->provider_name
, probe_desc
->provider_name
, event_desc
->event_name
);
63 return false; /* provider mismatch */
70 * Called under ust lock.
73 void lttng_lazy_probe_register(struct lttng_ust_probe_desc
*desc
)
75 struct lttng_ust_probe_desc
*iter
;
76 struct cds_list_head
*probe_list
;
79 * The provider ensures there are no duplicate event names.
80 * Duplicated TRACEPOINT_EVENT event names would generate a
81 * compile-time error due to duplicated symbol names.
85 * We sort the providers by struct lttng_ust_probe_desc pointer
88 probe_list
= &_probe_list
;
89 cds_list_for_each_entry_reverse(iter
, probe_list
, head
) {
90 BUG_ON(iter
== desc
); /* Should never be in the list twice */
92 /* We belong to the location right after iter. */
93 cds_list_add(&desc
->head
, &iter
->head
);
97 /* We should be added at the head of the list */
98 cds_list_add(&desc
->head
, probe_list
);
100 DBG("just registered probe %s containing %u events",
101 desc
->provider_name
, desc
->nr_events
);
105 * Called under ust lock.
108 void fixup_lazy_probes(void)
110 struct lttng_ust_probe_desc
*iter
, *tmp
;
114 cds_list_for_each_entry_safe(iter
, tmp
,
115 &lazy_probe_init
, lazy_init_head
) {
116 lttng_lazy_probe_register(iter
);
118 cds_list_del(&iter
->lazy_init_head
);
120 ret
= lttng_fix_pending_events();
126 * Called under ust lock.
128 struct cds_list_head
*lttng_get_probe_list_head(void)
130 if (!lazy_nesting
&& !cds_list_empty(&lazy_probe_init
))
136 int check_provider_version(struct lttng_ust_probe_desc
*desc
)
139 * Check tracepoint provider version compatibility.
141 if (desc
->major
<= LTTNG_UST_PROVIDER_MAJOR
) {
142 DBG("Provider \"%s\" accepted, version %u.%u is compatible "
143 "with LTTng UST provider version %u.%u.",
144 desc
->provider_name
, desc
->major
, desc
->minor
,
145 LTTNG_UST_PROVIDER_MAJOR
,
146 LTTNG_UST_PROVIDER_MINOR
);
147 if (desc
->major
< LTTNG_UST_PROVIDER_MAJOR
) {
148 DBG("However, some LTTng UST features might not be "
149 "available for this provider unless it is "
150 "recompiled against a more recent LTTng UST.");
152 return 1; /* accept */
154 ERR("Provider \"%s\" rejected, version %u.%u is incompatible "
155 "with LTTng UST provider version %u.%u. Please upgrade "
157 desc
->provider_name
, desc
->major
, desc
->minor
,
158 LTTNG_UST_PROVIDER_MAJOR
,
159 LTTNG_UST_PROVIDER_MINOR
);
160 return 0; /* reject */
165 int lttng_ust_probe_register(struct lttng_ust_probe_desc
*desc
)
169 lttng_ust_fixup_tls();
172 * If version mismatch, don't register, but don't trigger assert
173 * on caller. The version check just prints an error.
175 if (!check_provider_version(desc
))
177 if (!check_event_provider(desc
))
182 cds_list_add(&desc
->lazy_init_head
, &lazy_probe_init
);
184 DBG("adding probe %s containing %u events to lazy registration list",
185 desc
->provider_name
, desc
->nr_events
);
187 * If there is at least one active session, we need to register
188 * the probe immediately, since we cannot delay event
189 * registration because they are needed ASAP.
191 if (lttng_session_active())
194 lttng_fix_pending_event_notifiers();
200 void lttng_ust_probe_unregister(struct lttng_ust_probe_desc
*desc
)
202 lttng_ust_fixup_tls();
204 if (!check_provider_version(desc
))
209 cds_list_del(&desc
->head
);
211 cds_list_del(&desc
->lazy_init_head
);
213 lttng_probe_provider_unregister_events(desc
);
214 DBG("just unregistered probes of provider %s", desc
->provider_name
);
219 void lttng_probes_prune_event_list(struct lttng_ust_tracepoint_list
*list
)
221 struct tp_list_entry
*list_entry
, *tmp
;
223 cds_list_for_each_entry_safe(list_entry
, tmp
, &list
->head
, head
) {
224 cds_list_del(&list_entry
->head
);
230 * called with UST lock held.
232 int lttng_probes_get_event_list(struct lttng_ust_tracepoint_list
*list
)
234 struct lttng_ust_probe_desc
*probe_desc
;
236 struct cds_list_head
*probe_list
;
238 probe_list
= lttng_get_probe_list_head();
239 CDS_INIT_LIST_HEAD(&list
->head
);
240 cds_list_for_each_entry(probe_desc
, probe_list
, head
) {
241 for (i
= 0; i
< probe_desc
->nr_events
; i
++) {
242 const struct lttng_ust_event_desc
*event_desc
=
243 probe_desc
->event_desc
[i
];
244 struct tp_list_entry
*list_entry
;
246 /* Skip event if name is too long. */
247 if (!lttng_ust_validate_event_name(event_desc
))
249 list_entry
= zmalloc(sizeof(*list_entry
));
252 cds_list_add(&list_entry
->head
, &list
->head
);
253 lttng_ust_format_event_name(event_desc
, list_entry
->tp
.name
);
254 if (!event_desc
->loglevel
) {
255 list_entry
->tp
.loglevel
= TRACE_DEFAULT
;
257 list_entry
->tp
.loglevel
= *(*event_desc
->loglevel
);
261 if (cds_list_empty(&list
->head
))
265 cds_list_first_entry(&list
->head
, struct tp_list_entry
, head
);
269 lttng_probes_prune_event_list(list
);
274 * Return current iteration position, advance internal iterator to next.
275 * Return NULL if end of list.
277 struct lttng_ust_abi_tracepoint_iter
*
278 lttng_ust_tracepoint_list_get_iter_next(struct lttng_ust_tracepoint_list
*list
)
280 struct tp_list_entry
*entry
;
285 if (entry
->head
.next
== &list
->head
)
288 list
->iter
= cds_list_entry(entry
->head
.next
,
289 struct tp_list_entry
, head
);
293 void lttng_probes_prune_field_list(struct lttng_ust_field_list
*list
)
295 struct tp_field_list_entry
*list_entry
, *tmp
;
297 cds_list_for_each_entry_safe(list_entry
, tmp
, &list
->head
, head
) {
298 cds_list_del(&list_entry
->head
);
304 * called with UST lock held.
306 int lttng_probes_get_field_list(struct lttng_ust_field_list
*list
)
308 struct lttng_ust_probe_desc
*probe_desc
;
310 struct cds_list_head
*probe_list
;
312 probe_list
= lttng_get_probe_list_head();
313 CDS_INIT_LIST_HEAD(&list
->head
);
314 cds_list_for_each_entry(probe_desc
, probe_list
, head
) {
315 for (i
= 0; i
< probe_desc
->nr_events
; i
++) {
316 const struct lttng_ust_event_desc
*event_desc
=
317 probe_desc
->event_desc
[i
];
320 if (event_desc
->nr_fields
== 0) {
321 /* Events without fields. */
322 struct tp_field_list_entry
*list_entry
;
324 /* Skip event if name is too long. */
325 if (!lttng_ust_validate_event_name(event_desc
))
327 list_entry
= zmalloc(sizeof(*list_entry
));
330 cds_list_add(&list_entry
->head
, &list
->head
);
331 lttng_ust_format_event_name(event_desc
, list_entry
->field
.event_name
);
332 list_entry
->field
.field_name
[0] = '\0';
333 list_entry
->field
.type
= LTTNG_UST_ABI_FIELD_OTHER
;
334 if (!event_desc
->loglevel
) {
335 list_entry
->field
.loglevel
= TRACE_DEFAULT
;
337 list_entry
->field
.loglevel
= *(*event_desc
->loglevel
);
339 list_entry
->field
.nowrite
= 1;
342 for (j
= 0; j
< event_desc
->nr_fields
; j
++) {
343 const struct lttng_ust_event_field
*event_field
=
344 event_desc
->fields
[j
];
345 struct tp_field_list_entry
*list_entry
;
347 /* Skip event if name is too long. */
348 if (!lttng_ust_validate_event_name(event_desc
))
350 list_entry
= zmalloc(sizeof(*list_entry
));
353 cds_list_add(&list_entry
->head
, &list
->head
);
354 lttng_ust_format_event_name(event_desc
, list_entry
->field
.event_name
);
355 strncpy(list_entry
->field
.field_name
,
357 LTTNG_UST_ABI_SYM_NAME_LEN
);
358 list_entry
->field
.field_name
[LTTNG_UST_ABI_SYM_NAME_LEN
- 1] = '\0';
359 switch (event_field
->type
->type
) {
360 case lttng_ust_type_integer
:
361 list_entry
->field
.type
= LTTNG_UST_ABI_FIELD_INTEGER
;
363 case lttng_ust_type_string
:
364 list_entry
->field
.type
= LTTNG_UST_ABI_FIELD_STRING
;
366 case lttng_ust_type_array
:
367 if (lttng_ust_get_type_array(event_field
->type
)->encoding
== lttng_ust_string_encoding_none
)
368 list_entry
->field
.type
= LTTNG_UST_ABI_FIELD_OTHER
;
370 list_entry
->field
.type
= LTTNG_UST_ABI_FIELD_STRING
;
372 case lttng_ust_type_sequence
:
373 if (lttng_ust_get_type_sequence(event_field
->type
)->encoding
== lttng_ust_string_encoding_none
)
374 list_entry
->field
.type
= LTTNG_UST_ABI_FIELD_OTHER
;
376 list_entry
->field
.type
= LTTNG_UST_ABI_FIELD_STRING
;
378 case lttng_ust_type_float
:
379 list_entry
->field
.type
= LTTNG_UST_ABI_FIELD_FLOAT
;
381 case lttng_ust_type_enum
:
382 list_entry
->field
.type
= LTTNG_UST_ABI_FIELD_ENUM
;
385 list_entry
->field
.type
= LTTNG_UST_ABI_FIELD_OTHER
;
387 if (!event_desc
->loglevel
) {
388 list_entry
->field
.loglevel
= TRACE_DEFAULT
;
390 list_entry
->field
.loglevel
= *(*event_desc
->loglevel
);
392 list_entry
->field
.nowrite
= event_field
->nowrite
;
396 if (cds_list_empty(&list
->head
))
400 cds_list_first_entry(&list
->head
,
401 struct tp_field_list_entry
, head
);
405 lttng_probes_prune_field_list(list
);
410 * Return current iteration position, advance internal iterator to next.
411 * Return NULL if end of list.
413 struct lttng_ust_abi_field_iter
*
414 lttng_ust_field_list_get_iter_next(struct lttng_ust_field_list
*list
)
416 struct tp_field_list_entry
*entry
;
421 if (entry
->head
.next
== &list
->head
)
424 list
->iter
= cds_list_entry(entry
->head
.next
,
425 struct tp_field_list_entry
, head
);
426 return &entry
->field
;