blob: f19f93b7ec6a1599b57f8ec85e4e9d122da3e589 [file] [log] [blame]
Glenn Kasten9b4c8052015-01-06 14:13:13 -08001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "audio_utils_fifo"
19
Glenn Kasten9052f3b2016-07-08 16:24:41 -070020#include <errno.h>
Glenn Kasten0ab1d862016-06-20 12:04:56 -070021#include <limits.h>
Glenn Kasten9b4c8052015-01-06 14:13:13 -080022#include <stdlib.h>
23#include <string.h>
Glenn Kasten9052f3b2016-07-08 16:24:41 -070024
25// FIXME futex portion is not supported on Mac, should use the Mac alternative
26#ifdef __linux__
27#include <linux/futex.h>
Glenn Kasten3ddacbb2016-06-20 14:41:03 -070028#include <sys/syscall.h>
Glenn Kasten9052f3b2016-07-08 16:24:41 -070029#else
30#define FUTEX_WAIT 0
31#define FUTEX_WAIT_PRIVATE 0
32#define FUTEX_WAKE 0
33#define FUTEX_WAKE_PRIVATE 0
34#endif
Glenn Kasten3ddacbb2016-06-20 14:41:03 -070035
Glenn Kasten9b4c8052015-01-06 14:13:13 -080036#include <audio_utils/fifo.h>
37#include <audio_utils/roundup.h>
Glenn Kasten9b4c8052015-01-06 14:13:13 -080038#include <cutils/log.h>
Glenn Kasten9b4fe472016-06-13 09:34:57 -070039#include <utils/Errors.h>
Glenn Kasten9b4c8052015-01-06 14:13:13 -080040
Glenn Kasten3ddacbb2016-06-20 14:41:03 -070041static int sys_futex(void *addr1, int op, int val1, struct timespec *timeout, void *addr2, int val3)
42{
Glenn Kasten9052f3b2016-07-08 16:24:41 -070043#ifdef __linux__
Glenn Kasten3ddacbb2016-06-20 14:41:03 -070044 return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3);
Glenn Kasten9052f3b2016-07-08 16:24:41 -070045#else
Glenn Kasten86c4a6d2016-07-09 10:37:17 -070046 (void) addr1;
47 (void) op;
48 (void) val1;
49 (void) timeout;
50 (void) addr2;
51 (void) val3;
Glenn Kasten9052f3b2016-07-08 16:24:41 -070052 errno = ENOSYS;
53 return -1;
54#endif
Glenn Kasten3ddacbb2016-06-20 14:41:03 -070055}
56
Glenn Kastendc1ff1f2016-09-02 13:54:59 -070057audio_utils_fifo_base::audio_utils_fifo_base(uint32_t frameCount,
58 audio_utils_fifo_index& sharedRear, audio_utils_fifo_index *throttleFront)
Glenn Kasten6d7ad762016-06-15 17:05:54 -070059 __attribute__((no_sanitize("integer"))) :
Glenn Kasten9b4fe472016-06-13 09:34:57 -070060 mFrameCount(frameCount), mFrameCountP2(roundup(frameCount)),
Glenn Kasten09acf782016-06-17 10:28:05 -070061 mFudgeFactor(mFrameCountP2 - mFrameCount),
Glenn Kasten3ddacbb2016-06-20 14:41:03 -070062 mIsPrivate(true),
Glenn Kastendc1ff1f2016-09-02 13:54:59 -070063 mSharedRear(sharedRear), mThrottleFront(throttleFront)
Glenn Kasten9b4c8052015-01-06 14:13:13 -080064{
Glenn Kasten09acf782016-06-17 10:28:05 -070065 // actual upper bound on frameCount will depend on the frame size
Glenn Kasten0ab1d862016-06-20 12:04:56 -070066 LOG_ALWAYS_FATAL_IF(frameCount == 0 || frameCount > ((uint32_t) INT_MAX));
Glenn Kasten9b4c8052015-01-06 14:13:13 -080067}
68
Glenn Kasten09acf782016-06-17 10:28:05 -070069audio_utils_fifo_base::~audio_utils_fifo_base()
Glenn Kasten9b4c8052015-01-06 14:13:13 -080070{
71}
72
Glenn Kasten09acf782016-06-17 10:28:05 -070073uint32_t audio_utils_fifo_base::sum(uint32_t index, uint32_t increment)
Glenn Kasten9b4fe472016-06-13 09:34:57 -070074 __attribute__((no_sanitize("integer")))
Glenn Kasten9b4c8052015-01-06 14:13:13 -080075{
Glenn Kasten9b4fe472016-06-13 09:34:57 -070076 if (mFudgeFactor) {
77 uint32_t mask = mFrameCountP2 - 1;
78 ALOG_ASSERT((index & mask) < mFrameCount);
79 ALOG_ASSERT(increment <= mFrameCountP2);
80 if ((index & mask) + increment >= mFrameCount) {
81 increment += mFudgeFactor;
Glenn Kasten9b4c8052015-01-06 14:13:13 -080082 }
83 index += increment;
Glenn Kasten9b4fe472016-06-13 09:34:57 -070084 ALOG_ASSERT((index & mask) < mFrameCount);
Glenn Kasten9b4c8052015-01-06 14:13:13 -080085 return index;
86 } else {
87 return index + increment;
88 }
89}
90
Glenn Kasten09acf782016-06-17 10:28:05 -070091int32_t audio_utils_fifo_base::diff(uint32_t rear, uint32_t front, size_t *lost)
Glenn Kasten9b4fe472016-06-13 09:34:57 -070092 __attribute__((no_sanitize("integer")))
Glenn Kasten9b4c8052015-01-06 14:13:13 -080093{
Glenn Kasten9b4fe472016-06-13 09:34:57 -070094 uint32_t diff = rear - front;
95 if (mFudgeFactor) {
96 uint32_t mask = mFrameCountP2 - 1;
97 uint32_t rearMasked = rear & mask;
98 uint32_t frontMasked = front & mask;
99 if (rearMasked >= mFrameCount || frontMasked >= mFrameCount) {
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700100 return -EIO;
Glenn Kasten9b4fe472016-06-13 09:34:57 -0700101 }
102 uint32_t genDiff = (rear & ~mask) - (front & ~mask);
Glenn Kasten9b4c8052015-01-06 14:13:13 -0800103 if (genDiff != 0) {
Glenn Kasten9b4fe472016-06-13 09:34:57 -0700104 if (genDiff > mFrameCountP2) {
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700105 if (lost != NULL) {
106 // TODO provide a more accurate estimate
107 *lost = (genDiff / mFrameCountP2) * mFrameCount;
108 }
109 return -EOVERFLOW;
Glenn Kasten9b4fe472016-06-13 09:34:57 -0700110 }
111 diff -= mFudgeFactor;
Glenn Kasten9b4c8052015-01-06 14:13:13 -0800112 }
113 }
114 // FIFO should not be overfull
Glenn Kasten9b4fe472016-06-13 09:34:57 -0700115 if (diff > mFrameCount) {
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700116 if (lost != NULL) {
117 *lost = diff - mFrameCount;
118 }
119 return -EOVERFLOW;
Glenn Kasten9b4fe472016-06-13 09:34:57 -0700120 }
121 return (int32_t) diff;
Glenn Kasten9b4c8052015-01-06 14:13:13 -0800122}
123
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700124////////////////////////////////////////////////////////////////////////////////
125
Glenn Kastendc1ff1f2016-09-02 13:54:59 -0700126audio_utils_fifo::audio_utils_fifo(uint32_t frameCount, uint32_t frameSize, void *buffer,
127 audio_utils_fifo_index& sharedRear, audio_utils_fifo_index *throttleFront)
Glenn Kasten09acf782016-06-17 10:28:05 -0700128 __attribute__((no_sanitize("integer"))) :
Glenn Kastendc1ff1f2016-09-02 13:54:59 -0700129 audio_utils_fifo_base(frameCount, sharedRear, throttleFront),
130 mFrameSize(frameSize), mBuffer(buffer)
Glenn Kasten09acf782016-06-17 10:28:05 -0700131{
132 // maximum value of frameCount * frameSize is INT_MAX (2^31 - 1), not 2^31, because we need to
133 // be able to distinguish successful and error return values from read and write.
Glenn Kasten0ab1d862016-06-20 12:04:56 -0700134 LOG_ALWAYS_FATAL_IF(frameCount == 0 || frameSize == 0 || buffer == NULL ||
135 frameCount > ((uint32_t) INT_MAX) / frameSize);
Glenn Kasten09acf782016-06-17 10:28:05 -0700136}
137
Glenn Kastendc1ff1f2016-09-02 13:54:59 -0700138audio_utils_fifo::audio_utils_fifo(uint32_t frameCount, uint32_t frameSize, void *buffer,
139 bool throttlesWriter) :
140 audio_utils_fifo(frameCount, frameSize, buffer, mSingleProcessSharedRear,
141 throttlesWriter ? &mSingleProcessSharedFront : NULL)
142{
143}
144
Glenn Kasten09acf782016-06-17 10:28:05 -0700145audio_utils_fifo::~audio_utils_fifo()
146{
147}
148
149////////////////////////////////////////////////////////////////////////////////
150
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700151audio_utils_fifo_provider::audio_utils_fifo_provider() :
152 mObtained(0)
153{
154}
155
156audio_utils_fifo_provider::~audio_utils_fifo_provider()
157{
158}
159
160////////////////////////////////////////////////////////////////////////////////
161
162audio_utils_fifo_writer::audio_utils_fifo_writer(audio_utils_fifo& fifo) :
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700163 audio_utils_fifo_provider(), mFifo(fifo), mLocalRear(0),
164 mLowLevelArm(fifo.mFrameCount), mHighLevelTrigger(0), mArmed(false),
165 mEffectiveFrames(fifo.mFrameCount)
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700166{
167}
168
169audio_utils_fifo_writer::~audio_utils_fifo_writer()
170{
171}
172
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700173ssize_t audio_utils_fifo_writer::write(const void *buffer, size_t count, struct timespec *timeout)
Glenn Kasten9b4fe472016-06-13 09:34:57 -0700174 __attribute__((no_sanitize("integer")))
Glenn Kasten9b4c8052015-01-06 14:13:13 -0800175{
Glenn Kasten547a9922016-06-15 13:07:31 -0700176 audio_utils_iovec iovec[2];
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700177 ssize_t availToWrite = obtain(iovec, count, timeout);
Glenn Kasten547a9922016-06-15 13:07:31 -0700178 if (availToWrite > 0) {
Glenn Kasten169f3a22016-06-17 10:43:34 -0700179 memcpy((char *) mFifo.mBuffer + iovec[0].mOffset * mFifo.mFrameSize, buffer,
180 iovec[0].mLength * mFifo.mFrameSize);
181 if (iovec[1].mLength > 0) {
182 memcpy((char *) mFifo.mBuffer + iovec[1].mOffset * mFifo.mFrameSize,
183 (char *) buffer + (iovec[0].mLength * mFifo.mFrameSize),
184 iovec[1].mLength * mFifo.mFrameSize);
Glenn Kasten547a9922016-06-15 13:07:31 -0700185 }
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700186 release(availToWrite);
Glenn Kasten547a9922016-06-15 13:07:31 -0700187 }
188 return availToWrite;
189}
190
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700191ssize_t audio_utils_fifo_writer::obtain(audio_utils_iovec iovec[2], size_t count,
192 struct timespec *timeout)
Glenn Kasten547a9922016-06-15 13:07:31 -0700193 __attribute__((no_sanitize("integer")))
194{
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700195 size_t availToWrite;
196 if (mFifo.mThrottleFront != NULL) {
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700197 uint32_t front;
198 for (;;) {
Glenn Kastendc1ff1f2016-09-02 13:54:59 -0700199 front = atomic_load_explicit(&mFifo.mThrottleFront->mIndex,
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700200 std::memory_order_acquire);
201 int32_t filled = mFifo.diff(mLocalRear, front, NULL /*lost*/);
202 if (filled < 0) {
203 mObtained = 0;
204 return (ssize_t) filled;
205 }
206 availToWrite = mEffectiveFrames > (uint32_t) filled ?
207 mEffectiveFrames - (uint32_t) filled : 0;
208 // TODO pull out "count == 0"
209 if (count == 0 || availToWrite > 0 || timeout == NULL ||
210 (timeout->tv_sec == 0 && timeout->tv_nsec == 0)) {
211 break;
212 }
Glenn Kastendc1ff1f2016-09-02 13:54:59 -0700213 int err = sys_futex(&mFifo.mThrottleFront->mIndex,
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700214 mFifo.mIsPrivate ? FUTEX_WAIT_PRIVATE : FUTEX_WAIT, front, timeout, NULL, 0);
215 if (err < 0) {
216 switch (errno) {
217 case EWOULDBLOCK:
218 case EINTR:
219 case ETIMEDOUT:
220 break;
221 default:
222 LOG_ALWAYS_FATAL("unexpected err=%d errno=%d", err, errno);
223 break;
224 }
225 }
226 timeout = NULL;
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700227 }
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700228 } else {
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700229 availToWrite = mEffectiveFrames;
Glenn Kasten9b4fe472016-06-13 09:34:57 -0700230 }
Glenn Kasten9b4c8052015-01-06 14:13:13 -0800231 if (availToWrite > count) {
232 availToWrite = count;
233 }
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700234 uint32_t rearMasked = mLocalRear & (mFifo.mFrameCountP2 - 1);
235 size_t part1 = mFifo.mFrameCount - rearMasked;
Glenn Kasten9b4c8052015-01-06 14:13:13 -0800236 if (part1 > availToWrite) {
237 part1 = availToWrite;
238 }
Glenn Kasten547a9922016-06-15 13:07:31 -0700239 size_t part2 = part1 > 0 ? availToWrite - part1 : 0;
Glenn Kasten169f3a22016-06-17 10:43:34 -0700240 iovec[0].mOffset = rearMasked;
241 iovec[0].mLength = part1;
242 iovec[1].mOffset = 0;
243 iovec[1].mLength = part2;
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700244 mObtained = availToWrite;
Glenn Kasten9b4c8052015-01-06 14:13:13 -0800245 return availToWrite;
246}
247
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700248void audio_utils_fifo_writer::release(size_t count)
249 __attribute__((no_sanitize("integer")))
Glenn Kasten547a9922016-06-15 13:07:31 -0700250{
251 if (count > 0) {
Glenn Kasten0ab1d862016-06-20 12:04:56 -0700252 LOG_ALWAYS_FATAL_IF(count > mObtained);
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700253 if (mFifo.mThrottleFront != NULL) {
Glenn Kastendc1ff1f2016-09-02 13:54:59 -0700254 uint32_t front = atomic_load_explicit(&mFifo.mThrottleFront->mIndex,
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700255 std::memory_order_acquire);
256 int32_t filled = mFifo.diff(mLocalRear, front, NULL /*lost*/);
257 mLocalRear = mFifo.sum(mLocalRear, count);
Glenn Kastendc1ff1f2016-09-02 13:54:59 -0700258 atomic_store_explicit(&mFifo.mSharedRear.mIndex, mLocalRear,
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700259 std::memory_order_release);
260 if (filled >= 0) {
261 if (filled + count <= mLowLevelArm) {
262 mArmed = true;
263 }
264 if (mArmed && filled + count >= mHighLevelTrigger) {
Glenn Kastendc1ff1f2016-09-02 13:54:59 -0700265 int err = sys_futex(&mFifo.mSharedRear.mIndex,
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700266 mFifo.mIsPrivate ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE,
267 INT_MAX /*waiters*/, NULL, NULL, 0);
268 // err is number of processes woken up
269 if (err < 0) {
270 LOG_ALWAYS_FATAL("%s: unexpected err=%d errno=%d", __func__, err, errno);
271 }
272 mArmed = false;
273 }
274 }
275 } else {
276 mLocalRear = mFifo.sum(mLocalRear, count);
Glenn Kastendc1ff1f2016-09-02 13:54:59 -0700277 atomic_store_explicit(&mFifo.mSharedRear.mIndex, mLocalRear,
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700278 std::memory_order_release);
279 }
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700280 mObtained -= count;
Glenn Kasten547a9922016-06-15 13:07:31 -0700281 }
282}
283
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700284////////////////////////////////////////////////////////////////////////////////
285
286audio_utils_fifo_reader::audio_utils_fifo_reader(audio_utils_fifo& fifo, bool throttlesWriter) :
Glenn Kastendc1ff1f2016-09-02 13:54:59 -0700287 audio_utils_fifo_provider(), mFifo(fifo), mLocalFront(0),
288 mThrottleFront(throttlesWriter ? mFifo.mThrottleFront : NULL),
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700289 mHighLevelArm(0), mLowLevelTrigger(mFifo.mFrameCount), mArmed(false)
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700290{
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700291}
292
293audio_utils_fifo_reader::~audio_utils_fifo_reader()
294{
Glenn Kasten0ab1d862016-06-20 12:04:56 -0700295 // TODO Need a way to pass throttle capability to the another reader, should one reader exit.
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700296}
297
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700298ssize_t audio_utils_fifo_reader::read(void *buffer, size_t count, struct timespec *timeout,
299 size_t *lost)
Glenn Kasten9b4fe472016-06-13 09:34:57 -0700300 __attribute__((no_sanitize("integer")))
Glenn Kasten9b4c8052015-01-06 14:13:13 -0800301{
Glenn Kasten547a9922016-06-15 13:07:31 -0700302 audio_utils_iovec iovec[2];
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700303 ssize_t availToRead = obtain(iovec, count, timeout, lost);
Glenn Kasten547a9922016-06-15 13:07:31 -0700304 if (availToRead > 0) {
Glenn Kasten169f3a22016-06-17 10:43:34 -0700305 memcpy(buffer, (char *) mFifo.mBuffer + iovec[0].mOffset * mFifo.mFrameSize,
306 iovec[0].mLength * mFifo.mFrameSize);
307 if (iovec[1].mLength > 0) {
308 memcpy((char *) buffer + (iovec[0].mLength * mFifo.mFrameSize),
309 (char *) mFifo.mBuffer + iovec[1].mOffset * mFifo.mFrameSize,
310 iovec[1].mLength * mFifo.mFrameSize);
Glenn Kasten547a9922016-06-15 13:07:31 -0700311 }
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700312 release(availToRead);
Glenn Kasten547a9922016-06-15 13:07:31 -0700313 }
314 return availToRead;
315}
316
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700317ssize_t audio_utils_fifo_reader::obtain(audio_utils_iovec iovec[2], size_t count,
318 struct timespec *timeout)
Glenn Kasten547a9922016-06-15 13:07:31 -0700319 __attribute__((no_sanitize("integer")))
320{
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700321 return obtain(iovec, count, timeout, NULL);
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700322}
323
324void audio_utils_fifo_reader::release(size_t count)
325 __attribute__((no_sanitize("integer")))
326{
327 if (count > 0) {
Glenn Kasten0ab1d862016-06-20 12:04:56 -0700328 LOG_ALWAYS_FATAL_IF(count > mObtained);
Glenn Kastendc1ff1f2016-09-02 13:54:59 -0700329 if (mThrottleFront != NULL) {
330 uint32_t rear = atomic_load_explicit(&mFifo.mSharedRear.mIndex,
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700331 std::memory_order_acquire);
332 int32_t filled = mFifo.diff(rear, mLocalFront, NULL /*lost*/);
333 mLocalFront = mFifo.sum(mLocalFront, count);
Glenn Kastendc1ff1f2016-09-02 13:54:59 -0700334 atomic_store_explicit(&mThrottleFront->mIndex, mLocalFront,
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700335 std::memory_order_release);
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700336 if (filled >= 0) {
337 if (filled - count >= mHighLevelArm) {
338 mArmed = true;
339 }
340 if (mArmed && filled - count <= mLowLevelTrigger) {
Glenn Kastendc1ff1f2016-09-02 13:54:59 -0700341 int err = sys_futex(&mFifo.mSharedRear.mIndex,
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700342 mFifo.mIsPrivate ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE,
343 1 /*waiters*/, NULL, NULL, 0);
344 // err is number of processes woken up
345 if (err < 0 || err > 1) {
346 LOG_ALWAYS_FATAL("%s: unexpected err=%d errno=%d", __func__, err, errno);
347 }
348 mArmed = false;
349 }
350 }
351 } else {
352 mLocalFront = mFifo.sum(mLocalFront, count);
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700353 }
354 mObtained -= count;
355 }
356}
357
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700358ssize_t audio_utils_fifo_reader::obtain(audio_utils_iovec iovec[2], size_t count,
359 struct timespec *timeout, size_t *lost)
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700360 __attribute__((no_sanitize("integer")))
361{
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700362 uint32_t rear;
363 for (;;) {
Glenn Kastendc1ff1f2016-09-02 13:54:59 -0700364 rear = atomic_load_explicit(&mFifo.mSharedRear.mIndex,
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700365 std::memory_order_acquire);
366 // TODO pull out "count == 0"
367 if (count == 0 || rear != mLocalFront || timeout == NULL ||
368 (timeout->tv_sec == 0 && timeout->tv_nsec == 0)) {
369 break;
370 }
Glenn Kastendc1ff1f2016-09-02 13:54:59 -0700371 int err = sys_futex(&mFifo.mSharedRear.mIndex,
372 mFifo.mIsPrivate ? FUTEX_WAIT_PRIVATE : FUTEX_WAIT,
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700373 rear, timeout, NULL, 0);
374 if (err < 0) {
375 switch (errno) {
376 case EWOULDBLOCK:
377 case EINTR:
378 case ETIMEDOUT:
379 break;
380 default:
381 LOG_ALWAYS_FATAL("unexpected err=%d errno=%d", err, errno);
382 break;
383 }
384 }
385 timeout = NULL;
386 }
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700387 int32_t filled = mFifo.diff(rear, mLocalFront, lost);
Glenn Kasten9b4fe472016-06-13 09:34:57 -0700388 if (filled < 0) {
Glenn Kasten3ddacbb2016-06-20 14:41:03 -0700389 if (filled == -EOVERFLOW) {
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700390 mLocalFront = rear;
391 }
392 mObtained = 0;
Glenn Kasten9b4fe472016-06-13 09:34:57 -0700393 return (ssize_t) filled;
394 }
395 size_t availToRead = (size_t) filled;
Glenn Kasten9b4c8052015-01-06 14:13:13 -0800396 if (availToRead > count) {
397 availToRead = count;
398 }
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700399 uint32_t frontMasked = mLocalFront & (mFifo.mFrameCountP2 - 1);
400 size_t part1 = mFifo.mFrameCount - frontMasked;
Glenn Kasten9b4c8052015-01-06 14:13:13 -0800401 if (part1 > availToRead) {
402 part1 = availToRead;
403 }
Glenn Kasten547a9922016-06-15 13:07:31 -0700404 size_t part2 = part1 > 0 ? availToRead - part1 : 0;
Glenn Kasten169f3a22016-06-17 10:43:34 -0700405 iovec[0].mOffset = frontMasked;
406 iovec[0].mLength = part1;
407 iovec[1].mOffset = 0;
408 iovec[1].mLength = part2;
Glenn Kasten6d7ad762016-06-15 17:05:54 -0700409 mObtained = availToRead;
Glenn Kasten547a9922016-06-15 13:07:31 -0700410 return availToRead;
411}