2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2 only,
6 * as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include <urcu/list.h>
25 #include <common/error.h>
26 #include <common/sessiond-comm/sessiond-comm.h>
31 #include "trace-ust.h"
34 * Add kernel context to an event of a specific channel.
36 static int add_kctx_to_event(struct lttng_kernel_context
*kctx
,
37 struct ltt_kernel_channel
*kchan
, char *event_name
)
40 struct ltt_kernel_event
*kevent
;
42 DBG("Add kernel context to event %s", event_name
);
44 kevent
= trace_kernel_get_event_by_name(event_name
, kchan
);
46 ret
= kernel_add_event_context(kevent
, kctx
);
60 * Add kernel context to all channel.
62 * If event_name is specified, add context to event instead.
64 static int add_kctx_all_channels(struct ltt_kernel_session
*ksession
,
65 struct lttng_kernel_context
*kctx
, char *event_name
)
67 int ret
, no_event
= 0, found
= 0;
68 struct ltt_kernel_channel
*kchan
;
70 if (strlen(event_name
) == 0) {
74 DBG("Adding kernel context to all channels (event: %s)", event_name
);
76 /* Go over all channels */
77 cds_list_for_each_entry(kchan
, &ksession
->channel_list
.head
, list
) {
79 ret
= kernel_add_channel_context(kchan
, kctx
);
81 ret
= LTTNG_ERR_KERN_CONTEXT_FAIL
;
85 ret
= add_kctx_to_event(kctx
, kchan
, event_name
);
87 ret
= LTTNG_ERR_KERN_CONTEXT_FAIL
;
89 } else if (ret
== 1) {
90 /* Event found and context added */
97 if (!found
&& !no_event
) {
98 ret
= LTTNG_ERR_NO_EVENT
;
109 * Add kernel context to a specific channel.
111 * If event_name is specified, add context to that event.
113 static int add_kctx_to_channel(struct lttng_kernel_context
*kctx
,
114 struct ltt_kernel_channel
*kchan
, char *event_name
)
116 int ret
, no_event
= 0, found
= 0;
118 if (strlen(event_name
) == 0) {
122 DBG("Add kernel context to channel '%s', event '%s'",
123 kchan
->channel
->name
, event_name
);
126 ret
= kernel_add_channel_context(kchan
, kctx
);
128 ret
= LTTNG_ERR_KERN_CONTEXT_FAIL
;
132 ret
= add_kctx_to_event(kctx
, kchan
, event_name
);
134 ret
= LTTNG_ERR_KERN_CONTEXT_FAIL
;
136 } else if (ret
== 1) {
137 /* Event found and context added */
142 if (!found
&& !no_event
) {
143 ret
= LTTNG_ERR_NO_EVENT
;
154 * Add UST context to channel.
156 static int add_uctx_to_channel(struct ltt_ust_session
*usess
, int domain
,
157 struct ltt_ust_channel
*uchan
, struct lttng_event_context
*ctx
)
160 struct ltt_ust_context
*uctx
;
161 struct lttng_ht_iter iter
;
162 struct lttng_ht_node_ulong
*uctx_node
;
164 /* Create ltt UST context */
165 uctx
= trace_ust_create_context(ctx
);
172 case LTTNG_DOMAIN_UST
:
173 ret
= ust_app_add_ctx_channel_glb(usess
, uchan
, uctx
);
183 /* Lookup context before adding it */
184 lttng_ht_lookup(uchan
->ctx
, (void *)((unsigned long)uctx
->ctx
.ctx
), &iter
);
185 uctx_node
= lttng_ht_iter_get_node_ulong(&iter
);
186 if (uctx_node
!= NULL
) {
191 /* Add ltt UST context node to ltt UST channel */
192 lttng_ht_add_unique_ulong(uchan
->ctx
, &uctx
->node
);
194 DBG("Context UST %d added to channel %s", uctx
->ctx
.ctx
, uchan
->name
);
204 * Add UST context to event.
206 static int add_uctx_to_event(struct ltt_ust_session
*usess
, int domain
,
207 struct ltt_ust_channel
*uchan
, struct ltt_ust_event
*uevent
,
208 struct lttng_event_context
*ctx
)
211 struct ltt_ust_context
*uctx
;
212 struct lttng_ht_iter iter
;
213 struct lttng_ht_node_ulong
*uctx_node
;
215 /* Create ltt UST context */
216 uctx
= trace_ust_create_context(ctx
);
218 /* Context values are invalid. */
224 case LTTNG_DOMAIN_UST
:
225 ret
= ust_app_add_ctx_event_glb(usess
, uchan
, uevent
, uctx
);
235 /* Lookup context before adding it */
236 lttng_ht_lookup(uevent
->ctx
, (void *)((unsigned long)uctx
->ctx
.ctx
), &iter
);
237 uctx_node
= lttng_ht_iter_get_node_ulong(&iter
);
238 if (uctx_node
!= NULL
) {
243 /* Add ltt UST context node to ltt UST event */
244 lttng_ht_add_unique_ulong(uevent
->ctx
, &uctx
->node
);
246 DBG("Context UST %d added to event %s", uctx
->ctx
.ctx
, uevent
->attr
.name
);
256 * Add kernel context to tracer.
258 int context_kernel_add(struct ltt_kernel_session
*ksession
,
259 struct lttng_event_context
*ctx
, char *event_name
,
263 struct ltt_kernel_channel
*kchan
;
264 struct lttng_kernel_context kctx
;
266 /* Setup kernel context structure */
268 case LTTNG_EVENT_CONTEXT_PID
:
269 kctx
.ctx
= LTTNG_KERNEL_CONTEXT_PID
;
271 case LTTNG_EVENT_CONTEXT_PERF_COUNTER
:
272 kctx
.ctx
= LTTNG_KERNEL_CONTEXT_PERF_COUNTER
;
274 case LTTNG_EVENT_CONTEXT_PROCNAME
:
275 kctx
.ctx
= LTTNG_KERNEL_CONTEXT_PROCNAME
;
277 case LTTNG_EVENT_CONTEXT_PRIO
:
278 kctx
.ctx
= LTTNG_KERNEL_CONTEXT_PRIO
;
280 case LTTNG_EVENT_CONTEXT_NICE
:
281 kctx
.ctx
= LTTNG_KERNEL_CONTEXT_NICE
;
283 case LTTNG_EVENT_CONTEXT_VPID
:
284 kctx
.ctx
= LTTNG_KERNEL_CONTEXT_VPID
;
286 case LTTNG_EVENT_CONTEXT_TID
:
287 kctx
.ctx
= LTTNG_KERNEL_CONTEXT_TID
;
289 case LTTNG_EVENT_CONTEXT_VTID
:
290 kctx
.ctx
= LTTNG_KERNEL_CONTEXT_VTID
;
292 case LTTNG_EVENT_CONTEXT_PPID
:
293 kctx
.ctx
= LTTNG_KERNEL_CONTEXT_PPID
;
295 case LTTNG_EVENT_CONTEXT_VPPID
:
296 kctx
.ctx
= LTTNG_KERNEL_CONTEXT_VPPID
;
298 case LTTNG_EVENT_CONTEXT_HOSTNAME
:
299 kctx
.ctx
= LTTNG_KERNEL_CONTEXT_HOSTNAME
;
302 return LTTNG_ERR_KERN_CONTEXT_FAIL
;
305 kctx
.u
.perf_counter
.type
= ctx
->u
.perf_counter
.type
;
306 kctx
.u
.perf_counter
.config
= ctx
->u
.perf_counter
.config
;
307 strncpy(kctx
.u
.perf_counter
.name
, ctx
->u
.perf_counter
.name
,
308 LTTNG_SYMBOL_NAME_LEN
);
309 kctx
.u
.perf_counter
.name
[LTTNG_SYMBOL_NAME_LEN
- 1] = '\0';
311 if (strlen(channel_name
) == 0) {
312 ret
= add_kctx_all_channels(ksession
, &kctx
, event_name
);
313 if (ret
!= LTTNG_OK
) {
317 /* Get kernel channel */
318 kchan
= trace_kernel_get_channel_by_name(channel_name
, ksession
);
320 ret
= LTTNG_ERR_KERN_CHAN_NOT_FOUND
;
324 ret
= add_kctx_to_channel(&kctx
, kchan
, event_name
);
325 if (ret
!= LTTNG_OK
) {
337 * Add UST context to tracer.
339 int context_ust_add(struct ltt_ust_session
*usess
, int domain
,
340 struct lttng_event_context
*ctx
, char *event_name
,
343 int ret
= LTTNG_OK
, have_event
= 0;
344 struct lttng_ht_iter iter
;
345 struct lttng_ht
*chan_ht
;
346 struct ltt_ust_channel
*uchan
= NULL
;
347 struct ltt_ust_event
*uevent
= NULL
;
350 * Define which channel's hashtable to use from the domain or quit if
354 case LTTNG_DOMAIN_UST
:
355 chan_ht
= usess
->domain_global
.channels
;
358 case LTTNG_DOMAIN_UST_EXEC_NAME
:
359 case LTTNG_DOMAIN_UST_PID
:
360 case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN
:
367 /* Do we have an event name */
368 if (strlen(event_name
) != 0) {
372 /* Get UST channel if defined */
373 if (strlen(channel_name
) != 0) {
374 uchan
= trace_ust_find_channel_by_name(chan_ht
, channel_name
);
376 ret
= LTTNG_ERR_UST_CHAN_NOT_FOUND
;
381 /* If UST channel specified and event name, get UST event ref */
382 if (uchan
&& have_event
) {
383 uevent
= trace_ust_find_event_by_name(uchan
->events
, event_name
);
384 if (uevent
== NULL
) {
385 ret
= LTTNG_ERR_UST_EVENT_NOT_FOUND
;
390 /* At this point, we have 4 possibilities */
392 if (uchan
&& uevent
) { /* Add ctx to event in channel */
393 ret
= add_uctx_to_event(usess
, domain
, uchan
, uevent
, ctx
);
394 } else if (uchan
&& !have_event
) { /* Add ctx to channel */
395 ret
= add_uctx_to_channel(usess
, domain
, uchan
, ctx
);
396 } else if (!uchan
&& have_event
) { /* Add ctx to event */
397 /* Add context to event without having the channel name */
398 cds_lfht_for_each_entry(chan_ht
->ht
, &iter
.iter
, uchan
, node
.node
) {
399 uevent
= trace_ust_find_event_by_name(uchan
->events
, event_name
);
400 if (uevent
!= NULL
) {
401 ret
= add_uctx_to_event(usess
, domain
, uchan
, uevent
, ctx
);
403 * LTTng UST does not allowed the same event to be registered
404 * multiple time in different or the same channel. So, if we
405 * found our event, we stop.
410 ret
= LTTNG_ERR_UST_EVENT_NOT_FOUND
;
412 } else if (!uchan
&& !have_event
) { /* Add ctx all events, all channels */
413 /* For all channels */
414 cds_lfht_for_each_entry(chan_ht
->ht
, &iter
.iter
, uchan
, node
.node
) {
415 ret
= add_uctx_to_channel(usess
, domain
, uchan
, ctx
);
417 ERR("Context failed for channel %s", uchan
->name
);
426 ret
= LTTNG_ERR_UST_CONTEXT_EXIST
;
429 ret
= LTTNG_ERR_FATAL
;
432 ret
= LTTNG_ERR_UST_CONTEXT_INVAL
;
435 ret
= LTTNG_ERR_UNKNOWN_DOMAIN
;