2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; only version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15 * Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include <urcu/list.h>
25 #include <lttng-sessiond-comm.h>
29 #include "hashtable.h"
32 #include "trace-ust.h"
35 * Add kernel context to an event of a specific channel.
37 static int add_kctx_to_event(struct lttng_kernel_context
*kctx
,
38 struct ltt_kernel_channel
*kchan
, char *event_name
)
41 struct ltt_kernel_event
*kevent
;
43 DBG("Add kernel context to event %s", event_name
);
45 kevent
= trace_kernel_get_event_by_name(event_name
, kchan
);
47 ret
= kernel_add_event_context(kevent
, kctx
);
61 * Add kernel context to all channel.
63 * If event_name is specified, add context to event instead.
65 static int add_kctx_all_channels(struct ltt_kernel_session
*ksession
,
66 struct lttng_kernel_context
*kctx
, char *event_name
)
68 int ret
, no_event
= 0, found
= 0;
69 struct ltt_kernel_channel
*kchan
;
71 if (strlen(event_name
) == 0) {
75 DBG("Adding kernel context to all channels (event: %s)", event_name
);
77 /* Go over all channels */
78 cds_list_for_each_entry(kchan
, &ksession
->channel_list
.head
, list
) {
80 ret
= kernel_add_channel_context(kchan
, kctx
);
82 ret
= LTTCOMM_KERN_CONTEXT_FAIL
;
86 ret
= add_kctx_to_event(kctx
, kchan
, event_name
);
88 ret
= LTTCOMM_KERN_CONTEXT_FAIL
;
90 } else if (ret
== 1) {
91 /* Event found and context added */
98 if (!found
&& !no_event
) {
99 ret
= LTTCOMM_NO_EVENT
;
110 * Add kernel context to a specific channel.
112 * If event_name is specified, add context to that event.
114 static int add_kctx_to_channel(struct lttng_kernel_context
*kctx
,
115 struct ltt_kernel_channel
*kchan
, char *event_name
)
117 int ret
, no_event
= 0, found
= 0;
119 if (strlen(event_name
) == 0) {
123 DBG("Add kernel context to channel '%s', event '%s'",
124 kchan
->channel
->name
, event_name
);
127 ret
= kernel_add_channel_context(kchan
, kctx
);
129 ret
= LTTCOMM_KERN_CONTEXT_FAIL
;
133 ret
= add_kctx_to_event(kctx
, kchan
, event_name
);
135 ret
= LTTCOMM_KERN_CONTEXT_FAIL
;
137 } else if (ret
== 1) {
138 /* Event found and context added */
143 if (!found
&& !no_event
) {
144 ret
= LTTCOMM_NO_EVENT
;
155 * Add UST context to channel.
157 static int add_uctx_to_channel(struct ltt_ust_session
*usess
, int domain
,
158 struct ltt_ust_channel
*uchan
, struct lttng_event_context
*ctx
)
161 struct ltt_ust_context
*uctx
;
163 /* Create ltt UST context */
164 uctx
= trace_ust_create_context(ctx
);
171 case LTTNG_DOMAIN_UST
:
172 ret
= ust_app_add_ctx_channel_glb(usess
, uchan
, uctx
);
178 ret
= LTTCOMM_NOT_IMPLEMENTED
;
182 /* Add ltt UST context node to ltt UST channel */
183 hashtable_add_unique(uchan
->ctx
, &uctx
->node
);
193 * Add UST context to event.
195 static int add_uctx_to_event(struct ltt_ust_session
*usess
, int domain
,
196 struct ltt_ust_channel
*uchan
, struct ltt_ust_event
*uevent
,
197 struct lttng_event_context
*ctx
)
200 struct ltt_ust_context
*uctx
;
202 /* Create ltt UST context */
203 uctx
= trace_ust_create_context(ctx
);
210 case LTTNG_DOMAIN_UST
:
211 ret
= ust_app_add_ctx_event_glb(usess
, uchan
, uevent
, uctx
);
217 ret
= LTTCOMM_NOT_IMPLEMENTED
;
221 /* Add ltt UST context node to ltt UST event */
222 hashtable_add_unique(uevent
->ctx
, &uctx
->node
);
232 * Add kernel context to tracer.
234 int context_kernel_add(struct ltt_kernel_session
*ksession
,
235 struct lttng_event_context
*ctx
, char *event_name
,
239 struct ltt_kernel_channel
*kchan
;
240 struct lttng_kernel_context kctx
;
242 /* Setup kernel context structure */
244 kctx
.u
.perf_counter
.type
= ctx
->u
.perf_counter
.type
;
245 kctx
.u
.perf_counter
.config
= ctx
->u
.perf_counter
.config
;
246 strncpy(kctx
.u
.perf_counter
.name
, ctx
->u
.perf_counter
.name
,
247 LTTNG_SYMBOL_NAME_LEN
);
248 kctx
.u
.perf_counter
.name
[LTTNG_SYMBOL_NAME_LEN
- 1] = '\0';
250 if (strlen(channel_name
) == 0) {
251 ret
= add_kctx_all_channels(ksession
, &kctx
, event_name
);
252 if (ret
!= LTTCOMM_OK
) {
256 /* Get kernel channel */
257 kchan
= trace_kernel_get_channel_by_name(channel_name
, ksession
);
259 ret
= LTTCOMM_KERN_CHAN_NOT_FOUND
;
263 ret
= add_kctx_to_channel(&kctx
, kchan
, event_name
);
264 if (ret
!= LTTCOMM_OK
) {
276 * Add UST context to tracer.
278 int context_ust_add(struct ltt_ust_session
*usess
, int domain
,
279 struct lttng_event_context
*ctx
, char *event_name
,
282 int ret
= LTTCOMM_OK
, have_event
= 0;
283 struct cds_lfht_iter iter
, uiter
;
284 struct cds_lfht
*chan_ht
;
285 struct ltt_ust_channel
*uchan
= NULL
;
286 struct ltt_ust_event
*uevent
= NULL
;
289 * Define which channel's hashtable to use from the domain or quit if
293 case LTTNG_DOMAIN_UST
:
294 chan_ht
= usess
->domain_global
.channels
;
296 case LTTNG_DOMAIN_UST_EXEC_NAME
:
297 case LTTNG_DOMAIN_UST_PID
:
298 case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN
:
300 ret
= LTTCOMM_NOT_IMPLEMENTED
;
304 /* Do we have an event name */
305 if (strlen(event_name
) != 0) {
309 /* Get UST channel if defined */
310 if (strlen(channel_name
) != 0) {
311 uchan
= trace_ust_find_channel_by_name(chan_ht
, channel_name
);
313 ret
= LTTCOMM_UST_CHAN_NOT_FOUND
;
318 /* If UST channel specified and event name, get UST event ref */
319 if (uchan
&& have_event
) {
320 uevent
= trace_ust_find_event_by_name(uchan
->events
, event_name
);
321 if (uevent
== NULL
) {
322 ret
= LTTCOMM_UST_EVENT_NOT_FOUND
;
327 /* At this point, we have 4 possibilities */
329 if (uchan
&& uevent
) { /* Add ctx to event in channel */
330 ret
= add_uctx_to_event(usess
, domain
, uchan
, uevent
, ctx
);
331 } else if (uchan
&& !have_event
) { /* Add ctx to channel */
332 ret
= add_uctx_to_channel(usess
, domain
, uchan
, ctx
);
333 } else if (!uchan
&& have_event
) { /* Add ctx to event */
334 /* Add context to event without having the channel name */
335 cds_lfht_for_each_entry(chan_ht
, &iter
, uchan
, node
) {
336 uevent
= trace_ust_find_event_by_name(uchan
->events
, event_name
);
337 if (uevent
!= NULL
) {
338 ret
= add_uctx_to_event(usess
, domain
, uchan
, uevent
, ctx
);
340 * LTTng UST does not allowed the same event to be registered
341 * multiple time in different or the same channel. So, if we
342 * found our event, we stop.
347 ret
= LTTCOMM_UST_EVENT_NOT_FOUND
;
349 } else if (!uchan
&& !have_event
) { /* Add ctx all events, all channels */
350 /* For all channels */
351 cds_lfht_for_each_entry(chan_ht
, &iter
, uchan
, node
) {
352 ret
= add_uctx_to_channel(usess
, domain
, uchan
, ctx
);
354 ERR("Context added to channel %s failed", uchan
->name
);
358 /* For all events in channel */
359 cds_lfht_for_each_entry(uchan
->events
, &uiter
, uevent
, node
) {
360 ret
= add_uctx_to_event(usess
, domain
, uchan
, uevent
, ctx
);
362 ERR("Context add to event %s in channel %s failed",
363 uevent
->attr
.name
, uchan
->name
);
373 ret
= LTTCOMM_UST_CONTEXT_EXIST
;