Implement loglevels as event and wildcard attributes
[lttng-ust.git] / liblttng-ust / ltt-probes.c
CommitLineData
ce5aef0b
MD
1/*
2 * ltt-probes.c
3 *
4 * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 *
6 * Holds LTTng probes registry.
7 *
8 * Dual LGPL v2.1/GPL v2 license.
9 */
10
8d8a24c8
MD
11#include <string.h>
12#include <errno.h>
13#include <urcu/list.h>
1f18504e 14#include <urcu/hlist.h>
4318ae1b 15#include <lttng/ust-events.h>
a3bb4b27 16#include <assert.h>
c8fcf224 17#include <helper.h>
48740cab 18#include <ctype.h>
ce5aef0b 19
882a56d7 20#include "tracepoint-internal.h"
8165c8da 21#include "ltt-tracer-core.h"
1f18504e
MD
22#include "jhash.h"
23#include "error.h"
8165c8da
MD
24
25/*
17dfb34b 26 * probe list is protected by ust_lock()/ust_unlock().
8165c8da 27 */
8d8a24c8 28static CDS_LIST_HEAD(probe_list);
ce5aef0b 29
df854e41
MD
30static
31const struct lttng_probe_desc *find_provider(const char *provider)
32{
33 struct lttng_probe_desc *iter;
34
35 cds_list_for_each_entry(iter, &probe_list, head) {
36 if (!strcmp(iter->provider, provider))
37 return iter;
38 }
39 return NULL;
40}
41
ce5aef0b
MD
42static
43const struct lttng_event_desc *find_event(const char *name)
44{
45 struct lttng_probe_desc *probe_desc;
46 int i;
47
8d8a24c8 48 cds_list_for_each_entry(probe_desc, &probe_list, head) {
ce5aef0b 49 for (i = 0; i < probe_desc->nr_events; i++) {
ff412fb5
MD
50 if (!strncmp(probe_desc->event_desc[i]->name, name,
51 LTTNG_UST_SYM_NAME_LEN - 1))
df854e41 52 return probe_desc->event_desc[i];
ce5aef0b
MD
53 }
54 }
55 return NULL;
56}
57
58int ltt_probe_register(struct lttng_probe_desc *desc)
59{
df854e41 60 struct lttng_probe_desc *iter;
ce5aef0b
MD
61 int ret = 0;
62 int i;
63
17dfb34b 64 ust_lock();
df854e41
MD
65 if (find_provider(desc->provider)) {
66 ret = -EEXIST;
67 goto end;
68 }
ce5aef0b
MD
69 /*
70 * TODO: This is O(N^2). Turn into a hash table when probe registration
71 * overhead becomes an issue.
72 */
73 for (i = 0; i < desc->nr_events; i++) {
df854e41 74 if (find_event(desc->event_desc[i]->name)) {
ce5aef0b
MD
75 ret = -EEXIST;
76 goto end;
77 }
78 }
df854e41
MD
79
80 /*
81 * We sort the providers by struct lttng_probe_desc pointer
82 * address.
83 */
84 cds_list_for_each_entry_reverse(iter, &probe_list, head) {
85 BUG_ON(iter == desc); /* Should never be in the list twice */
86 if (iter < desc) {
87 /* We belong to the location right after iter. */
88 cds_list_add(&desc->head, &iter->head);
89 goto desc_added;
90 }
91 }
92 /* We should be added at the head of the list */
8d8a24c8 93 cds_list_add(&desc->head, &probe_list);
df854e41 94desc_added:
e81a53af
MD
95 DBG("just registered probe %s containing %u events",
96 desc->provider, desc->nr_events);
8165c8da
MD
97 /*
98 * fix the events awaiting probe load.
99 */
100 for (i = 0; i < desc->nr_events; i++) {
df854e41 101 ret = pending_probe_fix_events(desc->event_desc[i]);
8165c8da
MD
102 assert(!ret);
103 }
ce5aef0b 104end:
17dfb34b 105 ust_unlock();
ce5aef0b
MD
106 return ret;
107}
ce5aef0b
MD
108
109void ltt_probe_unregister(struct lttng_probe_desc *desc)
110{
17dfb34b 111 ust_lock();
8d8a24c8 112 cds_list_del(&desc->head);
e81a53af 113 DBG("just unregistered probe %s", desc->provider);
17dfb34b 114 ust_unlock();
ce5aef0b 115}
ce5aef0b 116
8165c8da
MD
117/*
118 * called with UST lock held.
119 */
ce5aef0b
MD
120const struct lttng_event_desc *ltt_event_get(const char *name)
121{
122 const struct lttng_event_desc *event;
ce5aef0b 123
ce5aef0b 124 event = find_event(name);
ce5aef0b
MD
125 if (!event)
126 return NULL;
ce5aef0b
MD
127 return event;
128}
ce5aef0b
MD
129
130void ltt_event_put(const struct lttng_event_desc *event)
131{
ce5aef0b 132}
c8fcf224
MD
133
134void ltt_probes_prune_event_list(struct lttng_ust_tracepoint_list *list)
135{
136 struct tp_list_entry *list_entry, *tmp;
137
138 cds_list_for_each_entry_safe(list_entry, tmp, &list->head, head) {
139 cds_list_del(&list_entry->head);
140 free(list_entry);
141 }
142}
143
144/*
145 * called with UST lock held.
146 */
147int ltt_probes_get_event_list(struct lttng_ust_tracepoint_list *list)
148{
149 struct lttng_probe_desc *probe_desc;
150 int i;
151
152 CDS_INIT_LIST_HEAD(&list->head);
153 cds_list_for_each_entry(probe_desc, &probe_list, head) {
154 for (i = 0; i < probe_desc->nr_events; i++) {
155 struct tp_list_entry *list_entry;
156
157 list_entry = zmalloc(sizeof(*list_entry));
158 if (!list_entry)
159 goto err_nomem;
160 cds_list_add(&list_entry->head, &list->head);
161 strncpy(list_entry->tp.name,
162 probe_desc->event_desc[i]->name,
163 LTTNG_UST_SYM_NAME_LEN);
164 list_entry->tp.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
165 if (!probe_desc->event_desc[i]->loglevel) {
882a56d7 166 list_entry->tp.loglevel = TRACE_DEFAULT;
c8fcf224 167 } else {
882a56d7 168 list_entry->tp.loglevel = *(*probe_desc->event_desc[i]->loglevel);
c8fcf224
MD
169 }
170 }
171 }
172 if (cds_list_empty(&list->head))
173 list->iter = NULL;
174 else
175 list->iter =
176 cds_list_first_entry(&list->head, struct tp_list_entry, head);
177 return 0;
178
179err_nomem:
180 ltt_probes_prune_event_list(list);
181 return -ENOMEM;
182}
183
184/*
185 * Return current iteration position, advance internal iterator to next.
186 * Return NULL if end of list.
187 */
188struct lttng_ust_tracepoint_iter *
189 lttng_ust_tracepoint_list_get_iter_next(struct lttng_ust_tracepoint_list *list)
190{
191 struct tp_list_entry *entry;
192
193 if (!list->iter)
194 return NULL;
195 entry = list->iter;
196 if (entry->head.next == &list->head)
197 list->iter = NULL;
198 else
199 list->iter = cds_list_entry(entry->head.next,
200 struct tp_list_entry, head);
201 return &entry->tp;
202}
1f18504e 203
e6c12e3d
MD
204/*
205 * marshall all probes/all events and create those that fit the
206 * wildcard. Add them to the events list as created.
207 */
457a6b58 208void ltt_probes_create_wildcard_events(struct wildcard_entry *entry,
e6c12e3d
MD
209 struct session_wildcard *wildcard)
210{
211 struct lttng_probe_desc *probe_desc;
212 struct lttng_ust_event event_param;
213 int i;
214
215 cds_list_for_each_entry(probe_desc, &probe_list, head) {
216 for (i = 0; i < probe_desc->nr_events; i++) {
217 const struct lttng_event_desc *event_desc;
218 int match = 0;
219
220 event_desc = probe_desc->event_desc[i];
221 /* compare excluding final '*' */
222 assert(strlen(entry->name) > 0);
223 if (strcmp(event_desc->name, "lttng_ust:metadata")
224 && (strlen(entry->name) == 1
225 || !strncmp(event_desc->name, entry->name,
226 strlen(entry->name) - 1))) {
457a6b58
MD
227 if (ltt_loglevel_match(event_desc,
228 entry->loglevel_type,
229 entry->loglevel)) {
230 match = 1;
231 }
e6c12e3d
MD
232 }
233 if (match) {
234 struct ltt_event *ev;
235 int ret;
236
237 memcpy(&event_param, &wildcard->event_param,
238 sizeof(event_param));
239 memcpy(event_param.name,
240 event_desc->name,
241 sizeof(event_param.name));
242 /* create event */
243 ret = ltt_event_create(wildcard->chan,
244 &event_param, NULL,
245 &ev);
246 if (ret) {
247 DBG("Error creating event");
248 continue;
249 }
250 cds_list_add(&ev->wildcard_list,
251 &wildcard->events);
252 }
253 }
254 }
255}
256
This page took 0.03571 seconds and 4 git commands to generate.