summaryrefslogtreecommitdiffstats
path: root/ipc/glue/IdleSchedulerParent.h
blob: 62cf6fb772340d8ee5562048098c18b3fc2400b9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_ipc_IdleSchedulerParent_h__
#define mozilla_ipc_IdleSchedulerParent_h__

#include "mozilla/Assertions.h"
#include "mozilla/Atomics.h"
#include "mozilla/Attributes.h"
#include "mozilla/LinkedList.h"
#include "mozilla/ipc/PIdleSchedulerParent.h"
#include "base/shared_memory.h"
#include <bitset>

#define NS_IDLE_SCHEDULER_COUNTER_ARRAY_LENGHT 1024
#define NS_IDLE_SCHEDULER_INDEX_OF_ACTIVITY_COUNTER 0
#define NS_IDLE_SCHEDULER_INDEX_OF_CPU_COUNTER 1

class nsITimer;

namespace mozilla {

namespace ipc {

class BackgroundParentImpl;

class IdleSchedulerParent final
    : public PIdleSchedulerParent,
      public LinkedListElement<IdleSchedulerParent> {
 public:
  NS_INLINE_DECL_REFCOUNTING(IdleSchedulerParent)

  IPCResult RecvInitForIdleUse(InitForIdleUseResolver&& aResolve);
  IPCResult RecvRequestIdleTime(uint64_t aId, TimeDuration aBudget);
  IPCResult RecvIdleTimeUsed(uint64_t aId);
  IPCResult RecvSchedule();
  IPCResult RecvRunningPrioritizedOperation();
  IPCResult RecvPrioritizedOperationDone();
  IPCResult RecvRequestGC(RequestGCResolver&& aResolve);
  IPCResult RecvStartedGC();
  IPCResult RecvDoneGC();

 private:
  friend class BackgroundParentImpl;
  IdleSchedulerParent();
  ~IdleSchedulerParent();

  static void CalculateNumIdleTasks();

  static int32_t ActiveCount();
  static void Schedule(IdleSchedulerParent* aRequester);
  static bool HasSpareCycles(int32_t aActiveCount);
  static bool HasSpareGCCycles();
  using PIdleSchedulerParent::SendIdleTime;
  void SendIdleTime();
  void SendMayGC();

  static void EnsureStarvationTimer();
  static void StarvationCallback(nsITimer* aTimer, void* aData);

  uint64_t mCurrentRequestId = 0;
  // For now we don't really use idle budget for scheduling.  Zero if the
  // process isn't requestiong or running an idle task.
  TimeDuration mRequestedIdleBudget;

  // Counting all the prioritized operations the process is doing.
  uint32_t mRunningPrioritizedOperation = 0;

  // Only one of these may be true at a time, giving three states:
  // No active GC request, A pending GC request, or a granted GC request.
  Maybe<RequestGCResolver> mRequestingGC;
  bool mDoingGC = false;

  uint32_t mChildId = 0;

  // Current state, only one of these may be true at a time.
  bool IsWaitingForIdle() const { return isInList() && mRequestedIdleBudget; }
  bool IsDoingIdleTask() const { return !isInList() && mRequestedIdleBudget; }
  bool IsNotDoingIdleTask() const { return !mRequestedIdleBudget; }

  // Shared memory for counting how many child processes are running
  // tasks. This memory is shared across all the child processes.
  // The [0] is used for counting all the processes and
  // [childId] is for counting per process activity.
  // This way the global activity can be checked in a fast way by just looking
  // at [0] value.
  // [1] is used for cpu count for child processes.
  static base::SharedMemory* sActiveChildCounter;
  // A bit is set if there is a child with child Id as the offset.
  // The bit is used to check per child specific activity counters in
  // sActiveChildCounter.
  static std::bitset<NS_IDLE_SCHEDULER_COUNTER_ARRAY_LENGHT>
      sInUseChildCounters;

  // Processes on this list have requested (but the request hasn't yet been
  // granted) idle time or to start a GC or both.
  //
  // Either or both their mRequestedIdleBudget or mRequestingGC fields are
  // non-zero.  Child processes not on this list have either been granted all
  // their requests not made a request ever or since they last finished an idle
  // or GC task.
  //
  // Use the methods above to determine a process' idle time state, or check the
  // mRequestingGC and mDoingGC fields for the GC state.
  static LinkedList<IdleSchedulerParent> sIdleAndGCRequests;

  static int32_t sMaxConcurrentIdleTasksInChildProcesses;
  static uint32_t sMaxConcurrentGCs;
  static uint32_t sActiveGCs;

  // True if we should record some telemetry for GCs in the next Schedule().
  // This is set to true by either requesting a GC job or scheduling a GC job.
  static bool sRecordGCTelemetry;
  // The current number of waiting GCs.
  static uint32_t sNumWaitingGC;

  // Counting all the child processes which have at least one prioritized
  // operation.
  static uint32_t sChildProcessesRunningPrioritizedOperation;

  // When this hits zero, it's time to free the shared memory and pack up.
  static uint32_t sChildProcessesAlive;

  static nsITimer* sStarvationPreventer;

  static uint32_t sNumCPUs;
  static uint32_t sPrefConcurrentGCsMax;
  static uint32_t sPrefConcurrentGCsCPUDivisor;
};

}  // namespace ipc
}  // namespace mozilla

#endif  // mozilla_ipc_IdleSchedulerParent_h__