On Fri, Mar 4, 2016 at 1:00 PM, <linux-audio-dev-request@lists.linuxaudio.org> wrote:
Send Linux-audio-dev mailing list submissions to
        linux-audio-dev@lists.linuxaudio.org

To subscribe or unsubscribe via the World Wide Web, visit
        http://lists.linuxaudio.org/listinfo/linux-audio-dev
or, via email, send a message with subject or body 'help' to
        linux-audio-dev-request@lists.linuxaudio.org

You can reach the person managing the list at
        linux-audio-dev-owner@lists.linuxaudio.org

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Linux-audio-dev digest..."


Today's Topics:

   1. Re: Code reordering (Sebastian Gesemann)


----------------------------------------------------------------------

Message: 1
Date: Fri, 4 Mar 2016 10:16:02 +0100
From: Sebastian Gesemann <s.gesemann@gmail.com>
To: Jonathan Brickman <jeb@ponderworthy.com>
Cc: Linux Audio Developers <linux-audio-dev@lists.linuxaudio.org>
Subject: Re: [LAD] Code reordering
Message-ID:
        <CAGdQazeKzU1ZOyHrnZLoQnXgm2ca4yZ36+-+xT1MupZMfjTpPg@mail.gmail.com>
Content-Type: text/plain; charset=UTF-8

On Wed, Mar 2, 2016 at 5:55 PM, Jonathan Brickman <jeb@ponderworthy.com> wrote:
> On 3/1/2016 11:40 AM, Paul Davis wrote:
>
> > the JACK implementation relies on two things to work:
> >
> >    * pointer and integer operations are (weakly) atomic on all platforms
> > that JACK runs on
> >    * code reordering will either not happen or will be prevented by the
> > compiler
>
> Does #2 mean that -O3 should always be avoided when compiling JACK clients?

As I said, I consider JACK's ringbuffer implementation to be broken.
According to the C11/C++11 memory model there is nothing in the code
that prevents reordering the update to write_ptr and the update to
*buf in jack_ringbuffer_write. The use of volatile only makes sure
that read/write accesses to the volatile variables are not reordered
or "optimized out" by caching. Specificaly, a volatile write is not a
release barrier. It does not constrain reordering with respect to
other memory locations (*buf). This makes the access to the buffer's
content unordered and invokes undefined behaviour.

Having said that, if you can be sure that the compiler does not
reorder this (by checking the assembly code, for example) then you
will be fine on an x86/x64 platform because this platform makes an
extra guarantee: writes in one thread are never seen out of order from
another thread's perspective.


You are right. There was even a discussion about how broken it was
in 2008, and it was fixed, at least in practice.
http://lists.linuxaudio.org/pipermail/linux-audio-user/2008-October/056000.html

Theoretically (and not unlikely also in practice), it seems to be still broken.
This can also confirmed by compiling with -fsanitize=thread:

WARNING: ThreadSanitizer: data race (pid=24978)
Write of size 8 at 0x7d0c0000efd8 by thread T2:
#0 jack_ringbuffer_write jack/ringbuffer.c:247 (test-int-array-jack+0x000000401a30)
#1 writer_start /home/ksvalast/rbtest/test-int-array.c:85 (test-int-array-jack+0x000000400f4d)
#2 <null> <null> (libtsan.so.0+0x0000000235b9)

Previous read of size 8 at 0x7d0c0000efd8 by thread T1:
#0 jack_ringbuffer_read_space jack/ringbuffer.c:108 (test-int-array-jack+0x000000401346)
#1 reader_start /home/ksvalast/rbtest/test-int-array.c:48 (test-int-array-jack+0x000000400df2)
#2 <null> <null> (libtsan.so.0+0x0000000235b9)

Location is heap block of size 48 at 0x7d0c0000efd0 allocated by main thread:
#0 malloc <null> (libtsan.so.0+0x000000025993)
#1 jack_ringbuffer_create jack/ringbuffer.c:41 (test-int-array-jack+0x0000004010ab)
#2 main /home/ksvalast/rbtest/test-int-array.c:102 (test-int-array-jack+0x00000040100c)

Thread T2 (tid=24981, running) created by main thread at:
#0 pthread_create <null> (libtsan.so.0+0x000000027a67)
#1 main /home/ksvalast/rbtest/test-int-array.c:105 (test-int-array-jack+0x000000401056)

Thread T1 (tid=24980, running) created by main thread at:
#0 pthread_create <null> (libtsan.so.0+0x000000027a67)
#1 main /home/ksvalast/rbtest/test-int-array.c:104 (test-int-array-jack+0x00000040103b)

SUMMARY: ThreadSanitizer: data race jack/ringbuffer.c:247 jack_ringbuffer_write
==================
==================
WARNING: ThreadSanitizer: data race (pid=24978)
Read of size 8 at 0x7d500000fe00 by thread T1:
#0 memcpy <null> (libtsan.so.0+0x00000002666a)
#1 jack_ringbuffer_read jack/ringbuffer.c:166 (test-int-array-jack+0x0000004015fc)
#2 reader_start /home/ksvalast/rbtest/test-int-array.c:50 (test-int-array-jack+0x000000400e22)
#3 <null> <null> (libtsan.so.0+0x0000000235b9)

Previous write of size 8 at 0x7d500000fe00 by thread T2:
#0 memcpy <null> (libtsan.so.0+0x00000002666a)
#1 jack_ringbuffer_write jack/ringbuffer.c:246 (test-int-array-jack+0x0000004019e5)
#2 writer_start /home/ksvalast/rbtest/test-int-array.c:85 (test-int-array-jack+0x000000400f4d)
#3 <null> <null> (libtsan.so.0+0x0000000235b9)

Location is heap block of size 512 at 0x7d500000fe00 allocated by main thread:
#0 malloc <null> (libtsan.so.0+0x000000025993)
#1 jack_ringbuffer_create jack/ringbuffer.c:52 (test-int-array-jack+0x0000004011c8)
#2 main /home/ksvalast/rbtest/test-int-array.c:102 (test-int-array-jack+0x00000040100c)

Thread T1 (tid=24980, running) created by main thread at:
#0 pthread_create <null> (libtsan.so.0+0x000000027a67)
#1 main /home/ksvalast/rbtest/test-int-array.c:104 (test-int-array-jack+0x00000040103b)

Thread T2 (tid=24981, running) created by main thread at:
#0 pthread_create <null> (libtsan.so.0+0x000000027a67)
#1 main /home/ksvalast/rbtest/test-int-array.c:105 (test-int-array-jack+0x000000401056)

SUMMARY: ThreadSanitizer: data race ??:0 __interceptor_memcpy
==================
==================
WARNING: ThreadSanitizer: data race (pid=24978)
Write of size 8 at 0x7d0c0000efe0 by thread T1:
#0 jack_ringbuffer_read jack/ringbuffer.c:167 (test-int-array-jack+0x000000401647)
#1 reader_start /home/ksvalast/rbtest/test-int-array.c:50 (test-int-array-jack+0x000000400e22)
#2 <null> <null> (libtsan.so.0+0x0000000235b9)

Previous read of size 8 at 0x7d0c0000efe0 by thread T2:
#0 jack_ringbuffer_write_space jack/ringbuffer.c:128 (test-int-array-jack+0x00000040141a)
#1 writer_start /home/ksvalast/rbtest/test-int-array.c:83 (test-int-array-jack+0x000000400f1d)
#2 <null> <null> (libtsan.so.0+0x0000000235b9)

Location is heap block of size 48 at 0x7d0c0000efd0 allocated by main thread:
#0 malloc <null> (libtsan.so.0+0x000000025993)
#1 jack_ringbuffer_create jack/ringbuffer.c:41 (test-int-array-jack+0x0000004010ab)
#2 main /home/ksvalast/rbtest/test-int-array.c:102 (test-int-array-jack+0x00000040100c)

Thread T1 (tid=24980, running) created by main thread at:
#0 pthread_create <null> (libtsan.so.0+0x000000027a67)
#1 main /home/ksvalast/rbtest/test-int-array.c:104 (test-int-array-jack+0x00000040103b)

Thread T2 (tid=24981, running) created by main thread at:
#0 pthread_create <null> (libtsan.so.0+0x000000027a67)
#1 main /home/ksvalast/rbtest/test-int-array.c:105 (test-int-array-jack+0x000000401056)

SUMMARY: ThreadSanitizer: data race jack/ringbuffer.c:167 jack_ringbuffer_read
==================