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
, *clock_copy
;
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 clock_copy
= g_new0(struct ctf_clock
, 1);
108 *clock_copy
= *t_clock
;
109 if (t_clock
->description
) {
110 clock_copy
->description
= g_strdup(t_clock
->description
);
112 g_hash_table_insert(tc_clocks
,
113 (gpointer
) (unsigned long) v
,
115 } else if (!t_clock
->absolute
) {
119 * For non-absolute clocks, check that the
120 * offsets match. If not, warn the user that we
121 * do an arbitrary choice.
123 diff_ns
= clock_offset_ns(tc_clock
) - clock_offset_ns(t_clock
);
124 printf_debug("Clock \"%s\" offset between traces has a delta of %" PRIu64
" ns.",
125 g_quark_to_string(tc_clock
->name
),
126 diff_ns
< 0 ? -diff_ns
: diff_ns
);
127 if (diff_ns
> 10000 || diff_ns
< -10000) {
128 fprintf(stderr
, "[warning] Clock \"%s\" offset differs between traces (delta %" PRIu64
" ns). Using average.\n",
129 g_quark_to_string(tc_clock
->name
),
130 diff_ns
< 0 ? -diff_ns
: diff_ns
);
132 /* Compute average */
133 clock_match
->tc
->delta_offset_first_sum
+=
134 clock_offset_ns(t_clock
) - clock_match
->tc
->offset_first
;
135 clock_match
->tc
->offset_nr
++;
136 clock_match
->tc
->single_clock_offset_avg
=
137 clock_match
->tc
->offset_first
138 + (clock_match
->tc
->delta_offset_first_sum
/ clock_match
->tc
->offset_nr
);
139 /* Time need to use offset average */
140 clock_match
->tc
->clock_use_offset_avg
= 1;
146 * Whenever we add a trace to the trace collection, check that we can
147 * correlate this trace with at least one other clock in the trace and
148 * convert the index from cycles to real time.
150 int bt_trace_collection_add(struct trace_collection
*tc
,
151 struct bt_trace_descriptor
*trace
)
159 if (tc
->array
->len
> 1) {
160 struct clock_match clock_match
= {
161 .clocks
= tc
->clocks
,
167 * With two or more traces, we need correlation info
170 g_hash_table_foreach(trace
->clocks
,
173 if (!clock_match
.clock_match
) {
174 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");
179 g_ptr_array_add(tc
->array
, trace
);
180 trace
->collection
= tc
;
183 struct clock_match clock_match
= {
184 .clocks
= tc
->clocks
,
190 * Add each clock from the trace clocks into the trace
193 g_hash_table_foreach(trace
->clocks
,
203 int bt_trace_collection_remove(struct trace_collection
*tc
,
204 struct bt_trace_descriptor
*td
)
209 if (g_ptr_array_remove(tc
->array
, td
)) {
218 void clock_free(gpointer data
)
220 struct ctf_clock
*clock
= data
;
222 g_free(clock
->description
);
226 void bt_init_trace_collection(struct trace_collection
*tc
)
229 tc
->array
= g_ptr_array_new();
230 tc
->clocks
= g_hash_table_new_full(g_direct_hash
, g_direct_equal
,
232 tc
->single_clock_offset_avg
= 0;
233 tc
->offset_first
= 0;
234 tc
->delta_offset_first_sum
= 0;
239 * bt_finalize_trace_collection() closes the opened traces for read
240 * and free the memory allocated for trace collection
242 void bt_finalize_trace_collection(struct trace_collection
*tc
)
245 g_ptr_array_free(tc
->array
, TRUE
);
246 g_hash_table_destroy(tc
->clocks
);
This page took 0.033236 seconds and 4 git commands to generate.