Merge "Simplify ThreadBase::exit() aka requestExitAndWait"
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 285f7a1..aaf73ea 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -998,7 +998,7 @@
mChannelCount(0),
mFrameSize(1), mFormat(AUDIO_FORMAT_INVALID),
mParamStatus(NO_ERROR),
- mStandby(false), mId(id), mExiting(false),
+ mStandby(false), mId(id),
mDevice(device),
mDeathRecipient(new PMDeathRecipient(this))
{
@@ -1017,17 +1017,23 @@
void AudioFlinger::ThreadBase::exit()
{
- // keep a strong ref on ourself so that we won't get
- // destroyed in the middle of requestExitAndWait()
- sp <ThreadBase> strongMe = this;
-
ALOGV("ThreadBase::exit");
{
+ // This lock prevents the following race in thread (uniprocessor for illustration):
+ // if (!exitPending()) {
+ // // context switch from here to exit()
+ // // exit() calls requestExit(), what exitPending() observes
+ // // exit() calls signal(), which is dropped since no waiters
+ // // context switch back from exit() to here
+ // mWaitWorkCV.wait(...);
+ // // now thread is hung
+ // }
AutoMutex lock(mLock);
- mExiting = true;
requestExit();
mWaitWorkCV.signal();
}
+ // When Thread::requestExitAndWait is made virtual and this method is renamed to
+ // "virtual status_t requestExitAndWait()", replace by "return Thread::requestExitAndWait();"
requestExitAndWait();
}
@@ -4516,7 +4522,7 @@
ALOGV("Signal record thread");
mWaitWorkCV.signal();
// do not wait for mStartStopCond if exiting
- if (mExiting) {
+ if (exitPending()) {
mActiveTrack.clear();
status = INVALID_OPERATION;
goto startError;
@@ -4543,7 +4549,7 @@
if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
mActiveTrack->mState = TrackBase::PAUSING;
// do not wait for mStartStopCond if exiting
- if (mExiting) {
+ if (exitPending()) {
return;
}
mStartStopCond.wait(mLock);
@@ -4989,6 +4995,8 @@
mPlaybackThreads.removeItem(output);
}
thread->exit();
+ // The thread entity (active unit of execution) is no longer running here,
+ // but the ThreadBase container still exists.
if (thread->type() != ThreadBase::DUPLICATING) {
AudioStreamOut *out = thread->clearOutput();
@@ -5132,6 +5140,8 @@
mRecordThreads.removeItem(input);
}
thread->exit();
+ // The thread entity (active unit of execution) is no longer running here,
+ // but the ThreadBase container still exists.
AudioStreamIn *in = thread->clearInput();
assert(in != NULL);
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 45df893..c66b19e 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -401,6 +401,8 @@
audio_format_t format() const { return mFormat; }
size_t frameCount() const { return mFrameCount; }
void wakeUp() { mWaitWorkCV.broadcast(); }
+ // Should be "virtual status_t requestExitAndWait()" and override same
+ // method in Thread, but Thread::requestExitAndWait() is not yet virtual.
void exit();
virtual bool checkForNewParameters_l() = 0;
virtual status_t setParameters(const String8& keyValuePairs);
@@ -532,7 +534,6 @@
Vector<ConfigEvent> mConfigEvents;
bool mStandby;
const audio_io_handle_t mId;
- bool mExiting;
Vector< sp<EffectChain> > mEffectChains;
uint32_t mDevice; // output device for PlaybackThread
// input + output devices for RecordThread