6 * Copyright 2012 EfficiOS Inc. and Linux Foundation
8 * Author: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 #include <babeltrace/babeltrace.h>
29 #include <babeltrace/format.h>
30 #include <babeltrace/context.h>
31 #include <babeltrace/ctf/types.h>
32 #include <babeltrace/ctf-text/types.h>
33 #include <babeltrace/trace-collection.h>
34 #include <babeltrace/ctf-ir/metadata.h> /* for clocks */
35 #include <babeltrace/clock-internal.h>
41 struct ctf_clock
*clock_match
;
42 struct trace_collection
*tc
;
45 static void check_clock_match(gpointer key
, gpointer value
, gpointer user_data
)
47 struct clock_match
*match
= user_data
;
48 struct ctf_clock
*clock_a
= value
, *clock_b
;
50 if (clock_a
->absolute
) {
52 * Absolute time references, such as NTP, are looked up
55 clock_b
= g_hash_table_lookup(match
->clocks
,
56 (gpointer
) (unsigned long) clock_a
->name
);
58 match
->clock_match
= clock_b
;
61 } else if (clock_a
->uuid
!= 0) {
63 * Lookup the the trace clocks into the collection
66 clock_b
= g_hash_table_lookup(match
->clocks
,
67 (gpointer
) (unsigned long) clock_a
->uuid
);
69 match
->clock_match
= clock_b
;
75 static void clock_add(gpointer key
, gpointer value
, gpointer user_data
)
77 struct clock_match
*clock_match
= user_data
;
78 GHashTable
*tc_clocks
= clock_match
->clocks
;
79 struct ctf_clock
*t_clock
= value
;
82 if (t_clock
->absolute
)
87 struct ctf_clock
*tc_clock
;
89 tc_clock
= g_hash_table_lookup(tc_clocks
,
90 (gpointer
) (unsigned long) v
);
93 * For now we only support CTF that has one
94 * single clock uuid or name (absolute ref) per
97 if (g_hash_table_size(tc_clocks
) > 0) {
98 fprintf(stderr
, "[error] Only CTF traces with a single clock description are supported by this babeltrace version.\n");
100 if (!clock_match
->tc
->offset_nr
) {
101 clock_match
->tc
->offset_first
= clock_offset_ns(t_clock
);
102 clock_match
->tc
->delta_offset_first_sum
= 0;
103 clock_match
->tc
->offset_nr
++;
104 clock_match
->tc
->single_clock_offset_avg
=
105 clock_match
->tc
->offset_first
;
107 g_hash_table_insert(tc_clocks
,
108 (gpointer
) (unsigned long) v
,
110 } else if (!t_clock
->absolute
) {
114 * For non-absolute clocks, check that the
115 * offsets match. If not, warn the user that we
116 * do an arbitrary choice.
118 diff_ns
= clock_offset_ns(tc_clock
) - clock_offset_ns(t_clock
);
119 printf_debug("Clock \"%s\" offset between traces has a delta of %" PRIu64
" ns.",
120 g_quark_to_string(tc_clock
->name
),
121 diff_ns
< 0 ? -diff_ns
: diff_ns
);
122 if (diff_ns
> 10000 || diff_ns
< -10000) {
123 fprintf(stderr
, "[warning] Clock \"%s\" offset differs between traces (delta %" PRIu64
" ns). Using average.\n",
124 g_quark_to_string(tc_clock
->name
),
125 diff_ns
< 0 ? -diff_ns
: diff_ns
);
127 /* Compute average */
128 clock_match
->tc
->delta_offset_first_sum
+=
129 clock_offset_ns(t_clock
) - clock_match
->tc
->offset_first
;
130 clock_match
->tc
->offset_nr
++;
131 clock_match
->tc
->single_clock_offset_avg
=
132 clock_match
->tc
->offset_first
133 + (clock_match
->tc
->delta_offset_first_sum
/ clock_match
->tc
->offset_nr
);
134 /* Time need to use offset average */
135 clock_match
->tc
->clock_use_offset_avg
= 1;
141 * Whenever we add a trace to the trace collection, check that we can
142 * correlate this trace with at least one other clock in the trace and
143 * convert the index from cycles to real time.
145 int bt_trace_collection_add(struct trace_collection
*tc
,
146 struct bt_trace_descriptor
*trace
)
154 if (tc
->array
->len
> 1) {
155 struct clock_match clock_match
= {
156 .clocks
= tc
->clocks
,
162 * With two or more traces, we need correlation info
165 g_hash_table_foreach(trace
->clocks
,
168 if (!clock_match
.clock_match
) {
169 fprintf(stderr
, "[error] No clocks can be correlated and multiple traces are added to the collection. If you are certain those traces can be correlated, try using \"--clock-force-correlate\".\n");
174 g_ptr_array_add(tc
->array
, trace
);
175 trace
->collection
= tc
;
178 struct clock_match clock_match
= {
179 .clocks
= tc
->clocks
,
185 * Add each clock from the trace clocks into the trace
188 g_hash_table_foreach(trace
->clocks
,
198 int bt_trace_collection_remove(struct trace_collection
*tc
,
199 struct bt_trace_descriptor
*td
)
204 if (g_ptr_array_remove(tc
->array
, td
)) {
212 void bt_init_trace_collection(struct trace_collection
*tc
)
215 tc
->array
= g_ptr_array_new();
216 tc
->clocks
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
217 tc
->single_clock_offset_avg
= 0;
218 tc
->offset_first
= 0;
219 tc
->delta_offset_first_sum
= 0;
224 * bt_finalize_trace_collection() closes the opened traces for read
225 * and free the memory allocated for trace collection
227 void bt_finalize_trace_collection(struct trace_collection
*tc
)
230 g_ptr_array_free(tc
->array
, TRUE
);
231 g_hash_table_destroy(tc
->clocks
);
This page took 0.035589 seconds and 4 git commands to generate.