fifo: non-throttling reader doesn't see data already written
Test: see the multi-reader interactive test
Change-Id: I0663a8e90efc094fef09401c6e2ecd3391100efa
diff --git a/audio_utils/fifo.cpp b/audio_utils/fifo.cpp
index 8f89318..ee36cbd 100644
--- a/audio_utils/fifo.cpp
+++ b/audio_utils/fifo.cpp
@@ -397,7 +397,16 @@
////////////////////////////////////////////////////////////////////////////////
audio_utils_fifo_reader::audio_utils_fifo_reader(audio_utils_fifo& fifo, bool throttlesWriter) :
- audio_utils_fifo_provider(fifo), mLocalFront(0),
+ audio_utils_fifo_provider(fifo),
+
+ // If we throttle the writer, then initialize our front index to zero so that we see all data
+ // currently in the buffer.
+ // Otherwise, ignore everything currently in the buffer by initializing our front index to the
+ // current value of writer's rear. This avoids an immediate -EOVERFLOW (overrun) in the case
+ // where reader starts out more than one buffer behind writer. The initial catch-up does not
+ // contribute towards the totalLost, totalFlushed, or totalReleased counters.
+ mLocalFront(throttlesWriter ? 0 : mFifo.mWriterRear.loadConsume()),
+
mThrottleFront(throttlesWriter ? mFifo.mThrottleFront : NULL),
mArmLevel(-1), mTriggerLevel(mFifo.mFrameCount),
mIsArmed(true), // because initial fill level of zero is > mArmLevel
diff --git a/audio_utils/fifo_index.cpp b/audio_utils/fifo_index.cpp
index ab8292f..d9a200a 100644
--- a/audio_utils/fifo_index.cpp
+++ b/audio_utils/fifo_index.cpp
@@ -42,6 +42,11 @@
return sys_futex(&mIndex, op, waiters, NULL, NULL, 0);
}
+uint32_t audio_utils_fifo_index::loadConsume()
+{
+ return atomic_load_explicit(&mIndex, std::memory_order_consume);
+}
+
////
RefIndexDeferredStoreReleaseDeferredWake::RefIndexDeferredStoreReleaseDeferredWake(
diff --git a/audio_utils/include/audio_utils/fifo.h b/audio_utils/include/audio_utils/fifo.h
index 1b5eef1..2e911ab 100644
--- a/audio_utils/include/audio_utils/fifo.h
+++ b/audio_utils/include/audio_utils/fifo.h
@@ -455,6 +455,8 @@
* \param fifo Associated FIFO. Passed by reference because it must be non-NULL.
* \param throttlesWriter Whether this reader throttles the writer.
* At most one reader can specify throttlesWriter == true.
+ * A non-throttling reader does not see any data written
+ * prior to construction of the reader.
*/
explicit audio_utils_fifo_reader(audio_utils_fifo& fifo, bool throttlesWriter = true);
virtual ~audio_utils_fifo_reader();
diff --git a/audio_utils/include/audio_utils/fifo_index.h b/audio_utils/include/audio_utils/fifo_index.h
index 56de05f..1b8401f 100644
--- a/audio_utils/include/audio_utils/fifo_index.h
+++ b/audio_utils/include/audio_utils/fifo_index.h
@@ -75,6 +75,9 @@
*/
int wake(int op, int waiters = 1);
+ // specialized use only, prefer loadAcquire in most cases
+ uint32_t loadConsume();
+
private:
// Linux futex is 32 bits regardless of platform.
// It would make more sense to declare this as atomic_uint32_t, but there is no such type name.