Backout 12744c5b688d, edefcb820429 to investigate Android C1 permaorange.

This commit is contained in:
Marco Bonardo 2011-11-03 09:24:02 +01:00
Родитель 5db8d36c67
Коммит 2aebf9cdf8
4 изменённых файлов: 33 добавлений и 228 удалений

Просмотреть файл

@ -165,6 +165,13 @@ public:
const PRUint32 mRate;
};
static PRUint32 gStateMachineCount = 0;
static nsIThread* gStateMachineThread = 0;
nsIThread* nsBuiltinDecoderStateMachine::GetStateMachineThread() {
return gStateMachineThread;
}
// Shuts down a thread asynchronously.
class ShutdownThreadEvent : public nsRunnable
{
@ -180,161 +187,6 @@ private:
nsCOMPtr<nsIThread> mThread;
};
// Owns the global state machine thread and counts of
// state machine and decoder threads. There should
// only be one instance of this class.
class StateMachineTracker
{
private:
StateMachineTracker() :
mMonitor("media.statemachinetracker"),
mStateMachineCount(0),
mDecodeThreadCount(0),
mStateMachineThread(nsnull)
{
MOZ_COUNT_CTOR(StateMachineTracker);
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
}
~StateMachineTracker()
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
MOZ_COUNT_DTOR(StateMachineTracker);
}
public:
// Access singleton instance. This is initially called on the main
// thread in the nsBuiltinDecoderStateMachine constructor resulting
// in the global object being created lazily. Non-main thread
// access always occurs after this and uses the monitor to
// safely access the decode thread counts.
static StateMachineTracker& Instance();
// Instantiate the global state machine thread if required.
// Call on main thread only.
void EnsureGlobalStateMachine();
// Destroy global state machine thread if required.
// Call on main thread only.
void CleanupGlobalStateMachine();
// Return the global state machine thread. Call from any thread.
nsIThread* GetGlobalStateMachineThread()
{
ReentrantMonitorAutoEnter mon(mMonitor);
NS_ASSERTION(mStateMachineThread, "Should have non-null state machine thread!");
return mStateMachineThread;
}
// Maximum number of active decode threads allowed. When more
// than this number are active the thread creation will fail.
static const PRUint32 MAX_DECODE_THREADS = 50;
// Returns the number of active decode threads.
// Call on any thread. Holds the internal monitor so don't
// call with any other monitor held to avoid deadlock.
PRUint32 GetDecodeThreadCount();
// Keep track of the fact that a decode thread was created.
// Call on any thread. Holds the internal monitor so don't
// call with any other monitor held to avoid deadlock.
void NoteDecodeThreadCreated();
// Keep track of the fact that a decode thread was destroyed.
// Call on any thread. Holds the internal monitor so don't
// call with any other monitor held to avoid deadlock.
void NoteDecodeThreadDestroyed();
private:
// Holds global instance of StateMachineTracker.
// Writable on main thread only.
static StateMachineTracker* mInstance;
// Reentrant monitor that must be obtained to access
// the decode thread count member and methods.
ReentrantMonitor mMonitor;
// Number of instances of nsBuiltinDecoderStateMachine
// that are currently instantiated. Access on the
// main thread only.
PRUint32 mStateMachineCount;
// Number of instances of decoder threads that are
// currently instantiated. Access only with the
// mMonitor lock held. Can be used from any thread.
PRUint32 mDecodeThreadCount;
// Global state machine thread. Write on the main thread
// only, read from the decoder threads. Synchronized via
// the mMonitor.
nsIThread* mStateMachineThread;
};
StateMachineTracker* StateMachineTracker::mInstance = nsnull;
StateMachineTracker& StateMachineTracker::Instance()
{
if (!mInstance) {
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
mInstance = new StateMachineTracker();
}
return *mInstance;
}
void StateMachineTracker::EnsureGlobalStateMachine()
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
ReentrantMonitorAutoEnter mon(mMonitor);
if (mStateMachineCount == 0) {
NS_ASSERTION(!mStateMachineThread, "Should have null state machine thread!");
nsresult res = NS_NewThread(&mStateMachineThread,
nsnull);
NS_ABORT_IF_FALSE(NS_SUCCEEDED(res), "Can't create media state machine thread");
}
mStateMachineCount++;
}
void StateMachineTracker::CleanupGlobalStateMachine()
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
NS_ABORT_IF_FALSE(mStateMachineCount > 0,
"State machine ref count must be > 0");
mStateMachineCount--;
if (mStateMachineCount == 0) {
LOG(PR_LOG_DEBUG, ("Destroying media state machine thread"));
{
ReentrantMonitorAutoEnter mon(mMonitor);
nsCOMPtr<nsIRunnable> event = new ShutdownThreadEvent(mStateMachineThread);
NS_RELEASE(mStateMachineThread);
mStateMachineThread = nsnull;
NS_DispatchToMainThread(event);
NS_ASSERTION(mDecodeThreadCount == 0, "Decode thread count must be zero.");
mInstance = nsnull;
}
delete this;
}
}
void StateMachineTracker::NoteDecodeThreadCreated()
{
ReentrantMonitorAutoEnter mon(mMonitor);
++mDecodeThreadCount;
}
void StateMachineTracker::NoteDecodeThreadDestroyed()
{
ReentrantMonitorAutoEnter mon(mMonitor);
--mDecodeThreadCount;
}
PRUint32 StateMachineTracker::GetDecodeThreadCount()
{
ReentrantMonitorAutoEnter mon(mMonitor);
return mDecodeThreadCount;
}
nsBuiltinDecoderStateMachine::nsBuiltinDecoderStateMachine(nsBuiltinDecoder* aDecoder,
nsBuiltinDecoderReader* aReader,
bool aRealTime) :
@ -369,8 +221,14 @@ nsBuiltinDecoderStateMachine::nsBuiltinDecoderStateMachine(nsBuiltinDecoder* aDe
{
MOZ_COUNT_CTOR(nsBuiltinDecoderStateMachine);
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
StateMachineTracker::Instance().EnsureGlobalStateMachine();
if (gStateMachineCount == 0) {
NS_ASSERTION(!gStateMachineThread, "Should have null state machine thread!");
nsresult res = NS_NewThread(&gStateMachineThread,
nsnull,
MEDIA_THREAD_STACK_SIZE);
NS_ABORT_IF_FALSE(NS_SUCCEEDED(res), "Can't create media state machine thread");
}
gStateMachineCount++;
// only enable realtime mode when "media.realtime_decoder.enabled" is true.
if (Preferences::GetBool("media.realtime_decoder.enabled", false) == false)
@ -387,8 +245,18 @@ nsBuiltinDecoderStateMachine::~nsBuiltinDecoderStateMachine()
if (mTimer)
mTimer->Cancel();
mTimer = nsnull;
StateMachineTracker::Instance().CleanupGlobalStateMachine();
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
NS_ABORT_IF_FALSE(gStateMachineCount > 0,
"State machine ref count must be > 0");
gStateMachineCount--;
if (gStateMachineCount == 0) {
LOG(PR_LOG_DEBUG, ("Destroying media state machine thread"));
nsCOMPtr<nsIRunnable> event = new ShutdownThreadEvent(gStateMachineThread);
NS_RELEASE(gStateMachineThread);
gStateMachineThread = nsnull;
NS_DispatchToMainThread(event);
}
}
bool nsBuiltinDecoderStateMachine::HasFutureAudio() const {
@ -1188,7 +1056,6 @@ void nsBuiltinDecoderStateMachine::StopDecodeThread()
{
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
mDecodeThread->Shutdown();
StateMachineTracker::Instance().NoteDecodeThreadDestroyed();
}
mDecodeThread = nsnull;
mDecodeThreadIdle = false;
@ -1215,48 +1082,23 @@ nsBuiltinDecoderStateMachine::StartDecodeThread()
{
NS_ASSERTION(OnStateMachineThread(), "Should be on state machine thread.");
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
PRUint32 count = 0;
bool created = false;
{
ReentrantMonitorAutoExit mon(mDecoder->GetReentrantMonitor());
count = StateMachineTracker::Instance().GetDecodeThreadCount();
}
mStopDecodeThread = false;
if ((mDecodeThread && !mDecodeThreadIdle) || mState >= DECODER_STATE_COMPLETED)
return NS_OK;
if (!mDecodeThread && count > StateMachineTracker::MAX_DECODE_THREADS) {
// Have to run one iteration of the state machine loop to ensure the
// shutdown state is processed.
ScheduleStateMachine();
mState = DECODER_STATE_SHUTDOWN;
return NS_ERROR_FAILURE;
}
if (!mDecodeThread) {
nsresult rv = NS_NewThread(getter_AddRefs(mDecodeThread),
nsnull,
MEDIA_THREAD_STACK_SIZE);
if (NS_FAILED(rv)) {
// Have to run one iteration of the state machine loop to ensure the
// shutdown state is processed.
ScheduleStateMachine();
mState = DECODER_STATE_SHUTDOWN;
return rv;
}
created = true;
}
nsCOMPtr<nsIRunnable> event =
NS_NewRunnableMethod(this, &nsBuiltinDecoderStateMachine::DecodeThreadRun);
mDecodeThread->Dispatch(event, NS_DISPATCH_NORMAL);
mDecodeThreadIdle = false;
if (created) {
ReentrantMonitorAutoExit mon(mDecoder->GetReentrantMonitor());
StateMachineTracker::Instance().NoteDecodeThreadCreated();
}
return NS_OK;
}
@ -2132,7 +1974,7 @@ nsresult nsBuiltinDecoderStateMachine::ScheduleStateMachine() {
nsresult nsBuiltinDecoderStateMachine::ScheduleStateMachine(PRInt64 aUsecs) {
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
NS_ABORT_IF_FALSE(GetStateMachineThread(),
NS_ABORT_IF_FALSE(gStateMachineThread,
"Must have a state machine thread to schedule");
if (mState == DECODER_STATE_SHUTDOWN) {
@ -2167,7 +2009,7 @@ nsresult nsBuiltinDecoderStateMachine::ScheduleStateMachine(PRInt64 aUsecs) {
// We're not currently running this state machine on the state machine
// thread. Dispatch an event to run one cycle of the state machine.
mDispatchedRunEvent = true;
return GetStateMachineThread()->Dispatch(this, NS_DISPATCH_NORMAL);
return gStateMachineThread->Dispatch(this, NS_DISPATCH_NORMAL);
}
// We're not currently running this state machine on the state machine
// thread, but something has already dispatched an event to run it again,
@ -2181,7 +2023,7 @@ nsresult nsBuiltinDecoderStateMachine::ScheduleStateMachine(PRInt64 aUsecs) {
if (!mTimer) {
mTimer = do_CreateInstance("@mozilla.org/timer;1", &res);
if (NS_FAILED(res)) return res;
mTimer->SetTarget(GetStateMachineThread());
mTimer->SetTarget(gStateMachineThread);
}
res = mTimer->InitWithFuncCallback(::TimeoutExpired,
@ -2190,15 +2032,3 @@ nsresult nsBuiltinDecoderStateMachine::ScheduleStateMachine(PRInt64 aUsecs) {
nsITimer::TYPE_ONE_SHOT);
return res;
}
bool nsBuiltinDecoderStateMachine::OnStateMachineThread() const
{
return IsCurrentThread(GetStateMachineThread());
}
nsIThread* nsBuiltinDecoderStateMachine::GetStateMachineThread()
{
return StateMachineTracker::Instance().GetGlobalStateMachineThread();
}

Просмотреть файл

@ -205,7 +205,9 @@ public:
return IsCurrentThread(mAudioThread);
}
bool OnStateMachineThread() const;
bool OnStateMachineThread() const {
return IsCurrentThread(GetStateMachineThread());
}
nsresult GetBuffered(nsTimeRanges* aBuffered);

Просмотреть файл

@ -1,26 +0,0 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<script>
var ITERATIONS = 200;
function stoptest ()
{
document.documentElement.removeAttribute("class");
}
function boom()
{
for (var i = 0; i < ITERATIONS; ++i) {
a = document.createElementNS("http://www.w3.org/1999/xhtml", "audio");
a.addEventListener("loadedmetadata", stoptest);
a.setAttributeNS(null, "autoplay", "");
a.setAttributeNS(null, "src", "sound.ogg");
}
setTimeout(stoptest, 250);
}
</script>
</head>
<body onload="boom();"></body>
</html>

Просмотреть файл

@ -8,4 +8,3 @@ load 493915-1.html
skip-if(Android) load 495794-1.html
load 492286-1.xhtml
load 576612-1.html
load 691096-1.html