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 "tracepoint-internal.h"
21 #include "ltt-tracer-core.h"
26 * probe list is protected by ust_lock()/ust_unlock().
28 static CDS_LIST_HEAD(probe_list
);
31 * Wildcard list, containing the active wildcards.
32 * Protected by ust lock.
34 static CDS_LIST_HEAD(wildcard_list
);
37 const struct lttng_probe_desc
*find_provider(const char *provider
)
39 struct lttng_probe_desc
*iter
;
41 cds_list_for_each_entry(iter
, &probe_list
, head
) {
42 if (!strcmp(iter
->provider
, provider
))
49 const struct lttng_event_desc
*find_event(const char *name
)
51 struct lttng_probe_desc
*probe_desc
;
54 cds_list_for_each_entry(probe_desc
, &probe_list
, head
) {
55 for (i
= 0; i
< probe_desc
->nr_events
; i
++) {
56 if (!strncmp(probe_desc
->event_desc
[i
]->name
, name
,
57 LTTNG_UST_SYM_NAME_LEN
- 1))
58 return probe_desc
->event_desc
[i
];
64 int ltt_probe_register(struct lttng_probe_desc
*desc
)
66 struct lttng_probe_desc
*iter
;
71 if (find_provider(desc
->provider
)) {
76 * TODO: This is O(N^2). Turn into a hash table when probe registration
77 * overhead becomes an issue.
79 for (i
= 0; i
< desc
->nr_events
; i
++) {
80 if (find_event(desc
->event_desc
[i
]->name
)) {
87 * We sort the providers by struct lttng_probe_desc pointer
90 cds_list_for_each_entry_reverse(iter
, &probe_list
, head
) {
91 BUG_ON(iter
== desc
); /* Should never be in the list twice */
93 /* We belong to the location right after iter. */
94 cds_list_add(&desc
->head
, &iter
->head
);
98 /* We should be added at the head of the list */
99 cds_list_add(&desc
->head
, &probe_list
);
101 DBG("just registered probe %s containing %u events",
102 desc
->provider
, desc
->nr_events
);
104 * fix the events awaiting probe load.
106 for (i
= 0; i
< desc
->nr_events
; i
++) {
107 ret
= pending_probe_fix_events(desc
->event_desc
[i
]);
115 void ltt_probe_unregister(struct lttng_probe_desc
*desc
)
118 cds_list_del(&desc
->head
);
119 DBG("just unregistered probe %s", desc
->provider
);
124 * called with UST lock held.
126 const struct lttng_event_desc
*ltt_event_get(const char *name
)
128 const struct lttng_event_desc
*event
;
130 event
= find_event(name
);
136 void ltt_event_put(const struct lttng_event_desc
*event
)
140 void ltt_probes_prune_event_list(struct lttng_ust_tracepoint_list
*list
)
142 struct tp_list_entry
*list_entry
, *tmp
;
144 cds_list_for_each_entry_safe(list_entry
, tmp
, &list
->head
, head
) {
145 cds_list_del(&list_entry
->head
);
151 * called with UST lock held.
153 int ltt_probes_get_event_list(struct lttng_ust_tracepoint_list
*list
)
155 struct lttng_probe_desc
*probe_desc
;
158 CDS_INIT_LIST_HEAD(&list
->head
);
159 cds_list_for_each_entry(probe_desc
, &probe_list
, head
) {
160 for (i
= 0; i
< probe_desc
->nr_events
; i
++) {
161 struct tp_list_entry
*list_entry
;
163 list_entry
= zmalloc(sizeof(*list_entry
));
166 cds_list_add(&list_entry
->head
, &list
->head
);
167 strncpy(list_entry
->tp
.name
,
168 probe_desc
->event_desc
[i
]->name
,
169 LTTNG_UST_SYM_NAME_LEN
);
170 list_entry
->tp
.name
[LTTNG_UST_SYM_NAME_LEN
- 1] = '\0';
171 if (!probe_desc
->event_desc
[i
]->loglevel
) {
172 list_entry
->tp
.loglevel
= TRACE_DEFAULT
;
174 list_entry
->tp
.loglevel
= *(*probe_desc
->event_desc
[i
]->loglevel
);
178 if (cds_list_empty(&list
->head
))
182 cds_list_first_entry(&list
->head
, struct tp_list_entry
, head
);
186 ltt_probes_prune_event_list(list
);
191 * Return current iteration position, advance internal iterator to next.
192 * Return NULL if end of list.
194 struct lttng_ust_tracepoint_iter
*
195 lttng_ust_tracepoint_list_get_iter_next(struct lttng_ust_tracepoint_list
*list
)
197 struct tp_list_entry
*entry
;
202 if (entry
->head
.next
== &list
->head
)
205 list
->iter
= cds_list_entry(entry
->head
.next
,
206 struct tp_list_entry
, head
);
213 * Return wildcard for a given event name if the event name match the
214 * one of the wildcards.
215 * Must be called with ust lock held.
216 * Returns NULL if not present.
218 struct wildcard_entry
*match_wildcard(const char *name
)
220 struct wildcard_entry
*e
;
222 cds_list_for_each_entry(e
, &wildcard_list
, list
) {
223 /* If only contain '*' */
224 if (strlen(e
->name
) == 1)
226 /* Compare excluding final '*' */
227 if (!strncmp(name
, e
->name
, strlen(e
->name
) - 1))
234 * marshall all probes/all events and create those that fit the
235 * wildcard. Add them to the events list as created.
238 void _probes_create_wildcard_events(struct wildcard_entry
*entry
,
239 struct session_wildcard
*wildcard
)
241 struct lttng_probe_desc
*probe_desc
;
242 struct lttng_ust_event event_param
;
245 cds_list_for_each_entry(probe_desc
, &probe_list
, head
) {
246 for (i
= 0; i
< probe_desc
->nr_events
; i
++) {
247 const struct lttng_event_desc
*event_desc
;
250 event_desc
= probe_desc
->event_desc
[i
];
251 /* compare excluding final '*' */
252 assert(strlen(entry
->name
) > 0);
253 if (strcmp(event_desc
->name
, "lttng_ust:metadata")
254 && (strlen(entry
->name
) == 1
255 || !strncmp(event_desc
->name
, entry
->name
,
256 strlen(entry
->name
) - 1))) {
257 /* TODO: check if loglevel match */
258 //if (event_desc->loglevel
259 // && (*event_desc->loglevel) ...)
263 struct ltt_event
*ev
;
266 memcpy(&event_param
, &wildcard
->event_param
,
267 sizeof(event_param
));
268 memcpy(event_param
.name
,
270 sizeof(event_param
.name
));
272 ret
= ltt_event_create(wildcard
->chan
,
276 DBG("Error creating event");
279 cds_list_add(&ev
->wildcard_list
,
287 * Add the wildcard to the wildcard list. Must be called with
290 struct session_wildcard
*add_wildcard(const char *name
,
291 struct ltt_channel
*chan
,
292 struct lttng_ust_event
*event_param
)
294 struct wildcard_entry
*e
;
295 struct session_wildcard
*sw
;
296 size_t name_len
= strlen(name
) + 1;
299 /* try to find global wildcard entry */
300 cds_list_for_each_entry(e
, &wildcard_list
, list
) {
301 if (!strncmp(name
, e
->name
, LTTNG_UST_SYM_NAME_LEN
- 1)) {
309 * Create global wildcard entry if not found. Using
310 * zmalloc here to allocate a variable length element.
311 * Could cause some memory fragmentation if overused.
313 e
= zmalloc(sizeof(struct wildcard_entry
) + name_len
);
315 return ERR_PTR(-ENOMEM
);
316 memcpy(&e
->name
[0], name
, name_len
);
317 cds_list_add(&e
->list
, &wildcard_list
);
318 CDS_INIT_LIST_HEAD(&e
->session_list
);
321 /* session wildcard */
322 cds_list_for_each_entry(sw
, &e
->session_list
, session_list
) {
323 if (chan
== sw
->chan
) {
324 DBG("wildcard %s busy for this channel", name
);
325 return ERR_PTR(-EEXIST
); /* Already there */
328 sw
= zmalloc(sizeof(struct session_wildcard
));
330 return ERR_PTR(-ENOMEM
);
333 memcpy(&sw
->event_param
, event_param
, sizeof(sw
->event_param
));
334 sw
->event_param
.instrumentation
= LTTNG_UST_TRACEPOINT
;
335 CDS_INIT_LIST_HEAD(&sw
->events
);
336 cds_list_add(&sw
->list
, &chan
->session
->wildcards
);
337 cds_list_add(&sw
->session_list
, &e
->session_list
);
339 _probes_create_wildcard_events(e
, sw
);
344 * Remove the wildcard from the wildcard list. Must be called with
345 * ust_lock held. Only called at session teardown.
347 void _remove_wildcard(struct session_wildcard
*wildcard
)
349 struct ltt_event
*ev
, *tmp
;
352 * Just remove the events owned (for enable/disable) by this
353 * wildcard from the list. The session teardown will take care
354 * of freeing the event memory.
356 cds_list_for_each_entry_safe(ev
, tmp
, &wildcard
->events
,
358 cds_list_del(&ev
->wildcard_list
);
360 cds_list_del(&wildcard
->session_list
);
361 cds_list_del(&wildcard
->list
);
362 if (cds_list_empty(&wildcard
->entry
->session_list
)) {
363 cds_list_del(&wildcard
->entry
->list
);
364 free(wildcard
->entry
);
369 int ltt_wildcard_enable(struct session_wildcard
*wildcard
)
371 struct ltt_event
*ev
;
374 if (wildcard
->enabled
)
376 cds_list_for_each_entry(ev
, &wildcard
->events
, wildcard_list
) {
377 ret
= ltt_event_enable(ev
);
379 DBG("Error: enable error.\n");
383 wildcard
->enabled
= 1;
387 int ltt_wildcard_disable(struct session_wildcard
*wildcard
)
389 struct ltt_event
*ev
;
392 if (!wildcard
->enabled
)
394 cds_list_for_each_entry(ev
, &wildcard
->events
, wildcard_list
) {
395 ret
= ltt_event_disable(ev
);
397 DBG("Error: disable error.\n");
401 wildcard
->enabled
= 0;