1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=8 et ft=cpp : */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ProcessPriorityManager.h"
8 #include "mozilla/ClearOnShutdown.h"
9 #include "mozilla/dom/ContentParent.h"
10 #include "mozilla/dom/Element.h"
11 #include "mozilla/dom/TabParent.h"
12 #include "mozilla/Hal.h"
13 #include "mozilla/Preferences.h"
14 #include "mozilla/Services.h"
15 #include "mozilla/unused.h"
16 #include "AudioChannelService.h"
18 #include "nsPrintfCString.h"
19 #include "nsXULAppAPI.h"
20 #include "nsIFrameLoader.h"
21 #include "nsIObserverService.h"
22 #include "StaticPtr.h"
23 #include "nsIMozBrowserFrame.h"
24 #include "nsIObserver.h"
26 #include "nsIPropertyBag2.h"
27 #include "nsComponentManagerUtils.h"
31 #define getpid _getpid
40 // Use LOGP inside a ParticularProcessPriorityManager method; use LOG
41 // everywhere else. LOGP prints out information about the particular process
44 // (Wow, our logging story is a huge mess.)
46 // #define ENABLE_LOGGING 1
48 #if defined(ANDROID) && defined(ENABLE_LOGGING)
49 # include <android/log.h>
50 # define LOG(fmt, ...) \
51 __android_log_print(ANDROID_LOG_INFO, \
52 "Gecko:ProcessPriorityManager", \
54 # define LOGP(fmt, ...) \
55 __android_log_print(ANDROID_LOG_INFO, \
56 "Gecko:ProcessPriorityManager", \
57 "[%schild-id=%llu, pid=%d] " fmt, \
58 NameWithComma().get(), \
59 (long long unsigned) ChildID(), Pid(), ## __VA_ARGS__)
61 #elif defined(ENABLE_LOGGING)
62 # define LOG(fmt, ...) \
63 printf("ProcessPriorityManager - " fmt "\n", ##__VA_ARGS__)
64 # define LOGP(fmt, ...) \
65 printf("ProcessPriorityManager[%schild-id=%llu, pid=%d] - " fmt "\n", \
66 NameWithComma().get(), \
67 (unsigned long long) ChildID(), Pid(), ##__VA_ARGS__)
69 #elif defined(PR_LOGGING)
70 static PRLogModuleInfo
*
73 static PRLogModuleInfo
*sLog
;
75 sLog
= PR_NewLogModule("ProcessPriorityManager");
78 # define LOG(fmt, ...) \
79 PR_LOG(GetPPMLog(), PR_LOG_DEBUG, \
80 ("ProcessPriorityManager - " fmt, ##__VA_ARGS__))
81 # define LOGP(fmt, ...) \
82 PR_LOG(GetPPMLog(), PR_LOG_DEBUG, \
83 ("ProcessPriorityManager[%schild-id=%llu, pid=%d] - " fmt, \
84 NameWithComma().get(), \
85 (unsigned long long) ChildID(), Pid(), ##__VA_ARGS__))
88 #define LOGP(fmt, ...)
91 using namespace mozilla
;
92 using namespace mozilla::dom
;
93 using namespace mozilla::hal
;
97 class ParticularProcessPriorityManager
;
100 * This singleton class does the work to implement the process priority manager
101 * in the main process. This class may not be used in child processes. (You
102 * can call StaticInit, but it won't do anything, and GetSingleton() will
105 * ProcessPriorityManager::CurrentProcessIsForeground() and
106 * ProcessPriorityManager::AnyProcessHasHighPriority() which can be called in
107 * any process, are handled separately, by the ProcessPriorityManagerChild
110 class ProcessPriorityManagerImpl MOZ_FINAL
112 , public WakeLockObserver
116 * If we're in the main process, get the ProcessPriorityManagerImpl
117 * singleton. If we're in a child process, return null.
119 static ProcessPriorityManagerImpl
* GetSingleton();
121 static void StaticInit();
122 static bool PrefsEnabled();
128 * This function implements ProcessPriorityManager::SetProcessPriority.
130 void SetProcessPriority(ContentParent
* aContentParent
,
131 ProcessPriority aPriority
,
132 uint32_t aBackgroundLRU
= 0);
135 * If a magic testing-only pref is set, notify the observer service on the
136 * given topic with the given data. This is used for testing
138 void FireTestOnlyObserverNotification(const char* aTopic
,
139 const nsACString
& aData
= EmptyCString());
142 * Does some process, other than the one handled by aParticularManager, have
143 * priority FOREGROUND_HIGH?
145 bool OtherProcessHasHighPriority(
146 ParticularProcessPriorityManager
* aParticularManager
);
149 * Does one of the child processes have priority FOREGROUND_HIGH?
151 bool ChildProcessHasHighPriority();
154 * This must be called by a ParticularProcessPriorityManager when it changes
157 void NotifyProcessPriorityChanged(
158 ParticularProcessPriorityManager
* aParticularManager
,
159 hal::ProcessPriority aOldPriority
);
162 * Implements WakeLockObserver, used to monitor wake lock changes in the
165 virtual void Notify(const WakeLockInformation
& aInfo
) MOZ_OVERRIDE
;
168 static bool sPrefListenersRegistered
;
169 static bool sInitialized
;
170 static StaticRefPtr
<ProcessPriorityManagerImpl
> sSingleton
;
172 static void PrefChangedCallback(const char* aPref
, void* aClosure
);
174 ProcessPriorityManagerImpl();
175 ~ProcessPriorityManagerImpl();
176 DISALLOW_EVIL_CONSTRUCTORS(ProcessPriorityManagerImpl
);
180 already_AddRefed
<ParticularProcessPriorityManager
>
181 GetParticularProcessPriorityManager(ContentParent
* aContentParent
);
183 void ObserveContentParentCreated(nsISupports
* aContentParent
);
184 void ObserveContentParentDestroyed(nsISupports
* aSubject
);
185 void ResetAllCPUPriorities();
187 nsDataHashtable
<nsUint64HashKey
, nsRefPtr
<ParticularProcessPriorityManager
> >
191 nsTHashtable
<nsUint64HashKey
> mHighPriorityChildIDs
;
195 * This singleton class implements the parts of the process priority manager
196 * that are available from all processes.
198 class ProcessPriorityManagerChild MOZ_FINAL
202 static void StaticInit();
203 static ProcessPriorityManagerChild
* Singleton();
208 bool CurrentProcessIsForeground();
209 bool CurrentProcessIsHighPriority();
212 static StaticRefPtr
<ProcessPriorityManagerChild
> sSingleton
;
214 ProcessPriorityManagerChild();
215 ~ProcessPriorityManagerChild() {}
216 DISALLOW_EVIL_CONSTRUCTORS(ProcessPriorityManagerChild
);
220 hal::ProcessPriority mCachedPriority
;
224 * This class manages the priority of one particular process. It is
227 class ParticularProcessPriorityManager MOZ_FINAL
228 : public WakeLockObserver
230 , public nsITimerCallback
231 , public nsSupportsWeakReference
233 ~ParticularProcessPriorityManager();
235 explicit ParticularProcessPriorityManager(ContentParent
* aContentParent
);
239 NS_DECL_NSITIMERCALLBACK
241 virtual void Notify(const WakeLockInformation
& aInfo
) MOZ_OVERRIDE
;
245 uint64_t ChildID() const;
246 bool IsPreallocated() const;
249 * Used in logging, this method returns the ContentParent's name followed by
250 * ", ". If we can't get the ContentParent's name for some reason, it
251 * returns an empty string.
253 * The reference returned here is guaranteed to be live until the next call
254 * to NameWithComma() or until the ParticularProcessPriorityManager is
255 * destroyed, whichever comes first.
257 const nsAutoCString
& NameWithComma();
259 bool HasAppType(const char* aAppType
);
260 bool IsExpectingSystemMessage();
262 void OnAudioChannelProcessChanged(nsISupports
* aSubject
);
263 void OnRemoteBrowserFrameShown(nsISupports
* aSubject
);
264 void OnTabParentDestroyed(nsISupports
* aSubject
);
265 void OnFrameloaderVisibleChanged(nsISupports
* aSubject
);
266 void OnChannelConnected(nsISupports
* aSubject
);
268 ProcessPriority
CurrentPriority();
269 ProcessPriority
ComputePriority();
270 ProcessCPUPriority
ComputeCPUPriority(ProcessPriority aPriority
);
272 void ScheduleResetPriority(const char* aTimeoutPref
);
273 void ResetPriority();
274 void ResetPriorityNow();
275 void ResetCPUPriorityNow();
278 * This overload is equivalent to SetPriorityNow(aPriority,
279 * ComputeCPUPriority()).
281 void SetPriorityNow(ProcessPriority aPriority
,
282 uint32_t aBackgroundLRU
= 0);
284 void SetPriorityNow(ProcessPriority aPriority
,
285 ProcessCPUPriority aCPUPriority
,
286 uint32_t aBackgroundLRU
= 0);
291 void FireTestOnlyObserverNotification(
293 const nsACString
& aData
= EmptyCString());
295 void FireTestOnlyObserverNotification(
297 const char* aData
= nullptr);
299 ContentParent
* mContentParent
;
301 ProcessPriority mPriority
;
302 ProcessCPUPriority mCPUPriority
;
303 bool mHoldsCPUWakeLock
;
304 bool mHoldsHighPriorityWakeLock
;
307 * Used to implement NameWithComma().
309 nsAutoCString mNameWithComma
;
311 nsCOMPtr
<nsITimer
> mResetPriorityTimer
;
314 class BackgroundProcessLRUPool MOZ_FINAL
317 static BackgroundProcessLRUPool
* Singleton();
320 * Used to remove a ContentParent from background LRU pool when
321 * it is destroyed or its priority changed from BACKGROUND to others.
323 void RemoveFromBackgroundLRUPool(ContentParent
* aContentParent
);
326 * Used to add a ContentParent into background LRU pool when
327 * its priority changed to BACKGROUND from others.
329 void AddIntoBackgroundLRUPool(ContentParent
* aContentParent
);
332 static StaticAutoPtr
<BackgroundProcessLRUPool
> sSingleton
;
334 int32_t mLRUPoolLevels
;
335 int32_t mLRUPoolSize
;
336 int32_t mLRUPoolAvailableIndex
;
337 nsTArray
<ContentParent
*> mLRUPool
;
339 uint32_t CalculateLRULevel(uint32_t aBackgroundLRUPoolIndex
);
341 nsresult
UpdateAvailableIndexInLRUPool(
342 ContentParent
* aContentParent
,
343 int32_t aTargetIndex
= -1);
347 void EnsureLRUPool();
349 BackgroundProcessLRUPool();
350 DISALLOW_EVIL_CONSTRUCTORS(BackgroundProcessLRUPool
);
354 /* static */ bool ProcessPriorityManagerImpl::sInitialized
= false;
355 /* static */ bool ProcessPriorityManagerImpl::sPrefListenersRegistered
= false;
356 /* static */ StaticRefPtr
<ProcessPriorityManagerImpl
>
357 ProcessPriorityManagerImpl::sSingleton
;
359 NS_IMPL_ISUPPORTS(ProcessPriorityManagerImpl
,
363 ProcessPriorityManagerImpl::PrefChangedCallback(const char* aPref
,
370 ProcessPriorityManagerImpl::PrefsEnabled()
372 return Preferences::GetBool("dom.ipc.processPriorityManager.enabled") &&
373 !Preferences::GetBool("dom.ipc.tabs.disabled");
377 ProcessPriorityManagerImpl::StaticInit()
383 // The process priority manager is main-process only.
384 if (XRE_GetProcessType() != GeckoProcessType_Default
) {
389 // If IPC tabs aren't enabled at startup, don't bother with any of this.
390 if (!PrefsEnabled()) {
391 LOG("InitProcessPriorityManager bailing due to prefs.");
393 // Run StaticInit() again if the prefs change. We don't expect this to
394 // happen in normal operation, but it happens during testing.
395 if (!sPrefListenersRegistered
) {
396 sPrefListenersRegistered
= true;
397 Preferences::RegisterCallback(PrefChangedCallback
,
398 "dom.ipc.processPriorityManager.enabled");
399 Preferences::RegisterCallback(PrefChangedCallback
,
400 "dom.ipc.tabs.disabled");
407 sSingleton
= new ProcessPriorityManagerImpl();
409 ClearOnShutdown(&sSingleton
);
412 /* static */ ProcessPriorityManagerImpl
*
413 ProcessPriorityManagerImpl::GetSingleton()
422 ProcessPriorityManagerImpl::ProcessPriorityManagerImpl()
423 : mHighPriority(false)
425 MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default
);
426 RegisterWakeLockObserver(this);
429 ProcessPriorityManagerImpl::~ProcessPriorityManagerImpl()
431 UnregisterWakeLockObserver(this);
435 ProcessPriorityManagerImpl::Init()
437 LOG("Starting up. This is the master process.");
439 // The master process's priority never changes; set it here and then forget
440 // about it. We'll manage only subprocesses' priorities using the process
442 hal::SetProcessPriority(getpid(), PROCESS_PRIORITY_MASTER
,
443 PROCESS_CPU_PRIORITY_NORMAL
);
445 nsCOMPtr
<nsIObserverService
> os
= services::GetObserverService();
447 os
->AddObserver(this, "ipc:content-created", /* ownsWeak */ false);
448 os
->AddObserver(this, "ipc:content-shutdown", /* ownsWeak */ false);
453 ProcessPriorityManagerImpl::Observe(
454 nsISupports
* aSubject
,
456 const char16_t
* aData
)
458 nsDependentCString
topic(aTopic
);
459 if (topic
.EqualsLiteral("ipc:content-created")) {
460 ObserveContentParentCreated(aSubject
);
461 } else if (topic
.EqualsLiteral("ipc:content-shutdown")) {
462 ObserveContentParentDestroyed(aSubject
);
470 already_AddRefed
<ParticularProcessPriorityManager
>
471 ProcessPriorityManagerImpl::GetParticularProcessPriorityManager(
472 ContentParent
* aContentParent
)
474 nsRefPtr
<ParticularProcessPriorityManager
> pppm
;
475 mParticularManagers
.Get(aContentParent
->ChildID(), &pppm
);
477 pppm
= new ParticularProcessPriorityManager(aContentParent
);
479 mParticularManagers
.Put(aContentParent
->ChildID(), pppm
);
481 FireTestOnlyObserverNotification("process-created",
482 nsPrintfCString("%lld", aContentParent
->ChildID()));
485 return pppm
.forget();
489 ProcessPriorityManagerImpl::SetProcessPriority(ContentParent
* aContentParent
,
490 ProcessPriority aPriority
,
491 uint32_t aBackgroundLRU
)
493 MOZ_ASSERT(aContentParent
);
494 nsRefPtr
<ParticularProcessPriorityManager
> pppm
=
495 GetParticularProcessPriorityManager(aContentParent
);
496 pppm
->SetPriorityNow(aPriority
, aBackgroundLRU
);
500 ProcessPriorityManagerImpl::ObserveContentParentCreated(
501 nsISupports
* aContentParent
)
503 // Do nothing; it's sufficient to get the PPPM. But assign to nsRefPtr so we
504 // don't leak the already_AddRefed object.
505 nsCOMPtr
<nsIContentParent
> cp
= do_QueryInterface(aContentParent
);
506 nsRefPtr
<ParticularProcessPriorityManager
> pppm
=
507 GetParticularProcessPriorityManager(cp
->AsContentParent());
510 static PLDHashOperator
511 EnumerateParticularProcessPriorityManagers(
512 const uint64_t& aKey
,
513 nsRefPtr
<ParticularProcessPriorityManager
> aValue
,
516 nsTArray
<nsRefPtr
<ParticularProcessPriorityManager
> >* aArray
=
517 static_cast<nsTArray
<nsRefPtr
<ParticularProcessPriorityManager
> >*>(aUserData
);
518 aArray
->AppendElement(aValue
);
519 return PL_DHASH_NEXT
;
523 ProcessPriorityManagerImpl::ObserveContentParentDestroyed(nsISupports
* aSubject
)
525 nsCOMPtr
<nsIPropertyBag2
> props
= do_QueryInterface(aSubject
);
526 NS_ENSURE_TRUE_VOID(props
);
528 uint64_t childID
= CONTENT_PROCESS_ID_UNKNOWN
;
529 props
->GetPropertyAsUint64(NS_LITERAL_STRING("childID"), &childID
);
530 NS_ENSURE_TRUE_VOID(childID
!= CONTENT_PROCESS_ID_UNKNOWN
);
532 nsRefPtr
<ParticularProcessPriorityManager
> pppm
;
533 mParticularManagers
.Get(childID
, &pppm
);
539 mParticularManagers
.Remove(childID
);
541 if (mHighPriorityChildIDs
.Contains(childID
)) {
542 mHighPriorityChildIDs
.RemoveEntry(childID
);
544 // We just lost a high-priority process; reset everyone's CPU priorities.
545 ResetAllCPUPriorities();
550 ProcessPriorityManagerImpl::ResetAllCPUPriorities( void )
552 nsTArray
<nsRefPtr
<ParticularProcessPriorityManager
> > pppms
;
553 mParticularManagers
.EnumerateRead(
554 &EnumerateParticularProcessPriorityManagers
,
557 for (uint32_t i
= 0; i
< pppms
.Length(); i
++) {
558 pppms
[i
]->ResetCPUPriorityNow();
563 ProcessPriorityManagerImpl::OtherProcessHasHighPriority(
564 ParticularProcessPriorityManager
* aParticularManager
)
568 } else if (mHighPriorityChildIDs
.Contains(aParticularManager
->ChildID())) {
569 return mHighPriorityChildIDs
.Count() > 1;
571 return mHighPriorityChildIDs
.Count() > 0;
575 ProcessPriorityManagerImpl::ChildProcessHasHighPriority( void )
577 return mHighPriorityChildIDs
.Count() > 0;
581 ProcessPriorityManagerImpl::NotifyProcessPriorityChanged(
582 ParticularProcessPriorityManager
* aParticularManager
,
583 ProcessPriority aOldPriority
)
585 // This priority change can only affect other processes' priorities if we're
586 // changing to/from FOREGROUND_HIGH.
588 if (aOldPriority
< PROCESS_PRIORITY_FOREGROUND_HIGH
&&
589 aParticularManager
->CurrentPriority() <
590 PROCESS_PRIORITY_FOREGROUND_HIGH
) {
595 if (aParticularManager
->CurrentPriority() >=
596 PROCESS_PRIORITY_FOREGROUND_HIGH
) {
597 mHighPriorityChildIDs
.PutEntry(aParticularManager
->ChildID());
599 mHighPriorityChildIDs
.RemoveEntry(aParticularManager
->ChildID());
602 nsTArray
<nsRefPtr
<ParticularProcessPriorityManager
> > pppms
;
603 mParticularManagers
.EnumerateRead(
604 &EnumerateParticularProcessPriorityManagers
,
607 for (uint32_t i
= 0; i
< pppms
.Length(); i
++) {
608 if (pppms
[i
] != aParticularManager
) {
609 pppms
[i
]->ResetCPUPriorityNow();
615 ProcessPriorityManagerImpl::Notify(const WakeLockInformation
& aInfo
)
617 /* The main process always has an ID of 0, if it is present in the wake-lock
618 * information then we explicitly requested a high-priority wake-lock for the
620 if (aInfo
.topic().EqualsLiteral("high-priority")) {
621 if (aInfo
.lockingProcesses().Contains((uint64_t)0)) {
622 mHighPriority
= true;
624 mHighPriority
= false;
627 /* The main process got a high-priority wakelock change; reset everyone's
629 ResetAllCPUPriorities();
631 LOG("Got wake lock changed event. "
632 "Now mHighPriorityParent = %d\n", mHighPriority
);
637 NS_IMPL_ISUPPORTS(ParticularProcessPriorityManager
,
640 nsISupportsWeakReference
);
642 ParticularProcessPriorityManager::ParticularProcessPriorityManager(
643 ContentParent
* aContentParent
)
644 : mContentParent(aContentParent
)
645 , mChildID(aContentParent
->ChildID())
646 , mPriority(PROCESS_PRIORITY_UNKNOWN
)
647 , mCPUPriority(PROCESS_CPU_PRIORITY_NORMAL
)
648 , mHoldsCPUWakeLock(false)
649 , mHoldsHighPriorityWakeLock(false)
651 MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default
);
652 LOGP("Creating ParticularProcessPriorityManager.");
656 ParticularProcessPriorityManager::Init()
658 RegisterWakeLockObserver(this);
660 nsCOMPtr
<nsIObserverService
> os
= services::GetObserverService();
662 os
->AddObserver(this, "audio-channel-process-changed", /* ownsWeak */ true);
663 os
->AddObserver(this, "remote-browser-shown", /* ownsWeak */ true);
664 os
->AddObserver(this, "ipc:browser-destroyed", /* ownsWeak */ true);
665 os
->AddObserver(this, "frameloader-visible-changed", /* ownsWeak */ true);
668 // This process may already hold the CPU lock; for example, our parent may
669 // have acquired it on our behalf.
670 WakeLockInformation info1
, info2
;
671 GetWakeLockInfo(NS_LITERAL_STRING("cpu"), &info1
);
672 mHoldsCPUWakeLock
= info1
.lockingProcesses().Contains(ChildID());
674 GetWakeLockInfo(NS_LITERAL_STRING("high-priority"), &info2
);
675 mHoldsHighPriorityWakeLock
= info2
.lockingProcesses().Contains(ChildID());
676 LOGP("Done starting up. mHoldsCPUWakeLock=%d, mHoldsHighPriorityWakeLock=%d",
677 mHoldsCPUWakeLock
, mHoldsHighPriorityWakeLock
);
680 ParticularProcessPriorityManager::~ParticularProcessPriorityManager()
682 LOGP("Destroying ParticularProcessPriorityManager.");
684 // Unregister our wake lock observer if ShutDown hasn't been called. (The
685 // wake lock observer takes raw refs, so we don't want to take chances here!)
686 // We don't call UnregisterWakeLockObserver unconditionally because the code
687 // will print a warning if it's called unnecessarily.
689 if (mContentParent
) {
690 UnregisterWakeLockObserver(this);
695 ParticularProcessPriorityManager::Notify(const WakeLockInformation
& aInfo
)
697 if (!mContentParent
) {
698 // We've been shut down.
702 bool* dest
= nullptr;
703 if (aInfo
.topic().EqualsLiteral("cpu")) {
704 dest
= &mHoldsCPUWakeLock
;
705 } else if (aInfo
.topic().EqualsLiteral("high-priority")) {
706 dest
= &mHoldsHighPriorityWakeLock
;
710 bool thisProcessLocks
= aInfo
.lockingProcesses().Contains(ChildID());
711 if (thisProcessLocks
!= *dest
) {
712 *dest
= thisProcessLocks
;
713 LOGP("Got wake lock changed event. "
714 "Now mHoldsCPUWakeLock=%d, mHoldsHighPriorityWakeLock=%d",
715 mHoldsCPUWakeLock
, mHoldsHighPriorityWakeLock
);
722 ParticularProcessPriorityManager::Observe(nsISupports
* aSubject
,
724 const char16_t
* aData
)
726 if (!mContentParent
) {
727 // We've been shut down.
731 nsDependentCString
topic(aTopic
);
733 if (topic
.EqualsLiteral("audio-channel-process-changed")) {
734 OnAudioChannelProcessChanged(aSubject
);
735 } else if (topic
.EqualsLiteral("remote-browser-shown")) {
736 OnRemoteBrowserFrameShown(aSubject
);
737 } else if (topic
.EqualsLiteral("ipc:browser-destroyed")) {
738 OnTabParentDestroyed(aSubject
);
739 } else if (topic
.EqualsLiteral("frameloader-visible-changed")) {
740 OnFrameloaderVisibleChanged(aSubject
);
749 ParticularProcessPriorityManager::ChildID() const
751 // We have to cache mContentParent->ChildID() instead of getting it from the
752 // ContentParent each time because after ShutDown() is called, mContentParent
753 // is null. If we didn't cache ChildID(), then we wouldn't be able to run
754 // LOGP() after ShutDown().
759 ParticularProcessPriorityManager::Pid() const
761 return mContentParent
? mContentParent
->Pid() : -1;
765 ParticularProcessPriorityManager::IsPreallocated() const
767 return mContentParent
? mContentParent
->IsPreallocated() : false;
771 ParticularProcessPriorityManager::NameWithComma()
773 mNameWithComma
.Truncate();
774 if (!mContentParent
) {
775 return mNameWithComma
; // empty string
779 mContentParent
->FriendlyName(name
);
780 if (name
.IsEmpty()) {
781 return mNameWithComma
; // empty string
784 mNameWithComma
= NS_ConvertUTF16toUTF8(name
);
785 mNameWithComma
.AppendLiteral(", ");
786 return mNameWithComma
;
790 ParticularProcessPriorityManager::OnAudioChannelProcessChanged(nsISupports
* aSubject
)
792 nsCOMPtr
<nsIPropertyBag2
> props
= do_QueryInterface(aSubject
);
793 NS_ENSURE_TRUE_VOID(props
);
795 uint64_t childID
= CONTENT_PROCESS_ID_UNKNOWN
;
796 props
->GetPropertyAsUint64(NS_LITERAL_STRING("childID"), &childID
);
797 if (childID
== ChildID()) {
803 ParticularProcessPriorityManager::OnRemoteBrowserFrameShown(nsISupports
* aSubject
)
805 nsCOMPtr
<nsIFrameLoader
> fl
= do_QueryInterface(aSubject
);
806 NS_ENSURE_TRUE_VOID(fl
);
808 // Ignore notifications that aren't from a BrowserOrApp
810 fl
->GetOwnerIsBrowserOrAppFrame(&isBrowserOrApp
);
811 if (!isBrowserOrApp
) {
815 nsCOMPtr
<nsITabParent
> tp
;
816 fl
->GetTabParent(getter_AddRefs(tp
));
817 NS_ENSURE_TRUE_VOID(tp
);
819 MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default
);
820 if (static_cast<TabParent
*>(tp
.get())->Manager() != mContentParent
) {
828 ParticularProcessPriorityManager::OnTabParentDestroyed(nsISupports
* aSubject
)
830 nsCOMPtr
<nsITabParent
> tp
= do_QueryInterface(aSubject
);
831 NS_ENSURE_TRUE_VOID(tp
);
833 MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default
);
834 if (static_cast<TabParent
*>(tp
.get())->Manager() != mContentParent
) {
842 ParticularProcessPriorityManager::OnFrameloaderVisibleChanged(nsISupports
* aSubject
)
844 nsCOMPtr
<nsIFrameLoader
> fl
= do_QueryInterface(aSubject
);
845 NS_ENSURE_TRUE_VOID(fl
);
847 nsCOMPtr
<nsITabParent
> tp
;
848 fl
->GetTabParent(getter_AddRefs(tp
));
853 MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default
);
854 if (static_cast<TabParent
*>(tp
.get())->Manager() != mContentParent
) {
858 // Most of the time when something changes in a process we call
859 // ResetPriority(), giving a grace period before downgrading its priority.
860 // But notice that here don't give a grace period: We call ResetPriorityNow()
863 // We do this because we're reacting here to a setVisibility() call, which is
864 // an explicit signal from the process embedder that we should re-prioritize
865 // a process. If we gave a grace period in response to setVisibility()
866 // calls, it would be impossible for the embedder to explicitly prioritize
867 // processes and prevent e.g. the case where we switch which process is in
868 // the foreground and, during the old fg processs's grace period, it OOMs the
875 ParticularProcessPriorityManager::ResetPriority()
877 ProcessPriority processPriority
= ComputePriority();
878 if (mPriority
== PROCESS_PRIORITY_UNKNOWN
||
879 mPriority
> processPriority
) {
880 // Apps set at a perceivable background priority are often playing media.
881 // Most media will have short gaps while changing tracks between songs,
882 // switching videos, etc. Give these apps a longer grace period so they
883 // can get their next track started, if there is one, before getting
885 if (mPriority
== PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE
) {
886 ScheduleResetPriority("backgroundPerceivableGracePeriodMS");
888 ScheduleResetPriority("backgroundGracePeriodMS");
893 SetPriorityNow(processPriority
);
897 ParticularProcessPriorityManager::ResetPriorityNow()
899 SetPriorityNow(ComputePriority());
903 ParticularProcessPriorityManager::ScheduleResetPriority(const char* aTimeoutPref
)
905 if (mResetPriorityTimer
) {
906 LOGP("ScheduleResetPriority bailing; the timer is already running.");
910 uint32_t timeout
= Preferences::GetUint(
911 nsPrintfCString("dom.ipc.processPriorityManager.%s", aTimeoutPref
).get());
912 LOGP("Scheduling reset timer to fire in %dms.", timeout
);
913 mResetPriorityTimer
= do_CreateInstance("@mozilla.org/timer;1");
914 mResetPriorityTimer
->InitWithCallback(this, timeout
, nsITimer::TYPE_ONE_SHOT
);
919 ParticularProcessPriorityManager::Notify(nsITimer
* aTimer
)
921 LOGP("Reset priority timer callback; about to ResetPriorityNow.");
923 mResetPriorityTimer
= nullptr;
928 ParticularProcessPriorityManager::HasAppType(const char* aAppType
)
930 const InfallibleTArray
<PBrowserParent
*>& browsers
=
931 mContentParent
->ManagedPBrowserParent();
932 for (uint32_t i
= 0; i
< browsers
.Length(); i
++) {
933 nsAutoString appType
;
934 static_cast<TabParent
*>(browsers
[i
])->GetAppType(appType
);
935 if (appType
.EqualsASCII(aAppType
)) {
944 ParticularProcessPriorityManager::IsExpectingSystemMessage()
946 const InfallibleTArray
<PBrowserParent
*>& browsers
=
947 mContentParent
->ManagedPBrowserParent();
948 for (uint32_t i
= 0; i
< browsers
.Length(); i
++) {
949 TabParent
* tp
= static_cast<TabParent
*>(browsers
[i
]);
950 nsCOMPtr
<nsIMozBrowserFrame
> bf
= do_QueryInterface(tp
->GetOwnerElement());
955 if (bf
->GetIsExpectingSystemMessage()) {
964 ParticularProcessPriorityManager::CurrentPriority()
970 ParticularProcessPriorityManager::ComputePriority()
972 if ((mHoldsCPUWakeLock
|| mHoldsHighPriorityWakeLock
) &&
973 HasAppType("critical")) {
974 return PROCESS_PRIORITY_FOREGROUND_HIGH
;
977 bool isVisible
= false;
978 const InfallibleTArray
<PBrowserParent
*>& browsers
=
979 mContentParent
->ManagedPBrowserParent();
980 for (uint32_t i
= 0; i
< browsers
.Length(); i
++) {
981 if (static_cast<TabParent
*>(browsers
[i
])->IsVisible()) {
988 return HasAppType("inputmethod") ?
989 PROCESS_PRIORITY_FOREGROUND_KEYBOARD
:
990 PROCESS_PRIORITY_FOREGROUND
;
993 if ((mHoldsCPUWakeLock
|| mHoldsHighPriorityWakeLock
) &&
994 IsExpectingSystemMessage()) {
995 return PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE
;
998 AudioChannelService
* service
= AudioChannelService::GetOrCreateAudioChannelService();
999 if (service
->ProcessContentOrNormalChannelIsActive(ChildID())) {
1000 return PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE
;
1003 return HasAppType("homescreen") ?
1004 PROCESS_PRIORITY_BACKGROUND_HOMESCREEN
:
1005 PROCESS_PRIORITY_BACKGROUND
;
1009 ParticularProcessPriorityManager::ComputeCPUPriority(ProcessPriority aPriority
)
1011 if (aPriority
== PROCESS_PRIORITY_PREALLOC
) {
1012 return PROCESS_CPU_PRIORITY_LOW
;
1015 if (aPriority
>= PROCESS_PRIORITY_FOREGROUND_HIGH
) {
1016 return PROCESS_CPU_PRIORITY_NORMAL
;
1019 return ProcessPriorityManagerImpl::GetSingleton()->
1020 OtherProcessHasHighPriority(this) ?
1021 PROCESS_CPU_PRIORITY_LOW
:
1022 PROCESS_CPU_PRIORITY_NORMAL
;
1026 ParticularProcessPriorityManager::ResetCPUPriorityNow()
1028 SetPriorityNow(mPriority
);
1032 ParticularProcessPriorityManager::SetPriorityNow(ProcessPriority aPriority
,
1033 uint32_t aBackgroundLRU
)
1035 SetPriorityNow(aPriority
, ComputeCPUPriority(aPriority
), aBackgroundLRU
);
1039 ParticularProcessPriorityManager::SetPriorityNow(ProcessPriority aPriority
,
1040 ProcessCPUPriority aCPUPriority
,
1041 uint32_t aBackgroundLRU
)
1043 #ifdef MOZ_NUWA_PROCESS
1044 // Do not attempt to change the priority of the Nuwa process
1045 if (mContentParent
->IsNuwaProcess()) {
1050 if (aPriority
== PROCESS_PRIORITY_UNKNOWN
) {
1055 if (aBackgroundLRU
> 0 &&
1056 aPriority
== PROCESS_PRIORITY_BACKGROUND
&&
1057 mPriority
== PROCESS_PRIORITY_BACKGROUND
) {
1058 hal::SetProcessPriority(Pid(), mPriority
, mCPUPriority
, aBackgroundLRU
);
1060 nsPrintfCString
ProcessPriorityWithBackgroundLRU("%s:%d",
1061 ProcessPriorityToString(mPriority
, mCPUPriority
),
1064 FireTestOnlyObserverNotification("process-priority-with-background-LRU-set",
1065 ProcessPriorityWithBackgroundLRU
.get());
1068 if (!mContentParent
||
1069 !ProcessPriorityManagerImpl::PrefsEnabled() ||
1070 (mPriority
== aPriority
&& mCPUPriority
== aCPUPriority
)) {
1074 // If the prefs were disabled after this ParticularProcessPriorityManager was
1075 // created, we can at least avoid any further calls to
1076 // hal::SetProcessPriority. Supporting dynamic enabling/disabling of the
1077 // ProcessPriorityManager is mostly for testing.
1078 if (!ProcessPriorityManagerImpl::PrefsEnabled()) {
1082 if (aPriority
== PROCESS_PRIORITY_BACKGROUND
&&
1083 mPriority
!= PROCESS_PRIORITY_BACKGROUND
&&
1084 !IsPreallocated()) {
1085 ProcessPriorityManager::AddIntoBackgroundLRUPool(mContentParent
);
1088 if (aPriority
!= PROCESS_PRIORITY_BACKGROUND
&&
1089 mPriority
== PROCESS_PRIORITY_BACKGROUND
&&
1090 !IsPreallocated()) {
1091 ProcessPriorityManager::RemoveFromBackgroundLRUPool(mContentParent
);
1094 LOGP("Changing priority from %s to %s.",
1095 ProcessPriorityToString(mPriority
, mCPUPriority
),
1096 ProcessPriorityToString(aPriority
, aCPUPriority
));
1098 ProcessPriority oldPriority
= mPriority
;
1100 mPriority
= aPriority
;
1101 mCPUPriority
= aCPUPriority
;
1102 hal::SetProcessPriority(Pid(), mPriority
, mCPUPriority
);
1104 if (oldPriority
!= mPriority
) {
1105 unused
<< mContentParent
->SendNotifyProcessPriorityChanged(mPriority
);
1108 if (aPriority
< PROCESS_PRIORITY_FOREGROUND
) {
1109 unused
<< mContentParent
->SendFlushMemory(NS_LITERAL_STRING("low-memory"));
1112 FireTestOnlyObserverNotification("process-priority-set",
1113 ProcessPriorityToString(mPriority
, mCPUPriority
));
1115 if (oldPriority
!= mPriority
) {
1116 ProcessPriorityManagerImpl::GetSingleton()->
1117 NotifyProcessPriorityChanged(this, oldPriority
);
1122 ParticularProcessPriorityManager::ShutDown()
1124 MOZ_ASSERT(mContentParent
);
1126 UnregisterWakeLockObserver(this);
1128 if (mResetPriorityTimer
) {
1129 mResetPriorityTimer
->Cancel();
1130 mResetPriorityTimer
= nullptr;
1133 if (mPriority
== PROCESS_PRIORITY_BACKGROUND
&& !IsPreallocated()) {
1134 ProcessPriorityManager::RemoveFromBackgroundLRUPool(mContentParent
);
1137 mContentParent
= nullptr;
1141 ProcessPriorityManagerImpl::FireTestOnlyObserverNotification(
1143 const nsACString
& aData
/* = EmptyCString() */)
1145 if (!Preferences::GetBool("dom.ipc.processPriorityManager.testMode")) {
1149 nsCOMPtr
<nsIObserverService
> os
= services::GetObserverService();
1150 NS_ENSURE_TRUE_VOID(os
);
1152 nsPrintfCString
topic("process-priority-manager:TEST-ONLY:%s", aTopic
);
1154 LOG("Notifying observer %s, data %s",
1155 topic
.get(), PromiseFlatCString(aData
).get());
1156 os
->NotifyObservers(nullptr, topic
.get(), NS_ConvertUTF8toUTF16(aData
).get());
1160 ParticularProcessPriorityManager::FireTestOnlyObserverNotification(
1162 const char* aData
/* = nullptr */ )
1164 if (!Preferences::GetBool("dom.ipc.processPriorityManager.testMode")) {
1170 data
.AppendASCII(aData
);
1173 FireTestOnlyObserverNotification(aTopic
, data
);
1177 ParticularProcessPriorityManager::FireTestOnlyObserverNotification(
1179 const nsACString
& aData
/* = EmptyCString() */)
1181 if (!Preferences::GetBool("dom.ipc.processPriorityManager.testMode")) {
1185 nsAutoCString
data(nsPrintfCString("%lld", ChildID()));
1186 if (!aData
.IsEmpty()) {
1191 // ProcessPriorityManagerImpl::GetSingleton() is guaranteed not to return
1192 // null, since ProcessPriorityManagerImpl is the only class which creates
1193 // ParticularProcessPriorityManagers.
1195 ProcessPriorityManagerImpl::GetSingleton()->
1196 FireTestOnlyObserverNotification(aTopic
, data
);
1199 StaticRefPtr
<ProcessPriorityManagerChild
>
1200 ProcessPriorityManagerChild::sSingleton
;
1203 ProcessPriorityManagerChild::StaticInit()
1206 sSingleton
= new ProcessPriorityManagerChild();
1208 ClearOnShutdown(&sSingleton
);
1212 /* static */ ProcessPriorityManagerChild
*
1213 ProcessPriorityManagerChild::Singleton()
1219 NS_IMPL_ISUPPORTS(ProcessPriorityManagerChild
,
1222 ProcessPriorityManagerChild::ProcessPriorityManagerChild()
1224 if (XRE_GetProcessType() == GeckoProcessType_Default
) {
1225 mCachedPriority
= PROCESS_PRIORITY_MASTER
;
1227 mCachedPriority
= PROCESS_PRIORITY_UNKNOWN
;
1232 ProcessPriorityManagerChild::Init()
1234 // The process priority should only be changed in child processes; don't even
1235 // bother listening for changes if we're in the main process.
1236 if (XRE_GetProcessType() != GeckoProcessType_Default
) {
1237 nsCOMPtr
<nsIObserverService
> os
= services::GetObserverService();
1238 NS_ENSURE_TRUE_VOID(os
);
1239 os
->AddObserver(this, "ipc:process-priority-changed", /* weak = */ false);
1244 ProcessPriorityManagerChild::Observe(
1245 nsISupports
* aSubject
,
1247 const char16_t
* aData
)
1249 MOZ_ASSERT(!strcmp(aTopic
, "ipc:process-priority-changed"));
1251 nsCOMPtr
<nsIPropertyBag2
> props
= do_QueryInterface(aSubject
);
1252 NS_ENSURE_TRUE(props
, NS_OK
);
1254 int32_t priority
= static_cast<int32_t>(PROCESS_PRIORITY_UNKNOWN
);
1255 props
->GetPropertyAsInt32(NS_LITERAL_STRING("priority"), &priority
);
1256 NS_ENSURE_TRUE(ProcessPriority(priority
) != PROCESS_PRIORITY_UNKNOWN
, NS_OK
);
1258 mCachedPriority
= static_cast<ProcessPriority
>(priority
);
1264 ProcessPriorityManagerChild::CurrentProcessIsForeground()
1266 return mCachedPriority
== PROCESS_PRIORITY_UNKNOWN
||
1267 mCachedPriority
>= PROCESS_PRIORITY_FOREGROUND
;
1271 ProcessPriorityManagerChild::CurrentProcessIsHighPriority()
1273 return mCachedPriority
== PROCESS_PRIORITY_UNKNOWN
||
1274 mCachedPriority
>= PROCESS_PRIORITY_FOREGROUND_HIGH
;
1277 /* static */ StaticAutoPtr
<BackgroundProcessLRUPool
>
1278 BackgroundProcessLRUPool::sSingleton
;
1280 /* static */ BackgroundProcessLRUPool
*
1281 BackgroundProcessLRUPool::Singleton()
1284 sSingleton
= new BackgroundProcessLRUPool();
1285 ClearOnShutdown(&sSingleton
);
1290 BackgroundProcessLRUPool::BackgroundProcessLRUPool()
1296 BackgroundProcessLRUPool::CalculateLRULevel(uint32_t aBackgroundLRUPoolIndex
)
1298 // Set LRU level of each background process and maintain LRU buffer as below:
1300 // Priority background : LRU0
1301 // Priority background+1: LRU1, LRU2
1302 // Priority background+2: LRU3, LRU4, LRU5, LRU6
1303 // Priority background+3: LRU7, LRU8, LRU9, LRU10, LRU11, LRU12, LRU13, LRU14
1305 // Priority background+L-1: 2^(number of background LRU pool levels - 1)
1308 return (uint32_t)(log((float)aBackgroundLRUPoolIndex
) / log(2.0));
1312 BackgroundProcessLRUPool::EnsureLRUPool()
1314 // We set mBackgroundLRUPoolLevels according to our pref.
1315 // This value is used to set background process LRU pool
1316 if (!NS_SUCCEEDED(Preferences::GetInt(
1317 "dom.ipc.processPriorityManager.backgroundLRUPoolLevels",
1318 &mLRUPoolLevels
))) {
1322 if (mLRUPoolLevels
<= 0) {
1326 // GonkHal defines OOM_ADJUST_MAX is 15 and b2g.js defines
1327 // PROCESS_PRIORITY_BACKGROUND's oom_score_adj is 667 and oom_adj is 10.
1328 // This means we can only have at most (15 -10 + 1) = 6 background LRU levels.
1329 // See bug 822325 comment 49
1330 MOZ_ASSERT(mLRUPoolLevels
<= 6);
1332 // LRU pool size = 2 ^ (number of background LRU pool levels) - 1
1333 mLRUPoolSize
= (1 << mLRUPoolLevels
) - 1;
1335 mLRUPoolAvailableIndex
= 0;
1337 LOG("Making background LRU pool with size(%d)", mLRUPoolSize
);
1339 mLRUPool
.InsertElementsAt(0, mLRUPoolSize
, (ContentParent
*)nullptr);
1343 BackgroundProcessLRUPool::RemoveFromBackgroundLRUPool(
1344 ContentParent
* aContentParent
)
1346 for (int32_t i
= 0; i
< mLRUPoolSize
; i
++) {
1348 if (mLRUPool
[i
]->ChildID() == aContentParent
->ChildID()) {
1350 mLRUPool
[i
] = nullptr;
1351 LOG("Remove ChildID(%llu) from LRU pool", aContentParent
->ChildID());
1353 // After we remove this ContentParent from LRU pool, we still need to
1354 // update the available index if the index of removed one is less than
1355 // the available index we already have.
1356 UpdateAvailableIndexInLRUPool(aContentParent
, i
);
1364 BackgroundProcessLRUPool::UpdateAvailableIndexInLRUPool(
1365 ContentParent
* aContentParent
,
1366 int32_t aTargetIndex
)
1368 // If we specify which index we want to assign to mLRUPoolAvailableIndex,
1369 // We have to make sure the index in LRUPool doesn't point to any
1371 if (aTargetIndex
>= 0 && aTargetIndex
< mLRUPoolSize
&&
1372 aTargetIndex
< mLRUPoolAvailableIndex
&&
1373 !mLRUPool
[aTargetIndex
]) {
1374 mLRUPoolAvailableIndex
= aTargetIndex
;
1378 // When we didn't specify any legal aTargetIndex, then we just check
1379 // whether current mLRUPoolAvailableIndex points to any ContentParent or not.
1380 if (mLRUPoolAvailableIndex
>= 0 && mLRUPoolAvailableIndex
< mLRUPoolSize
&&
1381 !(mLRUPool
[mLRUPoolAvailableIndex
])) {
1385 // Both above way failed. So now we have to find proper value
1386 // for mLRUPoolAvailableIndex.
1387 // We are looking for an available index. We only shift process with
1388 // LRU less than the available index should have, so we stop update
1389 // mLRUPoolAvailableIndex from the for loop once we got a candidate.
1390 mLRUPoolAvailableIndex
= -1;
1392 for (int32_t i
= 0; i
< mLRUPoolSize
; i
++) {
1394 if (mLRUPool
[i
]->ChildID() == aContentParent
->ChildID()) {
1395 LOG("ChildID(%llu) already in LRU pool", aContentParent
->ChildID());
1397 return NS_ERROR_UNEXPECTED
;
1401 if (mLRUPoolAvailableIndex
== -1) {
1402 mLRUPoolAvailableIndex
= i
;
1407 // If the LRUPool is already full, mLRUPoolAvailableIndex is still -1 after
1408 // above loop finished. We should set mLRUPoolAvailableIndex
1409 // to mLRUPoolSize - 1 in this case. Here uses the mod operator to do it:
1410 // New mLRUPoolAvailableIndex either equals old mLRUPoolAvailableIndex, or
1411 // mLRUPoolSize - 1 if old mLRUPoolAvailableIndex is -1.
1412 mLRUPoolAvailableIndex
=
1413 (mLRUPoolAvailableIndex
+ mLRUPoolSize
) % mLRUPoolSize
;
1419 BackgroundProcessLRUPool::ShiftLRUPool()
1421 for (int32_t i
= mLRUPoolAvailableIndex
; i
> 0; i
--) {
1422 mLRUPool
[i
] = mLRUPool
[i
- 1];
1423 // Check whether i+1 is power of Two.
1424 // If so, then it crossed a LRU group boundary and
1425 // we need to assign its new process priority LRU.
1426 if (!((i
+ 1) & i
)) {
1427 ProcessPriorityManagerImpl::GetSingleton()->SetProcessPriority(
1428 mLRUPool
[i
], PROCESS_PRIORITY_BACKGROUND
, CalculateLRULevel(i
+ 1));
1434 BackgroundProcessLRUPool::AddIntoBackgroundLRUPool(
1435 ContentParent
* aContentParent
)
1437 // We have to make sure that we have correct available index in LRU pool
1439 UpdateAvailableIndexInLRUPool(aContentParent
))) {
1443 // Shift the list in the pool, so we have room at index 0 for the newly added
1447 mLRUPool
[0] = aContentParent
;
1449 LOG("Add ChildID(%llu) into LRU pool", aContentParent
->ChildID());
1452 } // anonymous namespace
1457 ProcessPriorityManager::Init()
1459 ProcessPriorityManagerImpl::StaticInit();
1460 ProcessPriorityManagerChild::StaticInit();
1464 ProcessPriorityManager::SetProcessPriority(ContentParent
* aContentParent
,
1465 ProcessPriority aPriority
)
1467 MOZ_ASSERT(aContentParent
);
1469 ProcessPriorityManagerImpl
* singleton
=
1470 ProcessPriorityManagerImpl::GetSingleton();
1472 singleton
->SetProcessPriority(aContentParent
, aPriority
);
1477 ProcessPriorityManager::RemoveFromBackgroundLRUPool(
1478 ContentParent
* aContentParent
)
1480 MOZ_ASSERT(aContentParent
);
1482 BackgroundProcessLRUPool
* singleton
=
1483 BackgroundProcessLRUPool::Singleton();
1485 singleton
->RemoveFromBackgroundLRUPool(aContentParent
);
1490 ProcessPriorityManager::AddIntoBackgroundLRUPool(ContentParent
* aContentParent
)
1492 MOZ_ASSERT(aContentParent
);
1494 BackgroundProcessLRUPool
* singleton
=
1495 BackgroundProcessLRUPool::Singleton();
1497 singleton
->AddIntoBackgroundLRUPool(aContentParent
);
1502 ProcessPriorityManager::CurrentProcessIsForeground()
1504 return ProcessPriorityManagerChild::Singleton()->
1505 CurrentProcessIsForeground();
1509 ProcessPriorityManager::AnyProcessHasHighPriority()
1511 ProcessPriorityManagerImpl
* singleton
=
1512 ProcessPriorityManagerImpl::GetSingleton();
1515 return singleton
->ChildProcessHasHighPriority();
1517 return ProcessPriorityManagerChild::Singleton()->
1518 CurrentProcessIsHighPriority();
1522 } // namespace mozilla