1f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten/* 2f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten * Copyright (C) 2014 The Android Open Source Project 3f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten * 4f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 5f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten * you may not use this file except in compliance with the License. 6f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten * You may obtain a copy of the License at 7f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten * 8f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 9f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten * 10f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten * Unless required by applicable law or agreed to in writing, software 11f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 12f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten * See the License for the specific language governing permissions and 14f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten * limitations under the License. 15f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten */ 16f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 17f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten#define LOG_TAG "FastCapture" 18f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten//#define LOG_NDEBUG 0 19f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 20f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten#define ATRACE_TAG ATRACE_TAG_AUDIO 21f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 22f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten#include "Configuration.h" 23f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten#include <linux/futex.h> 24f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten#include <sys/syscall.h> 25f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten#include <media/AudioBufferProvider.h> 26f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten#include <utils/Log.h> 27f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten#include <utils/Trace.h> 28f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten#include "FastCapture.h" 29f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 30f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kastennamespace android { 31f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 32e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten/*static*/ const FastCaptureState FastCapture::sInitial; 33f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 34f9715e43ea73361321663514c44129c939c5db2fGlenn KastenFastCapture::FastCapture() : FastThread("cycleC_ms", "loadC_us"), 35e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mInputSource(NULL), mInputSourceGen(0), mPipeSink(NULL), mPipeSinkGen(0), 36e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mReadBuffer(NULL), mReadBufferState(-1), mFormat(Format_Invalid), mSampleRate(0), 37e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten // mDummyDumpState 38e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mTotalNativeFramesRead(0) 39f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten{ 40e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mPrevious = &sInitial; 41e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mCurrent = &sInitial; 42f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 43e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mDummyDumpState = &mDummyFastCaptureDumpState; 44f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten} 45f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 46f91df1b368a140abd37c80b204bd48d78778cc43Glenn KastenFastCapture::~FastCapture() 47f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten{ 48f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten} 49f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 50f91df1b368a140abd37c80b204bd48d78778cc43Glenn KastenFastCaptureStateQueue* FastCapture::sq() 51f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten{ 52f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten return &mSQ; 53f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten} 54f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 55f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kastenconst FastThreadState *FastCapture::poll() 56f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten{ 57f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten return mSQ.poll(); 58f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten} 59f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 60f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kastenvoid FastCapture::setLog(NBLog::Writer *logWriter __unused) 61f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten{ 62f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten} 63f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 64f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kastenvoid FastCapture::onIdle() 65f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten{ 66e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mPreIdle = *(const FastCaptureState *)mCurrent; 67e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mCurrent = &mPreIdle; 68f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten} 69f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 70f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kastenvoid FastCapture::onExit() 71f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten{ 725115777127bb4d2d50833537e09054dcdffdfc76Glenn Kasten free(mReadBuffer); 73f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten} 74f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 75f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kastenbool FastCapture::isSubClassCommand(FastThreadState::Command command) 76f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten{ 77f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten switch ((FastCaptureState::Command) command) { 78f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten case FastCaptureState::READ: 79f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten case FastCaptureState::WRITE: 80f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten case FastCaptureState::READ_WRITE: 81f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten return true; 82f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten default: 83f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten return false; 84f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten } 85f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten} 86f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 87f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kastenvoid FastCapture::onStateChange() 88f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten{ 894dd03b5b68dcd8eb5f5ffe2cfe93d26b8f08b848Glenn Kasten const FastCaptureState * const current = (const FastCaptureState *) mCurrent; 904dd03b5b68dcd8eb5f5ffe2cfe93d26b8f08b848Glenn Kasten const FastCaptureState * const previous = (const FastCaptureState *) mPrevious; 914dd03b5b68dcd8eb5f5ffe2cfe93d26b8f08b848Glenn Kasten FastCaptureDumpState * const dumpState = (FastCaptureDumpState *) mDumpState; 92f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten const size_t frameCount = current->mFrameCount; 93f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 94f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten bool eitherChanged = false; 95f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 96f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten // check for change in input HAL configuration 97e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten NBAIO_Format previousFormat = mFormat; 98e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten if (current->mInputSourceGen != mInputSourceGen) { 99e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mInputSource = current->mInputSource; 100e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mInputSourceGen = current->mInputSourceGen; 101e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten if (mInputSource == NULL) { 102e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mFormat = Format_Invalid; 103e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mSampleRate = 0; 104f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten } else { 105e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mFormat = mInputSource->format(); 106e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mSampleRate = Format_sampleRate(mFormat); 10757c4e6f7464d458eb52d209c2a63524913d6406dGlenn Kasten#if !LOG_NDEBUG 108e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten unsigned channelCount = Format_channelCount(mFormat); 109d330ee46022f34da76d14d0c4d2910526ecc2321Andy Hung ALOG_ASSERT(channelCount >= 1 && channelCount <= FCC_8); 11057c4e6f7464d458eb52d209c2a63524913d6406dGlenn Kasten#endif 111f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten } 112e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten dumpState->mSampleRate = mSampleRate; 113f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten eitherChanged = true; 114f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten } 115f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 116f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten // check for change in pipe 117e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten if (current->mPipeSinkGen != mPipeSinkGen) { 118e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mPipeSink = current->mPipeSink; 119e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mPipeSinkGen = current->mPipeSinkGen; 120f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten eitherChanged = true; 121f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten } 122f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 123f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten // input source and pipe sink must be compatible 124e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten if (eitherChanged && mInputSource != NULL && mPipeSink != NULL) { 125e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten ALOG_ASSERT(Format_isEqual(mFormat, mPipeSink->format())); 126f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten } 127f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 128e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten if ((!Format_isEqual(mFormat, previousFormat)) || (frameCount != previous->mFrameCount)) { 1295115777127bb4d2d50833537e09054dcdffdfc76Glenn Kasten // FIXME to avoid priority inversion, don't free here 1305115777127bb4d2d50833537e09054dcdffdfc76Glenn Kasten free(mReadBuffer); 131e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mReadBuffer = NULL; 132e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten if (frameCount > 0 && mSampleRate > 0) { 133f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten // FIXME new may block for unbounded time at internal mutex of the heap 134f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten // implementation; it would be better to have normal capture thread allocate for 135f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten // us to avoid blocking here and to prevent possible priority inversion 1360a01c2fb68e6f35905de8dfaf938d099cd48587dAndy Hung size_t bufferSize = frameCount * Format_frameSize(mFormat); 1370a01c2fb68e6f35905de8dfaf938d099cd48587dAndy Hung (void)posix_memalign(&mReadBuffer, 32, bufferSize); 1380a01c2fb68e6f35905de8dfaf938d099cd48587dAndy Hung memset(mReadBuffer, 0, bufferSize); // if posix_memalign fails, will segv here. 139e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mPeriodNs = (frameCount * 1000000000LL) / mSampleRate; // 1.00 140e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mUnderrunNs = (frameCount * 1750000000LL) / mSampleRate; // 1.75 141e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mOverrunNs = (frameCount * 500000000LL) / mSampleRate; // 0.50 142e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mForceNs = (frameCount * 950000000LL) / mSampleRate; // 0.95 143e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mWarmupNsMin = (frameCount * 750000000LL) / mSampleRate; // 0.75 144e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mWarmupNsMax = (frameCount * 1250000000LL) / mSampleRate; // 1.25 145f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten } else { 146e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mPeriodNs = 0; 147e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mUnderrunNs = 0; 148e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mOverrunNs = 0; 149e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mForceNs = 0; 150e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mWarmupNsMin = 0; 151e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mWarmupNsMax = LONG_MAX; 152f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten } 153e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mReadBufferState = -1; 154f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten dumpState->mFrameCount = frameCount; 155f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten } 156f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 157f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten} 158f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 159f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kastenvoid FastCapture::onWork() 160f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten{ 1614dd03b5b68dcd8eb5f5ffe2cfe93d26b8f08b848Glenn Kasten const FastCaptureState * const current = (const FastCaptureState *) mCurrent; 1624dd03b5b68dcd8eb5f5ffe2cfe93d26b8f08b848Glenn Kasten FastCaptureDumpState * const dumpState = (FastCaptureDumpState *) mDumpState; 1634dd03b5b68dcd8eb5f5ffe2cfe93d26b8f08b848Glenn Kasten const FastCaptureState::Command command = mCommand; 164f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten const size_t frameCount = current->mFrameCount; 165f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 166f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten if ((command & FastCaptureState::READ) /*&& isWarm*/) { 167e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten ALOG_ASSERT(mInputSource != NULL); 168e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten ALOG_ASSERT(mReadBuffer != NULL); 169f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten dumpState->mReadSequence++; 170f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten ATRACE_BEGIN("read"); 171d79072e9dff59f767cce2cda1caab80ce5a0815bGlenn Kasten ssize_t framesRead = mInputSource->read(mReadBuffer, frameCount); 172f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten ATRACE_END(); 173f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten dumpState->mReadSequence++; 174f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten if (framesRead >= 0) { 175f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten LOG_ALWAYS_FATAL_IF((size_t) framesRead > frameCount); 176e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mTotalNativeFramesRead += framesRead; 177e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten dumpState->mFramesRead = mTotalNativeFramesRead; 178e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mReadBufferState = framesRead; 179f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten } else { 180f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten dumpState->mReadErrors++; 181e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mReadBufferState = 0; 182f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten } 183f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten // FIXME rename to attemptedIO 184e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mAttemptedWrite = true; 185f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten } 186f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 187f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten if (command & FastCaptureState::WRITE) { 188e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten ALOG_ASSERT(mPipeSink != NULL); 189e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten ALOG_ASSERT(mReadBuffer != NULL); 190e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten if (mReadBufferState < 0) { 1915115777127bb4d2d50833537e09054dcdffdfc76Glenn Kasten memset(mReadBuffer, 0, frameCount * Format_frameSize(mFormat)); 192e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten mReadBufferState = frameCount; 193f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten } 194e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten if (mReadBufferState > 0) { 195e4a7ce250cb94a00aa2f76e5edca1c4479dc5401Glenn Kasten ssize_t framesWritten = mPipeSink->write(mReadBuffer, mReadBufferState); 196f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten // FIXME This supports at most one fast capture client. 197f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten // To handle multiple clients this could be converted to an array, 198f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten // or with a lot more work the control block could be shared by all clients. 199f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten audio_track_cblk_t* cblk = current->mCblk; 200f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten if (cblk != NULL && framesWritten > 0) { 201f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten int32_t rear = cblk->u.mStreaming.mRear; 202f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten android_atomic_release_store(framesWritten + rear, &cblk->u.mStreaming.mRear); 203f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten cblk->mServer += framesWritten; 204f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex); 205f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten if (!(old & CBLK_FUTEX_WAKE)) { 206f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten // client is never in server process, so don't use FUTEX_WAKE_PRIVATE 207f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, 1); 208f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten } 209f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten } 210f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten } 211f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten } 212f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten} 213f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten 214f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten} // namespace android 215