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>
19 #include "ltt-tracer-core.h"
24 * probe list is protected by ust_lock()/ust_unlock().
26 static CDS_LIST_HEAD(probe_list
);
29 * Loglevel hash table, containing the active loglevels.
30 * Protected by ust lock.
32 #define LOGLEVEL_HASH_BITS 6
33 #define LOGLEVEL_TABLE_SIZE (1 << LOGLEVEL_HASH_BITS)
34 static struct cds_hlist_head loglevel_table
[LOGLEVEL_TABLE_SIZE
];
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 (!strcmp(probe_desc
->event_desc
[i
]->name
, name
))
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
);
102 * fix the events awaiting probe load.
104 for (i
= 0; i
< desc
->nr_events
; i
++) {
105 ret
= pending_probe_fix_events(desc
->event_desc
[i
]);
113 void ltt_probe_unregister(struct lttng_probe_desc
*desc
)
116 cds_list_del(&desc
->head
);
121 * called with UST lock held.
123 const struct lttng_event_desc
*ltt_event_get(const char *name
)
125 const struct lttng_event_desc
*event
;
127 event
= find_event(name
);
133 void ltt_event_put(const struct lttng_event_desc
*event
)
137 void ltt_probes_prune_event_list(struct lttng_ust_tracepoint_list
*list
)
139 struct tp_list_entry
*list_entry
, *tmp
;
141 cds_list_for_each_entry_safe(list_entry
, tmp
, &list
->head
, head
) {
142 cds_list_del(&list_entry
->head
);
148 * called with UST lock held.
150 int ltt_probes_get_event_list(struct lttng_ust_tracepoint_list
*list
)
152 struct lttng_probe_desc
*probe_desc
;
155 CDS_INIT_LIST_HEAD(&list
->head
);
156 cds_list_for_each_entry(probe_desc
, &probe_list
, head
) {
157 for (i
= 0; i
< probe_desc
->nr_events
; i
++) {
158 struct tp_list_entry
*list_entry
;
160 list_entry
= zmalloc(sizeof(*list_entry
));
163 cds_list_add(&list_entry
->head
, &list
->head
);
164 strncpy(list_entry
->tp
.name
,
165 probe_desc
->event_desc
[i
]->name
,
166 LTTNG_UST_SYM_NAME_LEN
);
167 list_entry
->tp
.name
[LTTNG_UST_SYM_NAME_LEN
- 1] = '\0';
168 if (!probe_desc
->event_desc
[i
]->loglevel
) {
169 list_entry
->tp
.loglevel
[0] = '\0';
170 list_entry
->tp
.loglevel_value
= 0;
172 strncpy(list_entry
->tp
.loglevel
,
173 (*probe_desc
->event_desc
[i
]->loglevel
)->identifier
,
174 LTTNG_UST_SYM_NAME_LEN
);
175 list_entry
->tp
.loglevel
[LTTNG_UST_SYM_NAME_LEN
- 1] = '\0';
176 list_entry
->tp
.loglevel_value
=
177 (*probe_desc
->event_desc
[i
]->loglevel
)->value
;
181 if (cds_list_empty(&list
->head
))
185 cds_list_first_entry(&list
->head
, struct tp_list_entry
, head
);
189 ltt_probes_prune_event_list(list
);
194 * Return current iteration position, advance internal iterator to next.
195 * Return NULL if end of list.
197 struct lttng_ust_tracepoint_iter
*
198 lttng_ust_tracepoint_list_get_iter_next(struct lttng_ust_tracepoint_list
*list
)
200 struct tp_list_entry
*entry
;
205 if (entry
->head
.next
== &list
->head
)
208 list
->iter
= cds_list_entry(entry
->head
.next
,
209 struct tp_list_entry
, head
);
214 * Get loglevel if the loglevel is present in the loglevel hash table.
215 * Must be called with ust lock held.
216 * Returns NULL if not present.
218 struct loglevel_entry
*get_loglevel(const char *name
)
220 struct cds_hlist_head
*head
;
221 struct cds_hlist_node
*node
;
222 struct loglevel_entry
*e
;
223 uint32_t hash
= jhash(name
, strlen(name
), 0);
225 head
= &loglevel_table
[hash
& (LOGLEVEL_TABLE_SIZE
- 1)];
226 cds_hlist_for_each_entry(e
, node
, head
, hlist
) {
227 if (!strcmp(name
, e
->name
))
234 * marshall all probes/all events and create those that fit the
235 * loglevel. Add them to the events list as created.
238 void _probes_create_loglevel_events(struct loglevel_entry
*entry
,
239 struct session_loglevel
*loglevel
)
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 tracepoint_loglevel_entry
*ev_ll
;
248 const struct lttng_event_desc
*event_desc
;
250 event_desc
= probe_desc
->event_desc
[i
];
251 if (!(event_desc
->loglevel
))
253 ev_ll
= *event_desc
->loglevel
;
254 if (!strcmp(ev_ll
->identifier
, entry
->name
)) {
255 struct ltt_event
*ev
;
258 memcpy(&event_param
, &loglevel
->event_param
,
259 sizeof(event_param
));
260 memcpy(event_param
.name
,
262 sizeof(event_param
.name
));
264 ret
= ltt_event_create(loglevel
->chan
,
268 DBG("Error creating event");
271 cds_list_add(&ev
->loglevel_list
,
279 * Add the loglevel to the loglevel hash table. Must be called with
282 struct session_loglevel
*add_loglevel(const char *name
,
283 struct ltt_channel
*chan
,
284 struct lttng_ust_event
*event_param
)
286 struct cds_hlist_head
*head
;
287 struct cds_hlist_node
*node
;
288 struct loglevel_entry
*e
;
289 struct session_loglevel
*sl
;
290 size_t name_len
= strlen(name
) + 1;
291 uint32_t hash
= jhash(name
, name_len
-1, 0);
295 head
= &loglevel_table
[hash
& (LOGLEVEL_TABLE_SIZE
- 1)];
296 cds_hlist_for_each_entry(e
, node
, head
, hlist
) {
297 if (!strcmp(name
, e
->name
)) {
305 * Using zmalloc here to allocate a variable length element. Could
306 * cause some memory fragmentation if overused.
308 e
= zmalloc(sizeof(struct loglevel_entry
) + name_len
);
310 return ERR_PTR(-ENOMEM
);
311 memcpy(&e
->name
[0], name
, name_len
);
312 cds_hlist_add_head(&e
->hlist
, head
);
313 CDS_INIT_LIST_HEAD(&e
->session_list
);
316 /* session loglevel */
317 cds_list_for_each_entry(sl
, &e
->session_list
, session_list
) {
318 if (chan
== sl
->chan
) {
319 DBG("loglevel %s busy for this channel", name
);
320 return ERR_PTR(-EEXIST
); /* Already there */
323 sl
= zmalloc(sizeof(struct session_loglevel
));
325 return ERR_PTR(-ENOMEM
);
328 memcpy(&sl
->event_param
, event_param
, sizeof(sl
->event_param
));
329 sl
->event_param
.instrumentation
= LTTNG_UST_TRACEPOINT
;
330 CDS_INIT_LIST_HEAD(&sl
->events
);
331 cds_list_add(&sl
->list
, &chan
->session
->loglevels
);
332 cds_list_add(&sl
->session_list
, &e
->session_list
);
334 _probes_create_loglevel_events(e
, sl
);
339 * Remove the loglevel from the loglevel hash table. Must be called with
340 * ust_lock held. Only called at session teardown.
342 void _remove_loglevel(struct session_loglevel
*loglevel
)
344 struct ltt_event
*ev
, *tmp
;
347 * Just remove the events owned (for enable/disable) by this
348 * loglevel from the list. The session teardown will take care
349 * of freeing the event memory.
351 cds_list_for_each_entry_safe(ev
, tmp
, &loglevel
->events
, list
) {
352 cds_list_del(&ev
->list
);
354 cds_list_del(&loglevel
->session_list
);
355 cds_list_del(&loglevel
->list
);
356 if (cds_list_empty(&loglevel
->entry
->session_list
)) {
357 cds_hlist_del(&loglevel
->entry
->hlist
);
358 free(loglevel
->entry
);
363 int ltt_loglevel_enable(struct session_loglevel
*loglevel
)
365 struct ltt_event
*ev
;
368 if (loglevel
->enabled
)
370 cds_list_for_each_entry(ev
, &loglevel
->events
, list
) {
371 ret
= ltt_event_enable(ev
);
373 DBG("Error: enable error.\n");
377 loglevel
->enabled
= 1;
381 int ltt_loglevel_disable(struct session_loglevel
*loglevel
)
383 struct ltt_event
*ev
;
386 if (!loglevel
->enabled
)
388 cds_list_for_each_entry(ev
, &loglevel
->events
, list
) {
389 ret
= ltt_event_disable(ev
);
391 DBG("Error: disable error.\n");
395 loglevel
->enabled
= 0;