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