@@ -762,6 +762,26 @@ static bool rb_time_cmpxchg(rb_time_t *t, u64 expect, u64 set)
}
#endif
+/*
+ * Returns true if t == expect, and if possible will update with set,
+ * but t is not guaranteed to be updated even if this returns true
+ */
+static bool rb_time_cmp_and_update(rb_time_t *t, u64 expect, u64 set)
+{
+ u64 old_time;
+
+ /* Should not happen */
+ if (!rb_time_read(t, &old_time))
+ return false;
+ if (expect == old_time) {
+ /* Try to update it */
+ rb_time_cmpxchg(t, expect, set);
+ return true;
+ }
+ /* No need to do the cmpxchg() */
+ return false;
+}
+
/*
* Enable this to make sure that the event passed to
* ring_buffer_event_time_stamp() is not committed and also
@@ -3622,9 +3642,17 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,
barrier();
/*E*/ if (write == (local_read(&tail_page->write) & RB_WRITE_MASK) &&
info->after < ts &&
- rb_time_cmpxchg(&cpu_buffer->write_stamp,
- info->after, ts)) {
- /* Nothing came after this event between C and E */
+ rb_time_cmp_and_update(&cpu_buffer->write_stamp,
+ info->after, ts)) {
+ /*
+ * Nothing came after this event between C and E it is
+ * safe to use info->after for the delta.
+ * The above rb_time_cmp_and_update() may or may not
+ * have updated the write_stamp. If it did not then
+ * the next event will simply add an absolute timestamp
+ * as the write_stamp will be different than the
+ * before_stamp.
+ */
info->delta = ts - info->after;
} else {
/*