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
*loglevel
)
240 struct lttng_probe_desc
*probe_desc
;
243 cds_list_for_each_entry(probe_desc
, &probe_list
, head
) {
244 for (i
= 0; i
< probe_desc
->nr_events
; i
++) {
245 const struct tracepoint_loglevel_entry
*ev_ll
;
247 if (!(probe_desc
->event_desc
[i
]->loglevel
))
249 ev_ll
= *probe_desc
->event_desc
[i
]->loglevel
;
250 if (!strcmp(ev_ll
->identifier
, loglevel
->name
)) {
251 struct ltt_event
*ev
;
255 ret
= ltt_event_create(loglevel
->chan
,
256 &loglevel
->event_param
, NULL
,
259 * TODO: report error.
263 cds_list_add(&ev
->loglevel_list
,
272 * Add the loglevel to the loglevel hash table. Must be called with
275 struct loglevel_entry
*add_loglevel(const char *name
,
276 struct ltt_channel
*chan
,
277 struct lttng_ust_event
*event_param
)
279 struct cds_hlist_head
*head
;
280 struct cds_hlist_node
*node
;
281 struct loglevel_entry
*e
;
282 size_t name_len
= strlen(name
) + 1;
283 uint32_t hash
= jhash(name
, name_len
-1, 0);
285 head
= &loglevel_table
[hash
& (LOGLEVEL_TABLE_SIZE
- 1)];
286 cds_hlist_for_each_entry(e
, node
, head
, hlist
) {
287 if (!strcmp(name
, e
->name
)) {
288 DBG("loglevel %s busy", name
);
289 return ERR_PTR(-EEXIST
); /* Already there */
293 * Using zmalloc here to allocate a variable length element. Could
294 * cause some memory fragmentation if overused.
296 e
= zmalloc(sizeof(struct loglevel_entry
) + name_len
);
298 return ERR_PTR(-ENOMEM
);
299 memcpy(&e
->name
[0], name
, name_len
);
302 memcpy(&e
->event_param
, event_param
, sizeof(e
->event_param
));
303 cds_hlist_add_head(&e
->hlist
, head
);
304 CDS_INIT_LIST_HEAD(&e
->events
);
305 _probes_create_loglevel_events(e
);
306 cds_list_add(&e
->list
, &chan
->session
->loglevels
);
311 * Remove the loglevel from the loglevel hash table. Must be called with
312 * ust_lock held. Only called at session teardown.
314 void _remove_loglevel(struct loglevel_entry
*loglevel
)
316 struct ltt_event
*ev
, *tmp
;
319 * Just remove the events owned (for enable/disable) by this
320 * loglevel from the list. The session teardown will take care
321 * of freeing the event memory.
323 cds_list_for_each_entry_safe(ev
, tmp
, &loglevel
->events
, list
) {
324 cds_list_del(&ev
->list
);
326 cds_hlist_del(&loglevel
->hlist
);
327 cds_list_del(&loglevel
->list
);
331 int ltt_loglevel_enable(struct loglevel_entry
*loglevel
)
333 struct ltt_event
*ev
;
336 if (loglevel
->enabled
)
338 cds_list_for_each_entry(ev
, &loglevel
->events
, list
) {
339 ret
= ltt_event_enable(ev
);
341 DBG("Error: enable error.\n");
345 loglevel
->enabled
= 1;
349 int ltt_loglevel_disable(struct loglevel_entry
*loglevel
)
351 struct ltt_event
*ev
;
354 if (!loglevel
->enabled
)
356 cds_list_for_each_entry(ev
, &loglevel
->events
, list
) {
357 ret
= ltt_event_disable(ev
);
359 DBG("Error: disable error.\n");
363 loglevel
->enabled
= 0;