From f22cec3d45150e388ce701478368fb86bf2f3e73 Mon Sep 17 00:00:00 2001 From: rossb Date: Thu, 18 Aug 2011 11:19:36 +0000 Subject: [PATCH] moved memory barriers as per this thread: http://music.columbia.edu/pipermail/portaudio/2011-August/012803.html . use volatile because MSVC Read/WriteBarrier() intrinsics are just compiler barriers, but MSVC will insert memory barriers if you use volatile. see: http://msdn.microsoft.com/en-us/library/ms686355(VS.85).aspx --- src/common/pa_ringbuffer.c | 22 +++++++++++++++++----- src/common/pa_ringbuffer.h | 4 ++-- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/common/pa_ringbuffer.c b/src/common/pa_ringbuffer.c index a0a5225..0047e70 100644 --- a/src/common/pa_ringbuffer.c +++ b/src/common/pa_ringbuffer.c @@ -79,14 +79,12 @@ ring_buffer_size_t PaUtil_InitializeRingBuffer( PaUtilRingBuffer *rbuf, ring_buf ** Return number of elements available for reading. */ ring_buffer_size_t PaUtil_GetRingBufferReadAvailable( const PaUtilRingBuffer *rbuf ) { - PaUtil_ReadMemoryBarrier(); return ( (rbuf->writeIndex - rbuf->readIndex) & rbuf->bigMask ); } /*************************************************************************** ** Return number of elements available for writing. */ ring_buffer_size_t PaUtil_GetRingBufferWriteAvailable( const PaUtilRingBuffer *rbuf ) { - /* Since we are calling PaUtil_GetRingBufferReadAvailable, we don't need an aditional MB */ return ( rbuf->bufferSize - PaUtil_GetRingBufferReadAvailable(rbuf)); } @@ -128,6 +126,12 @@ ring_buffer_size_t PaUtil_GetRingBufferWriteRegions( PaUtilRingBuffer *rbuf, rin *dataPtr2 = NULL; *sizePtr2 = 0; } + + /* fixme: do we want a memory barrier here for write-after-read / acquire ? + if( available ) + PaUtil_ReadMemoryBarrier(); / * (read-after-read / acquire) * / + */ + return elementCount; } @@ -136,7 +140,9 @@ ring_buffer_size_t PaUtil_GetRingBufferWriteRegions( PaUtilRingBuffer *rbuf, rin */ ring_buffer_size_t PaUtil_AdvanceRingBufferWriteIndex( PaUtilRingBuffer *rbuf, ring_buffer_size_t elementCount ) { - /* we need to ensure that previous writes are seen before we update the write index */ + /* we need to ensure that previous writes are seen before we update the write index + (write after write / release) + */ PaUtil_WriteMemoryBarrier(); return rbuf->writeIndex = (rbuf->writeIndex + elementCount) & rbuf->bigMask; } @@ -152,7 +158,7 @@ ring_buffer_size_t PaUtil_GetRingBufferReadRegions( PaUtilRingBuffer *rbuf, ring void **dataPtr2, ring_buffer_size_t *sizePtr2 ) { ring_buffer_size_t index; - ring_buffer_size_t available = PaUtil_GetRingBufferReadAvailable( rbuf ); + ring_buffer_size_t available = PaUtil_GetRingBufferReadAvailable( rbuf ); /* doesn't use memory barrier */ if( elementCount > available ) elementCount = available; /* Check to see if read is not contiguous. */ index = rbuf->readIndex & rbuf->smallMask; @@ -172,13 +178,19 @@ ring_buffer_size_t PaUtil_GetRingBufferReadRegions( PaUtilRingBuffer *rbuf, ring *dataPtr2 = NULL; *sizePtr2 = 0; } + + if( available ) + PaUtil_ReadMemoryBarrier(); /* (read-after-read / acquire) */ + return elementCount; } /*************************************************************************** */ ring_buffer_size_t PaUtil_AdvanceRingBufferReadIndex( PaUtilRingBuffer *rbuf, ring_buffer_size_t elementCount ) { - /* we need to ensure that previous writes are always seen before updating the index. */ + /* ensure that previous reads (copies out of the ring buffer) are always completed before updating the read index. + (write-after-read / release) + */ PaUtil_WriteMemoryBarrier(); return rbuf->readIndex = (rbuf->readIndex + elementCount) & rbuf->bigMask; } diff --git a/src/common/pa_ringbuffer.h b/src/common/pa_ringbuffer.h index 34a8d5c..004fdd5 100644 --- a/src/common/pa_ringbuffer.h +++ b/src/common/pa_ringbuffer.h @@ -90,8 +90,8 @@ extern "C" typedef struct PaUtilRingBuffer { ring_buffer_size_t bufferSize; /**< Number of elements in FIFO. Power of 2. Set by PaUtil_InitRingBuffer. */ - ring_buffer_size_t writeIndex; /**< Index of next writable element. Set by PaUtil_AdvanceRingBufferWriteIndex. */ - ring_buffer_size_t readIndex; /**< Index of next readable element. Set by PaUtil_AdvanceRingBufferReadIndex. */ + volatile ring_buffer_size_t writeIndex; /**< Index of next writable element. Set by PaUtil_AdvanceRingBufferWriteIndex. */ + volatile ring_buffer_size_t readIndex; /**< Index of next readable element. Set by PaUtil_AdvanceRingBufferReadIndex. */ ring_buffer_size_t bigMask; /**< Used for wrapping indices with extra bit to distinguish full/empty. */ ring_buffer_size_t smallMask; /**< Used for fitting indices to buffer. */ ring_buffer_size_t elementSizeBytes; /**< Number of bytes per element. */ -- 2.43.0