4 * Holds LTTng probes registry.
6 * Copyright 2010-2012 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; only
11 * version 2.1 of the License.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <urcu/list.h>
26 #include <urcu/hlist.h>
27 #include <lttng/ust-events.h>
28 #include <lttng/tracepoint.h>
29 #include "tracepoint-internal.h"
34 #include "lttng-tracer-core.h"
39 * probe list is protected by ust_lock()/ust_unlock().
41 CDS_LIST_HEAD(probe_list
);
43 struct cds_list_head
*lttng_get_probe_list_head(void)
49 const struct lttng_probe_desc
*find_provider(const char *provider
)
51 struct lttng_probe_desc
*iter
;
53 cds_list_for_each_entry(iter
, &probe_list
, head
) {
54 if (!strcmp(iter
->provider
, provider
))
61 int check_event_provider(struct lttng_probe_desc
*desc
)
64 size_t provider_name_len
;
66 provider_name_len
= strnlen(desc
->provider
,
67 LTTNG_UST_SYM_NAME_LEN
- 1);
68 for (i
= 0; i
< desc
->nr_events
; i
++) {
69 if (strncmp(desc
->event_desc
[i
]->name
,
72 return 0; /* provider mismatch */
77 int lttng_probe_register(struct lttng_probe_desc
*desc
)
79 struct lttng_probe_desc
*iter
;
86 * Check if the provider has already been registered.
88 if (find_provider(desc
->provider
)) {
94 * Each provider enforce that every event name begins with the
95 * provider name. Check this in an assertion for extra
96 * carefulness. This ensures we cannot have duplicate event
97 * names across providers.
99 assert(check_event_provider(desc
));
102 * The provider ensures there are no duplicate event names.
103 * Duplicated TRACEPOINT_EVENT event names would generate a
104 * compile-time error due to duplicated symbol names.
108 * We sort the providers by struct lttng_probe_desc pointer
111 cds_list_for_each_entry_reverse(iter
, &probe_list
, head
) {
112 BUG_ON(iter
== desc
); /* Should never be in the list twice */
114 /* We belong to the location right after iter. */
115 cds_list_add(&desc
->head
, &iter
->head
);
119 /* We should be added at the head of the list */
120 cds_list_add(&desc
->head
, &probe_list
);
122 DBG("just registered probe %s containing %u events",
123 desc
->provider
, desc
->nr_events
);
125 * fix the events awaiting probe load.
127 for (i
= 0; i
< desc
->nr_events
; i
++) {
128 const struct lttng_event_desc
*ed
;
130 ed
= desc
->event_desc
[i
];
131 DBG("Registered event probe \"%s\" with signature \"%s\"",
132 ed
->name
, ed
->signature
);
133 ret
= lttng_fix_pending_event_desc(ed
);
141 /* Backward compatibility with UST 2.0 */
142 int ltt_probe_register(struct lttng_probe_desc
*desc
)
144 return lttng_probe_register(desc
);
147 void lttng_probe_unregister(struct lttng_probe_desc
*desc
)
150 cds_list_del(&desc
->head
);
151 DBG("just unregistered probe %s", desc
->provider
);
155 /* Backward compatibility with UST 2.0 */
156 void ltt_probe_unregister(struct lttng_probe_desc
*desc
)
158 lttng_probe_unregister(desc
);
161 void lttng_probes_prune_event_list(struct lttng_ust_tracepoint_list
*list
)
163 struct tp_list_entry
*list_entry
, *tmp
;
165 cds_list_for_each_entry_safe(list_entry
, tmp
, &list
->head
, head
) {
166 cds_list_del(&list_entry
->head
);
172 * called with UST lock held.
174 int lttng_probes_get_event_list(struct lttng_ust_tracepoint_list
*list
)
176 struct lttng_probe_desc
*probe_desc
;
179 CDS_INIT_LIST_HEAD(&list
->head
);
180 cds_list_for_each_entry(probe_desc
, &probe_list
, head
) {
181 for (i
= 0; i
< probe_desc
->nr_events
; i
++) {
182 struct tp_list_entry
*list_entry
;
184 list_entry
= zmalloc(sizeof(*list_entry
));
187 cds_list_add(&list_entry
->head
, &list
->head
);
188 strncpy(list_entry
->tp
.name
,
189 probe_desc
->event_desc
[i
]->name
,
190 LTTNG_UST_SYM_NAME_LEN
);
191 list_entry
->tp
.name
[LTTNG_UST_SYM_NAME_LEN
- 1] = '\0';
192 if (!probe_desc
->event_desc
[i
]->loglevel
) {
193 list_entry
->tp
.loglevel
= TRACE_DEFAULT
;
195 list_entry
->tp
.loglevel
= *(*probe_desc
->event_desc
[i
]->loglevel
);
199 if (cds_list_empty(&list
->head
))
203 cds_list_first_entry(&list
->head
, struct tp_list_entry
, head
);
207 lttng_probes_prune_event_list(list
);
212 * Return current iteration position, advance internal iterator to next.
213 * Return NULL if end of list.
215 struct lttng_ust_tracepoint_iter
*
216 lttng_ust_tracepoint_list_get_iter_next(struct lttng_ust_tracepoint_list
*list
)
218 struct tp_list_entry
*entry
;
223 if (entry
->head
.next
== &list
->head
)
226 list
->iter
= cds_list_entry(entry
->head
.next
,
227 struct tp_list_entry
, head
);
231 void lttng_probes_prune_field_list(struct lttng_ust_field_list
*list
)
233 struct tp_field_list_entry
*list_entry
, *tmp
;
235 cds_list_for_each_entry_safe(list_entry
, tmp
, &list
->head
, head
) {
236 cds_list_del(&list_entry
->head
);
242 * called with UST lock held.
244 int lttng_probes_get_field_list(struct lttng_ust_field_list
*list
)
246 struct lttng_probe_desc
*probe_desc
;
249 CDS_INIT_LIST_HEAD(&list
->head
);
250 cds_list_for_each_entry(probe_desc
, &probe_list
, head
) {
251 for (i
= 0; i
< probe_desc
->nr_events
; i
++) {
252 const struct lttng_event_desc
*event_desc
=
253 probe_desc
->event_desc
[i
];
256 if (event_desc
->nr_fields
== 0) {
257 /* Events without fields. */
258 struct tp_field_list_entry
*list_entry
;
260 list_entry
= zmalloc(sizeof(*list_entry
));
263 cds_list_add(&list_entry
->head
, &list
->head
);
264 strncpy(list_entry
->field
.event_name
,
266 LTTNG_UST_SYM_NAME_LEN
);
267 list_entry
->field
.event_name
[LTTNG_UST_SYM_NAME_LEN
- 1] = '\0';
268 list_entry
->field
.field_name
[0] = '\0';
269 list_entry
->field
.type
= LTTNG_UST_FIELD_OTHER
;
270 if (!event_desc
->loglevel
) {
271 list_entry
->field
.loglevel
= TRACE_DEFAULT
;
273 list_entry
->field
.loglevel
= *(*event_desc
->loglevel
);
275 list_entry
->field
.nowrite
= 1;
278 for (j
= 0; j
< event_desc
->nr_fields
; j
++) {
279 const struct lttng_event_field
*event_field
=
280 &event_desc
->fields
[j
];
281 struct tp_field_list_entry
*list_entry
;
283 list_entry
= zmalloc(sizeof(*list_entry
));
286 cds_list_add(&list_entry
->head
, &list
->head
);
287 strncpy(list_entry
->field
.event_name
,
289 LTTNG_UST_SYM_NAME_LEN
);
290 list_entry
->field
.event_name
[LTTNG_UST_SYM_NAME_LEN
- 1] = '\0';
291 strncpy(list_entry
->field
.field_name
,
293 LTTNG_UST_SYM_NAME_LEN
);
294 list_entry
->field
.field_name
[LTTNG_UST_SYM_NAME_LEN
- 1] = '\0';
295 switch (event_field
->type
.atype
) {
297 list_entry
->field
.type
= LTTNG_UST_FIELD_INTEGER
;
300 list_entry
->field
.type
= LTTNG_UST_FIELD_STRING
;
303 if (event_field
->type
.u
.array
.elem_type
.atype
!= atype_integer
304 || event_field
->type
.u
.array
.elem_type
.u
.basic
.integer
.encoding
== lttng_encode_none
)
305 list_entry
->field
.type
= LTTNG_UST_FIELD_OTHER
;
307 list_entry
->field
.type
= LTTNG_UST_FIELD_STRING
;
310 if (event_field
->type
.u
.sequence
.elem_type
.atype
!= atype_integer
311 || event_field
->type
.u
.sequence
.elem_type
.u
.basic
.integer
.encoding
== lttng_encode_none
)
312 list_entry
->field
.type
= LTTNG_UST_FIELD_OTHER
;
314 list_entry
->field
.type
= LTTNG_UST_FIELD_STRING
;
317 list_entry
->field
.type
= LTTNG_UST_FIELD_FLOAT
;
320 list_entry
->field
.type
= LTTNG_UST_FIELD_ENUM
;
323 list_entry
->field
.type
= LTTNG_UST_FIELD_OTHER
;
325 if (!event_desc
->loglevel
) {
326 list_entry
->field
.loglevel
= TRACE_DEFAULT
;
328 list_entry
->field
.loglevel
= *(*event_desc
->loglevel
);
330 list_entry
->field
.nowrite
= event_field
->nowrite
;
334 if (cds_list_empty(&list
->head
))
338 cds_list_first_entry(&list
->head
,
339 struct tp_field_list_entry
, head
);
343 lttng_probes_prune_field_list(list
);
348 * Return current iteration position, advance internal iterator to next.
349 * Return NULL if end of list.
351 struct lttng_ust_field_iter
*
352 lttng_ust_field_list_get_iter_next(struct lttng_ust_field_list
*list
)
354 struct tp_field_list_entry
*entry
;
359 if (entry
->head
.next
== &list
->head
)
362 list
->iter
= cds_list_entry(entry
->head
.next
,
363 struct tp_field_list_entry
, head
);
364 return &entry
->field
;