summaryrefslogtreecommitdiffstats
path: root/tools/profiler/tasktracer/TracedTaskCommon.cpp
blob: 4b5d4d4cc608483eaf40b875ca2b07e850e5522a (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
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */

#include "TracedTaskCommon.h"

#include "GeckoTaskTracerImpl.h"

// NS_ENSURE_TRUE_VOID() without the warning on the debug build.
#define ENSURE_TRUE_VOID(x)   \
  do {                        \
    if (MOZ_UNLIKELY(!(x))) { \
      return;                 \
    }                         \
  } while (0)

namespace mozilla {
namespace tasktracer {

TracedTaskCommon::TracedTaskCommon()
    : mSourceEventType(SourceEventType::Unknown),
      mSourceEventId(0),
      mParentTaskId(0),
      mTaskId(0),
      mIsTraceInfoInit(false) {}

TracedTaskCommon::~TracedTaskCommon() {}

void TracedTaskCommon::Init() {
  // Keep the following line before GetOrCreateTraceInfo() to avoid a
  // deadlock.
  uint64_t taskid = GenNewUniqueTaskId();

  TraceInfoHolder info = GetOrCreateTraceInfo();
  ENSURE_TRUE_VOID(info);

  mTaskId = taskid;
  mSourceEventId = info->mCurTraceSourceId;
  mSourceEventType = info->mCurTraceSourceType;
  mParentTaskId = info->mCurTaskId;
  mIsTraceInfoInit = true;
}

void TracedTaskCommon::DispatchTask(int aDelayTimeMs) {
  LogDispatch(mTaskId, mParentTaskId, mSourceEventId, mSourceEventType,
              aDelayTimeMs);
}

void TracedTaskCommon::DoGetTLSTraceInfo() {
  TraceInfoHolder info = GetOrCreateTraceInfo();
  ENSURE_TRUE_VOID(info);
  MOZ_ASSERT(!mIsTraceInfoInit);

  mSourceEventType = info->mCurTraceSourceType;
  mSourceEventId = info->mCurTraceSourceId;
  mTaskId = info->mCurTaskId;
  mIsTraceInfoInit = true;
}

void TracedTaskCommon::DoSetTLSTraceInfo() {
  TraceInfoHolder info = GetOrCreateTraceInfo();
  ENSURE_TRUE_VOID(info);

  if (mIsTraceInfoInit) {
    info->mCurTraceSourceId = mSourceEventId;
    info->mCurTraceSourceType = mSourceEventType;
    info->mCurTaskId = mTaskId;
  }
}

void TracedTaskCommon::ClearTLSTraceInfo() {
  TraceInfoHolder info = GetOrCreateTraceInfo();
  ENSURE_TRUE_VOID(info);

  info->mCurTraceSourceId = 0;
  info->mCurTraceSourceType = SourceEventType::Unknown;
  info->mCurTaskId = 0;
}

/**
 * Implementation of class TracedRunnable.
 */

NS_IMPL_ISUPPORTS(TracedRunnable, nsIRunnable);

TracedRunnable::TracedRunnable(already_AddRefed<nsIRunnable>&& aOriginalObj)
    : TracedTaskCommon(), mOriginalObj(std::move(aOriginalObj)) {
  Init();
  LogVirtualTablePtr(mTaskId, mSourceEventId,
                     *reinterpret_cast<uintptr_t**>(mOriginalObj.get()));
}

TracedRunnable::~TracedRunnable() {}

NS_IMETHODIMP
TracedRunnable::Run() {
  SetTLSTraceInfo();
  LogBegin(mTaskId, mSourceEventId);
  nsresult rv = mOriginalObj->Run();
  LogEnd(mTaskId, mSourceEventId);
  ClearTLSTraceInfo();

  return rv;
}

/**
 * CreateTracedRunnable() returns a TracedRunnable wrapping the original
 * nsIRunnable object, aRunnable.
 */
already_AddRefed<nsIRunnable> CreateTracedRunnable(
    already_AddRefed<nsIRunnable>&& aRunnable) {
  RefPtr<nsIRunnable> runnable = new TracedRunnable(std::move(aRunnable));
  return runnable.forget();
}

void VirtualTask::AutoRunTask::StartScope(VirtualTask* aTask) {
  mTask->SetTLSTraceInfo();
  LogBegin(mTask->mTaskId, mTask->mSourceEventId);
}

void VirtualTask::AutoRunTask::StopScope() {
  LogEnd(mTask->mTaskId, mTask->mSourceEventId);
}

}  // namespace tasktracer
}  // namespace mozilla