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
);
110 * fix the events awaiting probe load.
112 for (i
= 0; i
< desc
->nr_events
; i
++) {
113 ret
= pending_probe_fix_events(desc
->event_desc
[i
]);
121 void ltt_probe_unregister(struct lttng_probe_desc
*desc
)
124 cds_list_del(&desc
->head
);
129 * called with UST lock held.
131 const struct lttng_event_desc
*ltt_event_get(const char *name
)
133 const struct lttng_event_desc
*event
;
135 event
= find_event(name
);
141 void ltt_event_put(const struct lttng_event_desc
*event
)
145 void ltt_probes_prune_event_list(struct lttng_ust_tracepoint_list
*list
)
147 struct tp_list_entry
*list_entry
, *tmp
;
149 cds_list_for_each_entry_safe(list_entry
, tmp
, &list
->head
, head
) {
150 cds_list_del(&list_entry
->head
);
156 * called with UST lock held.
158 int ltt_probes_get_event_list(struct lttng_ust_tracepoint_list
*list
)
160 struct lttng_probe_desc
*probe_desc
;
163 CDS_INIT_LIST_HEAD(&list
->head
);
164 cds_list_for_each_entry(probe_desc
, &probe_list
, head
) {
165 for (i
= 0; i
< probe_desc
->nr_events
; i
++) {
166 struct tp_list_entry
*list_entry
;
168 list_entry
= zmalloc(sizeof(*list_entry
));
171 cds_list_add(&list_entry
->head
, &list
->head
);
172 strncpy(list_entry
->tp
.name
,
173 probe_desc
->event_desc
[i
]->name
,
174 LTTNG_UST_SYM_NAME_LEN
);
175 list_entry
->tp
.name
[LTTNG_UST_SYM_NAME_LEN
- 1] = '\0';
176 if (!probe_desc
->event_desc
[i
]->loglevel
) {
177 list_entry
->tp
.loglevel
[0] = '\0';
178 list_entry
->tp
.loglevel_value
= 0;
180 strncpy(list_entry
->tp
.loglevel
,
181 (*probe_desc
->event_desc
[i
]->loglevel
)->identifier
,
182 LTTNG_UST_SYM_NAME_LEN
);
183 list_entry
->tp
.loglevel
[LTTNG_UST_SYM_NAME_LEN
- 1] = '\0';
184 list_entry
->tp
.loglevel_value
=
185 (*probe_desc
->event_desc
[i
]->loglevel
)->value
;
189 if (cds_list_empty(&list
->head
))
193 cds_list_first_entry(&list
->head
, struct tp_list_entry
, head
);
197 ltt_probes_prune_event_list(list
);
202 * Return current iteration position, advance internal iterator to next.
203 * Return NULL if end of list.
205 struct lttng_ust_tracepoint_iter
*
206 lttng_ust_tracepoint_list_get_iter_next(struct lttng_ust_tracepoint_list
*list
)
208 struct tp_list_entry
*entry
;
213 if (entry
->head
.next
== &list
->head
)
216 list
->iter
= cds_list_entry(entry
->head
.next
,
217 struct tp_list_entry
, head
);
222 * Get loglevel if the loglevel is present in the loglevel hash table.
223 * Must be called with ust lock held.
224 * Returns NULL if not present.
226 struct loglevel_entry
*get_loglevel(const char *name
)
228 struct cds_hlist_head
*head
;
229 struct cds_hlist_node
*node
;
230 struct loglevel_entry
*e
;
231 size_t name_len
= strlen(name
);
234 if (name_len
> LTTNG_UST_SYM_NAME_LEN
- 1) {
235 WARN("Truncating loglevel name %s which exceeds size limits of %u chars", name
, LTTNG_UST_SYM_NAME_LEN
- 1);
236 name_len
= LTTNG_UST_SYM_NAME_LEN
- 1;
238 hash
= jhash(name
, name_len
, 0);
239 head
= &loglevel_table
[hash
& (LOGLEVEL_TABLE_SIZE
- 1)];
240 cds_hlist_for_each_entry(e
, node
, head
, hlist
) {
241 if (!strncmp(name
, e
->name
, LTTNG_UST_SYM_NAME_LEN
- 1))
247 struct loglevel_entry
*get_loglevel_value(int64_t value
)
249 char name
[LTTNG_UST_SYM_NAME_LEN
];
252 ret
= snprintf(name
, LTTNG_UST_SYM_NAME_LEN
, "%lld", (long long) value
);
255 return get_loglevel(name
);
259 * marshall all probes/all events and create those that fit the
260 * loglevel. Add them to the events list as created.
263 void _probes_create_loglevel_events(struct loglevel_entry
*entry
,
264 struct session_loglevel
*loglevel
)
266 struct lttng_probe_desc
*probe_desc
;
267 struct lttng_ust_event event_param
;
270 cds_list_for_each_entry(probe_desc
, &probe_list
, head
) {
271 for (i
= 0; i
< probe_desc
->nr_events
; i
++) {
272 const struct tracepoint_loglevel_entry
*ev_ll
;
273 const struct lttng_event_desc
*event_desc
;
276 event_desc
= probe_desc
->event_desc
[i
];
277 if (!(event_desc
->loglevel
))
279 ev_ll
= *event_desc
->loglevel
;
280 if (isdigit(entry
->name
[0])) {
281 if (atoll(entry
->name
) == ev_ll
->value
) {
284 } else if (!strncmp(ev_ll
->identifier
, entry
->name
,
285 LTTNG_UST_SYM_NAME_LEN
- 1)) {
290 struct ltt_event
*ev
;
293 memcpy(&event_param
, &loglevel
->event_param
,
294 sizeof(event_param
));
295 memcpy(event_param
.name
,
297 sizeof(event_param
.name
));
299 ret
= ltt_event_create(loglevel
->chan
,
303 DBG("Error creating event");
306 cds_list_add(&ev
->loglevel_list
,
314 * Add the loglevel to the loglevel hash table. Must be called with
317 struct session_loglevel
*add_loglevel(const char *name
,
318 struct ltt_channel
*chan
,
319 struct lttng_ust_event
*event_param
)
321 struct cds_hlist_head
*head
;
322 struct cds_hlist_node
*node
;
323 struct loglevel_entry
*e
;
324 struct session_loglevel
*sl
;
326 size_t name_len
= strlen(name
);
329 if (name_len
> LTTNG_UST_SYM_NAME_LEN
- 1) {
330 WARN("Truncating loglevel name %s which exceeds size limits of %u chars", name
, LTTNG_UST_SYM_NAME_LEN
- 1);
331 name_len
= LTTNG_UST_SYM_NAME_LEN
- 1;
333 hash
= jhash(name
, name_len
, 0);
335 head
= &loglevel_table
[hash
& (LOGLEVEL_TABLE_SIZE
- 1)];
336 cds_hlist_for_each_entry(e
, node
, head
, hlist
) {
337 if (!strncmp(name
, e
->name
, LTTNG_UST_SYM_NAME_LEN
- 1)) {
345 * Using zmalloc here to allocate a variable length element. Could
346 * cause some memory fragmentation if overused.
348 e
= zmalloc(sizeof(struct loglevel_entry
) + name_len
+ 1);
350 return ERR_PTR(-ENOMEM
);
351 memcpy(&e
->name
[0], name
, name_len
+ 1);
352 e
->name
[name_len
] = '\0';
353 cds_hlist_add_head(&e
->hlist
, head
);
354 CDS_INIT_LIST_HEAD(&e
->session_list
);
357 /* session loglevel */
358 cds_list_for_each_entry(sl
, &e
->session_list
, session_list
) {
359 if (chan
== sl
->chan
) {
360 DBG("loglevel %s busy for this channel", name
);
361 return ERR_PTR(-EEXIST
); /* Already there */
364 sl
= zmalloc(sizeof(struct session_loglevel
));
366 return ERR_PTR(-ENOMEM
);
369 memcpy(&sl
->event_param
, event_param
, sizeof(sl
->event_param
));
370 sl
->event_param
.instrumentation
= LTTNG_UST_TRACEPOINT
;
371 CDS_INIT_LIST_HEAD(&sl
->events
);
372 cds_list_add(&sl
->list
, &chan
->session
->loglevels
);
373 cds_list_add(&sl
->session_list
, &e
->session_list
);
375 _probes_create_loglevel_events(e
, sl
);
380 * Remove the loglevel from the loglevel hash table. Must be called with
381 * ust_lock held. Only called at session teardown.
383 void _remove_loglevel(struct session_loglevel
*loglevel
)
385 struct ltt_event
*ev
, *tmp
;
388 * Just remove the events owned (for enable/disable) by this
389 * loglevel from the list. The session teardown will take care
390 * of freeing the event memory.
392 cds_list_for_each_entry_safe(ev
, tmp
, &loglevel
->events
,
394 cds_list_del(&ev
->loglevel_list
);
396 cds_list_del(&loglevel
->session_list
);
397 cds_list_del(&loglevel
->list
);
398 if (cds_list_empty(&loglevel
->entry
->session_list
)) {
399 cds_hlist_del(&loglevel
->entry
->hlist
);
400 free(loglevel
->entry
);
405 int ltt_loglevel_enable(struct session_loglevel
*loglevel
)
407 struct ltt_event
*ev
;
410 if (loglevel
->enabled
)
412 cds_list_for_each_entry(ev
, &loglevel
->events
, loglevel_list
) {
413 ret
= ltt_event_enable(ev
);
415 DBG("Error: enable error.\n");
419 loglevel
->enabled
= 1;
423 int ltt_loglevel_disable(struct session_loglevel
*loglevel
)
425 struct ltt_event
*ev
;
428 if (!loglevel
->enabled
)
430 cds_list_for_each_entry(ev
, &loglevel
->events
, loglevel_list
) {
431 ret
= ltt_event_disable(ev
);
433 DBG("Error: disable error.\n");
437 loglevel
->enabled
= 0;
444 * Return wildcard for a given event name if the event name match the
445 * one of the wildcards.
446 * Must be called with ust lock held.
447 * Returns NULL if not present.
449 struct wildcard_entry
*match_wildcard(const char *name
)
451 struct wildcard_entry
*e
;
453 cds_list_for_each_entry(e
, &wildcard_list
, list
) {
454 /* If only contain '*' */
455 if (strlen(e
->name
) == 1)
457 /* Compare excluding final '*' */
458 if (!strncmp(name
, e
->name
, strlen(e
->name
) - 1))
465 * marshall all probes/all events and create those that fit the
466 * wildcard. Add them to the events list as created.
469 void _probes_create_wildcard_events(struct wildcard_entry
*entry
,
470 struct session_wildcard
*wildcard
)
472 struct lttng_probe_desc
*probe_desc
;
473 struct lttng_ust_event event_param
;
476 cds_list_for_each_entry(probe_desc
, &probe_list
, head
) {
477 for (i
= 0; i
< probe_desc
->nr_events
; i
++) {
478 const struct lttng_event_desc
*event_desc
;
481 event_desc
= probe_desc
->event_desc
[i
];
482 /* compare excluding final '*' */
483 assert(strlen(entry
->name
) > 0);
484 if (strcmp(event_desc
->name
, "lttng_ust:metadata")
485 && (strlen(entry
->name
) == 1
486 || !strncmp(event_desc
->name
, entry
->name
,
487 strlen(entry
->name
) - 1))) {
491 struct ltt_event
*ev
;
494 memcpy(&event_param
, &wildcard
->event_param
,
495 sizeof(event_param
));
496 memcpy(event_param
.name
,
498 sizeof(event_param
.name
));
500 ret
= ltt_event_create(wildcard
->chan
,
504 DBG("Error creating event");
507 cds_list_add(&ev
->wildcard_list
,
515 * Add the wildcard to the wildcard hash table. Must be called with
518 struct session_wildcard
*add_wildcard(const char *name
,
519 struct ltt_channel
*chan
,
520 struct lttng_ust_event
*event_param
)
522 struct wildcard_entry
*e
;
523 struct session_wildcard
*sw
;
524 size_t name_len
= strlen(name
) + 1;
528 cds_list_for_each_entry(e
, &wildcard_list
, list
) {
529 if (!strncmp(name
, e
->name
, LTTNG_UST_SYM_NAME_LEN
- 1)) {
537 * Using zmalloc here to allocate a variable length element. Could
538 * cause some memory fragmentation if overused.
540 e
= zmalloc(sizeof(struct wildcard_entry
) + name_len
);
542 return ERR_PTR(-ENOMEM
);
543 memcpy(&e
->name
[0], name
, name_len
);
544 cds_list_add(&e
->list
, &wildcard_list
);
545 CDS_INIT_LIST_HEAD(&e
->session_list
);
548 /* session wildcard */
549 cds_list_for_each_entry(sw
, &e
->session_list
, session_list
) {
550 if (chan
== sw
->chan
) {
551 DBG("wildcard %s busy for this channel", name
);
552 return ERR_PTR(-EEXIST
); /* Already there */
555 sw
= zmalloc(sizeof(struct session_wildcard
));
557 return ERR_PTR(-ENOMEM
);
560 memcpy(&sw
->event_param
, event_param
, sizeof(sw
->event_param
));
561 sw
->event_param
.instrumentation
= LTTNG_UST_TRACEPOINT
;
562 CDS_INIT_LIST_HEAD(&sw
->events
);
563 cds_list_add(&sw
->list
, &chan
->session
->wildcards
);
564 cds_list_add(&sw
->session_list
, &e
->session_list
);
566 _probes_create_wildcard_events(e
, sw
);
571 * Remove the wildcard from the wildcard hash table. Must be called with
572 * ust_lock held. Only called at session teardown.
574 void _remove_wildcard(struct session_wildcard
*wildcard
)
576 struct ltt_event
*ev
, *tmp
;
579 * Just remove the events owned (for enable/disable) by this
580 * wildcard from the list. The session teardown will take care
581 * of freeing the event memory.
583 cds_list_for_each_entry_safe(ev
, tmp
, &wildcard
->events
,
585 cds_list_del(&ev
->wildcard_list
);
587 cds_list_del(&wildcard
->session_list
);
588 cds_list_del(&wildcard
->list
);
589 if (cds_list_empty(&wildcard
->entry
->session_list
)) {
590 cds_list_del(&wildcard
->entry
->list
);
591 free(wildcard
->entry
);
596 int ltt_wildcard_enable(struct session_wildcard
*wildcard
)
598 struct ltt_event
*ev
;
601 if (wildcard
->enabled
)
603 cds_list_for_each_entry(ev
, &wildcard
->events
, wildcard_list
) {
604 ret
= ltt_event_enable(ev
);
606 DBG("Error: enable error.\n");
610 wildcard
->enabled
= 1;
614 int ltt_wildcard_disable(struct session_wildcard
*wildcard
)
616 struct ltt_event
*ev
;
619 if (!wildcard
->enabled
)
621 cds_list_for_each_entry(ev
, &wildcard
->events
, wildcard_list
) {
622 ret
= ltt_event_disable(ev
);
624 DBG("Error: disable error.\n");
628 wildcard
->enabled
= 0;