[LAD] [LAU] Simple, easy multithreaded circular buffer library for Linux?

Sean Bolton musound at jps.net
Mon Oct 20 20:42:35 UTC 2008

Hi Olivier,

On Oct 20, 2008, at 6:13 AM, Olivier Guilyardi wrote:
> Until now, I just couldn't write a test that fail because of the  
> lack of memory
> barrier on x86. However, I think I found another bug in Jack  
> ringbuffer, by
> writing another test.
> It's a bit of a weird test, I call it "bit circle": I start 16  
> "node" threads.
> Each node :
> - communicate with its adjacent node through 2 ring buffers
> - is responsible for shifting an integer by one bit
> - send the shifted result to the next node through a ring buffer
> - checks that the value read from previous node is correct.
> On my Debian Quad Core and Mac OS X Core Duo boxes, this test fails  
> with Jack's
> ringbuffer even with my patch applied. But it succeeds with  
> Portaudio (both with
> and without memory barriers), and also with Fons' implementation.
> I wish someone could eventually run my test suite on a PowerPC,  
> especially SMP.
> The usage is unchanged:
> svn co http://svn.samalyse.com/misc/rbtest
> cd rbtest
> make test
> The run time is now shorter, about 2 minutes. Below is the output.  
> You can see
> that jack (test-bit-circle-jack) fails the bit circle test, even  
> when patched
> (test-bit-circle-jack-fix1). "|" is printed when a node thread  
> starts, and "-"
> when a node has read 1000 values, to ensure data is really flowing.
> The test-int-array-* tests are the same as my original test. All *- 
> lfq tests use
> Fons's Lfq ringbuffer (modified to use char instead of uint32_t) as  
> backend.
> ./run-tests.sh bit-circle 512 jack jack-fix1 portaudio portaudio- 
> nobarrier lfq
> test-bit-circle-jack - starting (5s max) - buffer size: 512
> || FAILURE: 2 != 514

I thought it suspicious that 514 = 2 + 2 * 256, while on a PPC it  
FAILURE: 2 != 0.  Endianness bug? No, but it's a clue...

I don't think you're seeing a *bug* in the jack ringbuffer, just a  
difference in
semantics between it and the PortAudio and lfq imlementations.  Both PA
and lfq mask the index after reading it, so they can completely fill  
the buffer.
The jack implementation masks the stored index, which means it can't
ever completely fill the buffer, or there would be an ambiguity as to  
it was full or empty.  The most it can store is (size - 1) bytes.

In the jack version of your code, at some point, the buffer almost  
fills, and
jack_ringbuffer_write only writes a single byte to the buffer (low  
order on x86,
high order on PPC).  Next time around, it does this again.  Then the  
thread reads, not 0x0002 like it should, but either 0x0202 (x86) or  
0x0000 (PPC).

Paul said he prefers storing the masked pointer, but I think Fons & PA's
approach is better: it allows for full use of the buffer.


More information about the Linux-audio-dev mailing list