summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorGlenn Kasten <gkasten@google.com>2012-01-06 08:39:38 -0800
committerGlenn Kasten <gkasten@google.com>2012-02-10 15:02:44 -0800
commitb28686f95daee16edeb5f39af2cd5274ac3dc99f (patch)
tree84d9f579f42b724ca4c1dce405f3c8a5901e9d9d /services
parent7ae4a2c130ec2cb5dec69d095b810698acc543b3 (diff)
downloadframeworks_av-b28686f95daee16edeb5f39af2cd5274ac3dc99f.zip
frameworks_av-b28686f95daee16edeb5f39af2cd5274ac3dc99f.tar.gz
frameworks_av-b28686f95daee16edeb5f39af2cd5274ac3dc99f.tar.bz2
Simplify ThreadBase::exit() aka requestExitAndWait
We can remove mExiting and use Thread::exitPending() instead. The local sp<> on "this" in exit() is not needed, since the caller must also hold an sp<> in order to be calling us. (Unless it was using a raw pointer, but that would be dangerous for other reasons.) Add comment explaining the mLock in exit(). Change-Id: I319e5107533a1a7cdbd13c292685f3e2be60f6c4
Diffstat (limited to 'services')
-rw-r--r--services/audioflinger/AudioFlinger.cpp26
-rw-r--r--services/audioflinger/AudioFlinger.h3
2 files changed, 20 insertions, 9 deletions
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 93c91fb..efa3c70 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -998,7 +998,7 @@ AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio
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 @@ AudioFlinger::ThreadBase::~ThreadBase()
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();
}
@@ -4540,7 +4546,7 @@ status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrac
ALOGV("Signal record thread");
mWaitWorkCV.signal();
// do not wait for mStartStopCond if exiting
- if (mExiting) {
+ if (exitPending()) {
mActiveTrack.clear();
status = INVALID_OPERATION;
goto startError;
@@ -4567,7 +4573,7 @@ void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
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);
@@ -5013,6 +5019,8 @@ status_t AudioFlinger::closeOutput(audio_io_handle_t output)
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();
@@ -5156,6 +5164,8 @@ status_t AudioFlinger::closeInput(audio_io_handle_t input)
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 97103c4..23cb924 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -419,6 +419,8 @@ private:
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);
@@ -550,7 +552,6 @@ private:
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