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 * Wildcard list, containing the active wildcards.
31 * Protected by ust lock.
33 static CDS_LIST_HEAD(wildcard_list
);
36 const struct lttng_probe_desc
*find_provider(const char *provider
)
38 struct lttng_probe_desc
*iter
;
40 cds_list_for_each_entry(iter
, &probe_list
, head
) {
41 if (!strcmp(iter
->provider
, provider
))
48 const struct lttng_event_desc
*find_event(const char *name
)
50 struct lttng_probe_desc
*probe_desc
;
53 cds_list_for_each_entry(probe_desc
, &probe_list
, head
) {
54 for (i
= 0; i
< probe_desc
->nr_events
; i
++) {
55 if (!strncmp(probe_desc
->event_desc
[i
]->name
, name
,
56 LTTNG_UST_SYM_NAME_LEN
- 1))
57 return probe_desc
->event_desc
[i
];
63 int ltt_probe_register(struct lttng_probe_desc
*desc
)
65 struct lttng_probe_desc
*iter
;
70 if (find_provider(desc
->provider
)) {
75 * TODO: This is O(N^2). Turn into a hash table when probe registration
76 * overhead becomes an issue.
78 for (i
= 0; i
< desc
->nr_events
; i
++) {
79 if (find_event(desc
->event_desc
[i
]->name
)) {
86 * We sort the providers by struct lttng_probe_desc pointer
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
, desc
->nr_events
);
103 * fix the events awaiting probe load.
105 for (i
= 0; i
< desc
->nr_events
; i
++) {
106 ret
= pending_probe_fix_events(desc
->event_desc
[i
]);
114 void ltt_probe_unregister(struct lttng_probe_desc
*desc
)
117 cds_list_del(&desc
->head
);
118 DBG("just unregistered probe %s", desc
->provider
);
123 * called with UST lock held.
125 const struct lttng_event_desc
*ltt_event_get(const char *name
)
127 const struct lttng_event_desc
*event
;
129 event
= find_event(name
);
135 void ltt_event_put(const struct lttng_event_desc
*event
)
139 void ltt_probes_prune_event_list(struct lttng_ust_tracepoint_list
*list
)
141 struct tp_list_entry
*list_entry
, *tmp
;
143 cds_list_for_each_entry_safe(list_entry
, tmp
, &list
->head
, head
) {
144 cds_list_del(&list_entry
->head
);
150 * called with UST lock held.
152 int ltt_probes_get_event_list(struct lttng_ust_tracepoint_list
*list
)
154 struct lttng_probe_desc
*probe_desc
;
157 CDS_INIT_LIST_HEAD(&list
->head
);
158 cds_list_for_each_entry(probe_desc
, &probe_list
, head
) {
159 for (i
= 0; i
< probe_desc
->nr_events
; i
++) {
160 struct tp_list_entry
*list_entry
;
162 list_entry
= zmalloc(sizeof(*list_entry
));
165 cds_list_add(&list_entry
->head
, &list
->head
);
166 strncpy(list_entry
->tp
.name
,
167 probe_desc
->event_desc
[i
]->name
,
168 LTTNG_UST_SYM_NAME_LEN
);
169 list_entry
->tp
.name
[LTTNG_UST_SYM_NAME_LEN
- 1] = '\0';
170 if (!probe_desc
->event_desc
[i
]->loglevel
) {
171 list_entry
->tp
.loglevel
[0] = '\0';
172 list_entry
->tp
.loglevel_value
= 0;
174 strncpy(list_entry
->tp
.loglevel
,
175 (*probe_desc
->event_desc
[i
]->loglevel
)->identifier
,
176 LTTNG_UST_SYM_NAME_LEN
);
177 list_entry
->tp
.loglevel
[LTTNG_UST_SYM_NAME_LEN
- 1] = '\0';
178 list_entry
->tp
.loglevel_value
=
179 (*probe_desc
->event_desc
[i
]->loglevel
)->value
;
183 if (cds_list_empty(&list
->head
))
187 cds_list_first_entry(&list
->head
, struct tp_list_entry
, head
);
191 ltt_probes_prune_event_list(list
);
196 * Return current iteration position, advance internal iterator to next.
197 * Return NULL if end of list.
199 struct lttng_ust_tracepoint_iter
*
200 lttng_ust_tracepoint_list_get_iter_next(struct lttng_ust_tracepoint_list
*list
)
202 struct tp_list_entry
*entry
;
207 if (entry
->head
.next
== &list
->head
)
210 list
->iter
= cds_list_entry(entry
->head
.next
,
211 struct tp_list_entry
, head
);
218 * Return wildcard for a given event name if the event name match the
219 * one of the wildcards.
220 * Must be called with ust lock held.
221 * Returns NULL if not present.
223 struct wildcard_entry
*match_wildcard(const char *name
)
225 struct wildcard_entry
*e
;
227 cds_list_for_each_entry(e
, &wildcard_list
, list
) {
228 /* If only contain '*' */
229 if (strlen(e
->name
) == 1)
231 /* Compare excluding final '*' */
232 if (!strncmp(name
, e
->name
, strlen(e
->name
) - 1))
239 * marshall all probes/all events and create those that fit the
240 * wildcard. Add them to the events list as created.
243 void _probes_create_wildcard_events(struct wildcard_entry
*entry
,
244 struct session_wildcard
*wildcard
)
246 struct lttng_probe_desc
*probe_desc
;
247 struct lttng_ust_event event_param
;
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
;
255 event_desc
= probe_desc
->event_desc
[i
];
256 /* compare excluding final '*' */
257 assert(strlen(entry
->name
) > 0);
258 if (strcmp(event_desc
->name
, "lttng_ust:metadata")
259 && (strlen(entry
->name
) == 1
260 || !strncmp(event_desc
->name
, entry
->name
,
261 strlen(entry
->name
) - 1))) {
262 /* TODO: get value from loglevel. */
264 /* TODO: check if loglevel match */
265 //if (event_desc->loglevel
266 // && (*event_desc->loglevel)->value ...)
270 struct ltt_event
*ev
;
273 memcpy(&event_param
, &wildcard
->event_param
,
274 sizeof(event_param
));
275 memcpy(event_param
.name
,
277 sizeof(event_param
.name
));
279 ret
= ltt_event_create(wildcard
->chan
,
283 DBG("Error creating event");
286 cds_list_add(&ev
->wildcard_list
,
294 * Add the wildcard to the wildcard list. Must be called with
297 struct session_wildcard
*add_wildcard(const char *name
,
298 struct ltt_channel
*chan
,
299 struct lttng_ust_event
*event_param
)
301 struct wildcard_entry
*e
;
302 struct session_wildcard
*sw
;
303 size_t name_len
= strlen(name
) + 1;
306 /* try to find global wildcard entry */
307 cds_list_for_each_entry(e
, &wildcard_list
, list
) {
308 if (!strncmp(name
, e
->name
, LTTNG_UST_SYM_NAME_LEN
- 1)) {
316 * Create global wildcard entry if not found. Using
317 * zmalloc here to allocate a variable length element.
318 * Could cause some memory fragmentation if overused.
320 e
= zmalloc(sizeof(struct wildcard_entry
) + name_len
);
322 return ERR_PTR(-ENOMEM
);
323 memcpy(&e
->name
[0], name
, name_len
);
324 cds_list_add(&e
->list
, &wildcard_list
);
325 CDS_INIT_LIST_HEAD(&e
->session_list
);
328 /* session wildcard */
329 cds_list_for_each_entry(sw
, &e
->session_list
, session_list
) {
330 if (chan
== sw
->chan
) {
331 DBG("wildcard %s busy for this channel", name
);
332 return ERR_PTR(-EEXIST
); /* Already there */
335 sw
= zmalloc(sizeof(struct session_wildcard
));
337 return ERR_PTR(-ENOMEM
);
340 memcpy(&sw
->event_param
, event_param
, sizeof(sw
->event_param
));
341 sw
->event_param
.instrumentation
= LTTNG_UST_TRACEPOINT
;
342 CDS_INIT_LIST_HEAD(&sw
->events
);
343 cds_list_add(&sw
->list
, &chan
->session
->wildcards
);
344 cds_list_add(&sw
->session_list
, &e
->session_list
);
346 _probes_create_wildcard_events(e
, sw
);
351 * Remove the wildcard from the wildcard list. Must be called with
352 * ust_lock held. Only called at session teardown.
354 void _remove_wildcard(struct session_wildcard
*wildcard
)
356 struct ltt_event
*ev
, *tmp
;
359 * Just remove the events owned (for enable/disable) by this
360 * wildcard from the list. The session teardown will take care
361 * of freeing the event memory.
363 cds_list_for_each_entry_safe(ev
, tmp
, &wildcard
->events
,
365 cds_list_del(&ev
->wildcard_list
);
367 cds_list_del(&wildcard
->session_list
);
368 cds_list_del(&wildcard
->list
);
369 if (cds_list_empty(&wildcard
->entry
->session_list
)) {
370 cds_list_del(&wildcard
->entry
->list
);
371 free(wildcard
->entry
);
376 int ltt_wildcard_enable(struct session_wildcard
*wildcard
)
378 struct ltt_event
*ev
;
381 if (wildcard
->enabled
)
383 cds_list_for_each_entry(ev
, &wildcard
->events
, wildcard_list
) {
384 ret
= ltt_event_enable(ev
);
386 DBG("Error: enable error.\n");
390 wildcard
->enabled
= 1;
394 int ltt_wildcard_disable(struct session_wildcard
*wildcard
)
396 struct ltt_event
*ev
;
399 if (!wildcard
->enabled
)
401 cds_list_for_each_entry(ev
, &wildcard
->events
, wildcard_list
) {
402 ret
= ltt_event_disable(ev
);
404 DBG("Error: disable error.\n");
408 wildcard
->enabled
= 0;