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

Pieter Palmers pieterp at joow.be
Mon Oct 20 21:13:16 UTC 2008


Sean Bolton wrote:
> 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  
> returns
> 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  
> whether
> 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  
> following
> thread reads, not 0x0002 like it should, but either 0x0202 (x86) or  
> 0x0000 (PPC).
> 

I can confirm this, since the following will make the test 'succeed', 
although it results in a very slow progress once the buffers are full.

Index: test-bit-circle.c
===================================================================
--- test-bit-circle.c   (revision 314)
+++ test-bit-circle.c   (working copy)
@@ -50,6 +50,9 @@

      if (value)
      {
+      while(jack_ringbuffer_write_space(rb[1]) < 2) {
+        usleep(1000);
+      }
        jack_ringbuffer_write (rb[1], (char *) &value, sizeof (uint16_t));
        value = 0;
      }

Pieter



More information about the Linux-audio-dev mailing list