1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 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 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_Scheduler_h 8 #define mozilla_Scheduler_h 9 10 #include "mozilla/Attributes.h" 11 #include "mozilla/EventQueue.h" 12 #include "mozilla/RefPtr.h" 13 #include "mozilla/ThreadLocal.h" 14 #include "mozilla/UniquePtr.h" 15 #include "nsTArray.h" 16 #include "nsILabelableRunnable.h" 17 18 // Windows silliness. winbase.h defines an empty no-argument Yield macro. 19 #undef Yield 20 21 class nsIBlockThreadedExecutionCallback; 22 class nsIIdlePeriod; 23 class nsThread; 24 25 namespace mozilla { 26 27 class SchedulerGroup; 28 class SchedulerImpl; 29 class SynchronizedEventQueue; 30 31 // This is the central class for scheduling work on the "main" thread. It starts 32 // a pool of cooperatively scheduled threads (using CooperativeThreadPool) and 33 // controls them using a single, main-thread event queue 34 // (SchedulerEventQueue). Even if cooperative scheduling is not enabled, 35 // Scheduler can schedule work on the main thread. Its behavior is controlled by 36 // a number of preferences: 37 // 38 // XXX The cooperative scheduler is disabled because it will crash immediately. 39 // 40 // "dom.ipc.scheduler.useMultipleQueues": When this pref is true, a 41 // LabeledEventQueue is used for the main thread event queue. This divides the 42 // event queue into multiple queues, one per SchedulerGroup. If the pref is 43 // false, a normal EventQueue is used. Either way, event prioritization via 44 // PrioritizedEventQueue still happens. 45 // 46 // "dom.ipc.scheduler.preemption": If this pref is true, then cooperative 47 // threads can be preempted before they have finished. This might happen if a 48 // different cooperative thread is running an event for a higher priority 49 // SchedulerGroup. 50 // 51 // "dom.ipc.scheduler.threadCount": The number of cooperative threads to start. 52 // 53 // "dom.ipc.scheduler.chaoticScheduling": When this pref is set, we make an 54 // effort to switch between threads even when it is not necessary to do 55 // this. This is useful for debugging. 56 class Scheduler { 57 public: 58 static already_AddRefed<nsThread> Init(nsIIdlePeriod* aIdlePeriod); 59 static void Start(); 60 static void Shutdown(); 61 62 // Scheduler prefs need to be handled differently because the scheduler needs 63 // to start up in the content process before the normal preferences service. 64 static nsCString GetPrefs(); 65 static void SetPrefs(const char* aPrefs); 66 67 static bool IsSchedulerEnabled(); 68 static bool UseMultipleQueues(); 69 70 static bool IsCooperativeThread(); 71 72 static void Yield(); 73 74 static bool UnlabeledEventRunning(); 75 static bool AnyEventRunning(); 76 77 static void BlockThreadedExecution( 78 nsIBlockThreadedExecutionCallback* aCallback); 79 static void UnblockThreadedExecution(); 80 81 class MOZ_RAII EventLoopActivation { 82 public: 83 using EventGroups = nsILabelableRunnable::SchedulerGroupSet; 84 EventLoopActivation(); 85 ~EventLoopActivation(); 86 87 static void Init(); 88 IsNested()89 bool IsNested() const { return !!mPrev; } 90 91 void SetEvent(nsIRunnable* aEvent, EventPriority aPriority); 92 Priority()93 EventPriority Priority() const { return mPriority; } IsLabeled()94 bool IsLabeled() { return mIsLabeled; } EventGroupsAffected()95 EventGroups& EventGroupsAffected() { return mEventGroups; } 96 97 private: 98 EventLoopActivation* mPrev; 99 bool mProcessingEvent; 100 bool mIsLabeled; 101 EventGroups mEventGroups; 102 EventPriority mPriority; 103 104 static MOZ_THREAD_LOCAL(EventLoopActivation*) sTopActivation; 105 }; 106 107 private: 108 friend class SchedulerImpl; 109 static UniquePtr<SchedulerImpl> sScheduler; 110 }; 111 112 } // namespace mozilla 113 114 #endif // mozilla_Scheduler_h 115