4 * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6 * Holds LTTng probes registry.
8 * Dual LGPL v2.1/GPL v2 license.
13 #include <urcu/list.h>
14 #include <urcu/hlist.h>
15 #include <lttng/ust-events.h>
20 #include "ltt-tracer-core.h"
25 * probe list is protected by ust_lock()/ust_unlock().
27 static CDS_LIST_HEAD(probe_list
);
30 * Loglevel hash table, containing the active loglevels.
31 * Protected by ust lock.
33 #define LOGLEVEL_HASH_BITS 6
34 #define LOGLEVEL_TABLE_SIZE (1 << LOGLEVEL_HASH_BITS)
35 static struct cds_hlist_head loglevel_table
[LOGLEVEL_TABLE_SIZE
];
38 * Wildcard list, containing the active wildcards.
39 * Protected by ust lock.
41 static CDS_LIST_HEAD(wildcard_list
);
44 const struct lttng_probe_desc
*find_provider(const char *provider
)
46 struct lttng_probe_desc
*iter
;
48 cds_list_for_each_entry(iter
, &probe_list
, head
) {
49 if (!strcmp(iter
->provider
, provider
))
56 const struct lttng_event_desc
*find_event(const char *name
)
58 struct lttng_probe_desc
*probe_desc
;
61 cds_list_for_each_entry(probe_desc
, &probe_list
, head
) {
62 for (i
= 0; i
< probe_desc
->nr_events
; i
++) {
63 if (!strncmp(probe_desc
->event_desc
[i
]->name
, name
,
64 LTTNG_UST_SYM_NAME_LEN
- 1))
65 return probe_desc
->event_desc
[i
];
71 int ltt_probe_register(struct lttng_probe_desc
*desc
)
73 struct lttng_probe_desc
*iter
;
78 if (find_provider(desc
->provider
)) {
83 * TODO: This is O(N^2). Turn into a hash table when probe registration
84 * overhead becomes an issue.
86 for (i
= 0; i
< desc
->nr_events
; i
++) {
87 if (find_event(desc
->event_desc
[i
]->name
)) {
94 * We sort the providers by struct lttng_probe_desc pointer
97 cds_list_for_each_entry_reverse(iter
, &probe_list
, head
) {
98 BUG_ON(iter
== desc
); /* Should never be in the list twice */
100 /* We belong to the location right after iter. */
101 cds_list_add(&desc
->head
, &iter
->head
);
105 /* We should be added at the head of the list */
106 cds_list_add(&desc
->head
, &probe_list
);
108 DBG("just registered probe %s containing %u events",
109 desc
->provider
, desc
->nr_events
);
111 * fix the events awaiting probe load.
113 for (i
= 0; i
< desc
->nr_events
; i
++) {
114 ret
= pending_probe_fix_events(desc
->event_desc
[i
]);
122 void ltt_probe_unregister(struct lttng_probe_desc
*desc
)
125 cds_list_del(&desc
->head
);
126 DBG("just unregistered probe %s", desc
->provider
);
131 * called with UST lock held.
133 const struct lttng_event_desc
*ltt_event_get(const char *name
)
135 const struct lttng_event_desc
*event
;
137 event
= find_event(name
);
143 void ltt_event_put(const struct lttng_event_desc
*event
)
147 void ltt_probes_prune_event_list(struct lttng_ust_tracepoint_list
*list
)
149 struct tp_list_entry
*list_entry
, *tmp
;
151 cds_list_for_each_entry_safe(list_entry
, tmp
, &list
->head
, head
) {
152 cds_list_del(&list_entry
->head
);
158 * called with UST lock held.
160 int ltt_probes_get_event_list(struct lttng_ust_tracepoint_list
*list
)
162 struct lttng_probe_desc
*probe_desc
;
165 CDS_INIT_LIST_HEAD(&list
->head
);
166 cds_list_for_each_entry(probe_desc
, &probe_list
, head
) {
167 for (i
= 0; i
< probe_desc
->nr_events
; i
++) {
168 struct tp_list_entry
*list_entry
;
170 list_entry
= zmalloc(sizeof(*list_entry
));
173 cds_list_add(&list_entry
->head
, &list
->head
);
174 strncpy(list_entry
->tp
.name
,
175 probe_desc
->event_desc
[i
]->name
,
176 LTTNG_UST_SYM_NAME_LEN
);
177 list_entry
->tp
.name
[LTTNG_UST_SYM_NAME_LEN
- 1] = '\0';
178 if (!probe_desc
->event_desc
[i
]->loglevel
) {
179 list_entry
->tp
.loglevel
[0] = '\0';
180 list_entry
->tp
.loglevel_value
= 0;
182 strncpy(list_entry
->tp
.loglevel
,
183 (*probe_desc
->event_desc
[i
]->loglevel
)->identifier
,
184 LTTNG_UST_SYM_NAME_LEN
);
185 list_entry
->tp
.loglevel
[LTTNG_UST_SYM_NAME_LEN
- 1] = '\0';
186 list_entry
->tp
.loglevel_value
=
187 (*probe_desc
->event_desc
[i
]->loglevel
)->value
;
191 if (cds_list_empty(&list
->head
))
195 cds_list_first_entry(&list
->head
, struct tp_list_entry
, head
);
199 ltt_probes_prune_event_list(list
);
204 * Return current iteration position, advance internal iterator to next.
205 * Return NULL if end of list.
207 struct lttng_ust_tracepoint_iter
*
208 lttng_ust_tracepoint_list_get_iter_next(struct lttng_ust_tracepoint_list
*list
)
210 struct tp_list_entry
*entry
;
215 if (entry
->head
.next
== &list
->head
)
218 list
->iter
= cds_list_entry(entry
->head
.next
,
219 struct tp_list_entry
, head
);
224 * Get loglevel if the loglevel is present in the loglevel hash table.
225 * Must be called with ust lock held.
226 * Returns NULL if not present.
228 struct loglevel_entry
*get_loglevel(const char *name
)
230 struct cds_hlist_head
*head
;
231 struct cds_hlist_node
*node
;
232 struct loglevel_entry
*e
;
233 size_t name_len
= strlen(name
);
236 if (name_len
> LTTNG_UST_SYM_NAME_LEN
- 1) {
237 WARN("Truncating loglevel name %s which exceeds size limits of %u chars", name
, LTTNG_UST_SYM_NAME_LEN
- 1);
238 name_len
= LTTNG_UST_SYM_NAME_LEN
- 1;
240 hash
= jhash(name
, name_len
, 0);
241 head
= &loglevel_table
[hash
& (LOGLEVEL_TABLE_SIZE
- 1)];
242 cds_hlist_for_each_entry(e
, node
, head
, hlist
) {
243 if (!strncmp(name
, e
->name
, LTTNG_UST_SYM_NAME_LEN
- 1))
249 struct loglevel_entry
*get_loglevel_value(int64_t value
)
251 char name
[LTTNG_UST_SYM_NAME_LEN
];
254 ret
= snprintf(name
, LTTNG_UST_SYM_NAME_LEN
, "%lld", (long long) value
);
257 return get_loglevel(name
);
261 * marshall all probes/all events and create those that fit the
262 * loglevel. Add them to the events list as created.
265 void _probes_create_loglevel_events(struct loglevel_entry
*entry
,
266 struct session_loglevel
*loglevel
)
268 struct lttng_probe_desc
*probe_desc
;
269 struct lttng_ust_event event_param
;
272 cds_list_for_each_entry(probe_desc
, &probe_list
, head
) {
273 for (i
= 0; i
< probe_desc
->nr_events
; i
++) {
274 const struct tracepoint_loglevel_entry
*ev_ll
;
275 const struct lttng_event_desc
*event_desc
;
278 event_desc
= probe_desc
->event_desc
[i
];
279 if (!(event_desc
->loglevel
))
281 ev_ll
= *event_desc
->loglevel
;
282 if (isdigit(entry
->name
[0])) {
283 if (atoll(entry
->name
) == ev_ll
->value
) {
286 } else if (!strncmp(ev_ll
->identifier
, entry
->name
,
287 LTTNG_UST_SYM_NAME_LEN
- 1)) {
292 struct ltt_event
*ev
;
295 memcpy(&event_param
, &loglevel
->event_param
,
296 sizeof(event_param
));
297 memcpy(event_param
.name
,
299 sizeof(event_param
.name
));
301 ret
= ltt_event_create(loglevel
->chan
,
305 DBG("Error creating event");
308 cds_list_add(&ev
->loglevel_list
,
316 * Add the loglevel to the loglevel hash table. Must be called with
319 struct session_loglevel
*add_loglevel(const char *name
,
320 struct ltt_channel
*chan
,
321 struct lttng_ust_event
*event_param
)
323 struct cds_hlist_head
*head
;
324 struct cds_hlist_node
*node
;
325 struct loglevel_entry
*e
;
326 struct session_loglevel
*sl
;
328 size_t name_len
= strlen(name
);
331 if (name_len
> LTTNG_UST_SYM_NAME_LEN
- 1) {
332 WARN("Truncating loglevel name %s which exceeds size limits of %u chars", name
, LTTNG_UST_SYM_NAME_LEN
- 1);
333 name_len
= LTTNG_UST_SYM_NAME_LEN
- 1;
335 hash
= jhash(name
, name_len
, 0);
337 head
= &loglevel_table
[hash
& (LOGLEVEL_TABLE_SIZE
- 1)];
338 cds_hlist_for_each_entry(e
, node
, head
, hlist
) {
339 if (!strncmp(name
, e
->name
, LTTNG_UST_SYM_NAME_LEN
- 1)) {
347 * Using zmalloc here to allocate a variable length element. Could
348 * cause some memory fragmentation if overused.
350 e
= zmalloc(sizeof(struct loglevel_entry
) + name_len
+ 1);
352 return ERR_PTR(-ENOMEM
);
353 memcpy(&e
->name
[0], name
, name_len
+ 1);
354 e
->name
[name_len
] = '\0';
355 cds_hlist_add_head(&e
->hlist
, head
);
356 CDS_INIT_LIST_HEAD(&e
->session_list
);
359 /* session loglevel */
360 cds_list_for_each_entry(sl
, &e
->session_list
, session_list
) {
361 if (chan
== sl
->chan
) {
362 DBG("loglevel %s busy for this channel", name
);
363 return ERR_PTR(-EEXIST
); /* Already there */
366 sl
= zmalloc(sizeof(struct session_loglevel
));
368 return ERR_PTR(-ENOMEM
);
371 memcpy(&sl
->event_param
, event_param
, sizeof(sl
->event_param
));
372 sl
->event_param
.instrumentation
= LTTNG_UST_TRACEPOINT
;
373 CDS_INIT_LIST_HEAD(&sl
->events
);
374 cds_list_add(&sl
->list
, &chan
->session
->loglevels
);
375 cds_list_add(&sl
->session_list
, &e
->session_list
);
377 _probes_create_loglevel_events(e
, sl
);
382 * Remove the loglevel from the loglevel hash table. Must be called with
383 * ust_lock held. Only called at session teardown.
385 void _remove_loglevel(struct session_loglevel
*loglevel
)
387 struct ltt_event
*ev
, *tmp
;
390 * Just remove the events owned (for enable/disable) by this
391 * loglevel from the list. The session teardown will take care
392 * of freeing the event memory.
394 cds_list_for_each_entry_safe(ev
, tmp
, &loglevel
->events
,
396 cds_list_del(&ev
->loglevel_list
);
398 cds_list_del(&loglevel
->session_list
);
399 cds_list_del(&loglevel
->list
);
400 if (cds_list_empty(&loglevel
->entry
->session_list
)) {
401 cds_hlist_del(&loglevel
->entry
->hlist
);
402 free(loglevel
->entry
);
407 int ltt_loglevel_enable(struct session_loglevel
*loglevel
)
409 struct ltt_event
*ev
;
412 if (loglevel
->enabled
)
414 cds_list_for_each_entry(ev
, &loglevel
->events
, loglevel_list
) {
415 ret
= ltt_event_enable(ev
);
417 DBG("Error: enable error.\n");
421 loglevel
->enabled
= 1;
425 int ltt_loglevel_disable(struct session_loglevel
*loglevel
)
427 struct ltt_event
*ev
;
430 if (!loglevel
->enabled
)
432 cds_list_for_each_entry(ev
, &loglevel
->events
, loglevel_list
) {
433 ret
= ltt_event_disable(ev
);
435 DBG("Error: disable error.\n");
439 loglevel
->enabled
= 0;
446 * Return wildcard for a given event name if the event name match the
447 * one of the wildcards.
448 * Must be called with ust lock held.
449 * Returns NULL if not present.
451 struct wildcard_entry
*match_wildcard(const char *name
)
453 struct wildcard_entry
*e
;
455 cds_list_for_each_entry(e
, &wildcard_list
, list
) {
456 /* If only contain '*' */
457 if (strlen(e
->name
) == 1)
459 /* Compare excluding final '*' */
460 if (!strncmp(name
, e
->name
, strlen(e
->name
) - 1))
467 * marshall all probes/all events and create those that fit the
468 * wildcard. Add them to the events list as created.
471 void _probes_create_wildcard_events(struct wildcard_entry
*entry
,
472 struct session_wildcard
*wildcard
)
474 struct lttng_probe_desc
*probe_desc
;
475 struct lttng_ust_event event_param
;
478 cds_list_for_each_entry(probe_desc
, &probe_list
, head
) {
479 for (i
= 0; i
< probe_desc
->nr_events
; i
++) {
480 const struct lttng_event_desc
*event_desc
;
483 event_desc
= probe_desc
->event_desc
[i
];
484 /* compare excluding final '*' */
485 assert(strlen(entry
->name
) > 0);
486 if (strcmp(event_desc
->name
, "lttng_ust:metadata")
487 && (strlen(entry
->name
) == 1
488 || !strncmp(event_desc
->name
, entry
->name
,
489 strlen(entry
->name
) - 1))) {
493 struct ltt_event
*ev
;
496 memcpy(&event_param
, &wildcard
->event_param
,
497 sizeof(event_param
));
498 memcpy(event_param
.name
,
500 sizeof(event_param
.name
));
502 ret
= ltt_event_create(wildcard
->chan
,
506 DBG("Error creating event");
509 cds_list_add(&ev
->wildcard_list
,
517 * Add the wildcard to the wildcard hash table. Must be called with
520 struct session_wildcard
*add_wildcard(const char *name
,
521 struct ltt_channel
*chan
,
522 struct lttng_ust_event
*event_param
)
524 struct wildcard_entry
*e
;
525 struct session_wildcard
*sw
;
526 size_t name_len
= strlen(name
) + 1;
530 cds_list_for_each_entry(e
, &wildcard_list
, list
) {
531 if (!strncmp(name
, e
->name
, LTTNG_UST_SYM_NAME_LEN
- 1)) {
539 * Using zmalloc here to allocate a variable length element. Could
540 * cause some memory fragmentation if overused.
542 e
= zmalloc(sizeof(struct wildcard_entry
) + name_len
);
544 return ERR_PTR(-ENOMEM
);
545 memcpy(&e
->name
[0], name
, name_len
);
546 cds_list_add(&e
->list
, &wildcard_list
);
547 CDS_INIT_LIST_HEAD(&e
->session_list
);
550 /* session wildcard */
551 cds_list_for_each_entry(sw
, &e
->session_list
, session_list
) {
552 if (chan
== sw
->chan
) {
553 DBG("wildcard %s busy for this channel", name
);
554 return ERR_PTR(-EEXIST
); /* Already there */
557 sw
= zmalloc(sizeof(struct session_wildcard
));
559 return ERR_PTR(-ENOMEM
);
562 memcpy(&sw
->event_param
, event_param
, sizeof(sw
->event_param
));
563 sw
->event_param
.instrumentation
= LTTNG_UST_TRACEPOINT
;
564 CDS_INIT_LIST_HEAD(&sw
->events
);
565 cds_list_add(&sw
->list
, &chan
->session
->wildcards
);
566 cds_list_add(&sw
->session_list
, &e
->session_list
);
568 _probes_create_wildcard_events(e
, sw
);
573 * Remove the wildcard from the wildcard hash table. Must be called with
574 * ust_lock held. Only called at session teardown.
576 void _remove_wildcard(struct session_wildcard
*wildcard
)
578 struct ltt_event
*ev
, *tmp
;
581 * Just remove the events owned (for enable/disable) by this
582 * wildcard from the list. The session teardown will take care
583 * of freeing the event memory.
585 cds_list_for_each_entry_safe(ev
, tmp
, &wildcard
->events
,
587 cds_list_del(&ev
->wildcard_list
);
589 cds_list_del(&wildcard
->session_list
);
590 cds_list_del(&wildcard
->list
);
591 if (cds_list_empty(&wildcard
->entry
->session_list
)) {
592 cds_list_del(&wildcard
->entry
->list
);
593 free(wildcard
->entry
);
598 int ltt_wildcard_enable(struct session_wildcard
*wildcard
)
600 struct ltt_event
*ev
;
603 if (wildcard
->enabled
)
605 cds_list_for_each_entry(ev
, &wildcard
->events
, wildcard_list
) {
606 ret
= ltt_event_enable(ev
);
608 DBG("Error: enable error.\n");
612 wildcard
->enabled
= 1;
616 int ltt_wildcard_disable(struct session_wildcard
*wildcard
)
618 struct ltt_event
*ev
;
621 if (!wildcard
->enabled
)
623 cds_list_for_each_entry(ev
, &wildcard
->events
, wildcard_list
) {
624 ret
= ltt_event_disable(ev
);
626 DBG("Error: disable error.\n");
630 wildcard
->enabled
= 0;