1010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten/* 2010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * Copyright (C) 2012 The Android Open Source Project 3010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * 4010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 5010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * you may not use this file except in compliance with the License. 6010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * You may obtain a copy of the License at 7010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * 8010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 9010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * 10010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * Unless required by applicable law or agreed to in writing, software 11010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 12010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * See the License for the specific language governing permissions and 14010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * limitations under the License. 15010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten */ 16010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 17010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#define LOG_TAG "PipeReader" 18010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten//#define LOG_NDEBUG 0 19010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 20010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#include <cutils/compiler.h> 21010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#include <utils/Log.h> 222dd4bdd715f586d4d30cf90cc6fc2bbfbce60fe0Glenn Kasten#include <media/nbaio/PipeReader.h> 23010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 24010662326b9c43c703725f933e95e0897f8a6bddGlenn Kastennamespace android { 25010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 26010662326b9c43c703725f933e95e0897f8a6bddGlenn KastenPipeReader::PipeReader(Pipe& pipe) : 27010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten NBAIO_Source(pipe.mFormat), 28010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mPipe(pipe), 29010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten // any data already in the pipe is not visible to this PipeReader 30010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mFront(android_atomic_acquire_load(&pipe.mRear)), 31010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mFramesOverrun(0), 32010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mOverruns(0) 33010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 34010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten android_atomic_inc(&pipe.mReaders); 35010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 36010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 37010662326b9c43c703725f933e95e0897f8a6bddGlenn KastenPipeReader::~PipeReader() 38010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 3957c4e6f7464d458eb52d209c2a63524913d6406dGlenn Kasten#if !LOG_NDEBUG 4057c4e6f7464d458eb52d209c2a63524913d6406dGlenn Kasten int32_t readers = 4157c4e6f7464d458eb52d209c2a63524913d6406dGlenn Kasten#else 4257c4e6f7464d458eb52d209c2a63524913d6406dGlenn Kasten (void) 4357c4e6f7464d458eb52d209c2a63524913d6406dGlenn Kasten#endif 4457c4e6f7464d458eb52d209c2a63524913d6406dGlenn Kasten android_atomic_dec(&mPipe.mReaders); 45010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ALOG_ASSERT(readers > 0); 46010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 47010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 48010662326b9c43c703725f933e95e0897f8a6bddGlenn Kastenssize_t PipeReader::availableToRead() 49010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 50010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_UNLIKELY(!mNegotiated)) { 51010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return NEGOTIATE; 52010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 53010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten int32_t rear = android_atomic_acquire_load(&mPipe.mRear); 54010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten // read() is not multi-thread safe w.r.t. itself, so no mutex or atomic op needed to read mFront 55010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t avail = rear - mFront; 56010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_UNLIKELY(avail > mPipe.mMaxFrames)) { 57fbae5dae5187aca9d974cbe15ec818e9c6f56705Glenn Kasten // Discard 1/16 of the most recent data in pipe to avoid another overrun immediately 58010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten int32_t oldFront = mFront; 59fbae5dae5187aca9d974cbe15ec818e9c6f56705Glenn Kasten mFront = rear - mPipe.mMaxFrames + (mPipe.mMaxFrames >> 4); 60010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mFramesOverrun += (size_t) (mFront - oldFront); 61010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ++mOverruns; 62010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return OVERRUN; 63010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 64010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return avail; 65010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 66010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 67d79072e9dff59f767cce2cda1caab80ce5a0815bGlenn Kastenssize_t PipeReader::read(void *buffer, size_t count) 68010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{ 69010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten ssize_t avail = availableToRead(); 70010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_UNLIKELY(avail <= 0)) { 71010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return avail; 72010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 73010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten // An overrun can occur from here on and be silently ignored, 74010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten // but it will be caught at next read() 75010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_LIKELY(count > (size_t) avail)) { 76010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten count = avail; 77010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 78010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t front = mFront & (mPipe.mMaxFrames - 1); 79010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten size_t red = mPipe.mMaxFrames - front; 80010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_LIKELY(red > count)) { 81010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten red = count; 82010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 83010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten // In particular, an overrun during the memcpy will result in reading corrupt data 844d693d6b8cc1283f92f5301daf19a07abc772a2bGlenn Kasten memcpy(buffer, (char *) mPipe.mBuffer + (front * mFrameSize), red * mFrameSize); 85010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten // We could re-read the rear pointer here to detect the corruption, but why bother? 86010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_UNLIKELY(front + red == mPipe.mMaxFrames)) { 87010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_UNLIKELY((count -= red) > front)) { 88010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten count = front; 89010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 90010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten if (CC_LIKELY(count > 0)) { 914d693d6b8cc1283f92f5301daf19a07abc772a2bGlenn Kasten memcpy((char *) buffer + (red * mFrameSize), mPipe.mBuffer, count * mFrameSize); 92010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten red += count; 93010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 94010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten } 95010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mFront += red; 96010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten mFramesRead += red; 97010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten return red; 98010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} 99010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten 100010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten} // namespace android 101