mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 940737 - Monitor Compositor thread hangs using BackgroundHangMonitor; r=bsmedberg r=BenWa
This commit is contained in:
parent
bbe7529af4
commit
9bac879d9e
@ -144,7 +144,17 @@ bool CompositorParent::CreateThread()
|
||||
}
|
||||
sCompositorThreadRefCount = 1;
|
||||
sCompositorThread = new Thread("Compositor");
|
||||
if (!sCompositorThread->Start()) {
|
||||
|
||||
Thread::Options options;
|
||||
/* Timeout values are powers-of-two to enable us get better data.
|
||||
128ms is chosen for transient hangs because 8Hz should be the minimally
|
||||
acceptable goal for Compositor responsiveness (normal goal is 60Hz). */
|
||||
options.transient_hang_timeout = 128; // milliseconds
|
||||
/* 8192ms is chosen for permanent hangs because it's several seconds longer
|
||||
than the default hang timeout on major platforms (about 5 seconds). */
|
||||
options.permanent_hang_timeout = 8192; // milliseconds
|
||||
|
||||
if (!sCompositorThread->StartWithOptions(options)) {
|
||||
delete sCompositorThread;
|
||||
sCompositorThread = nullptr;
|
||||
return false;
|
||||
|
@ -99,6 +99,8 @@ MessageLoop::MessageLoop(Type type)
|
||||
#ifdef OS_WIN
|
||||
os_modal_loop_(false),
|
||||
#endif // OS_WIN
|
||||
transient_hang_timeout_(0),
|
||||
permanent_hang_timeout_(0),
|
||||
next_sequence_num_(0) {
|
||||
DCHECK(!current()) << "should only have one message loop per thread";
|
||||
lazy_tls_ptr.Pointer()->Set(this);
|
||||
|
@ -269,6 +269,20 @@ public:
|
||||
}
|
||||
#endif // OS_WIN
|
||||
|
||||
// Set the timeouts for background hang monitoring.
|
||||
// A value of 0 indicates there is no timeout.
|
||||
void set_hang_timeouts(uint32_t transient_timeout_ms,
|
||||
uint32_t permanent_timeout_ms) {
|
||||
transient_hang_timeout_ = transient_timeout_ms;
|
||||
permanent_hang_timeout_ = permanent_timeout_ms;
|
||||
}
|
||||
uint32_t transient_hang_timeout() const {
|
||||
return transient_hang_timeout_;
|
||||
}
|
||||
uint32_t permanent_hang_timeout() const {
|
||||
return permanent_hang_timeout_;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
protected:
|
||||
struct RunState {
|
||||
@ -420,6 +434,10 @@ public:
|
||||
bool os_modal_loop_;
|
||||
#endif
|
||||
|
||||
// Timeout values for hang monitoring
|
||||
uint32_t transient_hang_timeout_;
|
||||
uint32_t permanent_hang_timeout_;
|
||||
|
||||
// The next sequence number to use for delayed tasks.
|
||||
int next_sequence_num_;
|
||||
|
||||
|
@ -5,9 +5,12 @@
|
||||
#include "base/message_pump_default.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/message_loop.h"
|
||||
#include "base/scoped_nsautorelease_pool.h"
|
||||
#include "GeckoProfiler.h"
|
||||
|
||||
#include "mozilla/BackgroundHangMonitor.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
MessagePumpDefault::MessagePumpDefault()
|
||||
@ -18,13 +21,21 @@ MessagePumpDefault::MessagePumpDefault()
|
||||
void MessagePumpDefault::Run(Delegate* delegate) {
|
||||
DCHECK(keep_running_) << "Quit must have been called outside of Run!";
|
||||
|
||||
const MessageLoop* const loop = MessageLoop::current();
|
||||
mozilla::BackgroundHangMonitor hangMonitor(
|
||||
loop->thread_name().c_str(),
|
||||
loop->transient_hang_timeout(),
|
||||
loop->permanent_hang_timeout());
|
||||
|
||||
for (;;) {
|
||||
ScopedNSAutoreleasePool autorelease_pool;
|
||||
|
||||
hangMonitor.NotifyActivity();
|
||||
bool did_work = delegate->DoWork();
|
||||
if (!keep_running_)
|
||||
break;
|
||||
|
||||
hangMonitor.NotifyActivity();
|
||||
did_work |= delegate->DoDelayedWork(&delayed_work_time_);
|
||||
if (!keep_running_)
|
||||
break;
|
||||
@ -32,6 +43,7 @@ void MessagePumpDefault::Run(Delegate* delegate) {
|
||||
if (did_work)
|
||||
continue;
|
||||
|
||||
hangMonitor.NotifyActivity();
|
||||
did_work = delegate->DoIdleWork();
|
||||
if (!keep_running_)
|
||||
break;
|
||||
@ -40,11 +52,13 @@ void MessagePumpDefault::Run(Delegate* delegate) {
|
||||
continue;
|
||||
|
||||
if (delayed_work_time_.is_null()) {
|
||||
hangMonitor.NotifyWait();
|
||||
PROFILER_LABEL("MessagePump", "Wait");
|
||||
event_.Wait();
|
||||
} else {
|
||||
TimeDelta delay = delayed_work_time_ - TimeTicks::Now();
|
||||
if (delay > TimeDelta()) {
|
||||
hangMonitor.NotifyWait();
|
||||
PROFILER_LABEL("MessagePump", "Wait");
|
||||
event_.TimedWait(delay);
|
||||
} else {
|
||||
|
@ -147,6 +147,8 @@ void Thread::ThreadMain() {
|
||||
thread_id_ = PlatformThread::CurrentId();
|
||||
PlatformThread::SetName(name_.c_str());
|
||||
message_loop.set_thread_name(name_);
|
||||
message_loop.set_hang_timeouts(startup_data_->options.transient_hang_timeout,
|
||||
startup_data_->options.permanent_hang_timeout);
|
||||
message_loop_ = &message_loop;
|
||||
|
||||
// Let the thread do extra initialization.
|
||||
|
@ -5,6 +5,7 @@
|
||||
#ifndef BASE_THREAD_H_
|
||||
#define BASE_THREAD_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
#include "base/message_loop.h"
|
||||
@ -28,9 +29,21 @@ class Thread : PlatformThread::Delegate {
|
||||
// A value of 0 indicates that the default maximum should be used.
|
||||
size_t stack_size;
|
||||
|
||||
Options() : message_loop_type(MessageLoop::TYPE_DEFAULT), stack_size(0) {}
|
||||
// Specifies the transient and permanent hang timeouts for background hang
|
||||
// monitoring. A value of 0 indicates there is no timeout.
|
||||
uint32_t transient_hang_timeout;
|
||||
uint32_t permanent_hang_timeout;
|
||||
|
||||
Options()
|
||||
: message_loop_type(MessageLoop::TYPE_DEFAULT)
|
||||
, stack_size(0)
|
||||
, transient_hang_timeout(0)
|
||||
, permanent_hang_timeout(0) {}
|
||||
Options(MessageLoop::Type type, size_t size)
|
||||
: message_loop_type(type), stack_size(size) {}
|
||||
: message_loop_type(type)
|
||||
, stack_size(size)
|
||||
, transient_hang_timeout(0)
|
||||
, permanent_hang_timeout(0) {}
|
||||
};
|
||||
|
||||
// Constructor.
|
||||
|
@ -301,8 +301,12 @@ BackgroundHangThread::BackgroundHangThread(const char* aName,
|
||||
uint32_t aMaxTimeoutMs)
|
||||
: mManager(BackgroundHangManager::sInstance)
|
||||
, mThreadID(PR_GetCurrentThread())
|
||||
, mTimeout(PR_MillisecondsToInterval(aTimeoutMs))
|
||||
, mMaxTimeout(PR_MillisecondsToInterval(aMaxTimeoutMs))
|
||||
, mTimeout(aTimeoutMs == BackgroundHangMonitor::kNoTimeout
|
||||
? PR_INTERVAL_NO_TIMEOUT
|
||||
: PR_MillisecondsToInterval(aTimeoutMs))
|
||||
, mMaxTimeout(aMaxTimeoutMs == BackgroundHangMonitor::kNoTimeout
|
||||
? PR_INTERVAL_NO_TIMEOUT
|
||||
: PR_MillisecondsToInterval(aMaxTimeoutMs))
|
||||
, mInterval(mManager->mIntervalNow)
|
||||
, mHangStart(mInterval)
|
||||
, mHanging(false)
|
||||
|
@ -106,6 +106,8 @@ private:
|
||||
RefPtr<BackgroundHangThread> mThread;
|
||||
|
||||
public:
|
||||
static const uint32_t kNoTimeout = 0;
|
||||
|
||||
/**
|
||||
* ThreadHangStatsIterator is used to iterate through the ThreadHangStats
|
||||
* associated with each active monitored thread. Because of an internal
|
||||
|
Loading…
Reference in New Issue
Block a user