Fix: eliminate timestamp overlap between packets
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Sun, 24 Nov 2013 09:09:04 +0000 (04:09 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Sun, 24 Nov 2013 09:36:36 +0000 (04:36 -0500)
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 <mathieu.desnoyers@efficios.com>
lib/ringbuffer/frontend_api.h
lib/ringbuffer/frontend_internal.h
lib/ringbuffer/ring_buffer_frontend.c

index c36ec3dc2e3f0e3e8436a54ebee50b0be26d77a4..31ccbfad020c5a1afa1b8570f1e6be0dd28438fa 100644 (file)
@@ -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.
index dbebdeec86f3362c30d59642ef9ab6910ca94a28..eda800de4e1fbaeb2aac47a720ba665269689021 100644 (file)
@@ -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),
index 225d78c6c49e9d0a5b31c8587c9ef81bdf6701c6..9bb4184143902472d35e474563a2a84f86ac31a8 100644 (file)
@@ -1256,7 +1256,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());
@@ -1300,7 +1300,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);
@@ -1343,7 +1343,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());
This page took 0.02966 seconds and 4 git commands to generate.