Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/tools/profiler/gecko/ProfilerParent.cpp
Line
Count
Source (jump to first uncovered line)
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
#include "ProfilerParent.h"
8
9
#include "mozilla/ClearOnShutdown.h"
10
#include "mozilla/RefPtr.h"
11
#include "mozilla/Unused.h"
12
13
#include "nsProfiler.h"
14
#include "nsTArray.h"
15
#include "nsThreadUtils.h"
16
17
namespace mozilla {
18
19
using namespace ipc;
20
21
class ProfilerParentTracker final {
22
public:
23
  static void StartTracking(ProfilerParent* aParent);
24
  static void StopTracking(ProfilerParent* aParent);
25
26
  template<typename FuncType>
27
  static void Enumerate(FuncType aIterFunc);
28
29
  ProfilerParentTracker();
30
  ~ProfilerParentTracker();
31
32
private:
33
  nsTArray<ProfilerParent*> mProfilerParents;
34
  static UniquePtr<ProfilerParentTracker> sInstance;
35
};
36
37
UniquePtr<ProfilerParentTracker> ProfilerParentTracker::sInstance;
38
39
/* static */ void
40
ProfilerParentTracker::StartTracking(ProfilerParent* aProfilerParent)
41
0
{
42
0
  if (!sInstance) {
43
0
    sInstance = MakeUnique<ProfilerParentTracker>();
44
0
    ClearOnShutdown(&sInstance);
45
0
  }
46
0
  sInstance->mProfilerParents.AppendElement(aProfilerParent);
47
0
}
48
49
/* static */ void
50
ProfilerParentTracker::StopTracking(ProfilerParent* aParent)
51
0
{
52
0
  if (sInstance) {
53
0
    sInstance->mProfilerParents.RemoveElement(aParent);
54
0
  }
55
0
}
56
57
template<typename FuncType>
58
/* static */ void
59
ProfilerParentTracker::Enumerate(FuncType aIterFunc)
60
0
{
61
0
  if (sInstance) {
62
0
    for (ProfilerParent* profilerParent : sInstance->mProfilerParents) {
63
0
      if (!profilerParent->mDestroyed) {
64
0
        aIterFunc(profilerParent);
65
0
      }
66
0
    }
67
0
  }
68
0
}
Unexecuted instantiation: Unified_cpp_tools_profiler0.cpp:void mozilla::ProfilerParentTracker::Enumerate<mozilla::ProfilerParent::GatherProfiles()::$_10>(mozilla::ProfilerParent::GatherProfiles()::$_10)
Unexecuted instantiation: Unified_cpp_tools_profiler0.cpp:void mozilla::ProfilerParentTracker::Enumerate<mozilla::ProfilerParent::ProfilerStarted(nsIProfilerStartParams*)::$_11>(mozilla::ProfilerParent::ProfilerStarted(nsIProfilerStartParams*)::$_11)
Unexecuted instantiation: Unified_cpp_tools_profiler0.cpp:void mozilla::ProfilerParentTracker::Enumerate<mozilla::ProfilerParent::ProfilerStopped()::$_12>(mozilla::ProfilerParent::ProfilerStopped()::$_12)
Unexecuted instantiation: Unified_cpp_tools_profiler0.cpp:void mozilla::ProfilerParentTracker::Enumerate<mozilla::ProfilerParent::ProfilerPaused()::$_13>(mozilla::ProfilerParent::ProfilerPaused()::$_13)
Unexecuted instantiation: Unified_cpp_tools_profiler0.cpp:void mozilla::ProfilerParentTracker::Enumerate<mozilla::ProfilerParent::ProfilerResumed()::$_14>(mozilla::ProfilerParent::ProfilerResumed()::$_14)
69
70
ProfilerParentTracker::ProfilerParentTracker()
71
0
{
72
0
  MOZ_COUNT_CTOR(ProfilerParentTracker);
73
0
}
74
75
ProfilerParentTracker::~ProfilerParentTracker()
76
0
{
77
0
  MOZ_COUNT_DTOR(ProfilerParentTracker);
78
0
79
0
  nsTArray<ProfilerParent*> parents;
80
0
  parents = mProfilerParents;
81
0
  // Close the channels of any profiler parents that haven't been destroyed.
82
0
  for (ProfilerParent* profilerParent : parents) {
83
0
    if (!profilerParent->mDestroyed) {
84
0
      // Keep the object alive until the call to Close() has completed.
85
0
      // Close() will trigger a call to DeallocPProfilerParent.
86
0
      RefPtr<ProfilerParent> actor = profilerParent;
87
0
      actor->Close();
88
0
    }
89
0
  }
90
0
}
91
92
/* static */ Endpoint<PProfilerChild>
93
ProfilerParent::CreateForProcess(base::ProcessId aOtherPid)
94
0
{
95
0
  MOZ_RELEASE_ASSERT(NS_IsMainThread());
96
0
  Endpoint<PProfilerParent> parent;
97
0
  Endpoint<PProfilerChild> child;
98
0
  nsresult rv = PProfiler::CreateEndpoints(base::GetCurrentProcId(),
99
0
                                           aOtherPid,
100
0
                                           &parent, &child);
101
0
102
0
  if (NS_FAILED(rv)) {
103
0
    MOZ_CRASH("Failed to create top level actor for PProfiler!");
104
0
  }
105
0
106
0
  RefPtr<ProfilerParent> actor = new ProfilerParent();
107
0
  if (!parent.Bind(actor)) {
108
0
    MOZ_CRASH("Failed to bind parent actor for PProfiler!");
109
0
  }
110
0
111
0
  // mSelfRef will be cleared in DeallocPProfilerParent.
112
0
  actor->mSelfRef = actor;
113
0
  actor->Init();
114
0
115
0
  return child;
116
0
}
117
118
ProfilerParent::ProfilerParent()
119
  : mDestroyed(false)
120
0
{
121
0
  MOZ_COUNT_CTOR(ProfilerParent);
122
0
123
0
  MOZ_RELEASE_ASSERT(NS_IsMainThread());
124
0
}
125
126
void
127
ProfilerParent::Init()
128
0
{
129
0
  MOZ_RELEASE_ASSERT(NS_IsMainThread());
130
0
131
0
  ProfilerParentTracker::StartTracking(this);
132
0
133
0
  // We propagated the profiler state from the parent process to the child
134
0
  // process through MOZ_PROFILER_STARTUP* environment variables.
135
0
  // However, the profiler state might have changed in this process since then,
136
0
  // and now that an active communication channel has been established with the
137
0
  // child process, it's a good time to sync up the two profilers again.
138
0
139
0
  int entries = 0;
140
0
  double interval = 0;
141
0
  mozilla::Vector<const char*> filters;
142
0
  uint32_t features;
143
0
  profiler_get_start_params(&entries, &interval, &features, &filters);
144
0
145
0
  if (entries != 0) {
146
0
    ProfilerInitParams ipcParams;
147
0
    ipcParams.enabled() = true;
148
0
    ipcParams.entries() = entries;
149
0
    ipcParams.interval() = interval;
150
0
    ipcParams.features() = features;
151
0
152
0
    for (uint32_t i = 0; i < filters.length(); ++i) {
153
0
      ipcParams.filters().AppendElement(filters[i]);
154
0
    }
155
0
156
0
    Unused << SendEnsureStarted(ipcParams);
157
0
  } else {
158
0
    Unused << SendStop();
159
0
  }
160
0
}
161
162
ProfilerParent::~ProfilerParent()
163
0
{
164
0
  MOZ_COUNT_DTOR(ProfilerParent);
165
0
166
0
  MOZ_RELEASE_ASSERT(NS_IsMainThread());
167
0
  ProfilerParentTracker::StopTracking(this);
168
0
}
169
170
/* static */ nsTArray<RefPtr<ProfilerParent::SingleProcessProfilePromise>>
171
ProfilerParent::GatherProfiles()
172
0
{
173
0
  if (!NS_IsMainThread()) {
174
0
    return nsTArray<RefPtr<ProfilerParent::SingleProcessProfilePromise>>();
175
0
  }
176
0
177
0
  nsTArray<RefPtr<SingleProcessProfilePromise>> results;
178
0
  ProfilerParentTracker::Enumerate([&](ProfilerParent* profilerParent) {
179
0
    results.AppendElement(profilerParent->SendGatherProfile());
180
0
  });
181
0
  return results;
182
0
}
183
184
/* static */ void
185
ProfilerParent::ProfilerStarted(nsIProfilerStartParams* aParams)
186
0
{
187
0
  if (!NS_IsMainThread()) {
188
0
    return;
189
0
  }
190
0
191
0
  ProfilerInitParams ipcParams;
192
0
  ipcParams.enabled() = true;
193
0
  aParams->GetEntries(&ipcParams.entries());
194
0
  aParams->GetInterval(&ipcParams.interval());
195
0
  aParams->GetFeatures(&ipcParams.features());
196
0
  ipcParams.filters() = aParams->GetFilters();
197
0
198
0
  ProfilerParentTracker::Enumerate([&](ProfilerParent* profilerParent) {
199
0
    Unused << profilerParent->SendStart(ipcParams);
200
0
  });
201
0
}
202
203
/* static */ void
204
ProfilerParent::ProfilerStopped()
205
0
{
206
0
  if (!NS_IsMainThread()) {
207
0
    return;
208
0
  }
209
0
210
0
  ProfilerParentTracker::Enumerate([](ProfilerParent* profilerParent) {
211
0
    Unused << profilerParent->SendStop();
212
0
  });
213
0
}
214
215
/* static */ void
216
ProfilerParent::ProfilerPaused()
217
0
{
218
0
  if (!NS_IsMainThread()) {
219
0
    return;
220
0
  }
221
0
222
0
  ProfilerParentTracker::Enumerate([](ProfilerParent* profilerParent) {
223
0
    Unused << profilerParent->SendPause();
224
0
  });
225
0
}
226
227
/* static */ void
228
ProfilerParent::ProfilerResumed()
229
0
{
230
0
  if (!NS_IsMainThread()) {
231
0
    return;
232
0
  }
233
0
234
0
  ProfilerParentTracker::Enumerate([](ProfilerParent* profilerParent) {
235
0
    Unused << profilerParent->SendResume();
236
0
  });
237
0
}
238
239
void
240
ProfilerParent::ActorDestroy(ActorDestroyReason aActorDestroyReason)
241
0
{
242
0
  MOZ_RELEASE_ASSERT(NS_IsMainThread());
243
0
  mDestroyed = true;
244
0
}
245
246
void
247
ProfilerParent::DeallocPProfilerParent()
248
0
{
249
0
  mSelfRef = nullptr;
250
0
}
251
252
} // namespace mozilla