From f313ca4daefa8aee7837f545a4b43795bd692789 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Tue, 23 Aug 2016 16:53:39 -0400 Subject: [PATCH] lib: Add full barrier before writing data_tail The kernel says here http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/kernel/events/ring_buffer.c?id=7a1dcf6ad#n61 : * Since the mmap() consumer (userspace) can run on a different CPU: * * kernel user * * if (LOAD ->data_tail) { LOAD ->data_head * (A) smp_rmb() (C) * STORE $data LOAD $data * smp_wmb() (B) smp_mb() (D) * STORE ->data_head STORE ->data_tail * } * * Where A pairs with D, and B pairs with C. * * In our case (A) is a control dependency that separates the load of * the ->data_tail and the stores of $data. In case ->data_tail * indicates there is no room in the buffer to store $data we do not. * * D needs to be a full barrier since it separates the data READ * from the tail WRITE. * * For B a WMB is sufficient since it separates two WRITEs, and for C * an RMB is sufficient since it separates two READs. * * See perf_output_begin(). So I'm pretty sure we need a full barrier before writing out data_tail. --- lib/sp-perf-counter.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/sp-perf-counter.c b/lib/sp-perf-counter.c index bd7315b3..d41bc9ea 100644 --- a/lib/sp-perf-counter.c +++ b/lib/sp-perf-counter.c @@ -291,6 +291,8 @@ sp_perf_counter_flush (SpPerfCounter *self, } info->tail = tail; + + atomic_thread_fence (memory_order_seq_cst); info->map->data_tail = tail; }