Update info page for 0.14 API
[ust.git] / libust / tracer.c
1 /*
2 * tracer.c
3 *
4 * (C) Copyright 2005-2008 -
5 * Mathieu Desnoyers (mathieu.desnoyers@polymtl.ca)
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 * Inspired from LTT :
22 * Karim Yaghmour (karim@opersys.com)
23 * Tom Zanussi (zanussi@us.ibm.com)
24 * Bob Wisniewski (bob@watson.ibm.com)
25 * And from K42 :
26 * Bob Wisniewski (bob@watson.ibm.com)
27 *
28 * Changelog:
29 * 22/09/06, Move to the marker/probes mechanism.
30 * 19/10/05, Complete lockless mechanism.
31 * 27/05/05, Modular redesign and rewrite.
32 */
33
34 #include <urcu-bp.h>
35 #include <urcu/rculist.h>
36
37 #include <ust/clock.h>
38
39 #include "tracercore.h"
40 #include "tracer.h"
41 #include "usterr_signal_safe.h"
42
43 struct chan_info_struct chan_infos[] = {
44 [LTT_CHANNEL_METADATA] = {
45 LTT_METADATA_CHANNEL,
46 LTT_DEFAULT_SUBBUF_SIZE_LOW,
47 LTT_DEFAULT_N_SUBBUFS_LOW,
48 },
49 [LTT_CHANNEL_UST] = {
50 LTT_UST_CHANNEL,
51 LTT_DEFAULT_SUBBUF_SIZE_HIGH,
52 LTT_DEFAULT_N_SUBBUFS_HIGH,
53 },
54 };
55
56 static enum ltt_channels get_channel_type_from_name(const char *name)
57 {
58 int i;
59
60 if (!name)
61 return LTT_CHANNEL_UST;
62
63 for (i = 0; i < ARRAY_SIZE(chan_infos); i++)
64 if (chan_infos[i].name && !strcmp(name, chan_infos[i].name))
65 return (enum ltt_channels)i;
66
67 return LTT_CHANNEL_UST;
68 }
69
70 static CDS_LIST_HEAD(ltt_transport_list);
71 /* transport mutex, nests inside traces mutex (ltt_lock_traces) */
72 static DEFINE_MUTEX(ltt_transport_mutex);
73 /**
74 * ltt_transport_register - LTT transport registration
75 * @transport: transport structure
76 *
77 * Registers a transport which can be used as output to extract the data out of
78 * LTTng. The module calling this registration function must ensure that no
79 * trap-inducing code will be executed by the transport functions. E.g.
80 * vmalloc_sync_all() must be called between a vmalloc and the moment the memory
81 * is made visible to the transport function. This registration acts as a
82 * vmalloc_sync_all. Therefore, only if the module allocates virtual memory
83 * after its registration must it synchronize the TLBs.
84 */
85 void ltt_transport_register(struct ltt_transport *transport)
86 {
87 pthread_mutex_lock(&ltt_transport_mutex);
88 cds_list_add_tail(&transport->node, &ltt_transport_list);
89 pthread_mutex_unlock(&ltt_transport_mutex);
90 }
91
92 /**
93 * ltt_transport_unregister - LTT transport unregistration
94 * @transport: transport structure
95 */
96 void ltt_transport_unregister(struct ltt_transport *transport)
97 {
98 pthread_mutex_lock(&ltt_transport_mutex);
99 cds_list_del(&transport->node);
100 pthread_mutex_unlock(&ltt_transport_mutex);
101 }
102
103 static inline int is_channel_overwrite(enum ltt_channels chan,
104 enum trace_mode mode)
105 {
106 switch (mode) {
107 case LTT_TRACE_NORMAL:
108 return 0;
109 case LTT_TRACE_FLIGHT:
110 switch (chan) {
111 case LTT_CHANNEL_METADATA:
112 return 0;
113 default:
114 return 1;
115 }
116 case LTT_TRACE_HYBRID:
117 switch (chan) {
118 case LTT_CHANNEL_METADATA:
119 return 0;
120 default:
121 return 1;
122 }
123 default:
124 return 0;
125 }
126 }
127
128 static void trace_async_wakeup(struct ust_trace *trace)
129 {
130 int i;
131 struct ust_channel *chan;
132
133 /* Must check each channel for pending read wakeup */
134 for (i = 0; i < trace->nr_channels; i++) {
135 chan = &trace->channels[i];
136 if (chan->active)
137 trace->ops->wakeup_channel(chan);
138 }
139 }
140
141 /**
142 * _ltt_trace_find - find a trace by given name.
143 * trace_name: trace name
144 *
145 * Returns a pointer to the trace structure, NULL if not found.
146 */
147 struct ust_trace *_ltt_trace_find(const char *trace_name)
148 {
149 struct ust_trace *trace;
150
151 cds_list_for_each_entry(trace, &ltt_traces.head, list)
152 if (!strncmp(trace->trace_name, trace_name, NAME_MAX))
153 return trace;
154
155 return NULL;
156 }
157
158 /* _ltt_trace_find_setup :
159 * find a trace in setup list by given name.
160 *
161 * Returns a pointer to the trace structure, NULL if not found.
162 */
163 struct ust_trace *_ltt_trace_find_setup(const char *trace_name)
164 {
165 struct ust_trace *trace;
166
167 cds_list_for_each_entry(trace, &ltt_traces.setup_head, list)
168 if (!strncmp(trace->trace_name, trace_name, NAME_MAX))
169 return trace;
170
171 return NULL;
172 }
173
174 /**
175 * ltt_release_transport - Release an LTT transport
176 * @kref : reference count on the transport
177 */
178 void ltt_release_transport(struct urcu_ref *urcu_ref)
179 {
180 return;
181 }
182
183 /**
184 * ltt_release_trace - Release a LTT trace
185 * @kref : reference count on the trace
186 */
187 void ltt_release_trace(struct urcu_ref *urcu_ref)
188 {
189 struct ust_trace *trace = _ust_container_of(urcu_ref,
190 struct ust_trace, urcu_ref);
191 ltt_channels_trace_free(trace->channels);
192 free(trace);
193 }
194
195 static inline void prepare_chan_size_num(unsigned int *subbuf_size,
196 unsigned int *n_subbufs)
197 {
198 /* Make sure the subbuffer size is larger than a page */
199 *subbuf_size = max_t(unsigned int, *subbuf_size, PAGE_SIZE);
200
201 /* round to next power of 2 */
202 *subbuf_size = 1 << get_count_order(*subbuf_size);
203 *n_subbufs = 1 << get_count_order(*n_subbufs);
204
205 /* Subbuf size and number must both be power of two */
206 WARN_ON(hweight32(*subbuf_size) != 1);
207 WARN_ON(hweight32(*n_subbufs) != 1);
208 }
209
210 int _ltt_trace_setup(const char *trace_name)
211 {
212 int err = 0;
213 struct ust_trace *new_trace = NULL;
214 int metadata_index;
215 unsigned int chan;
216 enum ltt_channels chantype;
217
218 if (_ltt_trace_find_setup(trace_name)) {
219 ERR("Trace name %s already used", trace_name);
220 err = -EEXIST;
221 goto traces_error;
222 }
223
224 if (_ltt_trace_find(trace_name)) {
225 ERR("Trace name %s already used", trace_name);
226 err = -EEXIST;
227 goto traces_error;
228 }
229
230 new_trace = zmalloc(sizeof(struct ust_trace));
231 if (!new_trace) {
232 ERR("Unable to allocate memory for trace %s", trace_name);
233 err = -ENOMEM;
234 goto traces_error;
235 }
236 strncpy(new_trace->trace_name, trace_name, NAME_MAX);
237 new_trace->channels = ltt_channels_trace_alloc(&new_trace->nr_channels,
238 ust_channels_overwrite_by_default,
239 ust_channels_request_collection_by_default, 1);
240 if (!new_trace->channels) {
241 ERR("Unable to allocate memory for chaninfo %s\n", trace_name);
242 err = -ENOMEM;
243 goto trace_free;
244 }
245
246 /*
247 * Force metadata channel to active, no overwrite.
248 */
249 metadata_index = ltt_channels_get_index_from_name("metadata");
250 WARN_ON(metadata_index < 0);
251 new_trace->channels[metadata_index].overwrite = 0;
252 new_trace->channels[metadata_index].active = 1;
253
254 /*
255 * Set hardcoded tracer defaults for some channels
256 */
257 for (chan = 0; chan < new_trace->nr_channels; chan++) {
258 if (!(new_trace->channels[chan].active))
259 continue;
260
261 chantype = get_channel_type_from_name(
262 ltt_channels_get_name_from_index(chan));
263 new_trace->channels[chan].subbuf_size =
264 chan_infos[chantype].def_subbufsize;
265 new_trace->channels[chan].subbuf_cnt =
266 chan_infos[chantype].def_subbufcount;
267 }
268
269 cds_list_add(&new_trace->list, &ltt_traces.setup_head);
270 return 0;
271
272 trace_free:
273 free(new_trace);
274 traces_error:
275 return err;
276 }
277
278
279 int ltt_trace_setup(const char *trace_name)
280 {
281 int ret;
282 ltt_lock_traces();
283 ret = _ltt_trace_setup(trace_name);
284 ltt_unlock_traces();
285 return ret;
286 }
287
288 /* must be called from within a traces lock. */
289 static void _ltt_trace_free(struct ust_trace *trace)
290 {
291 cds_list_del(&trace->list);
292 free(trace);
293 }
294
295 int ltt_trace_set_type(const char *trace_name, const char *trace_type)
296 {
297 int err = 0;
298 struct ust_trace *trace;
299 struct ltt_transport *tran_iter, *transport = NULL;
300
301 ltt_lock_traces();
302
303 trace = _ltt_trace_find_setup(trace_name);
304 if (!trace) {
305 ERR("Trace not found %s", trace_name);
306 err = -ENOENT;
307 goto traces_error;
308 }
309
310 pthread_mutex_lock(&ltt_transport_mutex);
311 cds_list_for_each_entry(tran_iter, &ltt_transport_list, node) {
312 if (!strcmp(tran_iter->name, trace_type)) {
313 transport = tran_iter;
314 break;
315 }
316 }
317 pthread_mutex_unlock(&ltt_transport_mutex);
318
319 if (!transport) {
320 ERR("Transport %s is not present", trace_type);
321 err = -EINVAL;
322 goto traces_error;
323 }
324
325 trace->transport = transport;
326
327 traces_error:
328 ltt_unlock_traces();
329 return err;
330 }
331
332 int ltt_trace_set_channel_subbufsize(const char *trace_name,
333 const char *channel_name, unsigned int size)
334 {
335 int err = 0;
336 struct ust_trace *trace;
337 int index;
338
339 ltt_lock_traces();
340
341 trace = _ltt_trace_find_setup(trace_name);
342 if (!trace) {
343 ERR("Trace not found %s", trace_name);
344 err = -ENOENT;
345 goto traces_error;
346 }
347
348 index = ltt_channels_get_index_from_name(channel_name);
349 if (index < 0) {
350 ERR("Channel %s not found", channel_name);
351 err = -ENOENT;
352 goto traces_error;
353 }
354 trace->channels[index].subbuf_size = size;
355
356 traces_error:
357 ltt_unlock_traces();
358 return err;
359 }
360
361 int ltt_trace_set_channel_subbufcount(const char *trace_name,
362 const char *channel_name, unsigned int cnt)
363 {
364 int err = 0;
365 struct ust_trace *trace;
366 int index;
367
368 ltt_lock_traces();
369
370 trace = _ltt_trace_find_setup(trace_name);
371 if (!trace) {
372 ERR("Trace not found %s", trace_name);
373 err = -ENOENT;
374 goto traces_error;
375 }
376
377 index = ltt_channels_get_index_from_name(channel_name);
378 if (index < 0) {
379 ERR("Channel %s not found", channel_name);
380 err = -ENOENT;
381 goto traces_error;
382 }
383 trace->channels[index].subbuf_cnt = cnt;
384
385 traces_error:
386 ltt_unlock_traces();
387 return err;
388 }
389
390 int ltt_trace_set_channel_enable(const char *trace_name,
391 const char *channel_name, unsigned int enable)
392 {
393 int err = 0;
394 struct ust_trace *trace;
395 int index;
396
397 ltt_lock_traces();
398
399 trace = _ltt_trace_find_setup(trace_name);
400 if (!trace) {
401 ERR("Trace not found %s", trace_name);
402 err = -ENOENT;
403 goto traces_error;
404 }
405
406 /*
407 * Datas in metadata channel(marker info) is necessary to be able to
408 * read the trace, we always enable this channel.
409 */
410 if (!enable && !strcmp(channel_name, "metadata")) {
411 ERR("Trying to disable metadata channel");
412 err = -EINVAL;
413 goto traces_error;
414 }
415
416 index = ltt_channels_get_index_from_name(channel_name);
417 if (index < 0) {
418 ERR("Channel %s not found", channel_name);
419 err = -ENOENT;
420 goto traces_error;
421 }
422
423 trace->channels[index].active = enable;
424
425 traces_error:
426 ltt_unlock_traces();
427 return err;
428 }
429
430 int ltt_trace_set_channel_overwrite(const char *trace_name,
431 const char *channel_name, unsigned int overwrite)
432 {
433 int err = 0;
434 struct ust_trace *trace;
435 int index;
436
437 ltt_lock_traces();
438
439 trace = _ltt_trace_find_setup(trace_name);
440 if (!trace) {
441 ERR("Trace not found %s", trace_name);
442 err = -ENOENT;
443 goto traces_error;
444 }
445
446 /*
447 * Always put the metadata channel in non-overwrite mode :
448 * This is a very low traffic channel and it can't afford to have its
449 * data overwritten : this data (marker info) is necessary to be
450 * able to read the trace.
451 */
452 if (overwrite && !strcmp(channel_name, "metadata")) {
453 ERR("Trying to set metadata channel to overwrite mode");
454 err = -EINVAL;
455 goto traces_error;
456 }
457
458 index = ltt_channels_get_index_from_name(channel_name);
459 if (index < 0) {
460 ERR("Channel %s not found", channel_name);
461 err = -ENOENT;
462 goto traces_error;
463 }
464
465 trace->channels[index].overwrite = overwrite;
466
467 traces_error:
468 ltt_unlock_traces();
469 return err;
470 }
471
472 int ltt_trace_alloc(const char *trace_name)
473 {
474 int err = 0;
475 struct ust_trace *trace;
476 unsigned int subbuf_size, subbuf_cnt;
477 int chan;
478 const char *channel_name;
479
480 ltt_lock_traces();
481
482 if (_ltt_trace_find(trace_name)) { /* Trace already allocated */
483 err = 1;
484 goto traces_error;
485 }
486
487 trace = _ltt_trace_find_setup(trace_name);
488 if (!trace) {
489 ERR("Trace not found %s", trace_name);
490 err = -ENOENT;
491 goto traces_error;
492 }
493
494 urcu_ref_init(&trace->urcu_ref);
495 urcu_ref_init(&trace->ltt_transport_urcu_ref);
496 trace->active = 0;
497 trace->freq_scale = trace_clock_freq_scale();
498
499 if (!trace->transport) {
500 ERR("Transport is not set");
501 err = -EINVAL;
502 goto transport_error;
503 }
504 trace->ops = &trace->transport->ops;
505
506 trace->start_freq = trace_clock_frequency();
507 trace->start_tsc = trace_clock_read64();
508 gettimeofday(&trace->start_time, NULL); //ust// changed /* FIXME: is this ok? */
509
510 for (chan = 0; chan < trace->nr_channels; chan++) {
511 if (!(trace->channels[chan].active))
512 continue;
513
514 channel_name = ltt_channels_get_name_from_index(chan);
515 WARN_ON(!channel_name);
516 subbuf_size = trace->channels[chan].subbuf_size;
517 subbuf_cnt = trace->channels[chan].subbuf_cnt;
518 prepare_chan_size_num(&subbuf_size, &subbuf_cnt);
519 err = trace->ops->create_channel(trace_name, trace,
520 channel_name,
521 &trace->channels[chan],
522 subbuf_size,
523 subbuf_cnt,
524 trace->channels[chan].overwrite);
525 if (err != 0) {
526 ERR("Cannot create channel %s", channel_name);
527 goto create_channel_error;
528 }
529 }
530
531 cds_list_del(&trace->list);
532 cds_list_add_rcu(&trace->list, &ltt_traces.head);
533
534 ltt_unlock_traces();
535
536 return 0;
537
538 create_channel_error:
539 for (chan--; chan >= 0; chan--)
540 if (trace->channels[chan].active)
541 trace->ops->remove_channel(&trace->channels[chan]);
542
543 transport_error:
544 traces_error:
545 ltt_unlock_traces();
546 return err;
547 }
548
549 /* Must be called while sure that trace is in the list. */
550 static int _ltt_trace_destroy(struct ust_trace *trace)
551 {
552 int err = -EPERM;
553
554 if (trace == NULL) {
555 err = -ENOENT;
556 goto traces_error;
557 }
558 if (trace->active) {
559 ERR("Can't destroy trace %s : tracer is active", trace->trace_name);
560 err = -EBUSY;
561 goto active_error;
562 }
563
564 cds_list_del_rcu(&trace->list);
565 synchronize_rcu();
566
567 return 0;
568
569 active_error:
570 traces_error:
571 return err;
572 }
573
574 /* Sleepable part of the destroy */
575 static void __ltt_trace_destroy(struct ust_trace *trace, int drop)
576 {
577 int i;
578 struct ust_channel *chan;
579
580 if(!drop) {
581 for (i = 0; i < trace->nr_channels; i++) {
582 chan = &trace->channels[i];
583 if (chan->active)
584 trace->ops->finish_channel(chan);
585 }
586 }
587
588 /*
589 * The currently destroyed trace is not in the trace list anymore,
590 * so it's safe to call the async wakeup ourself. It will deliver
591 * the last subbuffers.
592 */
593 trace_async_wakeup(trace);
594
595 for (i = 0; i < trace->nr_channels; i++) {
596 chan = &trace->channels[i];
597 if (chan->active)
598 trace->ops->remove_channel(chan);
599 }
600
601 urcu_ref_put(&trace->ltt_transport_urcu_ref, ltt_release_transport);
602
603 urcu_ref_put(&trace->urcu_ref, ltt_release_trace);
604 }
605
606 int ltt_trace_destroy(const char *trace_name, int drop)
607 {
608 int err = 0;
609 struct ust_trace *trace;
610
611 ltt_lock_traces();
612
613 trace = _ltt_trace_find(trace_name);
614 if (trace) {
615 err = _ltt_trace_destroy(trace);
616 if (err)
617 goto error;
618
619 ltt_unlock_traces();
620
621 __ltt_trace_destroy(trace, drop);
622
623 return 0;
624 }
625
626 trace = _ltt_trace_find_setup(trace_name);
627 if (trace) {
628 _ltt_trace_free(trace);
629 ltt_unlock_traces();
630 return 0;
631 }
632
633 err = -ENOENT;
634
635 error:
636 ltt_unlock_traces();
637 return err;
638 }
639
640 /* must be called from within a traces lock. */
641 static int _ltt_trace_start(struct ust_trace *trace)
642 {
643 int err = 0;
644
645 if (trace == NULL) {
646 err = -ENOENT;
647 goto traces_error;
648 }
649 if (trace->active)
650 DBG("Tracing already active for trace %s", trace->trace_name);
651 trace->active = 1;
652 /* Read by trace points without protection : be careful */
653 ltt_traces.num_active_traces++;
654 return err;
655
656 traces_error:
657 return err;
658 }
659
660 int ltt_trace_start(const char *trace_name)
661 {
662 int err = 0;
663 struct ust_trace *trace;
664
665 ltt_lock_traces();
666
667 trace = _ltt_trace_find(trace_name);
668 err = _ltt_trace_start(trace);
669 if (err)
670 goto no_trace;
671
672 ltt_unlock_traces();
673
674 /*
675 * Call the process-wide state dump.
676 * Notice that there is no protection on the trace : that's exactly
677 * why we iterate on the list and check for trace equality instead of
678 * directly using this trace handle inside the logging function: we want
679 * to record events only in a single trace in the trace session list.
680 */
681
682 ltt_dump_ust_marker_state(trace);
683
684 return err;
685
686 /* Error handling */
687 no_trace:
688 ltt_unlock_traces();
689 return err;
690 }
691
692 /* must be called from within traces lock */
693 static int _ltt_trace_stop(struct ust_trace *trace)
694 {
695 int err = -EPERM;
696
697 if (trace == NULL) {
698 err = -ENOENT;
699 goto traces_error;
700 }
701 if (!trace->active)
702 DBG("LTT : Tracing not active for trace %s", trace->trace_name);
703 if (trace->active) {
704 trace->active = 0;
705 ltt_traces.num_active_traces--;
706 }
707 return 0;
708
709 traces_error:
710 return err;
711 }
712
713 int ltt_trace_stop(const char *trace_name)
714 {
715 int err = 0;
716 struct ust_trace *trace;
717
718 ltt_lock_traces();
719 trace = _ltt_trace_find(trace_name);
720 err = _ltt_trace_stop(trace);
721 ltt_unlock_traces();
722 return err;
723 }
This page took 0.049949 seconds and 4 git commands to generate.