X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=blobdiff_plain;f=lib%2Ftrace-collection.c;h=1c78f280fe0bcb128d3da85dbdfdf5a0e5daa6b4;hp=0ee3c29f08fcb81ad213f4a349e3d4ec18196ce9;hb=91f361c1757256c11988ab16376419a72592e1a9;hpb=6cba487f031260536d6a77acde888c8b1a876fcf diff --git a/lib/trace-collection.c b/lib/trace-collection.c index 0ee3c29f..1c78f280 100644 --- a/lib/trace-collection.c +++ b/lib/trace-collection.c @@ -24,6 +24,7 @@ #include #include #include /* for clocks */ +#include #include @@ -63,6 +64,19 @@ static void check_clock_match(gpointer key, gpointer value, gpointer user_data) } } +/* + * Note: if using a frequency different from 1GHz for clock->offset, it + * is recommended to express the seconds in offset_s, otherwise there + * will be a loss of precision caused by the limited size of the double + * mantissa. + */ +static +uint64_t clock_offset_ns(struct ctf_clock *clock) +{ + return clock->offset_s * 1000000000ULL + + clock_cycles_to_ns(clock, clock->offset); +} + static void clock_add(gpointer key, gpointer value, gpointer user_data) { struct clock_match *clock_match = user_data; @@ -88,8 +102,7 @@ static void clock_add(gpointer key, gpointer value, gpointer user_data) fprintf(stderr, "[error] Only CTF traces with a single clock description are supported by this babeltrace version.\n"); } if (!clock_match->tc->offset_nr) { - clock_match->tc->offset_first = - (t_clock->offset_s * 1000000000ULL) + t_clock->offset; + clock_match->tc->offset_first = clock_offset_ns(t_clock); clock_match->tc->delta_offset_first_sum = 0; clock_match->tc->offset_nr++; clock_match->tc->single_clock_offset_avg = @@ -105,23 +118,18 @@ static void clock_add(gpointer key, gpointer value, gpointer user_data) * Check that the offsets match. If not, warn * the user that we do an arbitrary choice. */ - diff_ns = tc_clock->offset_s; - diff_ns -= t_clock->offset_s; - diff_ns *= 1000000000ULL; - diff_ns += tc_clock->offset; - diff_ns -= t_clock->offset; + diff_ns = clock_offset_ns(tc_clock) - clock_offset_ns(t_clock); printf_debug("Clock \"%s\" offset between traces has a delta of %" PRIu64 " ns.", g_quark_to_string(tc_clock->name), diff_ns < 0 ? -diff_ns : diff_ns); - if (diff_ns > 10000) { + if (diff_ns > 10000 || diff_ns < -10000) { fprintf(stderr, "[warning] Clock \"%s\" offset differs between traces (delta %" PRIu64 " ns). Using average.\n", g_quark_to_string(tc_clock->name), diff_ns < 0 ? -diff_ns : diff_ns); } /* Compute average */ clock_match->tc->delta_offset_first_sum += - (t_clock->offset_s * 1000000000ULL) + t_clock->offset - - clock_match->tc->offset_first; + clock_offset_ns(t_clock) - clock_match->tc->offset_first; clock_match->tc->offset_nr++; clock_match->tc->single_clock_offset_avg = clock_match->tc->offset_first @@ -132,13 +140,18 @@ static void clock_add(gpointer key, gpointer value, gpointer user_data) /* * Whenever we add a trace to the trace collection, check that we can - * correlate this trace with at least one other clock in the trace. + * correlate this trace with at least one other clock in the trace and + * convert the index from cycles to real time. */ int trace_collection_add(struct trace_collection *tc, struct trace_descriptor *td) { - struct ctf_trace *trace = container_of(td, struct ctf_trace, parent); + struct ctf_trace *trace; + + if (!tc || !td) + return -EINVAL; + trace = container_of(td, struct ctf_trace, parent); g_ptr_array_add(tc->array, td); trace->collection = tc; @@ -157,7 +170,7 @@ int trace_collection_add(struct trace_collection *tc, check_clock_match, &clock_match); if (!clock_match.clock_match) { - fprintf(stderr, "[error] No clocks can be correlated and multiple traces are added to the collection.\n"); + 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"); goto error; } } @@ -177,6 +190,7 @@ int trace_collection_add(struct trace_collection *tc, clock_add, &clock_match); } + return 0; error: return -EPERM; @@ -185,6 +199,9 @@ error: int trace_collection_remove(struct trace_collection *tc, struct trace_descriptor *td) { + if (!tc || !td) + return -EINVAL; + if (g_ptr_array_remove(tc->array, td)) { return 0; } else { @@ -195,6 +212,7 @@ int trace_collection_remove(struct trace_collection *tc, void init_trace_collection(struct trace_collection *tc) { + assert(tc); tc->array = g_ptr_array_new(); tc->clocks = g_hash_table_new(g_direct_hash, g_direct_equal); tc->single_clock_offset_avg = 0; @@ -209,6 +227,7 @@ void init_trace_collection(struct trace_collection *tc) */ void finalize_trace_collection(struct trace_collection *tc) { + assert(tc); g_ptr_array_free(tc->array, TRUE); g_hash_table_destroy(tc->clocks); }