fifo.cpp revision c0924bc38334c7adbf8cbc9cfa9d00559c002652
19b4c805bc22842480690f14826b729845887963aGlenn Kasten/* 29b4c805bc22842480690f14826b729845887963aGlenn Kasten * Copyright (C) 2015 The Android Open Source Project 39b4c805bc22842480690f14826b729845887963aGlenn Kasten * 49b4c805bc22842480690f14826b729845887963aGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 59b4c805bc22842480690f14826b729845887963aGlenn Kasten * you may not use this file except in compliance with the License. 69b4c805bc22842480690f14826b729845887963aGlenn Kasten * You may obtain a copy of the License at 79b4c805bc22842480690f14826b729845887963aGlenn Kasten * 89b4c805bc22842480690f14826b729845887963aGlenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 99b4c805bc22842480690f14826b729845887963aGlenn Kasten * 109b4c805bc22842480690f14826b729845887963aGlenn Kasten * Unless required by applicable law or agreed to in writing, software 119b4c805bc22842480690f14826b729845887963aGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 129b4c805bc22842480690f14826b729845887963aGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139b4c805bc22842480690f14826b729845887963aGlenn Kasten * See the License for the specific language governing permissions and 149b4c805bc22842480690f14826b729845887963aGlenn Kasten * limitations under the License. 159b4c805bc22842480690f14826b729845887963aGlenn Kasten */ 169b4c805bc22842480690f14826b729845887963aGlenn Kasten 179b4c805bc22842480690f14826b729845887963aGlenn Kasten//#define LOG_NDEBUG 0 189b4c805bc22842480690f14826b729845887963aGlenn Kasten#define LOG_TAG "audio_utils_fifo" 199b4c805bc22842480690f14826b729845887963aGlenn Kasten 209052f3b550e82b0dc6ea83f9cbe37e5a0b6f2573Glenn Kasten#include <errno.h> 210ab1d86bc08d6d94721a87dafd62beedd384ac4bGlenn Kasten#include <limits.h> 229b4c805bc22842480690f14826b729845887963aGlenn Kasten#include <stdlib.h> 239b4c805bc22842480690f14826b729845887963aGlenn Kasten#include <string.h> 249052f3b550e82b0dc6ea83f9cbe37e5a0b6f2573Glenn Kasten 25c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten// FIXME futex portion is not supported on macOS, should use the macOS alternative 269052f3b550e82b0dc6ea83f9cbe37e5a0b6f2573Glenn Kasten#ifdef __linux__ 279052f3b550e82b0dc6ea83f9cbe37e5a0b6f2573Glenn Kasten#include <linux/futex.h> 283ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten#include <sys/syscall.h> 299052f3b550e82b0dc6ea83f9cbe37e5a0b6f2573Glenn Kasten#else 309052f3b550e82b0dc6ea83f9cbe37e5a0b6f2573Glenn Kasten#define FUTEX_WAIT 0 319052f3b550e82b0dc6ea83f9cbe37e5a0b6f2573Glenn Kasten#define FUTEX_WAIT_PRIVATE 0 329052f3b550e82b0dc6ea83f9cbe37e5a0b6f2573Glenn Kasten#define FUTEX_WAKE 0 339052f3b550e82b0dc6ea83f9cbe37e5a0b6f2573Glenn Kasten#define FUTEX_WAKE_PRIVATE 0 349052f3b550e82b0dc6ea83f9cbe37e5a0b6f2573Glenn Kasten#endif 353ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten 369b4c805bc22842480690f14826b729845887963aGlenn Kasten#include <audio_utils/fifo.h> 379b4c805bc22842480690f14826b729845887963aGlenn Kasten#include <audio_utils/roundup.h> 389b4c805bc22842480690f14826b729845887963aGlenn Kasten#include <cutils/log.h> 399b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten#include <utils/Errors.h> 409b4c805bc22842480690f14826b729845887963aGlenn Kasten 41c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten#ifdef __linux__ 42c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten#ifdef __ANDROID__ 43c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten// bionic for Android provides clock_nanosleep 44c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten#else 45c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten// bionic for desktop Linux omits clock_nanosleep 46c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kastenint clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *request, 47c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten struct timespec *remain) 48c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten{ 49c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten return syscall(SYS_clock_nanosleep, clock_id, flags, request, remain); 50c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten} 51c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten#endif // __ANDROID__ 52c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten#else // __linux__ 53c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten// macOS doesn't have clock_nanosleep 54c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kastenint clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *request, 55c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten struct timespec *remain) 56c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten{ 57c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten errno = ENOSYS; 58c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten return -1; 59c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten} 60c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten#endif // __linux__ 61c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten 623ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kastenstatic int sys_futex(void *addr1, int op, int val1, struct timespec *timeout, void *addr2, int val3) 633ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten{ 649052f3b550e82b0dc6ea83f9cbe37e5a0b6f2573Glenn Kasten#ifdef __linux__ 653ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3); 66c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten#else // __linux__ 67c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // macOS doesn't have futex 6886c4a6da76eb80896349703c4d4bb928722e0110Glenn Kasten (void) addr1; 6986c4a6da76eb80896349703c4d4bb928722e0110Glenn Kasten (void) op; 7086c4a6da76eb80896349703c4d4bb928722e0110Glenn Kasten (void) val1; 7186c4a6da76eb80896349703c4d4bb928722e0110Glenn Kasten (void) timeout; 7286c4a6da76eb80896349703c4d4bb928722e0110Glenn Kasten (void) addr2; 7386c4a6da76eb80896349703c4d4bb928722e0110Glenn Kasten (void) val3; 749052f3b550e82b0dc6ea83f9cbe37e5a0b6f2573Glenn Kasten errno = ENOSYS; 759052f3b550e82b0dc6ea83f9cbe37e5a0b6f2573Glenn Kasten return -1; 76c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten#endif // __linux__ 773ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten} 783ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten 79dc1ff1f1ee8bdd6baccd558bd4e279ffbbe01400Glenn Kastenaudio_utils_fifo_base::audio_utils_fifo_base(uint32_t frameCount, 80c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten audio_utils_fifo_index& writerRear, audio_utils_fifo_index *throttleFront) 816d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten __attribute__((no_sanitize("integer"))) : 829b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten mFrameCount(frameCount), mFrameCountP2(roundup(frameCount)), 8309acf7816f5ed575051d5d60be60d3c2bccc5ddbGlenn Kasten mFudgeFactor(mFrameCountP2 - mFrameCount), 84c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // FIXME need an API to configure the sync types 85c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mWriterRear(writerRear), mWriterRearSync(AUDIO_UTILS_FIFO_SYNC_SHARED), 86c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mThrottleFront(throttleFront), mThrottleFrontSync(AUDIO_UTILS_FIFO_SYNC_SHARED) 879b4c805bc22842480690f14826b729845887963aGlenn Kasten{ 8809acf7816f5ed575051d5d60be60d3c2bccc5ddbGlenn Kasten // actual upper bound on frameCount will depend on the frame size 890ab1d86bc08d6d94721a87dafd62beedd384ac4bGlenn Kasten LOG_ALWAYS_FATAL_IF(frameCount == 0 || frameCount > ((uint32_t) INT_MAX)); 909b4c805bc22842480690f14826b729845887963aGlenn Kasten} 919b4c805bc22842480690f14826b729845887963aGlenn Kasten 9209acf7816f5ed575051d5d60be60d3c2bccc5ddbGlenn Kastenaudio_utils_fifo_base::~audio_utils_fifo_base() 939b4c805bc22842480690f14826b729845887963aGlenn Kasten{ 949b4c805bc22842480690f14826b729845887963aGlenn Kasten} 959b4c805bc22842480690f14826b729845887963aGlenn Kasten 9609acf7816f5ed575051d5d60be60d3c2bccc5ddbGlenn Kastenuint32_t audio_utils_fifo_base::sum(uint32_t index, uint32_t increment) 979b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten __attribute__((no_sanitize("integer"))) 989b4c805bc22842480690f14826b729845887963aGlenn Kasten{ 999b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten if (mFudgeFactor) { 1009b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten uint32_t mask = mFrameCountP2 - 1; 1019b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten ALOG_ASSERT((index & mask) < mFrameCount); 1029b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten ALOG_ASSERT(increment <= mFrameCountP2); 1039b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten if ((index & mask) + increment >= mFrameCount) { 1049b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten increment += mFudgeFactor; 1059b4c805bc22842480690f14826b729845887963aGlenn Kasten } 1069b4c805bc22842480690f14826b729845887963aGlenn Kasten index += increment; 1079b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten ALOG_ASSERT((index & mask) < mFrameCount); 1089b4c805bc22842480690f14826b729845887963aGlenn Kasten return index; 1099b4c805bc22842480690f14826b729845887963aGlenn Kasten } else { 1109b4c805bc22842480690f14826b729845887963aGlenn Kasten return index + increment; 1119b4c805bc22842480690f14826b729845887963aGlenn Kasten } 1129b4c805bc22842480690f14826b729845887963aGlenn Kasten} 1139b4c805bc22842480690f14826b729845887963aGlenn Kasten 11409acf7816f5ed575051d5d60be60d3c2bccc5ddbGlenn Kastenint32_t audio_utils_fifo_base::diff(uint32_t rear, uint32_t front, size_t *lost) 1159b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten __attribute__((no_sanitize("integer"))) 1169b4c805bc22842480690f14826b729845887963aGlenn Kasten{ 1179b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten uint32_t diff = rear - front; 1189b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten if (mFudgeFactor) { 1199b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten uint32_t mask = mFrameCountP2 - 1; 1209b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten uint32_t rearMasked = rear & mask; 1219b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten uint32_t frontMasked = front & mask; 1229b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten if (rearMasked >= mFrameCount || frontMasked >= mFrameCount) { 1236d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten return -EIO; 1249b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten } 1259b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten uint32_t genDiff = (rear & ~mask) - (front & ~mask); 1269b4c805bc22842480690f14826b729845887963aGlenn Kasten if (genDiff != 0) { 1279b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten if (genDiff > mFrameCountP2) { 1286d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten if (lost != NULL) { 1296d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten // TODO provide a more accurate estimate 1306d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten *lost = (genDiff / mFrameCountP2) * mFrameCount; 1316d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten } 1326d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten return -EOVERFLOW; 1339b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten } 1349b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten diff -= mFudgeFactor; 1359b4c805bc22842480690f14826b729845887963aGlenn Kasten } 1369b4c805bc22842480690f14826b729845887963aGlenn Kasten } 1379b4c805bc22842480690f14826b729845887963aGlenn Kasten // FIFO should not be overfull 1389b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten if (diff > mFrameCount) { 1396d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten if (lost != NULL) { 1406d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten *lost = diff - mFrameCount; 1416d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten } 1426d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten return -EOVERFLOW; 1439b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten } 1449b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten return (int32_t) diff; 1459b4c805bc22842480690f14826b729845887963aGlenn Kasten} 1469b4c805bc22842480690f14826b729845887963aGlenn Kasten 1476d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten//////////////////////////////////////////////////////////////////////////////// 1486d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten 149dc1ff1f1ee8bdd6baccd558bd4e279ffbbe01400Glenn Kastenaudio_utils_fifo::audio_utils_fifo(uint32_t frameCount, uint32_t frameSize, void *buffer, 150c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten audio_utils_fifo_index& writerRear, audio_utils_fifo_index *throttleFront) 15109acf7816f5ed575051d5d60be60d3c2bccc5ddbGlenn Kasten __attribute__((no_sanitize("integer"))) : 152c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten audio_utils_fifo_base(frameCount, writerRear, throttleFront), 153dc1ff1f1ee8bdd6baccd558bd4e279ffbbe01400Glenn Kasten mFrameSize(frameSize), mBuffer(buffer) 15409acf7816f5ed575051d5d60be60d3c2bccc5ddbGlenn Kasten{ 15509acf7816f5ed575051d5d60be60d3c2bccc5ddbGlenn Kasten // maximum value of frameCount * frameSize is INT_MAX (2^31 - 1), not 2^31, because we need to 15609acf7816f5ed575051d5d60be60d3c2bccc5ddbGlenn Kasten // be able to distinguish successful and error return values from read and write. 1570ab1d86bc08d6d94721a87dafd62beedd384ac4bGlenn Kasten LOG_ALWAYS_FATAL_IF(frameCount == 0 || frameSize == 0 || buffer == NULL || 1580ab1d86bc08d6d94721a87dafd62beedd384ac4bGlenn Kasten frameCount > ((uint32_t) INT_MAX) / frameSize); 15909acf7816f5ed575051d5d60be60d3c2bccc5ddbGlenn Kasten} 16009acf7816f5ed575051d5d60be60d3c2bccc5ddbGlenn Kasten 161dc1ff1f1ee8bdd6baccd558bd4e279ffbbe01400Glenn Kastenaudio_utils_fifo::audio_utils_fifo(uint32_t frameCount, uint32_t frameSize, void *buffer, 162dc1ff1f1ee8bdd6baccd558bd4e279ffbbe01400Glenn Kasten bool throttlesWriter) : 163dc1ff1f1ee8bdd6baccd558bd4e279ffbbe01400Glenn Kasten audio_utils_fifo(frameCount, frameSize, buffer, mSingleProcessSharedRear, 164dc1ff1f1ee8bdd6baccd558bd4e279ffbbe01400Glenn Kasten throttlesWriter ? &mSingleProcessSharedFront : NULL) 165dc1ff1f1ee8bdd6baccd558bd4e279ffbbe01400Glenn Kasten{ 166dc1ff1f1ee8bdd6baccd558bd4e279ffbbe01400Glenn Kasten} 167dc1ff1f1ee8bdd6baccd558bd4e279ffbbe01400Glenn Kasten 16809acf7816f5ed575051d5d60be60d3c2bccc5ddbGlenn Kastenaudio_utils_fifo::~audio_utils_fifo() 16909acf7816f5ed575051d5d60be60d3c2bccc5ddbGlenn Kasten{ 17009acf7816f5ed575051d5d60be60d3c2bccc5ddbGlenn Kasten} 17109acf7816f5ed575051d5d60be60d3c2bccc5ddbGlenn Kasten 17209acf7816f5ed575051d5d60be60d3c2bccc5ddbGlenn Kasten//////////////////////////////////////////////////////////////////////////////// 17309acf7816f5ed575051d5d60be60d3c2bccc5ddbGlenn Kasten 1746d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kastenaudio_utils_fifo_provider::audio_utils_fifo_provider() : 1756d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten mObtained(0) 1766d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten{ 1776d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten} 1786d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten 1796d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kastenaudio_utils_fifo_provider::~audio_utils_fifo_provider() 1806d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten{ 1816d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten} 1826d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten 1836d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten//////////////////////////////////////////////////////////////////////////////// 1846d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten 1856d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kastenaudio_utils_fifo_writer::audio_utils_fifo_writer(audio_utils_fifo& fifo) : 1863ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten audio_utils_fifo_provider(), mFifo(fifo), mLocalRear(0), 187c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mLowLevelArm(fifo.mFrameCount), mHighLevelTrigger(0), 188c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mArmed(true), // because initial fill level of zero is < mLowLevelArm 1893ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten mEffectiveFrames(fifo.mFrameCount) 1906d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten{ 1916d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten} 1926d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten 1936d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kastenaudio_utils_fifo_writer::~audio_utils_fifo_writer() 1946d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten{ 1956d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten} 1966d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten 1973ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kastenssize_t audio_utils_fifo_writer::write(const void *buffer, size_t count, struct timespec *timeout) 1989b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten __attribute__((no_sanitize("integer"))) 1999b4c805bc22842480690f14826b729845887963aGlenn Kasten{ 200547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten audio_utils_iovec iovec[2]; 2013ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten ssize_t availToWrite = obtain(iovec, count, timeout); 202547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten if (availToWrite > 0) { 203169f3a203c9cb698098d29d5353dd6cb71f03992Glenn Kasten memcpy((char *) mFifo.mBuffer + iovec[0].mOffset * mFifo.mFrameSize, buffer, 204169f3a203c9cb698098d29d5353dd6cb71f03992Glenn Kasten iovec[0].mLength * mFifo.mFrameSize); 205169f3a203c9cb698098d29d5353dd6cb71f03992Glenn Kasten if (iovec[1].mLength > 0) { 206169f3a203c9cb698098d29d5353dd6cb71f03992Glenn Kasten memcpy((char *) mFifo.mBuffer + iovec[1].mOffset * mFifo.mFrameSize, 207169f3a203c9cb698098d29d5353dd6cb71f03992Glenn Kasten (char *) buffer + (iovec[0].mLength * mFifo.mFrameSize), 208169f3a203c9cb698098d29d5353dd6cb71f03992Glenn Kasten iovec[1].mLength * mFifo.mFrameSize); 209547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten } 2106d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten release(availToWrite); 211547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten } 212547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten return availToWrite; 213547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten} 214547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten 215c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten// iovec == NULL is not part of the public API, but is used internally to mean don't set mObtained 2163ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kastenssize_t audio_utils_fifo_writer::obtain(audio_utils_iovec iovec[2], size_t count, 2173ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten struct timespec *timeout) 218547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten __attribute__((no_sanitize("integer"))) 219547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten{ 220c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten int err = 0; 2216d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten size_t availToWrite; 2226d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten if (mFifo.mThrottleFront != NULL) { 2233ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten uint32_t front; 2243ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten for (;;) { 225c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten front = atomic_load_explicit(&mFifo.mThrottleFront->mIndex, std::memory_order_acquire); 226c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten int32_t filled = mFifo.diff(mLocalRear, front); 2273ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten if (filled < 0) { 228c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // on error, return an empty slice 229c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (iovec != NULL) { 230c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten iovec[0].mOffset = 0; 231c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten iovec[0].mLength = 0; 232c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten iovec[1].mOffset = 0; 233c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten iovec[1].mLength = 0; 234c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mObtained = 0; 235c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 2363ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten return (ssize_t) filled; 2373ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten } 2383ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten availToWrite = mEffectiveFrames > (uint32_t) filled ? 2393ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten mEffectiveFrames - (uint32_t) filled : 0; 2403ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten // TODO pull out "count == 0" 2413ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten if (count == 0 || availToWrite > 0 || timeout == NULL || 2423ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten (timeout->tv_sec == 0 && timeout->tv_nsec == 0)) { 2433ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten break; 2443ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten } 245c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // TODO add comments 246c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // TODO abstract out switch and replace by general sync object 247c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten int op = FUTEX_WAIT; 248c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten switch (mFifo.mThrottleFrontSync) { 249c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten case AUDIO_UTILS_FIFO_SYNC_SLEEP: 250c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten err = clock_nanosleep(CLOCK_MONOTONIC, 0 /*flags*/, timeout, NULL /*remain*/); 251c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (err < 0) { 252c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten LOG_ALWAYS_FATAL_IF(errno != EINTR, "unexpected err=%d errno=%d", err, errno); 253c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten err = -errno; 254c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } else { 255c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten err = -ETIMEDOUT; 256c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 257c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten break; 258c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten case AUDIO_UTILS_FIFO_SYNC_PRIVATE: 259c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten op = FUTEX_WAIT_PRIVATE; 260c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // fall through 261c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten case AUDIO_UTILS_FIFO_SYNC_SHARED: 262c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (timeout->tv_sec == LONG_MAX) { 263c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten timeout = NULL; 264c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 265c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten err = sys_futex(&mFifo.mThrottleFront->mIndex, op, front, timeout, NULL, 0); 266c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (err < 0) { 267c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten switch (errno) { 268c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten case EINTR: 269c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten case ETIMEDOUT: 270c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten err = -errno; 271c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten break; 272c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten default: 273c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten LOG_ALWAYS_FATAL("unexpected err=%d errno=%d", err, errno); 274c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten break; 275c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 2763ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten } 277c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten break; 278c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten default: 279c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten LOG_ALWAYS_FATAL("mFifo.mThrottleFrontSync=%d", mFifo.mThrottleFrontSync); 280c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten break; 2813ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten } 2823ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten timeout = NULL; 2836d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten } 2846d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten } else { 2853ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten availToWrite = mEffectiveFrames; 2869b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten } 2879b4c805bc22842480690f14826b729845887963aGlenn Kasten if (availToWrite > count) { 2889b4c805bc22842480690f14826b729845887963aGlenn Kasten availToWrite = count; 2899b4c805bc22842480690f14826b729845887963aGlenn Kasten } 2906d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten uint32_t rearMasked = mLocalRear & (mFifo.mFrameCountP2 - 1); 2916d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten size_t part1 = mFifo.mFrameCount - rearMasked; 2929b4c805bc22842480690f14826b729845887963aGlenn Kasten if (part1 > availToWrite) { 2939b4c805bc22842480690f14826b729845887963aGlenn Kasten part1 = availToWrite; 2949b4c805bc22842480690f14826b729845887963aGlenn Kasten } 295547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten size_t part2 = part1 > 0 ? availToWrite - part1 : 0; 296c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // return slice 297c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (iovec != NULL) { 298c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten iovec[0].mOffset = rearMasked; 299c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten iovec[0].mLength = part1; 300c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten iovec[1].mOffset = 0; 301c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten iovec[1].mLength = part2; 302c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mObtained = availToWrite; 303c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 304c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten return availToWrite > 0 ? availToWrite : err; 305547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten} 306547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten 3076d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kastenvoid audio_utils_fifo_writer::release(size_t count) 3086d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten __attribute__((no_sanitize("integer"))) 309547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten{ 310547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten if (count > 0) { 3110ab1d86bc08d6d94721a87dafd62beedd384ac4bGlenn Kasten LOG_ALWAYS_FATAL_IF(count > mObtained); 3123ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten if (mFifo.mThrottleFront != NULL) { 313dc1ff1f1ee8bdd6baccd558bd4e279ffbbe01400Glenn Kasten uint32_t front = atomic_load_explicit(&mFifo.mThrottleFront->mIndex, 3143ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten std::memory_order_acquire); 315c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten int32_t filled = mFifo.diff(mLocalRear, front); 3163ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten mLocalRear = mFifo.sum(mLocalRear, count); 317c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten atomic_store_explicit(&mFifo.mWriterRear.mIndex, mLocalRear, 3183ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten std::memory_order_release); 319c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // TODO add comments 320c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten int op = FUTEX_WAKE; 321c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten switch (mFifo.mWriterRearSync) { 322c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten case AUDIO_UTILS_FIFO_SYNC_SLEEP: 323c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten break; 324c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten case AUDIO_UTILS_FIFO_SYNC_PRIVATE: 325c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten op = FUTEX_WAKE_PRIVATE; 326c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // fall through 327c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten case AUDIO_UTILS_FIFO_SYNC_SHARED: 328c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (filled >= 0) { 329c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if ((uint32_t) filled < mLowLevelArm) { 330c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mArmed = true; 331c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 332c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (mArmed && filled + count > mHighLevelTrigger) { 333c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten int err = sys_futex(&mFifo.mWriterRear.mIndex, 334c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten op, INT_MAX /*waiters*/, NULL, NULL, 0); 335c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // err is number of processes woken up 336c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (err < 0) { 337c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten LOG_ALWAYS_FATAL("%s: unexpected err=%d errno=%d", 338c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten __func__, err, errno); 339c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 340c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mArmed = false; 3413ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten } 3423ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten } 343c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten break; 344c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten default: 345c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten LOG_ALWAYS_FATAL("mFifo.mWriterRearSync=%d", mFifo.mWriterRearSync); 346c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten break; 3473ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten } 3483ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten } else { 3493ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten mLocalRear = mFifo.sum(mLocalRear, count); 350c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten atomic_store_explicit(&mFifo.mWriterRear.mIndex, mLocalRear, 3513ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten std::memory_order_release); 3523ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten } 3536d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten mObtained -= count; 3546d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten } 3556d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten} 3566d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten 357c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kastenssize_t audio_utils_fifo_writer::available() 358c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten{ 359c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten return obtain(NULL /*iovec*/, SIZE_MAX /*count*/, NULL /*timeout*/); 360c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten} 361c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten 362c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kastenvoid audio_utils_fifo_writer::resize(uint32_t frameCount) 363c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten{ 364c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // cap to range [0, mFifo.mFrameCount] 365c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (frameCount > mFifo.mFrameCount) { 366c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten frameCount = mFifo.mFrameCount; 367c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 368c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // if we reduce the effective frame count, update hysteresis points to be within the new range 369c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (frameCount < mEffectiveFrames) { 370c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (mLowLevelArm > frameCount) { 371c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mLowLevelArm = frameCount; 372c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 373c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (mHighLevelTrigger > frameCount) { 374c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mHighLevelTrigger = frameCount; 375c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 376c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 377c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mEffectiveFrames = frameCount; 378c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten} 379c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten 380c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kastenuint32_t audio_utils_fifo_writer::getSize() const 381c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten{ 382c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten return mEffectiveFrames; 383c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten} 384c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten 385c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kastenvoid audio_utils_fifo_writer::setHysteresis(uint32_t lowLevelArm, uint32_t highLevelTrigger) 386c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten{ 387c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // cap to range [0, mEffectiveFrames] 388c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (lowLevelArm > mEffectiveFrames) { 389c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten lowLevelArm = mEffectiveFrames; 390c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 391c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (highLevelTrigger > mEffectiveFrames) { 392c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten highLevelTrigger = mEffectiveFrames; 393c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 394c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // TODO this is overly conservative; it would be better to arm based on actual fill level 395c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (lowLevelArm > mLowLevelArm) { 396c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mArmed = true; 397c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 398c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mLowLevelArm = lowLevelArm; 399c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mHighLevelTrigger = highLevelTrigger; 400c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten} 401c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten 402c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kastenvoid audio_utils_fifo_writer::getHysteresis(uint32_t *lowLevelArm, uint32_t *highLevelTrigger) const 403c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten{ 404c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten *lowLevelArm = mLowLevelArm; 405c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten *highLevelTrigger = mHighLevelTrigger; 406c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten} 407c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten 4086d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten//////////////////////////////////////////////////////////////////////////////// 4096d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten 4106d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kastenaudio_utils_fifo_reader::audio_utils_fifo_reader(audio_utils_fifo& fifo, bool throttlesWriter) : 411dc1ff1f1ee8bdd6baccd558bd4e279ffbbe01400Glenn Kasten audio_utils_fifo_provider(), mFifo(fifo), mLocalFront(0), 412dc1ff1f1ee8bdd6baccd558bd4e279ffbbe01400Glenn Kasten mThrottleFront(throttlesWriter ? mFifo.mThrottleFront : NULL), 413c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mHighLevelArm(-1), mLowLevelTrigger(mFifo.mFrameCount), 414c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mArmed(true) // because initial fill level of zero is > mHighLevelArm 4156d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten{ 4169b4c805bc22842480690f14826b729845887963aGlenn Kasten} 4179b4c805bc22842480690f14826b729845887963aGlenn Kasten 4186d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kastenaudio_utils_fifo_reader::~audio_utils_fifo_reader() 4196d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten{ 4200ab1d86bc08d6d94721a87dafd62beedd384ac4bGlenn Kasten // TODO Need a way to pass throttle capability to the another reader, should one reader exit. 4216d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten} 4226d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten 4233ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kastenssize_t audio_utils_fifo_reader::read(void *buffer, size_t count, struct timespec *timeout, 4243ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten size_t *lost) 4259b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten __attribute__((no_sanitize("integer"))) 4269b4c805bc22842480690f14826b729845887963aGlenn Kasten{ 427547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten audio_utils_iovec iovec[2]; 4283ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten ssize_t availToRead = obtain(iovec, count, timeout, lost); 429547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten if (availToRead > 0) { 430169f3a203c9cb698098d29d5353dd6cb71f03992Glenn Kasten memcpy(buffer, (char *) mFifo.mBuffer + iovec[0].mOffset * mFifo.mFrameSize, 431169f3a203c9cb698098d29d5353dd6cb71f03992Glenn Kasten iovec[0].mLength * mFifo.mFrameSize); 432169f3a203c9cb698098d29d5353dd6cb71f03992Glenn Kasten if (iovec[1].mLength > 0) { 433169f3a203c9cb698098d29d5353dd6cb71f03992Glenn Kasten memcpy((char *) buffer + (iovec[0].mLength * mFifo.mFrameSize), 434169f3a203c9cb698098d29d5353dd6cb71f03992Glenn Kasten (char *) mFifo.mBuffer + iovec[1].mOffset * mFifo.mFrameSize, 435169f3a203c9cb698098d29d5353dd6cb71f03992Glenn Kasten iovec[1].mLength * mFifo.mFrameSize); 436547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten } 4376d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten release(availToRead); 438547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten } 439547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten return availToRead; 440547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten} 441547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten 4423ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kastenssize_t audio_utils_fifo_reader::obtain(audio_utils_iovec iovec[2], size_t count, 4433ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten struct timespec *timeout) 4446d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten __attribute__((no_sanitize("integer"))) 4456d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten{ 446c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten return obtain(iovec, count, timeout, NULL /*lost*/); 4476d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten} 4486d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten 4496d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kastenvoid audio_utils_fifo_reader::release(size_t count) 450547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten __attribute__((no_sanitize("integer"))) 451547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten{ 4526d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten if (count > 0) { 4530ab1d86bc08d6d94721a87dafd62beedd384ac4bGlenn Kasten LOG_ALWAYS_FATAL_IF(count > mObtained); 454dc1ff1f1ee8bdd6baccd558bd4e279ffbbe01400Glenn Kasten if (mThrottleFront != NULL) { 455c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten uint32_t rear = atomic_load_explicit(&mFifo.mWriterRear.mIndex, 4563ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten std::memory_order_acquire); 457c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten int32_t filled = mFifo.diff(rear, mLocalFront); 4583ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten mLocalFront = mFifo.sum(mLocalFront, count); 459dc1ff1f1ee8bdd6baccd558bd4e279ffbbe01400Glenn Kasten atomic_store_explicit(&mThrottleFront->mIndex, mLocalFront, 4606d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten std::memory_order_release); 461c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // TODO add comments 462c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten int op = FUTEX_WAKE; 463c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten switch (mFifo.mThrottleFrontSync) { 464c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten case AUDIO_UTILS_FIFO_SYNC_SLEEP: 465c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten break; 466c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten case AUDIO_UTILS_FIFO_SYNC_PRIVATE: 467c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten op = FUTEX_WAKE_PRIVATE; 468c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // fall through 469c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten case AUDIO_UTILS_FIFO_SYNC_SHARED: 470c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (filled >= 0) { 471c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (filled > mHighLevelArm) { 472c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mArmed = true; 473c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 474c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (mArmed && filled - count < mLowLevelTrigger) { 475c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten int err = sys_futex(&mThrottleFront->mIndex, 476c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten op, 1 /*waiters*/, NULL, NULL, 0); 477c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // err is number of processes woken up 478c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (err < 0 || err > 1) { 479c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten LOG_ALWAYS_FATAL("%s: unexpected err=%d errno=%d", 480c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten __func__, err, errno); 481c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 482c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mArmed = false; 4833ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten } 4843ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten } 485c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten break; 486c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten default: 487c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten LOG_ALWAYS_FATAL("mFifo.mThrottleFrontSync=%d", mFifo.mThrottleFrontSync); 488c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten break; 4893ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten } 4903ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten } else { 4913ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten mLocalFront = mFifo.sum(mLocalFront, count); 4926d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten } 4936d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten mObtained -= count; 4946d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten } 4956d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten} 4966d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten 497c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten// iovec == NULL is not part of the public API, but is used internally to mean don't set mObtained 4983ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kastenssize_t audio_utils_fifo_reader::obtain(audio_utils_iovec iovec[2], size_t count, 4993ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten struct timespec *timeout, size_t *lost) 5006d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten __attribute__((no_sanitize("integer"))) 5016d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten{ 502c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten int err = 0; 5033ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten uint32_t rear; 5043ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten for (;;) { 505c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten rear = atomic_load_explicit(&mFifo.mWriterRear.mIndex, 5063ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten std::memory_order_acquire); 5073ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten // TODO pull out "count == 0" 5083ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten if (count == 0 || rear != mLocalFront || timeout == NULL || 5093ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten (timeout->tv_sec == 0 && timeout->tv_nsec == 0)) { 5103ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten break; 5113ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten } 512c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // TODO add comments 513c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten int op = FUTEX_WAIT; 514c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten switch (mFifo.mWriterRearSync) { 515c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten case AUDIO_UTILS_FIFO_SYNC_SLEEP: 516c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten err = clock_nanosleep(CLOCK_MONOTONIC, 0 /*flags*/, timeout, NULL /*remain*/); 517c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (err < 0) { 518c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten LOG_ALWAYS_FATAL_IF(errno != EINTR, "unexpected err=%d errno=%d", err, errno); 519c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten err = -errno; 520c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } else { 521c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten err = -ETIMEDOUT; 522c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 523c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten break; 524c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten case AUDIO_UTILS_FIFO_SYNC_PRIVATE: 525c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten op = FUTEX_WAIT_PRIVATE; 526c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // fall through 527c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten case AUDIO_UTILS_FIFO_SYNC_SHARED: 528c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (timeout->tv_sec == LONG_MAX) { 529c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten timeout = NULL; 530c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 531c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten err = sys_futex(&mFifo.mWriterRear.mIndex, op, rear, timeout, NULL, 0); 532c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (err < 0) { 533c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten switch (errno) { 534c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten case EINTR: 535c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten case ETIMEDOUT: 536c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten err = -errno; 537c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten break; 538c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten default: 539c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten LOG_ALWAYS_FATAL("unexpected err=%d errno=%d", err, errno); 540c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten break; 541c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 5423ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten } 543c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten break; 544c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten default: 545c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten LOG_ALWAYS_FATAL("mFifo.mWriterRearSync=%d", mFifo.mWriterRearSync); 546c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten break; 5473ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten } 5483ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten timeout = NULL; 5493ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten } 5506d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten int32_t filled = mFifo.diff(rear, mLocalFront, lost); 5519b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten if (filled < 0) { 5523ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten if (filled == -EOVERFLOW) { 5536d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten mLocalFront = rear; 5546d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten } 555c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // on error, return an empty slice 556c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (iovec != NULL) { 557c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten iovec[0].mOffset = 0; 558c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten iovec[0].mLength = 0; 559c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten iovec[1].mOffset = 0; 560c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten iovec[1].mLength = 0; 561c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mObtained = 0; 562c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 5639b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten return (ssize_t) filled; 5649b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten } 5659b4fe47208fbc80e5a56508fc8e7210fa4d888adGlenn Kasten size_t availToRead = (size_t) filled; 5669b4c805bc22842480690f14826b729845887963aGlenn Kasten if (availToRead > count) { 5679b4c805bc22842480690f14826b729845887963aGlenn Kasten availToRead = count; 5689b4c805bc22842480690f14826b729845887963aGlenn Kasten } 5696d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten uint32_t frontMasked = mLocalFront & (mFifo.mFrameCountP2 - 1); 5706d7ad76b2a2b04f3a61605ca1ca019a80b94d339Glenn Kasten size_t part1 = mFifo.mFrameCount - frontMasked; 5719b4c805bc22842480690f14826b729845887963aGlenn Kasten if (part1 > availToRead) { 5729b4c805bc22842480690f14826b729845887963aGlenn Kasten part1 = availToRead; 5739b4c805bc22842480690f14826b729845887963aGlenn Kasten } 574547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten size_t part2 = part1 > 0 ? availToRead - part1 : 0; 575c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // return slice 576c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (iovec != NULL) { 577c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten iovec[0].mOffset = frontMasked; 578c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten iovec[0].mLength = part1; 579c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten iovec[1].mOffset = 0; 580c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten iovec[1].mLength = part2; 581c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mObtained = availToRead; 582c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 583c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten return availToRead > 0 ? availToRead : err; 584c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten} 585c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten 586c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kastenssize_t audio_utils_fifo_reader::available() 587c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten{ 588c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten return available(NULL /*lost*/); 589c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten} 590c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten 591c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kastenssize_t audio_utils_fifo_reader::available(size_t *lost) 592c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten{ 593c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten return obtain(NULL /*iovec*/, SIZE_MAX /*count*/, NULL /*timeout*/, lost); 594c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten} 595c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten 596c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kastenvoid audio_utils_fifo_reader::setHysteresis(int32_t highLevelArm, uint32_t lowLevelTrigger) 597c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten{ 598c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // cap to range [0, mFifo.mFrameCount] 599c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (highLevelArm < 0) { 600c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten highLevelArm = -1; 601c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } else if ((uint32_t) highLevelArm > mFifo.mFrameCount) { 602c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten highLevelArm = mFifo.mFrameCount; 603c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 604c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (lowLevelTrigger > mFifo.mFrameCount) { 605c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten lowLevelTrigger = mFifo.mFrameCount; 606c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 607c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten // TODO this is overly conservative; it would be better to arm based on actual fill level 608c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten if (highLevelArm < mHighLevelArm) { 609c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mArmed = true; 610c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten } 611c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mHighLevelArm = highLevelArm; 612c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten mLowLevelTrigger = lowLevelTrigger; 613c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten} 614c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten 615c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kastenvoid audio_utils_fifo_reader::getHysteresis(int32_t *highLevelArm, uint32_t *lowLevelTrigger) const 616c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten{ 617c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten *highLevelArm = mHighLevelArm; 618c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten *lowLevelTrigger = mLowLevelTrigger; 619547a99206f741bbe5adacd9bf8b75c2d6b2aff0dGlenn Kasten} 620