From 510f66d17bb0cddb209ac01db1ed5be3da49a567 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Sun, 24 Nov 2013 04:09:04 -0500 Subject: [PATCH] Fix: eliminate timestamp overlap between packets By using the timestamp sampled at space reservation when the packet is being filled as "end timestamp" for a packet, we can ensure there is no overlap between packet timestamp ranges, so that packet timestamp end <= following packets timestamp begin. Overlap between consecutive packets becomes an issue when the end timestamp of a packet is greater than the end timestamp of a following packet, IOW a packet completely contains the timestamp range of a following packet. This kind of situation does not allow trace viewers to do binary search within the packet timestamps. This kind of situation will typically never occur if packets are significantly larger than event size, but this fix ensures it can never even theoretically happen. The only case where packets can still theoretically overlap is if they have equal begin and end timestamps, which is valid. Signed-off-by: Mathieu Desnoyers --- lib/ringbuffer/frontend_api.h | 2 +- lib/ringbuffer/frontend_internal.h | 12 +++++++++--- lib/ringbuffer/ring_buffer_frontend.c | 6 +++--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/lib/ringbuffer/frontend_api.h b/lib/ringbuffer/frontend_api.h index c36ec3dc..31ccbfad 100644 --- a/lib/ringbuffer/frontend_api.h +++ b/lib/ringbuffer/frontend_api.h @@ -292,7 +292,7 @@ void lib_ring_buffer_commit(const struct lib_ring_buffer_config *config, commit_count = v_read(config, &buf->commit_hot[endidx].cc); lib_ring_buffer_check_deliver(config, buf, chan, offset_end - 1, - commit_count, endidx); + commit_count, endidx, ctx->tsc); /* * Update used size at each commit. It's needed only for extracting * ring_buffer buffers from vmcore, after crash. diff --git a/lib/ringbuffer/frontend_internal.h b/lib/ringbuffer/frontend_internal.h index dbebdeec..eda800de 100644 --- a/lib/ringbuffer/frontend_internal.h +++ b/lib/ringbuffer/frontend_internal.h @@ -290,17 +290,24 @@ int lib_ring_buffer_reserve_committed(const struct lib_ring_buffer_config *confi - (commit_count & chan->commit_count_mask) == 0); } +/* + * Receive end of subbuffer TSC as parameter. It has been read in the + * space reservation loop of either reserve or switch, which ensures it + * progresses monotonically with event records in the buffer. Therefore, + * it ensures that the end timestamp of a subbuffer is <= begin + * timestamp of the following subbuffers. + */ static inline void lib_ring_buffer_check_deliver(const struct lib_ring_buffer_config *config, struct lib_ring_buffer *buf, struct channel *chan, unsigned long offset, unsigned long commit_count, - unsigned long idx) + unsigned long idx, + u64 tsc) { unsigned long old_commit_count = commit_count - chan->backend.subbuf_size; - u64 tsc; /* Check if all commits have been done */ if (unlikely((buf_trunc(offset, chan) >> chan->backend.num_subbuf_order) @@ -346,7 +353,6 @@ void lib_ring_buffer_check_deliver(const struct lib_ring_buffer_config *config, * and any other writer trying to access this subbuffer * in this state is required to drop records. */ - tsc = config->cb.ring_buffer_clock_read(chan); v_add(config, subbuffer_get_records_count(config, &buf->backend, idx), diff --git a/lib/ringbuffer/ring_buffer_frontend.c b/lib/ringbuffer/ring_buffer_frontend.c index 2a0b2004..5043105e 100644 --- a/lib/ringbuffer/ring_buffer_frontend.c +++ b/lib/ringbuffer/ring_buffer_frontend.c @@ -1249,7 +1249,7 @@ void lib_ring_buffer_switch_old_start(struct lib_ring_buffer *buf, commit_count = v_read(config, &buf->commit_hot[oldidx].cc); /* Check if the written buffer has to be delivered */ lib_ring_buffer_check_deliver(config, buf, chan, offsets->old, - commit_count, oldidx); + commit_count, oldidx, tsc); lib_ring_buffer_write_commit_counter(config, buf, chan, oldidx, offsets->old, commit_count, config->cb.subbuffer_header_size()); @@ -1293,7 +1293,7 @@ void lib_ring_buffer_switch_old_end(struct lib_ring_buffer *buf, v_add(config, padding_size, &buf->commit_hot[oldidx].cc); commit_count = v_read(config, &buf->commit_hot[oldidx].cc); lib_ring_buffer_check_deliver(config, buf, chan, offsets->old - 1, - commit_count, oldidx); + commit_count, oldidx, tsc); lib_ring_buffer_write_commit_counter(config, buf, chan, oldidx, offsets->old, commit_count, padding_size); @@ -1336,7 +1336,7 @@ void lib_ring_buffer_switch_new_start(struct lib_ring_buffer *buf, commit_count = v_read(config, &buf->commit_hot[beginidx].cc); /* Check if the written buffer has to be delivered */ lib_ring_buffer_check_deliver(config, buf, chan, offsets->begin, - commit_count, beginidx); + commit_count, beginidx, tsc); lib_ring_buffer_write_commit_counter(config, buf, chan, beginidx, offsets->begin, commit_count, config->cb.subbuffer_header_size()); -- 2.34.1